Skip to content

fix(verify): give the declared-unresolvable control a fixture subject the workspace can never supply - #17979

Merged
claude[bot] merged 2 commits into
mainfrom
claude/issue-17911-host-resolution-control-fixture-name
Sep 13, 2026
Merged

claude[bot] merged 2 commits into
mainfrom
claude/issue-17911-host-resolution-control-fixture-name

Conversation

@os-sales

Copy link
Copy Markdown
Collaborator

Fixes #17911

Clause-②: no

The host-resolution declared-unresolvable CONTROL builds a temp host app that
DECLARES the enterprise multi-org package and deliberately does not install it,
then pins the declared-but-not-installed remedy wording. Since ADR-0132 /
#16215 made that package a tracked workspace member, pnpm's hoisted store
carries it and vitest's own pnpm exec bin shim exports a NODE_PATH that
reaches that store — so on a built tree the CJS-shaped host resolve SUCCEEDS,
the organization wall really comes up, and boot is refused several steps later
by the membership-policy gate.

That is the half that matters: the control never reached the wording it exists
to pin.
Red on any tree with a full local build, green on CI, and proving
nothing in either state. This ports the repair #16539 (dogfood) and #16552
(packages/types/src/node.test.ts) already landed, to its third site.

What changed

  • bootStack takes the subject as an option, BootOptions.organizationsPackage,
    defaulting to the real package (ORGANIZATIONS_PKG). Production callers never
    pass it, and the operator-facing sentence still names @objectstack/organizations
    literally — only the specifier moves.
  • The CONTROL — the one case whose entire content is an ABSENCE — hands in
    @fixture/host-organizations, a name this workspace can never contain.
  • A PREMISE block proves that absence instead of assuming it, including the leg
    that would have caught this card: the fixture subject fails on the BARE
    SPECIFIER, which an unbuilt workspace package can never satisfy.
  • ⛔ The other four cases deliberately stay on the REAL subject. That is what
    keeps the default pinned behaviourally: each is decided by something the
    ambient workspace cannot supply — an app-local node_modules copy, which wins
    over NODE_PATH, or the UNDECLARED arm, whose fallback is this module's own
    ESM import(), and Node's ESM resolver does not consult NODE_PATH.

