You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[finding] SendTemplateInput.org is declared ("Tenant id for org-overlay resolution (when supported)") but no implementation reads it #11832
Found while executing #11741 (widening SendEmailInput/SendTemplateInput with organizationId).
Observation
packages/spec/src/contracts/email-service.ts declares on SendTemplateInput:
/** Tenant id for org-overlay resolution (when supported). */
org?: string;
Measured on claude/issue-11741-sendemail-organization-id (base dce6a019f): zero readers. @objectstack/plugin-email — the only IEmailService implementation in this repo — never consults input.org anywhere (email-service.ts, template-loader.ts, email-plugin.ts; grep for a bare org read comes back empty apart from a prose comment in template-loader.ts:69 about overlay rows). Template resolution keys on (name, locale) only.
Declared ≠ enforced (Prime Directive #10): a caller passing org today gets no org-overlay resolution and no error — the key is silently inert. The "(when supported)" hedge in the TSDoc is the declaration admitting it.
#11741 adds organizationId (the sys_email.organization_id delivery stamp, pass-through) beside the inert org (declared as template resolution overlay). Two org-shaped keys on one input, one of which does nothing, is exactly the shape that invites an AI author to pick the wrong one. The #11741 TSDoc cross-references the distinction, but the long-term fix is for org to be either implemented (org-overlay template rows, if there is measured pull) or retired.
Disposition options for triage
Retireorg (ADR-0049 enforce-or-remove; it is a contracts interface key, not an authorable metadata key, so the retirement kit is lighter — no liveness ledger surface).
Implement org-overlay template resolution and make the declaration true (only with a real business pull; startup scope discipline argues against building it speculatively).
Not verified here: whether anything outside this repo (e.g. cloud) passes or reads org.
Concentrated triage batch: finding → pm:queue + domain:spec, Task — SendTemplateInput.org is declared with a "(when supported)" hedge and has zero readers (re-verified: no bare org read in plugin-email beyond a prose comment), while #11741 establishes organizationId as the read channel. Retire org via the spec-property-retirement / enforce-or-remove route (the playbook governs tombstones, forms, docs and pins). Clause-②: yes at claim (an input-contract member is removed) — contract-review tier per spec-lane rules; if the retirement route's ledger check finds a reader the grep missed, stop and report.
Claim: PM loop round R6
Session: session_01NDGG54XF5gbTLdQzCtnaVV
Branch: claude/issue-11832-retire-sendtemplate-org
Worktree: objectstack-issue-11832
Domain: domain:spec
File surface: packages/spec/src/contracts/email-service.ts (SendTemplateInput.org region ONLY — organizationId member untouched) + email-service tests + regenerated api-surface artifacts if moved + consumer call-site cleanup (examples) + changeset; conditional migrations tail-append only if the ADR-0087 gate demands it (stop on breach; explain in the report)
Container & model: M, mode:subagent, model: claude-fable-5 — dispatch-gates 2026-08-25 @0b04839: "no path-derived mandate … floor sonnet · default opus · ceiling fable … a card changing contract accept/reject behaviour or widening the public surface is claude-fable-5"; clause-② content leg (published contract member removal) ⇒ fable mandatory
Clause-②: yes
Serial constraints cleared: sole writer of contracts/email-service.ts this batch (prior writer PR #11839 for #11741 MERGED; #11741 CLOSED — verified). Conditional registry.ts tail-append shared with #11842/#12039 under the maintainer's parallel waiver (2026-08-25, chat, verbatim: 「并行5个子任务,加快进度」) + 4-point substitute discipline. Route: retire per ADR-0049 enforce-or-remove; premise (zero readers of input.org) is falsifiable — a found reader forks back as needs_decision, never a silent implement. No pin assertions on sibling behavior.
{
"issue": 11832,
"status": "done",
"branch": "claude/issue-11832-retire-sendtemplate-org",
"pr": "https://github.com/objectstack-ai/objectstack/pull/12114",
"premise_still_valid": true,
"summary": "Retired SendTemplateInput.org per ADR-0049 enforce-or-remove. Premise re-verified at claim (base 8d60dcd): zero readers and zero writers of the member in-repo (plugin-email resolves on (name, locale) only; no sendTemplate call site passes org; RenderTemplateInput never carried it; objectui has zero SendTemplateInput references); the member SHIPPED in published @objectstack/spec@17.2.0 (dist/contracts/index.d.ts:6318 in the npm tarball). Removal = member + JSDoc deleted with self-contained tombstone prose in the interface; compile-time pin (@ts-expect-error, bidirectional via TS2578) in email-service.test.ts; D3 SemanticMigration send-template-input-org-retired as one-file shard entries/semantic/18.send-template-input-org-retired.ts + gen:migration-registry (no D2 — call-time input bag, the options.upsert precedent; spec-changes.json/upgrade-guide byte-unchanged by construction, projections stop at PROTOCOL_MAJOR 17); changeset @objectstack/spec minor with BREAKING prose + adr-0087: registered (runtime-interface-only is structurally refused for contracts/ symbols and the body carries a FROM→TO, so registered is the only honest disposition). organizationId (#11741) untouched semantically; no consumer cleanup needed anywhere. Draft PR at final head 6a8a947 after pre-PR origin/main merge; delta vs main is exactly the 5 intended files (+156/−5).",
"tests": "All at final head 6a8a947, via scripts/pm/os-verify-lock.sh, exits captured before any pipe. spec vitest src/contracts/email-service.test.ts src/migrations/migrations.test.ts: 'Test Files 2 passed (2) / Tests 109 passed (109)'; spec full typecheck green incl. 'check:test-typecheck: OK — test layer compiles; 55 file(s)/263 error(s) held' (unchanged). plugin-email (downstream consumer of rebuilt narrowed dist; direction = it declares @objectstack/spec in dependencies): 'Test Files 27 passed (27) / Tests 429 passed (429)' + tsc --noEmit clean. example-showcase test/email-template-locale.test.ts: 'Test Files 1 passed (1) / Tests 6 passed (6)'. Reverse verification from committed state, both legs' mutations proven on disk by anchored grep (tsc reads src via tsconfig.test.json — no dist leg, so no rebuild owed): mutated (org re-added) moved the program 263 ledger-held → 264, the +1 being exactly 'src/contracts/email-service.test.ts(71,7): error TS2578: Unused @ts-expect-error directive'; restored leg grep-absent then back to 'check:test-typecheck: OK' at 263.",
"gates": "At 6a8a947 (re-run after the pre-PR merge), each read from its own verdict line: check:generated 'All 14 generated artifacts are up to date' (api-surface/export-origins/docs unchanged — interface-member removal is invisible to existence-level snapshots, expected for this route); check-adr-0087-registration '1 declared-breaking changeset(s), each carrying an ADR-0087 disposition … registered send-template-input-org-retired (new here)'; green: check:nul-bytes, check:merge-driver, check:published-files, check:slot-lookup, check:spec-parsed-alias, check:cross-package-test-inputs, check:changeset-gate-self-tests, check:objectui-changeset, check:query-options-erasure, check:test-source-alias, check:type-source-resolution, check:engine-double-contract, check:where-matcher, check:type-check-coverage, check-changeset-no-major, check-ci-filter-parity, check-empty-changeset, check-plugin-teardown-shape, spec check:liveness/check:empty-state/check:variant-docs/check:strictness-ledger, lint check:doc-formula-expressions. Dispatch-gates re-derived from the actual change set (script's own derivation, no hand-fed paths; answer attributed to objectstack tree) — the newly derived families beyond the dispatch list were all run and are in the green list above. Remote CI: in_progress at delivery (report at draft-PR time per standing rule).",
"files_changed": [
".changeset/send-template-input-org-retired.md",
"packages/spec/src/contracts/email-service.test.ts",
"packages/spec/src/contracts/email-service.ts",
"packages/spec/src/migrations/entries/semantic/18.send-template-input-org-retired.ts",
"packages/spec/src/migrations/registry.ts"
],
"line_budget": "n/a — diff touches no skills/** (published skill packages untouched)",
"deviations": [
"SendTemplateInput.organizationId TSDoc: one clause rewritten — the claim said organizationId untouched, but its final sentence cross-referenced {@link SendTemplateInput.org}, left dangling and misleading by the removal; rewritten to past-tense retired-member phrasing. Semantics untouched; SendEmailInput.organizationId untouched byte-for-byte. Named in the PR body.",
"check-dev-prereqs reds locally: 'The workspace is not built — 1 unmet precondition, not a list of problems' (fresh targeted worktree; the gate's own text says it is not a finding). CI builds first.",
"check:type-check-debt not run repo-wide — declared narrowing with measurement: its population is the DEBT/TEST_DEBT ledgers in scripts/check-type-check-coverage.mjs; @objectstack/spec graduated (#5286) and the @objectstack/spec-monorepo root program excludes packages/, so none of this PR's 5 paths is an input to any ledgered tsc program; the only tsc programs reading them are spec's own three, run in full (green above).",
"Repo-wide pnpm lint / remaining gate farm: CI-owned (standing narrowing).",
"Channel deviation: this session's egress proxy 403s repo-scoped api.github.com REST paths ('GitHub access is not enabled for this session'; /rate_limit reachable, git push/fetch normal), so the dispatch's REST-channel prescriptions were unavailable; single-issue reads/writes went through MCP issue_read/add_issue_comment/create_pull_request (the banned MCP list_issues/search_issues were not used). Duplicate-search leaned on the PM's dispatch-time dedup reading + local grep + git ls-remote, per the increment-only rule."
],
"open_questions": [],
"out_of_scope_findings": []
}
(Supersedes the previous comment, whose HTML-comment marker the body sanitizer stripped; JSON identical.)
{
"issue": 11832,
"status": "done",
"branch": "claude/issue-11832-retire-sendtemplate-org",
"pr": "https://github.com/objectstack-ai/objectstack/pull/12114",
"premise_still_valid": true,
"summary": "Retired SendTemplateInput.org per ADR-0049 enforce-or-remove. Premise re-verified at claim (base 8d60dcd): zero readers and zero writers of the member in-repo (plugin-email resolves on (name, locale) only; no sendTemplate call site passes org; RenderTemplateInput never carried it; objectui has zero SendTemplateInput references); the member SHIPPED in published @objectstack/spec@17.2.0 (dist/contracts/index.d.ts:6318 in the npm tarball). Removal = member + JSDoc deleted with self-contained tombstone prose in the interface; compile-time pin (@ts-expect-error, bidirectional via TS2578) in email-service.test.ts; D3 SemanticMigration send-template-input-org-retired as one-file shard entries/semantic/18.send-template-input-org-retired.ts + gen:migration-registry (no D2 — call-time input bag, the options.upsert precedent; spec-changes.json/upgrade-guide byte-unchanged by construction, projections stop at PROTOCOL_MAJOR 17); changeset @objectstack/spec minor with BREAKING prose + adr-0087: registered (runtime-interface-only is structurally refused for contracts/ symbols and the body carries a FROM→TO, so registered is the only honest disposition). organizationId (#11741) untouched semantically; no consumer cleanup needed anywhere. Draft PR at final head 6a8a947 after pre-PR origin/main merge; delta vs main is exactly the 5 intended files (+156/−5).",
"tests": "All at final head 6a8a947, via scripts/pm/os-verify-lock.sh, exits captured before any pipe. spec vitest src/contracts/email-service.test.ts src/migrations/migrations.test.ts: 'Test Files 2 passed (2) / Tests 109 passed (109)'; spec full typecheck green incl. 'check:test-typecheck: OK — test layer compiles; 55 file(s)/263 error(s) held' (unchanged). plugin-email (downstream consumer of rebuilt narrowed dist; direction = it declares @objectstack/spec in dependencies): 'Test Files 27 passed (27) / Tests 429 passed (429)' + tsc --noEmit clean. example-showcase test/email-template-locale.test.ts: 'Test Files 1 passed (1) / Tests 6 passed (6)'. Reverse verification from committed state, both legs' mutations proven on disk by anchored grep (tsc reads src via tsconfig.test.json — no dist leg, so no rebuild owed): mutated (org re-added) moved the program 263 ledger-held → 264, the +1 being exactly 'src/contracts/email-service.test.ts(71,7): error TS2578: Unused @ts-expect-error directive'; restored leg grep-absent then back to 'check:test-typecheck: OK' at 263.",
"gates": "At 6a8a947 (re-run after the pre-PR merge), each read from its own verdict line: check:generated 'All 14 generated artifacts are up to date' (api-surface/export-origins/docs unchanged — interface-member removal is invisible to existence-level snapshots, expected for this route); check-adr-0087-registration '1 declared-breaking changeset(s), each carrying an ADR-0087 disposition … registered send-template-input-org-retired (new here)'; green: check:nul-bytes, check:merge-driver, check:published-files, check:slot-lookup, check:spec-parsed-alias, check:cross-package-test-inputs, check:changeset-gate-self-tests, check:objectui-changeset, check:query-options-erasure, check:test-source-alias, check:type-source-resolution, check:engine-double-contract, check:where-matcher, check:type-check-coverage, check-changeset-no-major, check-ci-filter-parity, check-empty-changeset, check-plugin-teardown-shape, spec check:liveness/check:empty-state/check:variant-docs/check:strictness-ledger, lint check:doc-formula-expressions. Dispatch-gates re-derived from the actual change set (script's own derivation, no hand-fed paths; answer attributed to objectstack tree) — the newly derived families beyond the dispatch list were all run and are in the green list above. Remote CI: in_progress at delivery (report at draft-PR time per standing rule).",
"files_changed": [
".changeset/send-template-input-org-retired.md",
"packages/spec/src/contracts/email-service.test.ts",
"packages/spec/src/contracts/email-service.ts",
"packages/spec/src/migrations/entries/semantic/18.send-template-input-org-retired.ts",
"packages/spec/src/migrations/registry.ts"
],
"line_budget": "n/a — diff touches no skills/** (published skill packages untouched)",
"deviations": [
"SendTemplateInput.organizationId TSDoc: one clause rewritten — the claim said organizationId untouched, but its final sentence cross-referenced {@link SendTemplateInput.org}, left dangling and misleading by the removal; rewritten to past-tense retired-member phrasing. Semantics untouched; SendEmailInput.organizationId untouched byte-for-byte. Named in the PR body.",
"check-dev-prereqs reds locally: 'The workspace is not built — 1 unmet precondition, not a list of problems' (fresh targeted worktree; the gate's own text says it is not a finding). CI builds first.",
"check:type-check-debt not run repo-wide — declared narrowing with measurement: its population is the DEBT/TEST_DEBT ledgers in scripts/check-type-check-coverage.mjs; @objectstack/spec graduated (#5286) and the @objectstack/spec-monorepo root program excludes packages/, so none of this PR's 5 paths is an input to any ledgered tsc program; the only tsc programs reading them are spec's own three, run in full (green above).",
"Repo-wide pnpm lint / remaining gate farm: CI-owned (standing narrowing).",
"Channel deviation: this session's egress proxy 403s repo-scoped api.github.com REST paths ('GitHub access is not enabled for this session'; /rate_limit reachable, git push/fetch normal), so the dispatch's REST-channel prescriptions were unavailable; single-issue reads/writes went through MCP issue_read/add_issue_comment/create_pull_request (the banned MCP list_issues/search_issues were not used). Duplicate-search leaned on the PM's dispatch-time dedup reading + local grep + git ls-remote, per the increment-only rule."
],
"open_questions": [],
"out_of_scope_findings": []
}
Checklist conclusion (verified against GitHub + local git diff of the branch): draft ✓ · base main ✓ · Fixes #11832 first line ✓ · 5 files +156/−5 = member removal + tombstone, compile-time pin test, D3 semantic shard, regenerated migration registry, BREAKING-minor changeset with adr-0087: registered (gate verdict quoted in the PR) ✓ · no governed path ✓. Spot readings: tombstone is self-contained (dated, names why organizationId is NOT a replacement, and pins any revival to a NEW ruling); SendEmailInput.organizationId byte-untouched; the one declared deviation — rewriting SendTemplateInput.organizationId's now-dangling {@link} clause to past tense — is correct and was flagged, not taken silently.
Premise (third-tier, falsifiable): HELD — zero readers and zero writers re-measured at claim across plugin-email, all sendTemplate call sites, examples, docs, and objectui; the member's shipped status (spec@17.2.0 dist) was verified rather than assumed, which is what makes registered the honest ADR-0087 disposition. The fork clause never triggered. Consumer-package readings delivered per the lane's standing commitment: plugin-email 27 files / 429 tests, showcase locale suite 6 tests, spec contracts+migrations 109 tests — all green at final head 6a8a947. Rejection-surface evidence: bidirectional TS2578 pin proven 263→264→263 with on-disk mutation anchors.
Contract review (clause-② content leg: published contract member removal): fuse reading get_session.external_metadata.last_served_model = claude-fable-5 = CONTRACT_REVIEW_TIER (this seat, self-dispatched-card path). Verdict: PASS — removal narrows the compile-time surface exactly to the documented dead member; runtime accept/reject untouched (nothing ever parsed org); migration prescription present (D3, no D2 — call-time input bag precedent); startup-focus and ADR-0049 both satisfied. Clearing needs:contract-review both carriers in this write batch.
Next: ready + merge-queue once EVERY check on the PR is green (CI started 09:35Z, in progress at review time — flip rides the next check-in). Sibling note honored: #12039's dev re-merges main after this lands (shared migrations registry, per its dispatch clause).
Activity
claude commentedon Aug 25, 2026
Concentrated triage batch:
finding→pm:queue+domain:spec, Task —SendTemplateInput.orgis declared with a "(when supported)" hedge and has zero readers (re-verified: no bareorgread in plugin-email beyond a prose comment), while #11741 establishesorganizationIdas the read channel. Retireorgvia the spec-property-retirement / enforce-or-remove route (the playbook governs tombstones, forms, docs and pins). Clause-②: yes at claim (an input-contract member is removed) — contract-review tier per spec-lane rules; if the retirement route's ledger check finds a reader the grep missed, stop and report.Generated by Claude Code
os-litant commentedon Aug 25, 2026
Claim: PM loop round R6
Session:
session_01NDGG54XF5gbTLdQzCtnaVVBranch:
claude/issue-11832-retire-sendtemplate-orgWorktree:
objectstack-issue-11832Domain:
domain:specFile surface:
packages/spec/src/contracts/email-service.ts(SendTemplateInput.org region ONLY — organizationId member untouched) + email-service tests + regenerated api-surface artifacts if moved + consumer call-site cleanup (examples) + changeset; conditional migrations tail-append only if the ADR-0087 gate demands it (stop on breach; explain in the report)Container & model: M,
mode:subagent,model: claude-fable-5— dispatch-gates 2026-08-25 @0b04839: "no path-derived mandate … floor sonnet · default opus · ceiling fable … a card changing contract accept/reject behaviour or widening the public surface is claude-fable-5"; clause-② content leg (published contract member removal) ⇒ fable mandatoryClause-②: yes
Serial constraints cleared: sole writer of contracts/email-service.ts this batch (prior writer PR #11839 for #11741 MERGED; #11741 CLOSED — verified). Conditional registry.ts tail-append shared with #11842/#12039 under the maintainer's parallel waiver (2026-08-25, chat, verbatim: 「并行5个子任务,加快进度」) + 4-point substitute discipline. Route: retire per ADR-0049 enforce-or-remove; premise (zero readers of
input.org) is falsifiable — a found reader forks back as needs_decision, never a silent implement. No pin assertions on sibling behavior.Generated by Claude Code
feat(spec): retire SendTemplateInput.org — declared org-overlay tenan…
os-litant commentedon Aug 25, 2026
{ "issue": 11832, "status": "done", "branch": "claude/issue-11832-retire-sendtemplate-org", "pr": "https://github.com/objectstack-ai/objectstack/pull/12114", "premise_still_valid": true, "summary": "Retired SendTemplateInput.org per ADR-0049 enforce-or-remove. Premise re-verified at claim (base 8d60dcd): zero readers and zero writers of the member in-repo (plugin-email resolves on (name, locale) only; no sendTemplate call site passes org; RenderTemplateInput never carried it; objectui has zero SendTemplateInput references); the member SHIPPED in published @objectstack/spec@17.2.0 (dist/contracts/index.d.ts:6318 in the npm tarball). Removal = member + JSDoc deleted with self-contained tombstone prose in the interface; compile-time pin (@ts-expect-error, bidirectional via TS2578) in email-service.test.ts; D3 SemanticMigration send-template-input-org-retired as one-file shard entries/semantic/18.send-template-input-org-retired.ts + gen:migration-registry (no D2 — call-time input bag, the options.upsert precedent; spec-changes.json/upgrade-guide byte-unchanged by construction, projections stop at PROTOCOL_MAJOR 17); changeset @objectstack/spec minor with BREAKING prose + adr-0087: registered (runtime-interface-only is structurally refused for contracts/ symbols and the body carries a FROM→TO, so registered is the only honest disposition). organizationId (#11741) untouched semantically; no consumer cleanup needed anywhere. Draft PR at final head 6a8a947 after pre-PR origin/main merge; delta vs main is exactly the 5 intended files (+156/−5).", "tests": "All at final head 6a8a947, via scripts/pm/os-verify-lock.sh, exits captured before any pipe. spec vitest src/contracts/email-service.test.ts src/migrations/migrations.test.ts: 'Test Files 2 passed (2) / Tests 109 passed (109)'; spec full typecheck green incl. 'check:test-typecheck: OK — test layer compiles; 55 file(s)/263 error(s) held' (unchanged). plugin-email (downstream consumer of rebuilt narrowed dist; direction = it declares @objectstack/spec in dependencies): 'Test Files 27 passed (27) / Tests 429 passed (429)' + tsc --noEmit clean. example-showcase test/email-template-locale.test.ts: 'Test Files 1 passed (1) / Tests 6 passed (6)'. Reverse verification from committed state, both legs' mutations proven on disk by anchored grep (tsc reads src via tsconfig.test.json — no dist leg, so no rebuild owed): mutated (org re-added) moved the program 263 ledger-held → 264, the +1 being exactly 'src/contracts/email-service.test.ts(71,7): error TS2578: Unused @ts-expect-error directive'; restored leg grep-absent then back to 'check:test-typecheck: OK' at 263.", "gates": "At 6a8a947 (re-run after the pre-PR merge), each read from its own verdict line: check:generated 'All 14 generated artifacts are up to date' (api-surface/export-origins/docs unchanged — interface-member removal is invisible to existence-level snapshots, expected for this route); check-adr-0087-registration '1 declared-breaking changeset(s), each carrying an ADR-0087 disposition … registered send-template-input-org-retired (new here)'; green: check:nul-bytes, check:merge-driver, check:published-files, check:slot-lookup, check:spec-parsed-alias, check:cross-package-test-inputs, check:changeset-gate-self-tests, check:objectui-changeset, check:query-options-erasure, check:test-source-alias, check:type-source-resolution, check:engine-double-contract, check:where-matcher, check:type-check-coverage, check-changeset-no-major, check-ci-filter-parity, check-empty-changeset, check-plugin-teardown-shape, spec check:liveness/check:empty-state/check:variant-docs/check:strictness-ledger, lint check:doc-formula-expressions. Dispatch-gates re-derived from the actual change set (script's own derivation, no hand-fed paths; answer attributed to objectstack tree) — the newly derived families beyond the dispatch list were all run and are in the green list above. Remote CI: in_progress at delivery (report at draft-PR time per standing rule).", "files_changed": [ ".changeset/send-template-input-org-retired.md", "packages/spec/src/contracts/email-service.test.ts", "packages/spec/src/contracts/email-service.ts", "packages/spec/src/migrations/entries/semantic/18.send-template-input-org-retired.ts", "packages/spec/src/migrations/registry.ts" ], "line_budget": "n/a — diff touches no skills/** (published skill packages untouched)", "deviations": [ "SendTemplateInput.organizationId TSDoc: one clause rewritten — the claim said organizationId untouched, but its final sentence cross-referenced {@link SendTemplateInput.org}, left dangling and misleading by the removal; rewritten to past-tense retired-member phrasing. Semantics untouched; SendEmailInput.organizationId untouched byte-for-byte. Named in the PR body.", "check-dev-prereqs reds locally: 'The workspace is not built — 1 unmet precondition, not a list of problems' (fresh targeted worktree; the gate's own text says it is not a finding). CI builds first.", "check:type-check-debt not run repo-wide — declared narrowing with measurement: its population is the DEBT/TEST_DEBT ledgers in scripts/check-type-check-coverage.mjs; @objectstack/spec graduated (#5286) and the @objectstack/spec-monorepo root program excludes packages/, so none of this PR's 5 paths is an input to any ledgered tsc program; the only tsc programs reading them are spec's own three, run in full (green above).", "Repo-wide pnpm lint / remaining gate farm: CI-owned (standing narrowing).", "Channel deviation: this session's egress proxy 403s repo-scoped api.github.com REST paths ('GitHub access is not enabled for this session'; /rate_limit reachable, git push/fetch normal), so the dispatch's REST-channel prescriptions were unavailable; single-issue reads/writes went through MCP issue_read/add_issue_comment/create_pull_request (the banned MCP list_issues/search_issues were not used). Duplicate-search leaned on the PM's dispatch-time dedup reading + local grep + git ls-remote, per the increment-only rule." ], "open_questions": [], "out_of_scope_findings": [] }Generated by Claude Code
os-litant commentedon Aug 25, 2026
os-dev-report
(Supersedes the previous comment, whose HTML-comment marker the body sanitizer stripped; JSON identical.)
{ "issue": 11832, "status": "done", "branch": "claude/issue-11832-retire-sendtemplate-org", "pr": "https://github.com/objectstack-ai/objectstack/pull/12114", "premise_still_valid": true, "summary": "Retired SendTemplateInput.org per ADR-0049 enforce-or-remove. Premise re-verified at claim (base 8d60dcd): zero readers and zero writers of the member in-repo (plugin-email resolves on (name, locale) only; no sendTemplate call site passes org; RenderTemplateInput never carried it; objectui has zero SendTemplateInput references); the member SHIPPED in published @objectstack/spec@17.2.0 (dist/contracts/index.d.ts:6318 in the npm tarball). Removal = member + JSDoc deleted with self-contained tombstone prose in the interface; compile-time pin (@ts-expect-error, bidirectional via TS2578) in email-service.test.ts; D3 SemanticMigration send-template-input-org-retired as one-file shard entries/semantic/18.send-template-input-org-retired.ts + gen:migration-registry (no D2 — call-time input bag, the options.upsert precedent; spec-changes.json/upgrade-guide byte-unchanged by construction, projections stop at PROTOCOL_MAJOR 17); changeset @objectstack/spec minor with BREAKING prose + adr-0087: registered (runtime-interface-only is structurally refused for contracts/ symbols and the body carries a FROM→TO, so registered is the only honest disposition). organizationId (#11741) untouched semantically; no consumer cleanup needed anywhere. Draft PR at final head 6a8a947 after pre-PR origin/main merge; delta vs main is exactly the 5 intended files (+156/−5).", "tests": "All at final head 6a8a947, via scripts/pm/os-verify-lock.sh, exits captured before any pipe. spec vitest src/contracts/email-service.test.ts src/migrations/migrations.test.ts: 'Test Files 2 passed (2) / Tests 109 passed (109)'; spec full typecheck green incl. 'check:test-typecheck: OK — test layer compiles; 55 file(s)/263 error(s) held' (unchanged). plugin-email (downstream consumer of rebuilt narrowed dist; direction = it declares @objectstack/spec in dependencies): 'Test Files 27 passed (27) / Tests 429 passed (429)' + tsc --noEmit clean. example-showcase test/email-template-locale.test.ts: 'Test Files 1 passed (1) / Tests 6 passed (6)'. Reverse verification from committed state, both legs' mutations proven on disk by anchored grep (tsc reads src via tsconfig.test.json — no dist leg, so no rebuild owed): mutated (org re-added) moved the program 263 ledger-held → 264, the +1 being exactly 'src/contracts/email-service.test.ts(71,7): error TS2578: Unused @ts-expect-error directive'; restored leg grep-absent then back to 'check:test-typecheck: OK' at 263.", "gates": "At 6a8a947 (re-run after the pre-PR merge), each read from its own verdict line: check:generated 'All 14 generated artifacts are up to date' (api-surface/export-origins/docs unchanged — interface-member removal is invisible to existence-level snapshots, expected for this route); check-adr-0087-registration '1 declared-breaking changeset(s), each carrying an ADR-0087 disposition … registered send-template-input-org-retired (new here)'; green: check:nul-bytes, check:merge-driver, check:published-files, check:slot-lookup, check:spec-parsed-alias, check:cross-package-test-inputs, check:changeset-gate-self-tests, check:objectui-changeset, check:query-options-erasure, check:test-source-alias, check:type-source-resolution, check:engine-double-contract, check:where-matcher, check:type-check-coverage, check-changeset-no-major, check-ci-filter-parity, check-empty-changeset, check-plugin-teardown-shape, spec check:liveness/check:empty-state/check:variant-docs/check:strictness-ledger, lint check:doc-formula-expressions. Dispatch-gates re-derived from the actual change set (script's own derivation, no hand-fed paths; answer attributed to objectstack tree) — the newly derived families beyond the dispatch list were all run and are in the green list above. Remote CI: in_progress at delivery (report at draft-PR time per standing rule).", "files_changed": [ ".changeset/send-template-input-org-retired.md", "packages/spec/src/contracts/email-service.test.ts", "packages/spec/src/contracts/email-service.ts", "packages/spec/src/migrations/entries/semantic/18.send-template-input-org-retired.ts", "packages/spec/src/migrations/registry.ts" ], "line_budget": "n/a — diff touches no skills/** (published skill packages untouched)", "deviations": [ "SendTemplateInput.organizationId TSDoc: one clause rewritten — the claim said organizationId untouched, but its final sentence cross-referenced {@link SendTemplateInput.org}, left dangling and misleading by the removal; rewritten to past-tense retired-member phrasing. Semantics untouched; SendEmailInput.organizationId untouched byte-for-byte. Named in the PR body.", "check-dev-prereqs reds locally: 'The workspace is not built — 1 unmet precondition, not a list of problems' (fresh targeted worktree; the gate's own text says it is not a finding). CI builds first.", "check:type-check-debt not run repo-wide — declared narrowing with measurement: its population is the DEBT/TEST_DEBT ledgers in scripts/check-type-check-coverage.mjs; @objectstack/spec graduated (#5286) and the @objectstack/spec-monorepo root program excludes packages/, so none of this PR's 5 paths is an input to any ledgered tsc program; the only tsc programs reading them are spec's own three, run in full (green above).", "Repo-wide pnpm lint / remaining gate farm: CI-owned (standing narrowing).", "Channel deviation: this session's egress proxy 403s repo-scoped api.github.com REST paths ('GitHub access is not enabled for this session'; /rate_limit reachable, git push/fetch normal), so the dispatch's REST-channel prescriptions were unavailable; single-issue reads/writes went through MCP issue_read/add_issue_comment/create_pull_request (the banned MCP list_issues/search_issues were not used). Duplicate-search leaned on the PM's dispatch-time dedup reading + local grep + git ls-remote, per the increment-only rule." ], "open_questions": [], "out_of_scope_findings": [] }Generated by Claude Code
os-litant commentedon Aug 25, 2026
ACCEPT — PR #12114 (R6, reviewer of record: spec seat, session
session_01NDGG54XF5gbTLdQzCtnaVV).Checklist conclusion (verified against GitHub + local git diff of the branch): draft ✓ · base
main✓ ·Fixes #11832first line ✓ · 5 files +156/−5 = member removal + tombstone, compile-time pin test, D3 semantic shard, regenerated migration registry, BREAKING-minor changeset withadr-0087: registered(gate verdict quoted in the PR) ✓ · no governed path ✓. Spot readings: tombstone is self-contained (dated, names whyorganizationIdis NOT a replacement, and pins any revival to a NEW ruling);SendEmailInput.organizationIdbyte-untouched; the one declared deviation — rewritingSendTemplateInput.organizationId's now-dangling{@link}clause to past tense — is correct and was flagged, not taken silently.Premise (third-tier, falsifiable): HELD — zero readers and zero writers re-measured at claim across plugin-email, all sendTemplate call sites, examples, docs, and objectui; the member's shipped status (spec@17.2.0 dist) was verified rather than assumed, which is what makes
registeredthe honest ADR-0087 disposition. The fork clause never triggered. Consumer-package readings delivered per the lane's standing commitment: plugin-email 27 files / 429 tests, showcase locale suite 6 tests, spec contracts+migrations 109 tests — all green at final head6a8a947. Rejection-surface evidence: bidirectional TS2578 pin proven 263→264→263 with on-disk mutation anchors.Contract review (clause-② content leg: published contract member removal): fuse reading
get_session.external_metadata.last_served_model = claude-fable-5=CONTRACT_REVIEW_TIER(this seat, self-dispatched-card path). Verdict: PASS — removal narrows the compile-time surface exactly to the documented dead member; runtime accept/reject untouched (nothing ever parsedorg); migration prescription present (D3, no D2 — call-time input bag precedent); startup-focus and ADR-0049 both satisfied. Clearingneeds:contract-reviewboth carriers in this write batch.Next: ready + merge-queue once EVERY check on the PR is green (CI started 09:35Z, in progress at review time — flip rides the next check-in). Sibling note honored: #12039's dev re-merges main after this lands (shared migrations registry, per its dispatch clause).
Generated by Claude Code
feat(spec): retire SendTemplateInput.org — declared org-overlay tenan…
test(spec): contracts and conversions test titles state each cited de…