fix(spec): the pending connector-sync note matches the executor, and the error-code ledger lists its two refuse() codes (#21106) - #21150
Conversation
…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>
…tes-ledger Claude-Session: https://claude.ai/code/session_017VaLJnYwhPsanVCe9dMCJU Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 1 package(s): 5 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 4 release-owned page(s) also name something this change touched. These are read-only:
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): Which tree this was computed onThis run read A worktree cut from an older # 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
|
Contract reviewServed-tier: PR #21150 (card #21106; the three follow-ups the at-tier review of PR #21084, comment ① Derived judgments
Gates (the head's check-runs are the verdicts, read at 2026-10-01T10:18Z): 33 check-runs on ② Semver level
③ Boundary flagsRead from the dev report
Implemented-by: VERDICT: PASS Nothing is blocking. The stage-① note's correction is true of the code at Generated by Claude Code |
|
Designed red, recorded before enqueue ·
Generated by Claude Code |
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 commit8368f1c0. The target files are byte-identical between8368f1c0and this branch's base (git diff --statprinted nothing). No package source changes..changeset/20281-connector-sync-moved-to-mapping.mdsaidconnectorSourcewas "declared, not yet executed" and that "Nothing executes it in this release". The stage-② note.changeset/20919-spec-connector-source-live.mdsays the executor reads it. Both compile into the same@objectstack/specCHANGELOG version.ERROR_CODE_LEDGERface changes, in a new spec note,.changeset/21106-error-code-ledger-provenance-rows.md.@objectstack/service-automationprovenance rows,MAPPING_NOT_FOUNDandUNSUPPORTED_TRANSFORM, inpackages/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
os validate/os buildwarn when it is authored."@objectstack/service-automation'spullConnectorSource(#20919), reads it; nothing schedules a pull until thejobstage 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:packages/services/service-automation/src/connector-pull.tspullConnectorSource(:209) reads the mapping throughgetMetaItemand itsconnectorSource. It makes one action call and writes throughrunImport. The liveness rows say the same:packages/spec/liveness/mapping.json,connectorSourcelive, evidenceconnector-pull.ts#pullConnectorSource.jobstage lands". Outside tests,pullConnectorSourcehas 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.os validate/os buildwarn when it is authored" is NOT kept. It is false at8368f1c0, measured:livewithauthorWarn: true.lintLivenessProperties'sdescribe()(packages/lint/src/lint-liveness-properties.ts) has nolivebranch. It throws its sentinel for that pair, by design: its own header calls the pair "a ledger authoring mistake".runAuthoringRules('validate', …), the callos validatemakes (packages/cli/src/commands/validate.ts:522), THREWlintLivenessProperties: ledger entry has unrecognised status "live"for a stack whosemappings[]carriesconnectorSource. The control withoutconnectorSourcegave 0 findings.runRuntimeAuthoringRules) answered oneauthoring-rule-threwadvisory in place of the liveness warning.99398542band again at this head.lint-liveness-properties.ts,authoring-rules.ts,runtime-gate.tsandliveness/mapping.jsonhave no diff between8368f1c0and99398542b. The CLI process itself was not run: its closure was not built here.2 · The ledger sentence, and the counts behind it
Measured on
ERROR_CODE_LEDGERat8368f1c0against its parent2742e537, comments stripped:8368f1c0@objectstack/restAMBIGUOUS_MATCH,BLANK_MATCH_KEY,CONCURRENT_UPDATE,ERR_DATASOURCE_UNAVAILABLE,NO_MATCH,SUMMARY_RECOMPUTE_FAILED,UNIQUE_VIOLATION@objectstack/coreAMBIGUOUS_MATCH,BLANK_MATCH_KEY,NO_MATCH,SUMMARY_RECOMPUTE_FAILED,UNSUPPORTED_TRANSFORM@objectstack/typesCONCURRENT_UPDATE,ERR_DATASOURCE_UNAVAILABLE,UNIQUE_VIOLATIONErrorCode)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, whichresolveNamedMappingstill stamps. Literal counts inpackages/rest/srcnon-test source at8368f1c0: 0 for each of the seven, and 1 forUNSUPPORTED_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
8368f1c0(unchanged since).connector-pull.ts:234refuse('MAPPING_NOT_FOUND', 404, 'mapping_not_found', …)and:303-304refuse('UNSUPPORTED_TRANSFORM', 400, 'unsupported_transform', …). Both go ontoConnectorPullError.code, and the class is exported from the package index.@objectstack/rest, andUNSUPPORTED_TRANSFORMunder@objectstack/coretoo. Neither is inerrors.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.MAPPING_NOT_FOUNDafterINVALID_SIGNAL, andUNSUPPORTED_TRANSFORMlast. 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.check:error-code-provenance's header declares it blind to a helper indirection (amakeError(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.refuse('CODE', …)call-site form stamps a registered code at 7 sites in 3 packages: coreartifact-packages.ts×4, runtimeartifact-collections.ts×1, and these two. Before this PR, these two were the only unlisted ones; after it, none is unlisted.scanSourceTextfinds no site in arefuse('X', …)call. The other asserts thatERROR_CODE_LEDGER['@objectstack/service-automation']lists each code. It reads the ledger module insidepackages/spec, so the suite still reads nothing outside its package.scripts/ablation-replace.mjsin WRAP mode, run from the committed state atc227eb366:MAPPING_NOT_FOUNDrow gave1 failed | 16 passed (17): "expected [ …(9) ] to include 'MAPPING_NOT_FOUND'".UNSUPPORTED_TRANSFORMrow gave1 failed | 16 passed (17), on that code's case.229345964e13= HEAD,git diff HEADempty).Changeset gate: no
skip-changeset, andCheck Changesetstays red by designThis PR edits a pending changeset that it did not add.
node scripts/check-empty-changeset.mjs --base origin/mainexits 1 and refuses.changeset/20281-connector-sync-moved-to-mapping.mdas the DELIBERATE CORRECTION class. The precedents are PR #20991 and PR #21012. Ruling D on #18375 saysskip-changesetis never applied to a PR that edits an existing changeset, so no label is applied.Check Changesetis not a required context.Confirmation requested in writing on this PR: the stage-① note's
connectorSourceparagraph now says the executor reads the binding and nothing schedules a pull yet. It no longer says nothing executes it or thatos validate/os buildwarn.Clause-②: yes, not the claim'snoThe claim (
5926939917) and the dispatch saypatchwithClause-②: no. The dispatch also says not to keepnosilently if the diff widens a public surface, and it does:ERROR_CODE_LEDGER['@objectstack/service-automation'], a publishedas constface.no, #15963 landsyes, and they are the same class #16404 ruling) names this ledger, together withStandardErrorCode, as the published contract face for error codes.recordsOf(stack.packages)readers treat a non-arraypackagesas "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, each declared a provenance-row addition as@objectstack/specminorwithClause-②: yes. Both say "What widens is the per-package face".So the new note is
minorwithClause-②: yes, and this body's second line matches it. No accept set changes: theErrorCodeunion is unchanged. Every package is in the onefixedgroup, and@objectstack/specalready has a pendingminor, so the released version is the same either way. The seat can flip it back if it reads the precedent differently.Verification at
5748c8ddd(base99398542b, merged withorigin/main39ab2940e)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: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 nomajorbump"),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-erasureandcheck:type-check-debt.check-empty-changeset.mjs --base origin/main, the DELIBERATE CORRECTION class above.PREREQUISITE NOT MET):check:dual-build-cjs-loads(needs a fullpnpm build) andcheck:lean-entry-closure(needs@objectstack/objectqlbuilt). CI builds the tree. Reason: a built tree was not produced here.dispatch-gates.mjs --ranexit 0, "87 derived famil(ies) accounted for — 85 run, 2 NOT-MEASURED".pnpm --filter @objectstack/spec build:VERDICT command-exit 0. Thenpnpm --filter @objectstack/spec check:generated: "All 15 generated artifacts are up to date".vitest run --project localonsrc/apiplusscripts/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 coverstsc,check:scripts-typecheck, andcheck:test-typecheck("52 file(s) / 246 error(s) / 135 pinned signature(s) held", unchanged).origin/maingained 13 commits after the branch point. None touches the four files. The delta against39ab2940eis exactly them (+70 / −4).Acceptance notes
syncConfig/fieldMappings), and it stays true of them.jobsets that)." This describes the design; the corrected clause says nothing schedules a pull until thejobstage lands.connectorSource. Thelive+authorWarnrow reachesdescribe()'s sentinel throw, soos validate/os buildstop with an internal lint error, and the runtime door answersauthoring-rule-threw, instead of warning on an authoredconnectorSource. The comments inauthoring-rules.tsandruntime-gate.inert-type-writes.test.tsstill say it warns. The fix is a choice for its own card: teachdescribe()a caveat branch forlive, or change the row.turbo2.11.5 editsAGENTS.md. It arrived with the development-dependencies bump (840ec9dab, now onmain). On every turbo invocation it sees as an AI agent's, it appends a managedturborepo-agent-rulesblock toAGENTS.md, a Tier H governed surface, andturbo.jsondeclares noagentGuidance: false. Measured here:pnpm exec turbo run build --filter='@objectstack/lint...'andpnpm check:type-check-debteach leftM AGENTS.md, +11 lines. Each time it was restored withgit checkout HEAD -- AGENTS.md(blobe9e211fc= HEAD) and never committed. An agent that commits with-awould carry it into its PR.Generated by Claude Code