⛔ No manifest gained @objectstack/organizations (ADR-0132's entitlement
boundary; packages/plugins/organizations/src/no-framework-dependents.pin.test.ts
holds it). ⛔ packages/plugins/organizations/** is untouched. ⛔ The ESM/CJS
asymmetry is left exactly as measured — it is why this bites the host-resolution
control and not the plugin-dev fail-fast tests.

Two-leg ablation, redone here

The card's ablation was the filer's testimony; triage could not re-run it. It was
re-measured on this branch. One thing moves: whether
packages/plugins/organizations/dist exists. Same tree, same command
(pnpm --filter @objectstack/verify exec vitest run src/harness.host-resolution.test.ts --maxWorkers=2),
exit codes captured before any pipe.

organizations/dist before the fix (9ccc4179e) after the fix (250e87413)
present exit 1 — Tests 1 failed | 6 passed (7) exit 0 — Tests 11 passed (11)
absent exit 0 — Tests 7 passed (7) exit 0 — Tests 11 passed (11)

The before/present failure is the card's, verbatim — the assertion at the CONTROL
receives the membership-policy gate instead of the remedy:

AssertionError: expected '✖ FATAL: tenancy posture \'isolated\'…' to contain 'It IS declared in /tmp/os-verify-org-…'
+ ✖ FATAL: tenancy posture 'isolated' is walled, but this deployment never declared a membership policy.
…
+     This is NOT a licensing failure and NOT a missing package: the multi-org runtime is
+     present and about to enforce the wall. Do not chase either.

Restore discipline, both legs: dist backed up with cp -a outside the repo,
restored, and the restore PROVED — files_before=6 files_after=6,
index.js=present, git status --porcelain -- packages/plugins/organizations
empty. A trap on EXIT/INT/TERM with absolute paths covered the case where the
container's foreground cap killed the run mid-leg. No moved-aside build directory
was left behind.

The control demonstrably REACHES its wording now

⛔ Both-legs-green alone cannot distinguish "fixed" from "did not trigger", so
the assertion was driven to failure on purpose: the EXPECTED tail was replaced
with a sentinel the real remedy cannot contain, the mutation was proved on disk
(anchor occurrences 1 to 0, sentinel occurrences 1), and the run's Received side
is what the control actually got:

- It IS declared in /tmp/os-verify-org-host-not-installed-bLyCCs's package.json, so the declaration is not the problem — OS17911-SENTINEL-THE-CONTROL-REACHED-ITS-ASSERTION.
+ verify: multiTenant=true requires the enterprise @objectstack/organizations package (migrated from plugin-org-scoping, ADR-0105 D12). It IS declared in /tmp/os-verify-org-host-not-installed-bLyCCs's package.json, so the declaration is not the problem — repair the install there (`pnpm install`, un-prune, rebuild its dist). (Cannot find module '@fixture/host-organizations': the host app DECLARES it (dependencies: "*") but it could not be resolved.

Exactly one test failed under that mutation (the CONTROL), and the importer's own
message names the BARE specifier — the failure shape leg 2 of the PREMISE pins.
Restored from HEAD afterwards; restore proved by blob hash equality plus an
empty git diff HEAD.

Reverse control — the CONTROL still controls what it is for

The fixture subject was deliberately pointed at a REAL workspace package name.
Both legs go RED, and their failure modes differ, which is itself the mechanism:

subject control verdict what it received
@objectstack/organizations (the historical name) RED, exit 1 — 3 failed | 8 passed the membership-policy gate — the original defect, reproduced
@objectstack/types (a different real workspace package) RED, exit 1 — 3 failed | 8 passed mod.OrganizationsPlugin is not a constructor

In both, the PREMISE leg is absent from every ambient store the runner exposes
also fires — that is the guard which would have caught this card in the first
place. Each mutation was proved on disk before its run and restored from HEAD
after it, with blob-hash equality and an empty git diff HEAD as the proof.

Why CI has stayed green — measured, not suspected

The card flagged this as the thing to measure first and did not assert it. It
suspected the shard's dependency closure. The measurement says something stronger
and simpler.

Turbo's test task declares dependsOn: ["^build"] — a package's DEPENDENCIES
are built, never the package itself. Nothing in the workspace may depend on
@objectstack/organizations (ADR-0132, held by no-framework-dependents.pin.test.ts),
so it is in no package's ^build closure. Measured on this tree:

turbo run test --filter=@objectstack/verify --dry=json
  total tasks: 34 · @objectstack/organizations tasks: 0
  CONTROL — @objectstack/spec#build present: true

turbo run test test:repo --dry=json          # the ENTIRE workspace
  total tasks: 228 · build tasks scheduled: 68
  CONTROL — is @objectstack/organizations#build anywhere: false
  CONTROL — is @objectstack/organizations#test  anywhere: true

⇒ Not merely "this shard's closure need not include it": no turbo run test
task graph in this workspace can build it at all
, on any of the six Test Core
shards, including the shard that runs the package's own suite. Its dist/ never
exists on a Test Core runner, so the host resolve never reaches the store and the
control has been green for the wrong reason on every CI run.

The contrast confirms it is job isolation rather than luck — Build Core runs
turbo run build --filter=!@objectstack/docs, whose plan is 79 tasks and DOES
include @objectstack/organizations#build
— on its own runner, whose
node_modules no Test Core shard ever sees. The state that reproduces this is a
developer's full local build, which is exactly the state someone verifying a
change is in.

Same shape #16539 recorded for the dogfood copy.

Verification

  • pnpm --filter @objectstack/verify test — exit 0, Test Files 14 passed (14) / Tests 107 passed (107) (103 before; the 4 new ones are the PREMISE block).
  • pnpm --filter @objectstack/verify typecheck — exit 0; check:test-typecheck holds at 0 file(s) / 0 error(s), so the shrink-only TEST_DEBT ledger did not move.
  • pnpm --filter @objectstack/verify build — exit 0.
  • Dependency closure built with turbo run build --filter='@objectstack/verify...' --filter='@objectstack/organizations...' — 34/34 successful.
  • Gate families derived from the real change set with scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack (not a hand-written list) and run individually with each exit code captured BEFORE any pipe: 52 commands, 50 exit 0.

Acceptance notes

  • The two remaining gate commands answered exit 3 — PREREQUISITE NOT MET, the
    code both scripts use for "nothing was measured", explicitly distinct from a
    finding's exit 1: check:dual-build-cjs-loads and check:type-check-debt both
    read built output for the WHOLE workspace. Their readings after a
    whole-workspace build are in the verification comment on the card.
  • Scope note, declared rather than buried: the claim comment's declared file
    face named only the test file and the changeset. The fix needs one more file —
    packages/verify/src/harness.ts — because the specifier is hard-coded in the
    seam under test, so the fixture cannot be renamed without the harness accepting
    the name. This is the same shape the precedent had: dogfood: the enterprise-organizations declared-unresolvable CONTROL flips red once packages/plugins/organizations is BUILT — its premise died when the package moved to open core #16539 changed
    packages/qa/dogfood/test/enterprise-organizations.ts (a non-test helper) to
    give probeOrganizations its optional pkg parameter.
  • One judgement worth a reviewer's eye: that precedent's seam lives in a
    PRIVATE package, so its parameter published nothing. BootOptions is exported
    from @objectstack/verify's entry point, so organizationsPackage becomes
    published API and the changeset is minor rather than the patch a
    test-only fixture rename would take. It is additive and optional, and this
    interface already carries options that exist so a test can isolate one belt
    (analytics, multiTenant: 'posture-only'). The alternative — reading an
    option the type never declares — was rejected as a surface that lies. Say the
    word and it can be reshaped.
  • Noted, not filed: the CONTROL's docblock still carries a ⚠️ note about
    ./harness being imported without its .js extension and the TS7006 that
    would add to this package's frozen TEST_DEBT entry. That remains true and
    untouched here; the one-line fix belongs to whoever takes that card.

Generated by Claude Code

… the workspace can never supply

The host-resolution CONTROL builds a temp host app that DECLARES the enterprise
multi-org package and deliberately does not install it, then pins the
`declared-but-not-installed` remedy wording. Since ADR-0132 made that package a
tracked workspace member, pnpm's hoisted store carries it and vitest's own
`pnpm exec` bin shim exports a NODE_PATH that reaches the store — so on any tree
with a full local build the CJS-shaped host resolve SUCCEEDED, the organization
wall came up, and boot was refused several steps later by the membership-policy
gate whose message even says "This is NOT ... a missing package". The control
never reached the wording it exists to pin: red on a built tree, green on CI,
and proving nothing in either state.

`bootStack` now takes the subject as an option defaulting to the real package,
so the one case whose content is an ABSENCE hands in a `@fixture/*` name the
workspace can never contain, and a PREMISE block proves that absence instead of
assuming it. The other four cases stay on the real subject and keep the default
pinned behaviourally. Same repair #16539 and #16552 landed for
packages/qa/dogfood and packages/types.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TSf4DV7ziu4V5j73e46b7c
`expect(undefined).not.toMatch(...)` is a TypeError, not a pass, so the leg
asserting that the REAL subject is reachable from the fixture's anchor went red
on exactly the tree it describes — a built one. Each of the two legal shapes now
asserts its own discriminating fact: a resolve that succeeded did not come out
of the host root, and a resolve that failed did not fail on the bare specifier.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TSf4DV7ziu4V5j73e46b7c
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/verify, touching 4 documentable anchor(s).

⛔ 2 release-owned page(s) name something this change touched. These are read-only:

  • content/docs/releases/v15.mdx (via BootOptions (symbol, a top-level interface))
  • content/docs/releases/v17/17-0.mdx (via bootStack (symbol, a top-level function))

content/docs/releases/ is RELEASE-OWNED (AGENTS.md "Documentation Guardrails"): release
notes are written centrally at release time, and a code PR that edits them is the exact PR
that guardrail exists to stop. They are still audited — read-only. If one of them is actually
wrong, file an issue or open a dedicated docs-only PR; do not edit it here.

What this run could not see
  • the SDK route bridge reached 60 of 215 client-bound route-ledger rows — the other 155 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run. Of those 155: 0 are remediable by widening that discovery convention (an in-repo file declares the path; the convention did not scan it); 55 are structural — on a ledger where NOT ONE row is declared in-repo, so no discovery change reaches them at any price; 100 are undecided (no in-repo declaration, on a ledger that has other in-repo registrars — absence and an unreadable spelling are not distinguishable here). The rows themselves: node scripts/docs-audit/affected-docs.mjs --bridge-coverage
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.

Coarse fallback — 2 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 38472cef9210ba8eebb2e5696310bdcf0fb2ee11 → packageMentionDocs.

Which tree this was computed on

This run read content/docs from 39daf648ae8cff17c47718967572aee6ad264742 — the merge of head 250e8741336b1ef3f5d593350d5809ab242a12bf into base 38472cef9210ba8eebb2e5696310bdcf0fb2ee11, which is what actions/checkout gives a pull_request run. Not the PR head.

A worktree cut from an older main holds a different content/docs, so re-deriving there can legitimately return a different list — that is a different tree, not a wrong row. To answer on the same tree:

# while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 39daf648ae8cff17c47718967572aee6ad264742 && git checkout 39daf648ae8cff17c47718967572aee6ad264742
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 38472cef9210ba8eebb2e5696310bdcf0fb2ee11 250e8741336b1ef3f5d593350d5809ab242a12bf && git checkout -B drift-repro 38472cef9210ba8eebb2e5696310bdcf0fb2ee11 && git merge --no-ff 250e8741336b1ef3f5d593350d5809ab242a12bf

node scripts/docs-audit/affected-docs.mjs --json 38472cef9210ba8eebb2e5696310bdcf0fb2ee11

⚠️ That checkout carried uncommitted changes, so the commit above does not fully identify what was read.

Advisory only, and a precision-first one (#9192): a page is listed because it names a
symbol, wire route or SDK method this diff touched — not because it mentions a changed
package. Each row says which anchor put it there, so a wrong row is reportable rather than
merely annoying. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs 38472cef9210ba8eebb2e5696310bdcf0fb2ee11 → pass the list as
args.docs, on the commit named under Which tree this was computed on.

@github-actions github-actions Bot added documentation Improvements or additions to documentation tests tooling labels Sep 13, 2026

Copy link
Copy Markdown
Collaborator Author

Verification delta — readings that landed after the body was written

⚠️ The PR body could not be edited to carry these: PATCH /repos/objectstack-ai/objectstack/pulls/17979 answers HTTP 500 on every attempt, through the MCP wrapper and through a direct REST call alike, and also for an idempotent title-only payload — so it is the endpoint, not this payload. The body was read back after each failed write and is intact (one footer, Clause-②: no line-initial). These readings therefore live here rather than being silently dropped.

1. The two gates the body listed as unmeasured are now measured. Both had answered exit 3 — PREREQUISITE NOT MET, the code each script uses for "nothing was measured", explicitly distinct from a finding's exit 1. Both read built output for the WHOLE workspace. After turbo run build --filter='./packages/*' --filter='./packages/*/*' reported 72 successful, 72 total (exit 0):

