Skip to content

docs(adr): ADR-0097 records that a held degraded connector instance is not retried - #28161

Merged
os-zhuang merged 3 commits into
mainfrom
claude/project-thread-8t7yh8
Oct 31, 2026
Merged

os-zhuang merged 3 commits into
mainfrom
claude/project-thread-8t7yh8

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Elon · project thread

domain:skills#2 · os-elon-musk · session_016WV4cypdG8XcEafFNG2EFa

Fixes #28038

Clause-②: no
Metadata-protocol: none

维护者速读

What changes

Why

#28038 (triage 6521083653): since PR #28014 and #27237 the ADR's degraded section contradicted the runtime, and PR #28037 (merged b59bf60c8) made the refusal itself say so. Measured on origin/main 27e0bd584: scheduleDeclarativeRetry filters !d.held; reconcileDeclaredConnectors continues on held?.held && held.signature === signature; the two hold sites set held: true and pass a ConnectorHold to registerDegradedConnector; the dispatch refusal branches on engine.getConnectorDegradedHold.

Verification

All readings at head f4345a9d, in a fresh worktree after pnpm install --frozen-lockfile --ignore-scripts (and turbo run build --filter=@objectstack/formula --filter=@objectstack/lint for the doc-formula gate).

  • check:adr-symbol-anchors: exit 0 on base 27e0bd584 (2843 anchors, 623 symbol: 597 declaration / 26 literal) and on head (2850 anchors, 630 symbol: 604 declaration / 26 literal). The 7 new anchors all resolve as declarations.
  • check:adr-index: exit 0 (derived; the ADR's title is unchanged).
  • check-governed-merges.mjs --test docs/adr/0097-declarative-connector-instances.md: GOVERNED, 1 of 1 path on the register (Tier H).
  • dispatch-gates --ran: 21 derived families accounted for, 21 run, 0 NOT-MEASURED. No changeset family is derived (docs only), hence skip-changeset.
dispatch-gates families (21 derived, 21 run)
node scripts/check-adr-links.mjs :: exit 0
node scripts/check-adr-links.mjs --self-test :: exit 0
node scripts/check-closing-keyword-parity.mjs :: exit 0
node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0
node scripts/check-comment-mask-corpus.mjs :: exit 0
node scripts/ci/plan-test-core-shards.mjs --self-test :: exit 0
pnpm --filter @objectstack/lint run check:doc-formula-expressions :: exit 0
pnpm check:adr-anchors :: exit 0
pnpm check:adr-index :: exit 0
pnpm check:adr-symbol-anchors :: exit 0
pnpm check:ci-filter-parity :: exit 0
pnpm check:closed-ceremony-text :: exit 0
pnpm check:cross-package-test-inputs :: exit 0
pnpm check:doc-authoring :: exit 0
pnpm check:driver-memory-census :: exit 0
pnpm check:gitlink-declared :: exit 0
pnpm check:nul-bytes :: exit 0
pnpm check:pm-governed-merges :: exit 0
pnpm check:pm-prior-rulings :: exit 0
pnpm check:refd-timer-probe :: exit 0
pnpm check:watch-hint-literal :: exit 0

Human Minimum

  • 1. Schemas start as Zod; packages/spec holds no runtime logic. (not touched)
  • 2. Every name I added uses the casing for its kind. (no names added)
  • 3. No formatter ran. (pnpm lint not run: the diff touches no lintable source, only one ADR .md)
  • 4. One issue, one branch off an up-to-date main, one pull request.
  • 5. A change that publishes carries a changeset, and both declaration lines are filled in here and in the changeset. (docs only, publishes nothing: skip-changeset)
  • 6. packages/spec touched: its generated artifacts are regenerated and committed. (not touched)
  • 7. No hand edits to content/docs/references/, packages/*/CHANGELOG.md or content/docs/releases/.
  • 8. Title, body and comments are in English.
  • The Before Submitting list in CONTRIBUTING.md is done.

Generated by Claude Code

🤖 Generated with Claude Code

https://claude.ai/code/session_016WV4cypdG8XcEafFNG2EFa

…s not retried

The degraded-instance section said every husk's dispatch refusal promises
"the platform retries automatically". Since #27992 and #27237 a held
instance (a configuration fault met on a retry, a refused stored or
declared credential) is skipped by the backoff timer and by an unchanged
reconcile, and #28016 makes its refusal name the edit or the credential
that unblocks it. A dated amendment note records this beside the kept
bullets, plus the matching Amended-by entry.

Fixes #28038

Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016WV4cypdG8XcEafFNG2EFa
@objectstack-fleet objectstack-fleet Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Oct 30, 2026
@github-actions github-actions Bot added size/s documentation Improvements or additions to documentation labels Oct 30, 2026
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:skills#2 · os-elon-musk · session_016WV4d1QkPVVzNz3FJqb2iS

Contract-review-claim: session_016WV4d1QkPVVzNz3FJqb2iS · head f4345a9 · 2026-10-30T14:48Z

…redential, and code-spans the ref placeholder

Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016WV4cypdG8XcEafFNG2EFa
… sentence contradicted

Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016WV4cypdG8XcEafFNG2EFa
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:skills#2 · os-elon-musk · session_016WV4d1QkPVVzNz3FJqb2iS

Contract-review-claim: session_016WV4d1QkPVVzNz3FJqb2iS · head 1a9e3f7 · 2026-10-30T15:17Z

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:skills#2 · os-elon-musk · session_016WV4d1QkPVVzNz3FJqb2iS

Contract review

Head-sha: 1a9e3f73a2bdc9ea3f196a907e9a37d317d91bda
Served-tier: CONTRACT_REVIEW_TIER
Local-runs: probe — node scripts/check-adr-symbol-anchors.mjs and node scripts/adr-index.mjs on a detached worktree at this head (porcelain empty after the index run), and node scripts/pm/check-governed-merges.mjs --pr 28161, were executed locally, because the one gate this diff can turn red (the symbol-anchor count, 2843 at the base to 2850 here) is a head-versus-base reading no check-run prints as a number and the seven anchors must be seen to resolve; the base reading (2843 / 623) is the first record's, on a detached worktree at 27e0bd584; nothing else was built or run.
Scope: docs/adr/0097-declarative-connector-instances.md (the register's one hit, Tier H) + packages/services/service-automation/src/plugin.ts (degradedInstances and its docblock, reconcileDeclaredConnectors including the signature build, the factory catch routing and the held-skip, failDegradedConnectorInstance, holdConnectorForRejectedCredential, degradeConnectorInstance, degradeConnectorForCredential, scheduleDeclarativeRetry, setConnectorCredential, clearConnectorCredential, the metadata:reloaded hook), packages/services/service-automation/src/connector-credentials.ts (connectorCredentialFingerprint, resolveConnectorCredential, missingCredentialReason, the store's clear), packages/services/service-automation/src/engine.ts (RegisteredConnector.degradedHold, ConnectorHold, getConnectorDegradedReason, getConnectorDegradedHold), packages/services/service-automation/src/plugin-extension-api.ts (registerDegradedConnector, describeHold), packages/services/service-automation/src/builtin/connector-nodes.ts (registerConnectorNodes, the refusal branch), packages/services/service-automation/src/connector-held-dispatch-refusal.test.ts (the pinned wording, read not run), content/docs/automation/connectors.mdx (the credential and failure-modes prose, for ④), docs/adr/0143-outbound-connector-auth-is-open-tier.md (the backoff sentence, for ④), .github/workflows/pr-automation.yml (the Check Changeset opt-out, for ③), scripts/check-adr-symbol-anchors.mjs and scripts/adr-index.mjs (the gates that hold the anchors and the index)

Inputs: this is a delta review over the first record (the PASS on f4345a9d68b9693e5e2b790f3e15234ff344ca93, 2026-10-30, claim 6525641438); the delta git diff f4345a9d6..1a9e3f73a (1 file, +6 / −3 within the one blockquote note, two commits ea406edf and 1a9e3f73, author Claude, trailers Co-authored-by and Claude-Session present, no model name, no Refs); the whole git diff 27e0bd584..1a9e3f73a (1 file, +28 / −1); git merge-base pr-28161 origin/main is 27e0bd584; origin/main had moved eight commits to 9f13ee815 at review time (the four the first record saw, then #28136, #28141, #28132, #28151) and none of them touches the ADR, any cited file, scripts/pm, or the two gates; the PR body (unchanged since the first head) and its two comments (6525641438, the claim on the first head; 6526256844, the claim naming this session and this head, 2026-10-30T15:17Z; no reviews, no hold, no hand-off); card #28038 (body, triage 6521083653, claim 6525245002; no comment since the first record); #27992 / PR #28014, #27237, #28016 / PR #28037 as the first record read them; the dispatch order and the dev report at /mnt/project-files/skills-lane-seat2/; .claude/skills/pm-dispatch/references/contract-review.md and review-checklist.md; AGENTS.md Prime Directive #13; the full ADR-0097 at this head and at the base; the code at origin/main for every symbol the note cites and for every path the three new claims rest on; the head's check-runs (three polls, last at 2026-10-30T15:21Z, all completed); micromark 4.0.2 and marked 16.4.2 (a sibling checkout's copies) for the rendering reading.

① Derived judgments

  1. Accept set: unchanged — correct. The diff against the base is ADR prose only: one blockquote note of 26 lines inserted after the third degraded-section bullet (:199-224 at this head), and one entry appended to the Amended by header line (the −1 is that line rewritten with the entry added; every prior entry is byte-identical). The delta since the first head rewrites three sentences inside the note and adds one; it adds no anchor, touches no other line, and moves nothing in any schema, export, type or runtime path. Clause-②: no and Metadata-protocol: none hold.
  2. Which degraded instances are held — the note's two cases are exactly the code's two (carried over, re-read on origin/main, unchanged lines). held: true is written at two sites of plugin.ts and nowhere else: failDegradedConnectorInstance (:2580), reached from the factory catch when the thrown value is neither a credential rejection nor CONNECTOR_UPSTREAM_UNAVAILABLE, the run is soft and the name is already in degradedInstances (:2383-2384); and holdConnectorForRejectedCredential (:3105), where held = info.credential === undefined || stored !== undefined (:3102) — a credential written into the declaration, or a value whose source is object (the sys_connector_credential row). An environment or vault value takes the else branch (:3106-3114): attempts counted, no held, the refusal recorded in credentialRefusals. The note's held list is complete and true, and its backoff parenthetical names true members of the other set (degradeConnectorInstance, and the env/vault branch) without claiming to be exhaustive.
  3. Delta (a), the configuration-fault sentence — now the code's own definition (should-fix 1 of the first record, folded). The note reads "a configuration fault met by an instance that is already degraded, on its backoff retry or on a metadata:reloaded reconcile". The guard is !opts.fatal && this.degradedInstances.has(name) (:2383); the comment above it says "its backoff retry, or a reload" (:2380-2381); the method's docblock says "neither the retry timer nor an unchanged reload re-attempts it" (:2562-2563). The two paths the note names are the two the code names: the retry timer runs materializeDeclaredConnectors(ctx, { fatal: false }) (:3342) and the metadata:reloaded hook (:1666) runs the reload mode, fatal: false (:2036). Observation, no fix owed: the guard is on soft runs as a class, so the reconcile a credential write or clear runs (:2937, :2970) and the one a peer's credential signal runs (:2985-2988) would hold a configuration fault the same way; the ADR's own third bullet already names the soft reconcile by its hook (metadata:reloaded), and the note follows that spelling, so a reader of this file reads it as the soft-reconcile class. The header entry's "met on a retry" (:8) is a summary that the third bullet's own wording ("retried on an exponential backoff ... and immediately by any reconcile") covers.
  4. Not retried: both skips are as stated (carried over). scheduleDeclarativeRetry (:3332) arms the timer over the degradedInstances values filtered to !d.held (:3336); reconcileDeclaredConnectors (:2221-2222) does if (held?.held && held.signature === signature) continue;. The note's "the backoff timer skips it ... and so does a reconcile while its signature is unchanged" is those two lines.
  5. Delta (b) and (c), the re-attempt sentences — true, and the new sentence is traced end to end. "An edit of its declaration, setting its stored credential again (the row's revision is part of the signature), or a restart re-attempts it" drops the first head's "Only", which the next sentence would have contradicted. The three named ways stand as the first record read them: the per-instance signature is connectorInstanceSignature(bound) plus |credential: and connectorCredentialFingerprint(...) (:2171-2173), which returns object:${row.revision} for a stored row (connector-credentials.ts :537), so a PUT (store.set returns the new revision, :2925; then a soft reconcile, :2937) changes the signature and passes the held-skip; a declaration edit changes connectorInstanceSignature; a restart empties the in-memory map. The new sentence, "Clearing the stored credential also ends the hold, since the reference's fingerprint changes: the instance then degrades for the missing reference and goes back on the backoff", is each of four facts in the code: (i) the clear triggers a reconcile — clearConnectorCredential (:2949) calls store.clear(ref, userId) (:2959), which deletes the sys_connector_credential row (connector-credentials.ts :351-358, engine.delete at :357), then reconcileDeclaredConnectors(ctx, { fatal: false }) (:2970) on the reconcile queue, as its docblock says (:2942-2947: "remove the stored value for one reference, then reconcile: every instance naming it is torn down and registered degraded, naming the reference"); (ii) the fingerprint changes — with the row gone connectorCredentialFingerprint falls through :537 to :539 and returns vault or missing instead of object:N, so the signature at :2173 differs from the held record's and the skip at :2222 no longer fires (the stale refusal record for the reference is also dropped, :2178-2181); (iii) what runs sets no held flag — with nothing answering the reference resolveConnectorCredential returns { kind: 'missing' } (connector-credentials.ts :582), the reconcile routes to degradeConnectorForCredential (:2273-2277), and that method writes { attempts, signature, reason } to degradedInstances with no held (:2731-2735) and registers the husk with no hold (:2740), the reason being missingCredentialReason (:2721-2722); (iv) a missing reference is on the backoff — the record has no held, so the !d.held filter at :3336 keeps it, and the method's docblock says so ("Both retry on the feat(connector-mcp): declarative provider — non-fatal / lazy boot for unreachable MCP servers (ADR-0096 follow-up) #3017 backoff", :2705). connectors.mdx :341-342 says the same for DELETE. One edge, consistent with the sentence's point and not owed a fix: when the host's resolver answers the reference after the clear, the fingerprint is vault, the hold ends the same way, and the reconcile re-attempts with that value instead of degrading for a missing one; a refusal of that value takes the env/vault branch (:3112-3113), which is on the backoff — never held.
  6. The husk carries the hold (carried over). registerDegradedConnector (plugin-extension-api.ts :363-380) spreads degradedHold: hold into the RegisteredConnector; both hold sites pass it ({ kind: 'declaration' } at :2589, and stored ? { kind: 'credential', ref: stored.ref } : { kind: 'declaration' } at :3126); getConnectorDegradedHold (engine.ts :4189-4192) reads it back only while state === 'degraded'. A later unheld degrade of the same name (the cleared-credential path of ①.5, registerDegradedConnector at :2740 with no hold) replaces the record without degradedHold, which is what "goes back on the backoff" means for the dispatch refusal.
  7. The refusal wording is PR fix(service-automation): a dispatch to a held connector instance names its fix, not a retry #28037's, verbatim (carried over). connector-nodes.ts :75-84 and describeHold (plugin-extension-api.ts :401-403). The note's two quoted held strings and its one quoted backoff string are those, character for character (the second held string abbreviated with an ellipsis and a placeholder for the reference name, which is fair), and connector-held-dispatch-refusal.test.ts :106, :119, :135 pins them.
  8. Delta (d), the placeholder — now a code span, and it renders literally (should-fix 2 of the first record, folded). At :221 the reference placeholder sits in a code span inside the plain quotes. Rendered with micromark 4.0.2 (CommonMark) and marked 16.4.2 (gfm: true), the new line yields a code element whose text is the escaped placeholder, so the page reads "until credential 'ref-placeholder' is set again" with the placeholder visible; the first head's bare spelling rendered as a raw HTML tag in marked (which GitHub's sanitizer drops, as the first record said). CommonMark §6.1 is the rule: HTML is not parsed inside a code span. The spelling now matches the corpus (ADR-0079 :141, ADR-0116 :50, ADR-0137 :63).
  9. Anchors: seven added at the first head, none since, all resolve, and the gate holds them. Local probe on this head: 2850 anchors, 630 symbol (604 declaration, 26 literal), 2173 file-level, 47 cross-repo, exit 0 — the same figures as the first head and as the dev reports; base 27e0bd584 2843 / 623 (597, 26) per the first record. The delta adds no anchor (git diff shows no new backticked path). The Lint · docs & code guards check-run, the job that runs check:adr-symbol-anchors, is success on this head.
  10. adr-index: no change owed. node scripts/adr-index.mjs on this head prints "unchanged docs/adr/README.md (235 lines)" and the porcelain is empty; Lint · repo & tooling gates, the job that runs check:adr-index, is success on this head.
  11. Citations, numbers and dates (carried over, untouched by the delta). service-automation: a configuration fault first seen on a degraded connector's backoff retry is logged and skipped, but the instance stays degraded with the stale "could not reach" reason and keeps retrying every 5 minutes #27992 / PR fix(service-automation): end the backoff retry of a degraded connector on a configuration fault #28014 (merged 2026-10-30T08:38Z, 066ff51e2), connectors: sys_connector_credential + open-tier resolver chain (env → credential object → vault), reconcile on credential change, install-local prompt for missing credentialRefs (ruling A on #27230) #27237 (closed 2026-10-29), automation: a held connector instance (a configuration fault or a refused stored credential) still tells a dispatch "the platform retries automatically", and the connectors page has no row for a configuration fault met on a retry #28016 / PR fix(service-automation): a dispatch to a held connector instance names its fix, not a retry #28037 (merged 2026-10-30T10:36Z, b59bf60c8) — all ancestors of the base or closed before the amendment's date; the card's "not before PR fix(service-automation): a dispatch to a held connector instance names its fix, not a retry #28037 merges" condition is met.
  12. PR body declarations (carried over; see ③ for the stale Verification head). Fixes #28038 on its own line; no closing keyword beside any other card number. Clause-②: no, Metadata-protocol: none; the six ## 维护者速读 lines present. Labels documentation, size/s, skip-changeset; author objectstack-fleet[bot]; draft; base main.
  13. Register. check-governed-merges.mjs --pr 28161 on this head: 1 of 1 path hits (docs/adr/**), GOVERNED, Tier H, 29 changed lines (+28 / −1) under the human-merge threshold.

② Semver level

No release. skip-changeset is right: the diff publishes nothing from any released package (one ADR file under docs/adr/, which no package's files[] ships); no changeset family is derived for a docs-only diff. On this head the Check Changeset check-run is skipped rather than success: the synchronize run's payload already carries the skip-changeset label, so the job's if: fast path (pr-automation.yml :308-309, the skip-changeset opt-out its comment at :266 names) skips it without a runner, where the first head's success came from the labeled event's run. Same verdict, cheaper path. Clause-②: no is right; no narrowing is declared or present.

③ Boundary flags

  • Dev flags: no open_questions. The three declared deviations of the first record stand unchanged ((1) skip-changeset carried on pr_create, accepted; (2) dispatch-gates --tier reads docs/adr/** as a MANDATORY fable tier while the dev ran on opus/medium — this record is the compensating CONTRACT_REVIEW_TIER review; (3) pnpm lint not run locally — Lint · ESLint is success on this head). The two fold commits carry the same trailers as the first.
  • Independence: the delta was produced by session_016WV4cypdG8XcEafFNG2EFa on claude/project-thread-8t7yh8 (the card thread's platform-assigned branch, the recorded exception the claim names); this record is rendered by session_016WV4d1QkPVVzNz3FJqb2iS, which did not draft it. Claim comment 6526256844 names this session and this head; no competing claim, hold or hand-off; no reviews on the PR.
  • Author: PR user.login is objectstack-fleet[bot]; no non-bot login to record.
  • Tier: H by the register (docs/adr/**); the maintainer or a GOVERNED_APPROVERS review lands it. Draft PR; nothing to disarm.
  • CI (41 check-runs on this head, all completed at the last poll, 2026-10-30T15:21Z): 25 success, 16 skipped by path or design, 0 failure, 0 in progress. Success includes both required jobs (Lint & Repo Gates, TypeScript Type Check) and their sub-jobs: Lint · repo & tooling gates (runs check:adr-index), Lint · docs & code guards (runs check:adr-symbol-anchors), Lint · ESLint, Lint · PM dispatch-gates, Lint · CI, release & engine gates, the three Lint · scoped jobs, Type Check · workspace, · source gates, · consumer gates, · debt ledger; plus Test Core and Test Core (1/8), Test UI, Plan Test Core shards, PR-body guards, Governed Surface Queue Guard, Dogfood Regression Gate, Check PR Size, Check Documentation Links, Auto Label, filter. Skipped: Check Changeset (the label opt-out, ②), the UI build, lint, type-check and test shards, Build Docs, Build Core, Build UI Deps, Temporal Conformance, Dogfood Verify CLI, UI Published Artifacts, the opt-in harnesses, the schedule gate, the UI Live E2E. The first head's 46 were the same set plus the opened and labeled event runs' duplicates. The all-green condition for landing is met on this head.
  • PR body versus head: the body's Verification section still says "All readings at head f4345a9d", and its "What changes" bullets paraphrase the first head's wording (the "first met on a backoff retry" clause, the "only an edit ..." sentence, the bare placeholder). The relay cannot patch a PR body. This does not matter for landing: every number the body cites was re-measured on this head here and is identical (anchors 2850 / 630, check:adr-index unchanged, GOVERNED 1 of 1, 21 dispatch-gates families — Lint · PM dispatch-gates is success on this head); the only figure that moved is the line count, +25 to +28, which the body states nowhere as a number (the size/s label is live); and the governed text a maintainer approves is the diff, not the body's paraphrase of it. Recorded here so the stale head cite is read as stale and not as a claim about this head.
  • Not re-run here: the dev's 21 dispatch-gates families (read from the report; Lint · PM dispatch-gates is success on this head); the service-automation test suite (the wording is read from the test file and from the source it exercises, not executed); the base reading of the anchor gate (the first record's, at the same base).

④ Design judgment

Rules face, docs/adr/0097-declarative-connector-instances.md, against its first consumer and its execution plan:

  • Prime Directive [WIP] Add Chinese version of the documentation #13 and the ADR's own convention — hold. The three degraded-section bullets (:186-197) are context lines in the diff, byte for byte; the note opens by saying the first and third "are kept as written; they now hold only for an instance on the backoff", so the recorded sentences stand and the amendment sits beside them. The form is this file's own: a blockquote paragraph opening with the bold Amendment note (date, #card — provenance). head, the spelling of all five prior notes in 0097, placed directly under the bullets it qualifies. The Amended by header entry follows the three existing entries' shape. The Status line is right to be unchanged: this ADR's Status has never carried an amendment, unlike ADR-0066; the convention is per file. The delta keeps all of this: it edits only the note's inside.
  • First consumer. The reader deciding what a degraded instance's dispatch refusal means now reads a section that is true against origin/main as a definition and not only as an instance: the hold is anchored to the two sites that set it with the guard's own two paths, the two skips, the four ways out (edit, set again, clear, restart) with the mechanism for each, the husk's carrier and the two refusal spellings. The seven anchors bind the prose to the symbols: a rename or move of any of them turns check:adr-symbol-anchors red, which is what the card asked for.
  • Execution plan. Nothing is left to implement: the mechanism (PR fix(service-automation): end the backoff retry of a degraded connector on a configuration fault #28014, connectors: sys_connector_credential + open-tier resolver chain (env → credential object → vault), reconcile on credential change, install-local prompt for missing credentialRefs (ruling A on #27230) #27237) and the wording (PR fix(service-automation): a dispatch to a held connector instance names its fix, not a retry #28037) are on main and the amendment records them after the fact. The clearing sentence adds no mechanism; it names one connectors.mdx :341-342 and clearConnectorCredential's docblock already state.
  • No contradiction elsewhere (carried over, re-checked for the new sentence). The first record's git grep over skills/**, content/docs/** and docs/adr/** stands (no sentence promises a retry for every degraded instance). The new clearing sentence agrees with connectors.mdx :341-342 ("DELETE removes the stored value. The instances naming the reference are torn down and registered degraded again") and with the 2026-10-28 §6 note's unresolved-credentialRef-on-the-backoff reading. The observation outside this PR stands: ADR-0143's revoked-grant "not retried into existence" is a third not-retried kind with no code on main today (should-fix 3).
  • Rendering. Folded; ①.8.
  • The tier deviation. The diff is 28 lines of prose; this review read every cited symbol, the two routing sites around them, the clear and set paths end to end, the test that pins the wording, and the two docs surfaces that restate the rule, all at origin/main. Nothing in the diff is under-reviewed because of the model the dev ran on.
  • Cited code was read to judge the prose, not reviewed.

Implemented-by: claude/project-thread-8t7yh8
Reviewed-by: session_016WV4d1QkPVVzNz3FJqb2iS

VERDICT: PASS

Must-fix: none.

Should-fix:

  1. Folded at ea406edf (precision: the configuration-fault hold is entered on the backoff retry or on a reload reconcile; the cleared-credential way out is now stated) and 1a9e3f73 (the "Only" the new sentence contradicted is dropped). Verified at ①.3 and ①.5; nothing further owed.
  2. Folded at ea406edf (the reference placeholder in the second quoted held string is inside a code span). Verified at ①.8; nothing further owed.
  3. (carrier: the ADR-0143 grant mechanism, not this PR) When a revoked or never-authorized grant lands as a degraded-not-retried instance, its carrier owes 0097's "Upstream availability" section the hold kind it uses (ConnectorHold has declaration and credential today) or a sentence placing it on the backoff, so the held-versus-backoff dichotomy this note records stays complete.

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:skills#2 · os-elon-musk · session_016WV4d1QkPVVzNz3FJqb2iS

维护者速读

席位意见:ACCEPT。契约复核分两轮:

  • 首轮在 f4345a9d 上 PASS,提了两条 should-fix:重载时也会 held;尖括号占位符在 GitHub 上渲染成空。
  • 本席没有直接贴首轮记录,而是让卡线程先把这两条修进同一段注,再做增量复核(1a9e3f73),结果 PASS,没有 must-fix。
  • 复核逐句对过代码:held 只在 failDegradedConnectorInstance 和 holdConnectorForRejectedCredential 两处设置;scheduleDeclarativeRetry 会跳过 held 实例;清掉凭据会改变指纹,之后走 degradeConnectorForCredential,不设 held,所以回到 backoff。
  • 报错文本和 PR fix(service-automation): a dispatch to a held connector instance names its fix, not a retry #28037 发布的逐字一致。

席位核对

  • 形态: one PR, Fixes #28038, one file docs/adr/0097-declarative-connector-instances.md (+28 −1), skip-changeset. check-governed-merges.mjs --pr 28161: GOVERNED, Tier H (1 of 1 path).
  • 前提实测: PR fix(service-automation): end the backoff retry of a degraded connector on a configuration fault #28014 merged 2026-10-30T08:38Z (066ff51e2) and PR fix(service-automation): a dispatch to a held connector instance names its fix, not a retry #28037 merged 2026-10-30T10:36Z (b59bf60c8); both are ancestors of the base. connectors: sys_connector_credential + open-tier resolver chain (env → credential object → vault), reconcile on credential change, install-local prompt for missing credentialRefs (ruling A on #27230) #27237 is closed. The three degraded bullets are context lines, byte for byte. Symbol anchors: head 630 vs base 623, and the +7 are all declarations.
  • 门禁 check-runs: head 1a9e3f73a2bdc9ea3f196a907e9a37d317d91bda: 41 check-runs, 25 success, 16 skipped, 0 failed. Lint & Repo Gates and TypeScript Type Check are success. Check Changeset is skipped because the synchronize event already carries skip-changeset. The dev report shows 21 of 21 derived gate families exit 0.
  • 接受的偏差: two.
    • Dev model and effort: dispatch-gates --tier gives fable/xhigh for docs/adr/**, but this card was developed on opus/medium per the seat's order. Two fable review rounds make up the depth; the review judged that nothing is under-reviewed.
    • The PR body's Verification still cites the first head, because the relay cannot patch PR bodies. Every number in it was re-measured on this head and is unchanged.
  • 范围外去向: review should-fix 3 is carried by ADR-0143's revoked-grant mechanism. That mechanism has no code yet; when it lands, it owes 0097 a third kind of hold. There is no new card.
  • 落地条款: Tier H. The seat posts the record and this ACCEPT, adds needs-user-decision, and requests os-zhuang and hotlong. After a governed approver's APPROVED review on this head and green CI, the PR goes ready and into the queue, and the seat clears needs-user-decision. Maintainer's landing grant for this term: seat thread, 2026-10-29 22:04Z.

@os-zhuang
os-zhuang marked this pull request as ready for review October 31, 2026 02:30
@os-zhuang
os-zhuang enabled auto-merge October 31, 2026 02:30
@os-zhuang
os-zhuang added this pull request to the merge queue Oct 31, 2026
Merged via the queue into main with commit 6285203 Oct 31, 2026
50 checks passed
@os-zhuang
os-zhuang deleted the claude/project-thread-8t7yh8 branch October 31, 2026 02:39
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 skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants