Skip to content

fix(spec): the pending connector-sync note matches the executor, and the error-code ledger lists its two refuse() codes (#21106) - #21150

Merged
objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/issue-21106-connector-sync-notes-ledger
Oct 1, 2026
Merged

objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/issue-21106-connector-sync-notes-ledger

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Fixes #21106
Clause-②: yes

Three release-text follow-ups from the at-tier contract review of PR #21084 (comment 5926057594), all due before Version Packages #20639 next picks up PR #21084. Each sentence was checked against the code at PR #21084's merge commit 8368f1c0. The target files are byte-identical between 8368f1c0 and this branch's base (git diff --stat printed nothing). No package source changes.

  1. A deliberate correction of the stage-① pending note. .changeset/20281-connector-sync-moved-to-mapping.md said connectorSource was "declared, not yet executed" and that "Nothing executes it in this release". The stage-② note .changeset/20919-spec-connector-source-live.md says the executor reads it. Both compile into the same @objectstack/spec CHANGELOG version.
  2. The "provenance, not identity" ledger sentence for this release's ERROR_CODE_LEDGER face changes, in a new spec note, .changeset/21106-error-code-ledger-provenance-rows.md.
  3. The two @objectstack/service-automation provenance rows, MAPPING_NOT_FOUND and UNSUPPORTED_TRANSFORM, in packages/spec/src/api/error-code-ledger.zod.ts. A hand pin in the provenance gate's own test, packages/spec/scripts/check-error-code-provenance.test.ts, guards them.

1 · The stage-① note correction

Before After
Lead label "Added (declared, not yet executed):" "Added:"
Last sentence of that paragraph "Nothing executes it in this release, and os validate / os build warn when it is authored." "The connector sync executor, @objectstack/service-automation's pullConnectorSource (#20919), reads it; nothing schedules a pull until the job stage lands."

Everything else in the file is byte-identical: the front matter, the summary line, the BREAKING banner, the FROM → TO table and the retirement kit. The diff is +4 / −3 lines in one paragraph.

Readings at 8368f1c0:

  • "reads it". packages/services/service-automation/src/connector-pull.ts pullConnectorSource (:209) reads the mapping through getMetaItem and its connectorSource. It makes one action call and writes through runImport. The liveness rows say the same: packages/spec/liveness/mapping.json, connectorSource live, evidence connector-pull.ts#pullConnectorSource.
  • "nothing schedules a pull until the job stage lands". Outside tests, pullConnectorSource has three places in its own package: the definition, the index re-export and the plugin method (plugin.ts:621). No package source calls the plugin method.
  • Why the review's suggested clause "os validate / os build warn when it is authored" is NOT kept. It is false at 8368f1c0, measured:
    • The ledger row is live with authorWarn: true. lintLivenessProperties's describe() (packages/lint/src/lint-liveness-properties.ts) has no live branch. It throws its sentinel for that pair, by design: its own header calls the pair "a ledger authoring mistake".
    • Through lint's source, against the built spec: runAuthoringRules('validate', …), the call os validate makes (packages/cli/src/commands/validate.ts:522), THREW lintLivenessProperties: ledger entry has unrecognised status "live" for a stack whose mappings[] carries connectorSource. The control without connectorSource gave 0 findings.
    • The runtime metadata-write door (runRuntimeAuthoringRules) answered one authoring-rule-threw advisory in place of the liveness warning.
    • Read at 99398542b and again at this head. lint-liveness-properties.ts, authoring-rules.ts, runtime-gate.ts and liveness/mapping.json have no diff between 8368f1c0 and 99398542b. The CLI process itself was not run: its closure was not built here.
    • So the corrected note claims no warning. The defect is reported to the seat as a separate finding below and not changed here.

2 · The ledger sentence, and the counts behind it

Measured on ERROR_CODE_LEDGER at 8368f1c0 against its parent 2742e537, comments stripped:

Key Parent 8368f1c0 Change
@objectstack/rest 83 76 −7: AMBIGUOUS_MATCH, BLANK_MATCH_KEY, CONCURRENT_UPDATE, ERR_DATASOURCE_UNAVAILABLE, NO_MATCH, SUMMARY_RECOMPUTE_FAILED, UNIQUE_VIOLATION
@objectstack/core 12 17 +5: AMBIGUOUS_MATCH, BLANK_MATCH_KEY, NO_MATCH, SUMMARY_RECOMPUTE_FAILED, UNSUPPORTED_TRANSFORM
@objectstack/types absent 3 new key: CONCURRENT_UPDATE, ERR_DATASOURCE_UNAVAILABLE, UNIQUE_VIOLATION
owner keys 30 31
union (ErrorCode) 280 280 none added, none removed

The card and the review say rest lost −8. The measurement is −7. Eight codes moved (5 to core and 3 to types), but rest kept UNSUPPORTED_TRANSFORM, which resolveNamedMapping still stamps. Literal counts in packages/rest/src non-test source at 8368f1c0: 0 for each of the seven, and 1 for UNSUPPORTED_TRANSFORM. The note says seven.

The sentence follows the #20206 (5f9d7d78) and #19441 (3f9e2eaa) paragraphs. It names both steps of this release's face change, the #20919 move and this PR's two rows, and says the union, the wire and the HTTP answers are unchanged.

3 · The two rows, and why a pin rather than a wider gate

  • Stamp sites at 8368f1c0 (unchanged since). connector-pull.ts:234 refuse('MAPPING_NOT_FOUND', 404, 'mapping_not_found', …) and :303-304 refuse('UNSUPPORTED_TRANSFORM', 400, 'unsupported_transform', …). Both go onto ConnectorPullError.code, and the class is exported from the package index.
  • Both codes are registered extension codes. They are listed under @objectstack/rest, and UNSUPPORTED_TRANSFORM under @objectstack/core too. Neither is in errors.zod.ts. The executor's other five codes are standard-catalog members and owe no row: VALIDATION_ERROR, EXTERNAL_SERVICE_ERROR, INTEGRATION_ERROR, SERVICE_UNAVAILABLE, INVALID_FIELD.
  • Placement. The rows go in the key's existing ASCII order: MAPPING_NOT_FOUND after INVALID_SIGNAL, and UNSUPPORTED_TRANSFORM last. One comment records the stamp sites, the statuses and the reachability reading: no HTTP door on this tree, so the thrown value is the boundary. No other package's rows were touched.
  • Not widened. check:error-code-provenance's header declares it blind to a helper indirection (a makeError(code, …) call site). It also says "Widening is a gate-population change with an unmeasured blast radius — its own card, never a rider". So this PR keeps the gate's patterns and pins the two rows by hand instead.
  • Measured for the seat, read-only. The refuse('CODE', …) call-site form stamps a registered code at 7 sites in 3 packages: core artifact-packages.ts ×4, runtime artifact-collections.ts ×1, and these two. Before this PR, these two were the only unlisted ones; after it, none is unlisted.
  • The pin. A new block in the gate's test file has two halves. One pins the blind spot itself: scanSourceText finds no site in a refuse('X', …) call. The other asserts that ERROR_CODE_LEDGER['@objectstack/service-automation'] lists each code. It reads the ledger module inside packages/spec, so the suite still reads nothing outside its package.
  • Ablation, two legs through scripts/ablation-replace.mjs in WRAP mode, run from the committed state at c227eb366:
    • Removing the MAPPING_NOT_FOUND row gave 1 failed | 16 passed (17): "expected [ …(9) ] to include 'MAPPING_NOT_FOUND'".
    • Removing the UNSUPPORTED_TRANSFORM row gave 1 failed | 16 passed (17), on that code's case.
    • Each leg restored the file (blob 229345964e13 = HEAD, git diff HEAD empty).
    • A first attempt at leg one was refused by the tool before any test ran: its replacement text already existed in the file. The anchor was changed and the leg re-run. That first attempt is not counted as a run.

Changeset gate: no skip-changeset, and Check Changeset stays red by design

This PR edits a pending changeset that it did not add. node scripts/check-empty-changeset.mjs --base origin/main exits 1 and refuses .changeset/20281-connector-sync-moved-to-mapping.md as the DELIBERATE CORRECTION class. The precedents are PR #20991 and PR #21012. Ruling D on #18375 says skip-changeset is never applied to a PR that edits an existing changeset, so no label is applied. Check Changeset is not a required context.

Confirmation requested in writing on this PR: the stage-① note's connectorSource paragraph now says the executor reads the binding and nothing schedules a pull yet. It no longer says nothing executes it or that os validate / os build warn.

Clause-②: yes, not the claim's no

The claim (5926939917) and the dispatch say patch with Clause-②: no. The dispatch also says not to keep no silently if the diff widens a public surface, and it does:

So the new note is minor with Clause-②: yes, and this body's second line matches it. No accept set changes: the ErrorCode union is unchanged. Every package is in the one fixed group, and @objectstack/spec already has a pending minor, so the released version is the same either way. The seat can flip it back if it reads the precedent differently.

Verification at 5748c8ddd (base 99398542b, merged with origin/main 39ab2940e)

  • node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack (exit 0) derived 87 commands from the four changed paths. Each ran on this head, with its exit code captured before any pipe:
    • 84 exit 0. Among them: check:error-code-provenance ("scanned 2636 files; 335 registered-code stamp site(s): 316 listed, 19 waived" / "OK"), check-adr-0087-registration.mjs --base origin/main ("this PR adds no declared-breaking changeset (2 non-breaking changeset(s) seen)"), check-changeset-no-major.mjs --base origin/main ("This diff introduces no major bump"), check:api-surface, check:authorable-surface, check:docs, check:liveness, check:error-code-casing, check:dispatcher-error-vocabulary, check:cross-package-test-inputs, check:nul-bytes, check:query-options-erasure and check:type-check-debt.
    • 1 exit 1, by design: check-empty-changeset.mjs --base origin/main, the DELIBERATE CORRECTION class above.
    • 2 NOT MEASURED (exit 3, PREREQUISITE NOT MET): check:dual-build-cjs-loads (needs a full pnpm build) and check:lean-entry-closure (needs @objectstack/objectql built). CI builds the tree. Reason: a built tree was not produced here.
    • Reconciled: dispatch-gates.mjs --ran exit 0, "87 derived famil(ies) accounted for — 85 run, 2 NOT-MEASURED".
  • pnpm --filter @objectstack/spec build: VERDICT command-exit 0. Then pnpm --filter @objectstack/spec check:generated: "All 15 generated artifacts are up to date".
  • vitest run --project local on src/api plus scripts/check-error-code-provenance.test.ts: 47 files / 1546 tests passed. The 12 other spec test files that read the ledger: 182 tests passed.
  • pnpm --filter @objectstack/spec typecheck: exit 0. That covers tsc, check:scripts-typecheck, and check:test-typecheck ("52 file(s) / 246 error(s) / 135 pinned signature(s) held", unchanged).
  • Main moved during the run: origin/main gained 13 commits after the branch point. None touches the four files. The delta against 39ab2940e is exactly them (+70 / −4).

Acceptance notes

  • Read and kept in the stage-① note:
    • "Runtime behaviour is deliberately unchanged: no connector sync ever ran." This is about the retired connector-attached keys (syncConfig / fieldMappings), and it stays true of them.
    • "It carries no cadence (a job sets that)." This describes the design; the corrected clause says nothing schedules a pull until the job stage lands.
  • Reported to the seat, not changed here:
    • The liveness lint throws on connectorSource. The live + authorWarn row reaches describe()'s sentinel throw, so os validate / os build stop with an internal lint error, and the runtime door answers authoring-rule-threw, instead of warning on an authored connectorSource. The comments in authoring-rules.ts and runtime-gate.inert-type-writes.test.ts still say it warns. The fix is a choice for its own card: teach describe() a caveat branch for live, or change the row.
    • turbo 2.11.5 edits AGENTS.md. It arrived with the development-dependencies bump (840ec9dab, now on main). On every turbo invocation it sees as an AI agent's, it appends a managed turborepo-agent-rules block to AGENTS.md, a Tier H governed surface, and turbo.json declares no agentGuidance: false. Measured here: pnpm exec turbo run build --filter='@objectstack/lint...' and pnpm check:type-check-debt each left M AGENTS.md, +11 lines. Each time it was restored with git checkout HEAD -- AGENTS.md (blob e9e211fc = HEAD) and never committed. An agent that commits with -a would carry it into its PR.

Generated by Claude Code

claude added 3 commits October 1, 2026 08:12
…r @objectstack/service-automation's ledger key

MAPPING_NOT_FOUND and UNSUPPORTED_TRANSFORM are stamped onto
ConnectorPullError.code through connector-pull.ts's local refuse(...)
helper, a call-site form check:error-code-provenance declares itself
blind to; the gate's own test pins both rows by hand and pins the blind
spot itself. The new spec note carries the provenance-not-identity
sentence for this release's ledger face changes.

Claude-Session: https://claude.ai/code/session_017VaLJnYwhPsanVCe9dMCJU
Co-authored-by: Claude <noreply@anthropic.com>
…ads connectorSource, not that nothing executes it

A deliberate correction of the stage-1 pending note before the next
changeset version, so the version that carries the executor does not
also say nothing executes the binding. The clause about os validate /
os build warning is dropped: at this tree the liveness lint throws on
the binding's live + authorWarn row instead of warning.

Claude-Session: https://claude.ai/code/session_017VaLJnYwhPsanVCe9dMCJU
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added size/s documentation Improvements or additions to documentation tests tooling labels Oct 1, 2026
@github-actions

github-actions Bot commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

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

5 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:

  • content/docs/api/client-sdk.mdx (via ERROR_CODE_LEDGER (symbol, a top-level const object))
  • content/docs/api/error-catalog.mdx (via ERROR_CODE_LEDGER (symbol, a top-level const object))
  • content/docs/api/error-handling-server.mdx (via ERROR_CODE_LEDGER (symbol, a top-level const object))
  • content/docs/data-modeling/import-mappings.mdx (via MAPPING_NOT_FOUND (literal, a string literal in ERROR_CODE_LEDGER), UNSUPPORTED_TRANSFORM (literal, a string literal in ERROR_CODE_LEDGER))
  • content/docs/kernel/contracts/data-engine.mdx (via ERROR_CODE_LEDGER (symbol, a top-level const object))

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

  • content/docs/releases/v12.mdx (via MAPPING_NOT_FOUND (literal, a string literal in ERROR_CODE_LEDGER), UNSUPPORTED_TRANSFORM (literal, a string literal in ERROR_CODE_LEDGER))
  • content/docs/releases/v17/17-0.mdx (via ERROR_CODE_LEDGER (symbol, a top-level const object))
  • content/docs/releases/v17/17-1.mdx (via ERROR_CODE_LEDGER (symbol, a top-level const object))
  • content/docs/releases/v17/17-4.mdx (via ERROR_CODE_LEDGER (symbol, a top-level const object))

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

Coarse fallback — 137 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 e952cff578cc936daab3241570c4c2c36804bbd6 → packageMentionDocs.

Which tree this was computed on

This run read content/docs from ebc0968c1491ed1d1141e52ec1409921f3d30875 — the merge of head 5748c8ddd10f9d056f143ad470a9dec1a3c80d52 into base e952cff578cc936daab3241570c4c2c36804bbd6, 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 ebc0968c1491ed1d1141e52ec1409921f3d30875 && git checkout ebc0968c1491ed1d1141e52ec1409921f3d30875
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin e952cff578cc936daab3241570c4c2c36804bbd6 5748c8ddd10f9d056f143ad470a9dec1a3c80d52 && git checkout -B drift-repro e952cff578cc936daab3241570c4c2c36804bbd6 && git merge --no-ff 5748c8ddd10f9d056f143ad470a9dec1a3c80d52

node scripts/docs-audit/affected-docs.mjs --json e952cff578cc936daab3241570c4c2c36804bbd6

⚠️ 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 e952cff578cc936daab3241570c4c2c36804bbd6 → pass the list as
args.docs, on the commit named under Which tree this was computed on.

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 5748c8ddd10f9d056f143ad470a9dec1a3c80d52
Local-runs: none

PR #21150 (card #21106; the three follow-ups the at-tier review of PR #21084, comment 5926057594, escalated), reviewed on its current head 5748c8dd, rendered 2026-10-01T10:22Z by an isolated contract-review subagent of the domain:spec seat, adversarially to the dispatch order. Inputs, and nothing else: the card body and its four comments (triage 5926594302, claim 5926939917, dispatch note 5927380796, dev report 5929227465), the PR body, its four-file list, the net diff against main (merge-base 39ab2940e; the same four files, +70 / −4, against the origin/main tip e952cff57 as well), the head's check-runs, and, as the card directs, the code at PR #21084's merge commit 8368f1c0 and its parent 2742e537, read with git show. The precedents the card names were read the same way: the #20206 note at 5f9d7d78, the #19441 note at 3f9e2eaa, PR #20991 and PR #21012. Every judgment below was re-derived from the diff and those commits, not taken from the PR body, the dev report or the dispatching seat. Nothing was built, run or re-run locally; the ledger counts were taken by reading the ledger text at the three commits.

① Derived judgments

  1. The stage-① note, .changeset/20281-connector-sync-moved-to-mapping.md, is a DELIBERATE CORRECTION of a pending note, and this record names it and judges each rewritten sentence (landing-operations: a same-head at-tier PASS is the confirmation). The diff touches one paragraph of the file; the front matter ('@objectstack/spec': minor), the feat(spec)!: summary, the BREAKING banner, the FROM → TO table, the retirement kit, the Clause-②: yes (narrowing) line and the ADR-0087 marker are unchanged bytes.

    • Rewritten piece 1, the lead label: "Added (declared, not yet executed):" becomes "Added:". RIGHT. At 8368f1c0, packages/services/service-automation/src/connector-pull.ts pullConnectorSource (line 209) reads the mapping through protocol.getMetaItem({ type: 'mapping', name }) (line 230) and its connectorSource (line 236), so "not yet executed" was false at that commit; the stage-② note .changeset/20919-spec-connector-source-live.md already says the executor reads it, and both notes compile into the same @objectstack/spec version.
    • Rewritten piece 2, the paragraph's last sentence: "Nothing executes it in this release, and os validate / os build warn when it is authored." becomes "The connector sync executor, @objectstack/service-automation's pullConnectorSource (connector sync, stage ② of #20281: an executor in service-automation pulls a mapping whose connectorSource names a rest/openapi connector and writes through the import runner's upsert-by-match-key #20919), reads it; nothing schedules a pull until the job stage lands." Judged clause by clause:
      • "reads it": TRUE at 8368f1c0 (the reads above; the liveness row packages/spec/liveness/mapping.json props.connectorSource is live with evidence connector-pull.ts#pullConnectorSource).
      • "nothing schedules a pull until the job stage lands": TRUE at 8368f1c0. Outside tests, pullConnectorSource has three references in its own package (the definition, the index.ts re-export, the plugin method plugin.ts:621) and one comment in packages/spec/src/data/mapping.zod.ts; no package, app or example source calls the plugin method. The wording is the stage-② note's own sentence, so the two notes now agree.
      • The dropped clause "Nothing executes it in this release": FALSE at 8368f1c0, so dropping it is right.
      • The dropped clause "os validate / os build warn when it is authored" (the clause the feat(service-automation,core,types): the connector sync executor pulls a mapping's connectorSource through the import runner, moved beside bulkWrite #21084 review's suggested remedy kept): FALSE at 8368f1c0, so dropping it is right, and the dev's reading is confirmed from the source. packages/lint/src/lint-liveness-properties.ts at 8368f1c0: shouldWarn (line 159) admits every row with authorWarn === true; describe() (line 224) has branches for experimental, planned, dead and live-elsewhere only and throws its sentinel for any other status (line 265, "unrecognised status"); the file's own test pins the throw. The connectorSource row is live with authorWarn: true, so an authored connectorSource reaches the throw, not a warning. The dev read the lint at 99398542b and said those files have no diff from 8368f1c0 to 99398542b; that is correct for that range. At this head the files DO differ (b616c0a63, feat(lint): a ledger-dead or live-elsewhere key warns without an authorWarn opt-in, and never shows the ledger note (#16094) #21092, is between 99398542b and the merge parent 39ab2940e): shouldWarn was rewritten so dead, live-elsewhere and experimental warn without an opt-in, but it still admits authorWarn: true rows, and describe() still has no live branch and still throws (line 303), while liveness/mapping.json is byte-identical to 8368f1c0. So the clause is false at the head as well. The crash has its own card, [finding] os lint / os validate crash on any stack whose mapping authors connectorSource: the ledger row is live with authorWarn: true, and the liveness rule throws its integrity sentinel #21127 (open, p1, pm:dispatched). A release note that says nothing about the warning is the only text true at both commits; the corrected note claims nothing about it. RIGHT.
    • The two kept sentences the dev flagged: "Runtime behaviour is deliberately unchanged: no connector sync ever ran." qualifies the removal of the connector-attached keys (syncConfig / fieldMappings, the paragraph it sits in) and stays true: nothing invokes the pull on this tree. "It carries no cadence (a job sets that)" is true of the schema (no schedule key) and is what the corrected clause restates. RIGHT to keep both.
  2. The new spec note .changeset/21106-error-code-ledger-provenance-rows.md, sentence by sentence against 8368f1c0 and its parent 2742e537. ERROR_CODE_LEDGER parsed per owner key at each commit, comments stripped:

  3. The ledger edit itself. Both rows land in the @objectstack/service-automation key in its existing ASCII order (MAPPING_NOT_FOUND after INVALID_SIGNAL, UNSUPPORTED_TRANSFORM last; the ten rows sort byte-identically under LC_ALL=C); no other key is touched. None of the three provenance waivers that name @objectstack/service-automation (FLOW_DISABLED, FLOW_NO_START_NODE, FLOW_INPUT_SCHEMA_INVALID) is for either code, so no row-plus-waiver pair is created. The generated reference content/docs/references/api/error-code-ledger.mdx lists the flat union, which both codes were already in, so no generated artifact goes stale behind this diff; the docs-drift rows are the hand-written pages that name the two codes as the import door's HTTP answers (unchanged) and error-catalog.mdx, which carries no per-package list, so no content/docs/** edit is owed. RIGHT.

  4. The hand pin in place of a wider gate. packages/spec/scripts/check-error-code-provenance.ts's header (lines 58-66 at this head) declares the gate BLIND to a helper indirection ({ code } shorthand, makeError(code, …) call sites) and says widening "is a gate-population change with an unmeasured blast radius — its own card, never a rider". The executor's form is exactly that blind form twice over: a refuse('CODE', …) call whose body builds the error with a { code, … } shorthand. So leaving the gate's patterns alone is what the gate's own text requires, and the card allowed a pin for that case. The pin block in check-error-code-provenance.test.ts has the right two halves: one asserts scanSourceText sees no site in return refuse('REGISTERED_ONE', 404, 'reason', 'message'); (the ratchet that reddens the day the gate learns the form, so the hand rows can come out with the widening), and an it.each asserts ERROR_CODE_LEDGER['@objectstack/service-automation'] contains each code, read from ../src/api/error-code-ledger.zod inside the package. registered and scanSourceText are already in the file's scope. The test is not a published surface. RIGHT. The dev's read-only census ("7 refuse('CODE', …) sites in 3 packages, none unlisted after this PR") was offered to the seat, not relied on here, and was not re-derived.

  5. Accept sets and public surface. No schema shape, enum, default or refinement changes; ErrorCode and ApiErrorSchema.code are unchanged, so no accept set moves. The one public-surface change is the literal type of the published as const face ERROR_CODE_LEDGER['@objectstack/service-automation'], which gains two members (what a consumer reading that key sees), the same class as lint: four recordsOf(stack.packages) readers treat a non-array packages as "no packages" instead of refusing it — the packages/lint half of #19925 (ruling #15293-A) #20206 and [finding] plugin-security 四处错误码发射点未登记 ledger,且免登记的理由注释经实测为假(NOT_OVERRIDABLE 不在 StandardErrorCode、在 ledger 里) #19441. No package.json, no exports map, no route, no content/docs/**. RIGHT, and declared (②).

Gates (the head's check-runs are the verdicts, read at 2026-10-01T10:18Z): 33 check-runs on 5748c8dd: 23 success, 3 skipped (Build Docs, Console Pin Gate, the opt-in packed-tarball smoke), 1 failure, 6 still in progress at the read: Lint & Repo Gates, Test Core 1/6, 2/6, 5/6 and 6/6, and Type Check · workspace. Among the 23 green: Build Core, Test Core 3/6 and 4/6, the three other Type Check jobs (consumer gates, debt ledger, source gates), Spec property liveness, Governed Surface Queue Guard, the three claim guards, Check PR Size, Dogfood Regression Gate (all three shards), Dogfood Verify CLI and the Temporal Conformance run; the one commit status (Vercel) is success. The one failure is Check Changeset, red by design. Its job's steps, read from the Actions API: "Require a changeset (or the skip-changeset label)" is green (this PR adds the 21106 note); the failing step is "Reject an empty-frontmatter changeset added by this PR", which runs scripts/check-empty-changeset.mjs --self-test and then --base on the merge base, the script that refuses the DELIBERATE CORRECTION class and whose own text says "this gate stays red either way" (lines 605-612), with the workflow's route-0 text saying "LEAVE THIS CHECK RED" and refusing the skip-changeset label (ruling D on #18375). The first error line was not readable here (the job-log blob store is behind the proxy's CONNECT deny), so the signature is the step name alone. The PR carries no skip-changeset label (its labels: documentation, size/s, tests, tooling). RIGHT. Of the three conditions SKILL.md sets for landing with a designed red, two are verified from the source: the gate self-describes the red on pushed branches, and pr-automation.yml runs on pull_request only, never merge_group; the third (a PR comment naming the gate and the reason) is the seat's to satisfy, see ③. The six in-progress runs are not a FAIL by themselves; their conclusions are the seat's landing condition.

② Semver level

③ Boundary flags

Read from the dev report 5929227465 (one open question, seven deviations, three out-of-scope findings) and the PR body's "Confirmation requested" and Acceptance notes.

Implemented-by: claude/issue-21106-connector-sync-notes-ledger
Reviewed-by: session_017VaLJnYwhPsanVCe9dMCJU

VERDICT: PASS

Nothing is blocking. The stage-① note's correction is true of the code at 8368f1c0 sentence by sentence and this record confirms it; the ledger sentence's counts are right against 8368f1c0 and its parent, including the seven the card had as eight; the two rows are owed under the ledger's own rule and are pinned by hand where the gate's header forbids a rider; the bump and the Clause-②: yes match the diff and both precedents. Read on the head's check-runs as they stood at 2026-10-01T10:18Z, with Check Changeset red by design and six runs still in progress; nothing was built, run or re-run locally.


Generated by Claude Code

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Designed red, recorded before enqueue · domain:spec seat 2 (session_017VaLJnYwhPsanVCe9dMCJU) · 2026-10-01T10:24Z

  • Gate: Check Changeset, step "Reject an empty-frontmatter changeset added by this PR" (scripts/check-empty-changeset.mjs --base origin/main). "Require a changeset" is green.
  • Why it is red: this PR corrects a PENDING release note in place, .changeset/20281-connector-sync-moved-to-mapping.md, so that it stops saying the connector-source binding is "declared, not yet executed". The gate classifies that as a DELIBERATE CORRECTION and goes red by design. Its remedy is to have the correction confirmed on the PR, not to restore the false sentence. The mechanism precedents are PR docs(changeset): scope two pending service-analytics BREAKING banners to the SQL echo on either strategy, and anchor the nested-relation note to its measured base #21012 (merged through the queue the same way) and PR docs(changeset): correct two scope sentences in the pending service-analytics masked-field note #20991.
  • The three conditions (SKILL.md) for entering the queue with a designed red:
    1. The gate's source states this red on a pushed branch.
    2. pr-automation.yml runs on pull_request only, never on merge_group.
    3. This comment names the gate and the reason.
  • The confirmation: the at-tier record 5929446191 on this head (5748c8ddd1) judges each rewritten sentence true at 8368f1c0, and is a PASS. Per landing-operations.md, a same-head at-tier PASS confirms a DELIBERATE CORRECTION, with no wait for the maintainer.

Generated by Claude Code

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 1, 2026 10:31
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge October 1, 2026 10:31
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 1, 2026
Merged via the queue into main with commit df1feae Oct 1, 2026
36 of 37 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-21106-connector-sync-notes-ledger branch October 1, 2026 11:04
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/s tests tooling

Projects

None yet

1 participant