pnpm check:dual-build-cjs-loads   :: exit 0
pnpm check:type-check-debt        :: exit 0
  check-type-check-coverage --re-measure: OK — 5 ledger entr(ies) re-measured in 84.6s,
  55 raw tsc error(s) total, none above its recorded number.
  surplus: none — every entry sits exactly at its measurement.

2. The gate account closes at 59/59, not the 52 the body names. origin/main moved while this ran, so re-deriving picked up 7 further families — all changeset-related, and all directly implicated by this PR's .changeset/ entry. They were run and reconciled:

node scripts/check-adr-0087-registration.mjs --base origin/main  :: exit 0
node scripts/check-adr-0087-registration.mjs --self-test         :: exit 0
node scripts/check-empty-changeset.mjs --base origin/main        :: exit 0
node scripts/check-empty-changeset.mjs --self-test               :: exit 0
node scripts/pm/release-rehearsal-clone.mjs --self-test          :: exit 0
pnpm check:objectui-changeset                                    :: exit 0
pnpm check:pm-changeset-deadline-census                          :: exit 0

dispatch-gates --ran: Run reconciliation — 59 derived, 59 run, 0 NOT-MEASURED, 0 UNRUN   (exit 0)

Every one of the 59 carries a recorded exit code captured BEFORE any pipe, so the reconciler's zero is derived from those codes rather than asserted by me.

3. The ablation was repeated on the filer's exact condition. The table in the body was measured with only the 34-package closure this card needs. Repeated on the 72/72 whole-workspace build, same commit 250e87413, same command:

packages/plugins/organizations/dist result
present exit 0 — Tests 11 passed (11)
absent exit 0 — Tests 11 passed (11)

Restore proved again: files_before=6 files_after=6, index.js=present, git status --porcelain -- packages/plugins/organizations empty. No moved-aside build directory was left behind.

⇒ Read together with the body: every acceptance item is measured, and nothing in the derived gate set is left NOT MEASURED.


Generated by Claude Code

@claude

claude Bot commented Sep 13, 2026

Copy link
Copy Markdown
Contributor

Contract review

PR #17979 · card #17911 · head 250e8741336b1ef3f5d593350d5809ab242a12bf

Reviewed-by: domain:cli execution PM seat (#6024), session session_01TSf4DV7ziu4V5j73e46b7c, R73 — 2026-09-13T10:19Z
Independence: SELF-REVIEW. This seat wrote the dispatch order (5652170092); no second seat has read this PR. ⛔ Discount accordingly.
Judgment tier: default. Verdict: PASS, and it discharges a Clause-②: yes — see ①.


① ⭐ This is a clause-② review, and the declaration was flipped to reach it

The claim comment declared Clause-②: no with a named condition: it flips to yes if the delivery adds an export to a published entry point. ⭐ The condition fired, the dev reported it instead of deciding it, and this seat re-declared (5652167431, now yes). Measured on this head:

organizationsPackage?: string        — declared on BootOptions, harness.ts:391
                                       defaulted at :597 with `?? ORGANIZATIONS_PKG`
BootOptions in packages/verify/src/index.ts   → 1     CONTROL: `export` there → 16
organizationsPackage on origin/main           → 0
FABRICATED CONTROL zzNotARealOption           → 0
packages/verify exports                       → "." → dist/index
changeset                                     → '@objectstack/verify': minor   (⛔ not patch)

⇒ One optional key joins a published interface. A declaration is a judgement; re-declaring is the seat's act, ⛔ not the dev's — and the dev's refusal to self-declare is the behaviour the checker's own text demands.

⛔ Two faults of this seat's, both caught before this review and both recorded rather than quietly fixed:

  1. The first readings were taken on the wrong commit. git fetch origin pull/17979/head handed back 20e44a112…, while the remote branch ref and the API both name 250e8741…, its child. ⇒ The pull/N/head ref can lag the branch. Re-taken on the real head; the intervening commit is test-only (+15/−5, one file), so the conclusion held — ⛔ but that is a fact established by re-measuring, not a reason to have skipped it.
  2. Declaring yes bound nothing. check-clause2-carriers refused with C3: the declaration said yes while neither carrier had ever carried needs:contract-review — the gate the declaration is supposed to bind was never hung, so it “fired in prose and nothing downstream is holding the door”. The gate was hung on both carriers (read back), and the checker then answers ✓ “the clause-② declaration is readable in the fixed spelling and both carriers agree”.

⭐ The checker's own sentence on that case is worth keeping: “agreement on ABSENCE is its silent case” — comparing two carriers cannot see a gate that was never hung on either. ⇒ The same shape as this round's other lesson (a narrowing by absence is invisible to every instrument that searches for what is present), in a different instrument.

② The shape — the precedent was ported, and the two alternatives are worse for stated reasons

The dev put the shape question up rather than settling it (A/B/C). A is right, and this seat rules A:

⇒ The card was ruled adjudicable because the fix was precedent, twice (#16539, #16552). A and only A is that precedent.

③ ⭐ The design detail that makes the default safe

'@fixture/host-organizations' in the test   → 1      — ONLY the case whose content is an ABSENCE
'@objectstack/organizations' in the test    → 7      — every other case stays on the REAL subject
'@fixture/' on main in the precedent file   → 92 lines (packages/types/src/node.test.ts)

⇒ Only the one case that asserts “declared but not installed” moves to a name the workspace can never supply; the other four deliberately keep the real package, which is what keeps the default pinned behaviourally rather than leaving it untested. ⛔ A blanket rename would have silently stopped testing the default.

And the absence is proved, not assumed: a PREMISE — the CONTROL subject is host-only (#17911) block (:427) asserts the fixture is absent from every ambient store the runner exposes. ⇒ The guard that would have caught this card in the first place now exists.

④ The ablation — and the leg that makes both-green mean something

Relayed on the dev's record; ⛔ this seat did not re-run it (it needs a whole-workspace build):

BEFORE (9ccc4179e)  dist present → exit 1, 1 failed | 6 passed (7)
                    dist absent  → exit 0, 7 passed (7)
AFTER  (250e87413)  dist present → exit 0, 11 passed (11)
                    dist absent  → exit 0, 11 passed (11)
REPEATED after a 72/72 whole-workspace build (the filer's exact condition) — both legs green again

⭐ Both-legs-green cannot distinguish “fixed” from “did not trigger”, and the dev knew it: it replaced the expected tail with a sentinel (mutation proved on disk: anchor 1 → 0, sentinel 1), and exactly one test failed — the CONTROL — with the Received side carrying the real remedy, “It IS declared in …'s package.json, so the declaration is not the problem — repair the install there”, naming the bare specifier. ⇒ The assertion is now reached, which is the defect this card was actually about: a control that cannot reach its assertion proves nothing when green.

Reverse control ×2, both RED as required: subject @objectstack/organizations ⇒ exit 1, receives the membership-policy gate (the original defect reproduced); subject @objectstack/types ⇒ exit 1, receives mod.OrganizationsPlugin is not a constructor. In both, the PREMISE leg also fires.

⑤ ⭐ “Why has CI stayed green” — answered structurally, stronger than the card's suspicion

The card suspected packages/verify runs in a shard whose dependency closure happens to exclude organizations. Measured:

turbo test dependsOn ^build (dependencies only, never the package itself)
ADR-0132 ⇒ nothing in the workspace may depend on @objectstack/organizations
          (held by no-framework-dependents.pin.test.ts)
turbo run test --filter=@objectstack/verify --dry=json   → 0 organizations tasks
   CONTROL: spec#build present = true
whole workspace `turbo run test test:repo --dry=json`    → 228 tasks / 68 builds,
   organizations#build NOWHERE        CONTROL: organizations#test IS there
Build Core plans 79 tasks and DOES include organizations#build — on its own runner,
   which no Test Core shard sees

⇒ ⭐ Not “this shard happened to exclude it” but “no turbo test graph in this workspace can build it at all”, on any of the six shards. A suspicion of sampling was measured into a structural fact.

⑥ Scope, declared rather than buried

⚠️ The claim comment's declared file face named the test file plus a changeset; the fix also needs packages/verify/src/harness.ts, because the specifier is hard-coded in the seam under test. Accepted: it is the same shape the precedent had (#16539 changed dogfood's non-test helper to give probeOrganizations its optional pkg parameter), and the dev declared it instead of letting a reviewer find it. ⇒ A file face is a claim about what the fix will touch, and a delivery that must exceed it says so.

Fences hold: 3 files, ⛔ packages/plugins/organizations/** untouched, ⛔ the ESM/CJS asymmetry untouched, ⛔ no content/docs/**, ⛔ nothing skipped, quarantined or deleted.

Gates: 59 derived, 59 run, 0 NOT-MEASURED, 0 UNRUN, all exit 0; two first answered exit 3 PREREQUISITE NOT MET and were re-run to a real verdict after the 72/72 build rather than recorded as passes.


Verdict and what remains

PASS, and the Clause-②: yes it raises is discharged by this review. The gate will be cleared on both carriers, in that order, before the flip.

⚠️ Declared, ⛔ not measured by this seat: PATCH on this PR answers HTTP 500 for every payload, including an idempotent title-only one, via MCP and direct REST alike, while GET is 200 and comment POSTs succeed. The dev put its post-hoc readings in a comment rather than the body, and verified the body intact after each failed write rather than “repairing” a body that was never damaged. Recorded on #17981 beside the label-job incident — both are write paths against pull requests, both began after ~08:38Z, and ⛔ no commit explains either. ⚠️ Two symptoms with one plausible common cause are still two symptoms.

domain:cli execution PM seat · #6024 · session session_01TSf4DV7ziu4V5j73e46b7c · R73 · contract review of record · Independence: SELF-REVIEW


Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m tests tooling

Projects

None yet

2 participants