Skip to content

fix(sdk): preserve contract errors through safe() and isDefinedError - #1692

Merged
rickylabs merged 21 commits into
mainfrom
fix/sdk-typed-error-channel
Aug 23, 2026
Merged

fix(sdk): preserve contract errors through safe() and isDefinedError#1692
rickylabs merged 21 commits into
mainfrom
fix/sdk-typed-error-channel

Conversation

@rickylabs

@rickylabs rickylabs commented Aug 23, 2026

Copy link
Copy Markdown
Owner

Closes #1350

Preserves NetScript's exact six-code contract error union through safe() and isDefinedError(), and
removes this leaf's own private-type-ref regressions from the published surface.

Supersedes PR #1671 — same branch, same author thread, same work. See Provenance.

⚠️ Breaking change — 0.0.7, not patch-level

Published surface in @netscript/sdk and @netscript/contracts changes. The type:fix label and the
fix(...) prefixes on the early commits do not soften this; the disclosure commits carry docs(sdk)!
with BREAKING CHANGE: footers.

Surface Before After
SafeFailure / SafeResult failure payload second tuple slot and data were null both are undefined
SafeFailure arms one arm, isDefined: boolean two literal-discriminated arms, isDefined: false / isDefined: true
Default error type SafeFailure/SafeResult defaulted TError to unknown; safe<TOutput> had no TError parameter and inherited that default all three default TError to Error
ServiceClientMethod <TInput, TOutput> returning Promise<TOutput> <TInput, TOutput, TError = Error> returning Promise<TOutput> & { __error?: { type: TError } }; the phantom marker is what lets safe() recover TError
safe(promise) input PromiseLike<TOutput> Promise<TOutput> & { __error?: … } — non-Promise thenables now fail TS2345; wrap with Promise.resolve(...)
isDefinedError return error is Extract<T, DefinedError> narrowed via an inlined Extract<…> & DefinedError
baseContract error-map key space open exactly the six declared literals; comparing error.code to an undeclared code is now a type error

Migration. Change failure.data === null to failure.data === undefined, or prefer the
discriminated form (result.isSuccess, then result.isDefined). Branch on the literal rather than
typing isDefined as boolean. Wrap non-Promise thenables. Annotate explicitly if you relied on
TError = unknown. The tuple form is not removed — both arms remain tuple-and-object
intersections, so destructuring still works.

surface:diff does not corroborate this and must not be cited as a clean surface result: deno doc
drops the instantiation argument from the new baseContract annotation, so the tool stopped reporting
its signature change (undeclared majors 532 → 531). That is a tooling false negative.

Scope at head 686bae07b2bc66353b2eec9dd56baa0779a63a20

Four source/test paths, one derived artifact, two docs pages, plus run artifacts:

  • packages/contracts/src/application/contract-primitives.ts
  • packages/sdk/src/client/errors.ts
  • packages/sdk/src/ports/service-client.ts
  • packages/sdk/tests/readme-doctest_test.ts
  • packages/mcp/src/infrastructure/export-surfaces/export-surface-corpus.generated.ts (regenerated; delta is 5 @netscript/sdk signature changes, 0 added/removed exports)
  • docs/site/services-sdk/sdk.md, docs/site/services-sdk/how-to/discover-services.md

packages/contracts/src/public/mod.ts is not touched. No metadata vocabulary, no lint suppressions,
no docs/site/reference/ page.

The baseContract annotation

ReturnType<typeof oc.errors> collapses the type parameter to its ErrorMap upper bound and erases the
six literal codes — the defect this issue exists to repair. A ContractBuilder<…> annotation preserved
them but put three oRPC private types into a published signature. This uses a TypeScript instantiation
expression
, ReturnType<typeof oc.errors<{…exact map…}>>, which keeps the parameter instantiated so
the six codes survive while naming no oRPC builder type; ContractBuilder is no longer imported.

Exposing ContractBuilder/Schema/BaseContractErrors from the public barrel was measured and
withdrawn: it takes packages/contracts/mod.ts from 10 to 21 private-type-ref diagnostics and
turns docs:exports-drift red.

Prerequisite #1691 (merged)

check:mcp-export-corpus was already red on main@9634735bc0 before this branch existed. Regenerating
inside this PR would have made it the carrier for 9 exports belonging to @netscript/ai and
@netscript/prisma-adapter-mysql. That repair landed separately as #1691
(61bfd858d20f3bf61e7ee45b5646537af567f247); this branch is rebased onto it and the rebase introduced no
content change.

Definition of Done

Acceptance evidence — all seven #1350 boxes

issue: 1350
entries:
  - box: "Real `safe()` and `isDefinedError()` exports carry the error generic and `SafeResult` discriminates on `isDefined`."
    evidence: "errors.ts at 686bae07b2bc66353b2eec9dd56baa0779a63a20 declares SafeFailure<TError = Error> as two literal-discriminated arms (isDefined false / true) and safe<TOutput, TError = Error>; IMPL-EVAL claim 1 CONFIRMED with the six codes re-derived from source rather than from the test constant: https://github.com/rickylabs/netscript/pull/1692#issuecomment-5385128267"
  - box: "`ServiceClientMethod` preserves the contract error channel into `safe()`."
    evidence: "service-client.ts at 686bae07b2bc66353b2eec9dd56baa0779a63a20 declares ServiceClientMethod<TInput, TOutput, TError = Error> returning a promise carrying the __error phantom marker that lets safe() recover TError; IMPL-EVAL claims 1 and 7 CONFIRMED: https://github.com/rickylabs/netscript/pull/1692#issuecomment-5385128267"
  - box: "`baseContract` preserves exactly the six declared error-map keys without adding public barrel exports or private-type-reference debt."
    evidence: "contract-primitives.ts at 686bae07b2bc66353b2eec9dd56baa0779a63a20 annotates baseContract as ReturnType<typeof oc.errors<exact six-key map>> with ContractBuilder no longer imported and packages/contracts/src/public/mod.ts untouched; contracts doc-lint 9 equals base 9 and baseContract's only private-type reference is the pre-existing pinned oc; the barrel-exposure alternative was measured at 10 to 21 diagnostics and withdrawn; IMPL-EVAL claims 2 and 3 CONFIRMED: https://github.com/rickylabs/netscript/pull/1692#issuecomment-5385128267"
  - box: "A real-export type fixture proves `error.code` narrows to the six-code union, rejects a removed/undeclared code, and keeps non-defined values from narrowing."
    evidence: "readme-doctest_test.ts Equal<> assertions with IsAny and [never] guards pass at 686bae07b2bc66353b2eec9dd56baa0779a63a20, and the same assertion fails TS2344 plus TS2571 and TS2339 against base 61bfd858d20f3bf61e7ee45b5646537af567f247, proving it is non-vacuous; IMPL-EVAL claim 1 CONFIRMED: https://github.com/rickylabs/netscript/pull/1692#issuecomment-5385128267"
  - box: "The SDK reference and discovery examples compile as written, explain the migration, and the README doctest contains no local helper shims."
    evidence: "docs:snippets exit 0 at 686bae07b2bc66353b2eec9dd56baa0779a63a20 with migration tables on both docs/site/services-sdk pages and no local helper shims in the doctest; amendment review raised A1 to A4 (https://github.com/rickylabs/netscript/pull/1692#issuecomment-5385236468), S8 commit 8e568e49f corrected them, and the delta re-review returned PASS with no new findings: https://github.com/rickylabs/netscript/pull/1692#issuecomment-5385289186"
  - box: "Contracts and SDK checks/tests/lint/fmt, JSR specifier checks, publish dry-runs, docs export drift, doc-lint parity, and deterministic export-corpus checks pass at the exact PR head."
    evidence: "All at exact head 686bae07b2bc66353b2eec9dd56baa0779a63a20: deno check 0 errors across contracts/mod.ts, contracts/crud.ts and sdk/mod.ts; suites 78 passed 0 failed; lint contracts 0 and sdk 0; doc-lint parity contracts 9 equals 9 and sdk 3 equals 3; JSR specifier guard scanned 2361 with 0 failures; publish dry-run contracts exit 0 and sdk exit 0; docs:exports-drift PASS exit 0; check:mcp-export-corpus PASS exit 0 with sha256 a8f0779228987ed7 unchanged since S6; and after the S9 generated-cascade regeneration check:agent-docs-prose, check:assets-barrel and check:publish-assets all PASS exit 0, with the cascade independently reproduced byte-identical"
  - box: "A fresh opposite-family IMPL-EVAL passes and all merge-blocking findings are resolved at an exact reviewed head."
    evidence: "Fresh opposite-family IMPL-EVAL (Fable 5 against the Codex author) at bcc9f393d993cd5468015c883c8b0dc6a5b6dc62 returned PASS: https://github.com/rickylabs/netscript/pull/1692#issuecomment-5385128267; dispositions - F1 to the PR body, both docs pages and docs(sdk)! BREAKING CHANGE footers, F2 into the breaking table, F3 and F5 into issue 1693, F4 rewritten in exported vocabulary in sdk.md, F6 stated as a tooling false negative; amendment review https://github.com/rickylabs/netscript/pull/1692#issuecomment-5385236468 then delta re-review PASS on A1 to A4 with no new findings at 7a880c01804d566c28424f3b70254a296fdd3f15: https://github.com/rickylabs/netscript/pull/1692#issuecomment-5385289186"

Provenance

PR #1671 carried slices S1–S5 and was closed unmerged at 2026-08-23T08:18:03Z as an unintended side
effect of merging #1691, whose body contained a literal closing keyword token inside a sentence
disclaiming one — GitHub's parser matches the token and does not read negation. #1671 was never merged.
Reopening was refused because the branch had since been rebased. No work was lost: same branch, same
commit history, same author thread.

Status

Draft. Not ready for merge: readiness, labels, and issue checkboxes are the coordinator's to flip.

rickylabs and others added 10 commits August 23, 2026 10:18
Separate-session Fable 5 medium evaluation of PR #1671 plan head 2fa2f71.
Verdict PASS with five non-blocking advisories.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015RuDy1h3UiCkLzo1PLk5Sc
…correction map

Maps all 13 new leaf-owned deno-doc-lint private-type-ref findings from S4
(contracts 3, SDK 10) to individual type-safe corrections, verified against
isolated deno doc --lint probes and the real @orpc/* .d.ts files. 12 of 13
resolve cleanly (SDK 10/10; contracts BaseContractErrors + Schema); one
(baseContract -> ContractBuilder) is reported unresolved pending a
coordinator ruling rather than planned around. Run-artifact-only: no
product/test/docs/lock file touched.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TYBPuyVoK8Bc8926DfnPah
@rickylabs rickylabs added this to the 0.0.7 milestone Aug 23, 2026
rickylabs added a commit that referenced this pull request Aug 23, 2026
…replaced by #1692; S6 dispatched

Records plainly that merging #1691 closed #1671 because the body I wrote
contained the literal token 'close #1671' inside a sentence disclaiming it -
GitHub matches the token and does not read negation. Lesson: never write the
literal closing token even to deny it.

Rebase onto 61bfd85 replayed all ten commits with zero conflicts and proven
byte-identical leaf content. #1692 opened as the replacement at 9cdba63.

Gates re-executed at the new head all green. The S6 corpus precondition now
PASSES - 0 added/removed exports, 5 changed signatures all @netscript/sdk and
all already approved - so S6 was dispatched to the same author thread.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XmfcnZVCo7NfkhWBuToAiV
@rickylabs

Copy link
Copy Markdown
Owner Author

[PHASE: IMPL]

S6 regenerated the derived MCP export corpus for the five approved SDK signature changes and stopped at pushed head bcc9f393d993cd5468015c883c8b0dc6a5b6dc62. Immutable generated-content commit: b427e035488e5eabd9f3a92870787006aa9a6813.

Scope

  • Product mutation: exactly packages/mcp/src/infrastructure/export-surfaces/export-surface-corpus.generated.ts, generated by deno task gen:mcp-export-corpus; no hand edit.
  • Existing run artifacts updated: worklog.md, context-pack.md, and drift.md.
  • The four S5 source/test paths and deno.lock remain byte-identical to the S6 starting head.
  • No second S6 product path, runtime lease, Aspire, Docker, e2e:cli, issue/label/checkbox/readiness, or merge action.

Structured evidence

{
  "gateId": "mcp-export-corpus-determinism",
  "outcome": "PASS",
  "exitCode": 0,
  "runs": 2,
  "byteIdentical": true,
  "generatedFileSha256": "f7bbc8925481e8682f84f9057263387030838e6bc7ee366c56e98a9b2829f904",
  "embeddedCorpusSha256": "a8f0779228987ed7e304dc032d45d1488b0cfb651b088d563c1e17fbafa2fb0b"
}
{
  "gateId": "mcp-export-corpus-semantic-delta",
  "outcome": "PASS",
  "schemaVersionUnchanged": true,
  "frameworkVersionUnchanged": true,
  "surfacesUnchanged": true,
  "addedExports": 0,
  "removedExports": 0,
  "changedSignatureCount": 5,
  "changedSignatures": [
    "@netscript/sdk:.#SafeFailure",
    "@netscript/sdk:.#SafeResult",
    "@netscript/sdk:.#ServiceClientMethod",
    "@netscript/sdk:.#isDefinedError",
    "@netscript/sdk:.#safe"
  ]
}
{
  "gateId": "check:mcp-export-corpus",
  "gitHead": "b427e035488e5eabd9f3a92870787006aa9a6813",
  "actualGitHead": "b427e035488e5eabd9f3a92870787006aa9a6813",
  "waiver": null,
  "outcome": "PASS",
  "exitCode": 0,
  "packageCount": 35,
  "subpathCount": 270,
  "symbolCount": 7611
}
{
  "gitHead": "b427e035488e5eabd9f3a92870787006aa9a6813",
  "actualGitHead": "b427e035488e5eabd9f3a92870787006aa9a6813",
  "waiver": null,
  "gates": [
    {
      "gateId": "mcp-scoped-lint",
      "outcome": "RED_PRE_EXISTING_TOOLING",
      "exitCode": 1,
      "findings": 0,
      "failure": "Failed to parse workspace configuration"
    },
    {
      "gateId": "mcp-scoped-fmt",
      "outcome": "RED_PRE_EXISTING_TOOLING",
      "exitCode": 1,
      "findings": 0,
      "failure": "Failed to parse workspace configuration"
    }
  ]
}

The lint/format wrappers reproduce the accepted exit-1/zero-findings tooling red. Their local structured detail is an early workspace-configuration parse failure, not a source finding, and no suppression or source change was attempted.

Next

  • Generator stops here. Fresh Tier-A and opposite-family IMPL-EVAL remain separate coordinator-owned steps.

rickylabs added a commit that referenced this pull request Aug 23, 2026
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XmfcnZVCo7NfkhWBuToAiV
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@rickylabs

rickylabs commented Aug 23, 2026

Copy link
Copy Markdown
Owner Author

[PHASE: IMPL-EVAL] [VERDICT: PASS]

Evaluated head: bcc9f393d993cd5468015c883c8b0dc6a5b6dc62 · original verdict at that head: PASS-WITH-FINDINGS (2026-08-23). This comment is edited in place by coordinator ruling to record the terminal state; the original verdict and its evidence are preserved verbatim below. PASS on the first line reflects that every finding has since been dispositioned — it does not retcon the original result.

Evaluator: Claude Fable 5 · medium, fresh native session, own detached worktree. Generator: Codex gpt-5.6-sol (thread 01a006f3).

Product content: packages/, plugins/, deno.lock are byte-identical from bcc9f393d through the final head 587ade9f30e619410a4192daadab137b0548eb88 (verified at each review step); all gate results below describe the final head exactly.

Disposition of findings

Finding Severity Disposition Verified by
F1 — breaking disclosure only in harness artifacts Medium PR body breaking table + both docs/site/services-sdk/ pages' "Migrating to 0.0.7" sections + docs(sdk)! commits 29c9e40aa, 8e568e49f with BREAKING CHANGE footers amendment review at 7b0024967 (comment 5385236468)
F2 — safe() rejects non-Promise thenables, undisclosed Low Enumerated in the PR body breaking table and both docs tables (TS2345, Promise.resolve remedy) same
F3 — ThrowableError → Error foreclosure, no pointer Low Tracked in #1693 gh issue view 1693 OPEN, drift.md cites it
F4 — typed-unreachable / runtime-reachable isDefined arm Low Documented in sdk.md "Bare promises and the defined-error arm", rewritten in exported vocabulary per A3 delta review (comment 5385289186)
F5 — A4-advisory debt "tracked" with no entry Low Tracked in #1693; drift.md contradiction resolved amendment review
F6 — surface:diff 532→531 is a deno doc false negative Info Stated in the PR body as a tooling false negative; not cited as a clean result. Not present in the docs pages (0 hits), which is appropriate — it is a repo-tooling note, not consumer guidance grep -ci 'false negative' PR body = 1; docs = 0
A1–A4 — amendment-text under-claims / precision Low/Info Corrected in S8 8e568e49f; delta re-review PASS on A1–A4, no new findings delta review, comment 5385289186

Review trail: IMPL-EVAL at bcc9f393d (this comment) → amendment review at 7b0024967 (comment 5385236468, ACCEPT-WITH-FINDINGS) → delta review at 7a880c018 (comment 5385289186, PASS). Artifacts: impl-eval.md (1772dfdf9), amendment-review.md (34eb1f524), amendment-review-delta.md (587ade9f3), all under .llm/runs/fix-sdk-typed-error-channel--0.0.7-wave1/.

Scope of this evaluator: no merge, labels, readiness, checkboxes, #1348/#1466 mutation, or runtime lease were touched at any step.


Original IMPL-EVAL at bcc9f39 — PASS-WITH-FINDINGS (verbatim, unedited)

IMPL-EVAL — PR #1692 (#1350 sdk-typed-error-channel)

Field Value
Head evaluated bcc9f393d993cd5468015c883c8b0dc6a5b6dc62
Base main@61bfd858d20f3bf61e7ee45b5646537af567f247 (merge-base confirmed equal)
Evaluator Claude Fable 5 · medium, fresh native session, worktree netscript-007-eval-1692
Generator Codex gpt-5.6-sol (opposite family)
Base control detached worktree /tmp/ns-eval-base at the base SHA (read-only; removed afterwards)
Archetype Archetype 1 — small contract, docs overlay

Verdict

PASS-WITH-FINDINGS (harness vocabulary: PASS; no FAIL_* condition is met).

Blocking for a later status:ready-merge flip, not for this draft head: F1 (breaking-change
disclosure is absent from every consumer-visible record — PR body, commit messages, docs pages).
Everything else is non-blocking.

Head identity

git rev-parse HEAD                                  → bcc9f393d993cd5468015c883c8b0dc6a5b6dc62
git ls-remote origin fix/sdk-typed-error-channel    → bcc9f393d993cd5468015c883c8b0dc6a5b6dc62
gh pr view 1692 --json headRefOid                   → bcc9f393d993cd5468015c883c8b0dc6a5b6dc62
git merge-base HEAD 61bfd858d                       → 61bfd858d20f3bf61e7ee45b5646537af567f247

Diff stat vs base: 15 paths — 8 run artifacts, 4 source/test, 1 generated corpus, 2 docs pages.
packages/contracts/src/public/mod.ts is not in the diff (claim 3 holds).

Claims tested

1. Six-code union preserved; assertion non-vacuous — CONFIRMED

Codes re-derived from source (awk over the commonErrorMap literal in
contract-primitives.ts, not from the test's constant):
NOT_FOUND|VALIDATION_ERROR|UNAUTHORIZED|FORBIDDEN|RATE_LIMITED|SERVICE_UNAVAILABLE.

Independent probe (my own file, imports @netscript/contracts + packages/sdk/mod.ts, asserts
Equal<keyof baseContract['~orpc']['errorMap'], Src>, IsAny=false, [never]=false, and the same
union on safe().error.code and isDefinedError()-narrowed error.code):

Run Result
head, probe deno check exit 0
head, probe with one code removed TS2344 Type 'false' does not satisfy 'true', exit 1
base worktree, same probe TS2344 + TS2571 unknown + TS2339 'code' on never, exit 1

The base failure texts are exactly the two RED texts PLAN-EVAL advisory A1 predicted.

2. Doc-lint at exact baseline parity — CONFIRMED

deno run --allow-read --allow-write --allow-run .llm/tools/run-deno-doc-lint.ts --root packages/<p>:

Package head totalPrivateTypeRef base totalPrivateTypeRef
contracts 9 9
sdk 3 3

Raw deno doc --lint packages/contracts/mod.ts at head: the only baseContract diagnostic is
references private type 'oc' (contract-primitives.ts:120:14). sdk's 3 are QueryClient refs,
pre-existing.

3. No public-barrel growth — CONFIRMED

git diff --stat 61bfd858d..HEAD does not list packages/contracts/src/public/mod.ts.
deno task docs:exports-driftExports & Symbols drift check: PASS, exit 0.

4. Corpus delta leaf-owned only — CONFIRMED (decoded, not file-diffed)

Decoded both gzip/base64 corpora (7611 entries each) and compared on
(packageName, subpath, symbol, kind):

ADDED []   REMOVED []   CHANGED 5
  @netscript/sdk . SafeFailure         typeAlias  signature
  @netscript/sdk . SafeResult          typeAlias  signature
  @netscript/sdk . ServiceClientMethod typeAlias  signature
  @netscript/sdk . isDefinedError      function   signature
  @netscript/sdk . safe                function   signature
surfaces equal: True   frameworkVersion 0.0.6 == 0.0.6

deno task gen:mcp-export-corpus re-run at head: decoded output identical to the committed
artifact (regen decoded == committed decoded: True); file restored afterwards.

5. Breaking-change disclosure at full strength — PARTIAL → F1

The surface:diff 532 → 531 signal is recorded as a tooling false negative, not banked:
worklog.md:1366-1368 ("drops the instantiation argument, so the signal is a known tooling false
negative"). Independently confirmed: the decoded corpus renders baseContract as
const baseContract: ReturnType<oc.errors> at head — identical to the base rendering — so the tool
cannot see the change.

The strength problem is location. The breaking verdict exists only in harness artifacts
(plan.md §"Breaking-change verdict", worklog.md S4/S5 sections). Executed searches:

| Record | Grep for break|undefined|null|migrat|major|semver | Hit |
| -------------------------------------------------------------- | ---------------------------------------------------- | --- |
| PR #1692 body (gh pr view 1692 --json body) | none | 0 |
| 12 leaf commit messages + bodies (git log 61bfd858d..HEAD) | none; no ! or BREAKING CHANGE footer | 0 |
| docs/site/services-sdk/sdk.md, how-to/discover-services.md | none | 0 |
| sole PR comment (2026-08-23T08:34:38Z) | only "waiver": null in JSON | 0 |

The PR carries type:fix, the commits are fix(sdk)/fix(contracts), and the docs pages replace the
old const [error, result] = await safe(...) idiom with the new result.isSuccess/isDefined idiom
without saying the old shape (data: null, single isDefined: boolean arm, TError = unknown)
is gone. plan.md:251 requires "Declare breaking change explicitly … document migration".

6. ThrowableError → Error — ACCEPTABLE, recorded

grep -rn "declare module '@orpc/shared'|throwableError" packages plugins → 0 hits; Registry
is un-augmented, so ThrowableErrorError today. "Leaf-new" holds in the sense that matters:
at base the published default was TError = unknown; ThrowableError was only ever a plan-level
choice (PLAN-EVAL A3), never published, so no JSR consumer can depend on it. Moving Error → ThrowableError later is additive for every consumer that has not augmented Registry. Recorded as
a declared design decision in worklog.md:1166-1170. No finding beyond F3 (no follow-up pointer).

7. Bounded couplings (__error?: { type: E } inlined) — ACCEPTABLE

Inlined shape is Promise<T> & { __error?: { type: E } }, duplicated in errors.ts and
service-client.ts. Judgement: this is a two-property phantom marker, not a reconstructed class —
the asymmetry with rejecting a local ContractBuilder reconstruction (many generics + method
surface) is defensible and does not meet AP-1/AP-9. Drift behaviour if oRPC renames the marker:
TError inference silently degrades to the Error default — but the in-tree
readme-doctest_test.ts Equal<typeof discriminated.error.code, ExpectedBaseErrorCode> assertion
turns TS2344, and claim-1 probe above shows that assertion is live. The drift risk is therefore
detected by a gate, not only "named".

Gates executed at head (structured wrappers; raw exit codes)

Gate Result Exit
run-deno-check.ts --root packages/sdk --root packages/contracts 105 files, 0 findings 0
run-deno-check.ts --root packages/fresh (only out-of-leaf consumer of isDefinedError) 197 files, 0 findings 0
run-deno-test.ts -- --allow-all packages/sdk/tests packages/contracts 77 passed / 0 failed 0
run-deno-lint.ts (sdk+contracts) 0 findings 0
run-deno-fmt.ts --ext ts,tsx (sdk+contracts) 0 findings 0
deno publish --dry-run --allow-dirty in packages/contracts Dry run complete 0
deno publish --dry-run --allow-dirty in packages/sdk Dry run complete 0
deno task docs:exports-drift PASS 0
run-deno-doc-lint.ts contracts / sdk, head vs base 9/9, 3/3
gen:mcp-export-corpus regen vs committed (decoded) identical 0

Known pre-existing reds (packages/mcp fmt/lint batch, surface:diff ~531 majors, F-DOCT-5) were
not re-run and are not attributed to the leaf.

Process checks

  • PLAN-EVAL: plan-eval.md verdict PASS (commit e78f87b12) precedes the first
    implementation commit 5d348fbc8 in ancestry. OK.
  • Design checkpoint: worklog.md §"Design" (public surface, vocabulary, ports, constants, slices,
    deferred scope, contributor path). Slices S1–S6 match plan "Commit slices". OK.
  • Out-of-leaf consumers: only packages/fresh/src/diagnostics/error/extract.ts imports
    isDefinedError; type-checks clean. No repo source asserts SafeFailure.data === null.
  • arch-debt delta: none (no doctrine violation introduced; see F5 for the A4 advisory).
  • Close-gate: PR is draft; [sdk-client S1] fix(sdk): preserve contract errors through safe() and isDefinedError #1350 boxes not assessed for ticking (out of this pass's remit).
  • ## SKILL chapters: the run dir stores no agent briefs, so this cannot be verified from artifacts
    (grep -c "## SKILL" .llm/runs/…/*.md → 0 in every file). Recorded as unverifiable, not as a
    finding against the generator.

Findings

ID Severity Finding Evidence
F1 Medium (blocks ready-merge, not this draft) Breaking-change disclosure exists only in plan.md/worklog.md. PR body, all 12 commit messages, and both docs pages contain no breaking/migration statement; PR is labelled type:fix, commits are fix(...) with no !/BREAKING CHANGE. plan.md:251 requires explicit declaration + migration notes. greps in §5 above; gh pr view 1692 --json body
F2 Low safe() parameter narrowed from PromiseLike<TOutput> to Promise<TOutput> & { __error?: … }; non-Promise thenables are now rejected. Not enumerated anywhere as a consumer-visible break (only the base signature is quoted at plan-eval.md:97). probe declare const p: PromiseLike<number>; safe(p)TS2345 … not assignable to 'Promise<number> & { __error?: …}', exit 1
F3 Low ThrowableError → Error foreclosure is recorded in worklog.md:1166-1170 but has no follow-up pointer (issue/debt) for the day Registry.throwableError augmentation becomes wanted. grep -rn throwableError packages plugins → 0; worklog lines cited
F4 Low For an untyped Promise<T> (TError defaults to Error), the isDefined: true arm types error as never (Extract<Error, DefinedErrorLike>), while createSafeFailure can still return isDefined: true at runtime if an ORPCError with defined: true rejects that promise. Typed-unreachable, runtime-reachable branch. The leaf's own _PlainErrorRejectedFromDefinedArm asserts this typing deliberately and sdk.md documents the intent; noting it because it is a behavioural difference from the base's isDefined: boolean arm. errors.ts:141-148 (runtime); readme-doctest_test.ts _PlainErrorRejectedFromDefinedArm
F5 Low PLAN-EVAL advisory A4 asked for an arch-debt.md/issue entry so the bench-prose follow-up is literally "tracked". drift.md:35-36 states "No new file or debt entry was created; the coordinator owns any later issue" while drift.md:25 still says "remains tracked follow-up debt". Not a doctrine violation by this leaf, so not FAIL_DEBT; the word "tracked" is currently unbacked. drift.md:25,35-36; git diff --stat shows no debt file change
F6 Info surface:diff 532→531 on baseContract is a deno doc rendering loss (ReturnType<oc.errors> at both base and head in the decoded corpus). Correctly recorded as a false negative in worklog.md:1366-1368; must not be cited as a clean surface result at cut time. corpus decode above

What I did not do

No product, test, docs, or label mutation. No merge, readiness flip, checkbox, #1348/#1466 change,
or runtime lease. Scratch probes were created under packages/sdk/tests/__eval1692/ and removed;
git status is clean apart from this artifact. /tmp/ns-eval-base worktree removed after use.

rickylabs added a commit that referenced this pull request Aug 23, 2026
…f repaired

Fable 5 medium evaluator confirmed six of seven claims with executed evidence,
including a three-way control stronger than this topic's own. Claim 5 became
F1: breaking-change disclosure existed only in harness artifacts.

F1's PR-body half was mine - I wrote #1692's replacement body and omitted the
disclosure - and is now repaired with a full breaking table, migration notes,
and the explicit statement that surface:diff must not be cited as
corroboration. F2 is enumerated there too.

Commit messages and docs pages remain unrepaired and need a coordinator ruling;
F3/F4/F5 open with recommendations. Readiness not flipped.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XmfcnZVCo7NfkhWBuToAiV
Document the consumer migration path and the bare-Promise defined-arm characteristic. Link the deferred prose and ThrowableError substitution follow-up.

BREAKING CHANGE: SafeFailure/SafeResult failure payload changes null -> undefined, default TError changes unknown -> Error, and safe() no longer accepts non-Promise thenables. Pre-1.0 intentional break; not patch-compatible. See PR #1692.

Refs #1693
@rickylabs

Copy link
Copy Markdown
Owner Author

[PHASE: IMPL]

S7 closes the consumer-documentation half of IMPL-EVAL finding F1 and stops at pushed head 7b00249673bf1eaac5af14f000869e378b999c71. Immutable consumer-doc content commit: 29c9e40aad391381e79afa92a6052cbcd07d9a4a.

Scope and disclosure

  • Updated only docs/site/services-sdk/sdk.md, docs/site/services-sdk/how-to/discover-services.md, and the existing worklog.md, context-pack.md, and drift.md run artifacts.
  • Both pages now declare 0.0.7 an intentional pre-1.0 breaking change that is not patch-compatible.
  • Both pages cover failure null -> undefined, TError: unknown -> Error, the three-generic ServiceClientMethod and its __error phantom marker, the narrowed safe() Promise parameter and TS2345 thenable migration, discriminated result handling, and continued tuple compatibility.
  • The SDK hub documents the bare-Promise characteristic: the isDefined: true arm has error: never statically but remains runtime-reachable for a rejecting defined ORPCError; typed access requires a contract-typed service-client promise.
  • The drift record now points the deferred prose debt and accepted ThrowableError -> Error decision to sdk/contracts: record the ThrowableError substitution decision and back the deferred bench-prose debt #1693.
  • Content commit 29c9e40aa carries docs(sdk)!, a BREAKING CHANGE: footer, and Refs #1693. Existing commits were not rewritten.

Structured evidence

{
  "gateId": "docs:snippets",
  "gitHead": "29c9e40aad391381e79afa92a6052cbcd07d9a4a",
  "actualGitHead": "29c9e40aad391381e79afa92a6052cbcd07d9a4a",
  "outcome": "PASS",
  "exitCode": 0,
  "scanned": 581,
  "tier1": 36,
  "checked": 22,
  "exempt": 14,
  "malformed": 0
}
{
  "gateId": "docs-source-format",
  "gitHead": "29c9e40aad391381e79afa92a6052cbcd07d9a4a",
  "actualGitHead": "29c9e40aad391381e79afa92a6052cbcd07d9a4a",
  "waiver": null,
  "outcome": "PASS",
  "exitCode": 0,
  "durationMs": 223,
  "requestHash": "b92bd2a4471968dd3d58219ab2200a368a2fca2703fce03206a12105d23142cf"
}
{
  "gateId": "docs-accuracy",
  "gitHead": "29c9e40aad391381e79afa92a6052cbcd07d9a4a",
  "actualGitHead": "29c9e40aad391381e79afa92a6052cbcd07d9a4a",
  "waiver": null,
  "outcome": "PASS",
  "exitCode": 0,
  "durationMs": 8640,
  "requestHash": "743dcd4a345037ec14c817c7f3bed19febdcf2a664570e9bdab2fc1dc8ff5cd6",
  "existingNonBlockingWarning": "@tanstack/ai-preact peer @tanstack/ai constraint mismatch"
}
{
  "gates": [
    {
      "gateId": "docs:exports-drift",
      "outcome": "PASS",
      "exitCode": 0
    },
    {
      "gateId": "check:mcp-export-corpus",
      "outcome": "PASS",
      "exitCode": 0,
      "unchanged": true,
      "sha256": "a8f0779228987ed7e304dc032d45d1488b0cfb651b088d563c1e17fbafa2fb0b"
    },
    {
      "gateId": "s7-packages-scope",
      "command": "git diff --name-only 1772dfdf9f26a9c7ed76f196e93505732696fb30..HEAD -- packages/",
      "outcome": "PASS",
      "exitCode": 0,
      "paths": []
    }
  ],
  "denoLock": "BYTE_IDENTICAL",
  "exportCorpusGeneratedFile": "BYTE_IDENTICAL"
}

docs:accuracy is reported only for the invariants implemented by that script; it is not used as proof of the page-level migration narrative.

Next

  • Generator stops here. The separate opposite-family focused amendment review remains coordinator-owned.

…0249

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@rickylabs

Copy link
Copy Markdown
Owner Author

Amendment review (F1/F3/F4/F5 closure) — ACCEPT-WITH-FINDINGS

Head reviewed: 7b00249673bf1eaac5af14f000869e378b999c71 · prior IMPL-EVAL PASS-WITH-FINDINGS at bcc9f393d unchanged · packages/+plugins/ byte-identical to bcc9f393d (verified)
Reviewer: Claude Fable 5 · medium, fresh native session. Artifact commit 34eb1f524 (artifact-only, pushed).

Full review (verbatim artifact)

Amendment review — PR #1692, F1/F3/F4/F5 closure

Field Value
Head reviewed 7b00249673bf1eaac5af14f000869e378b999c71
Prior verdict IMPL-EVAL PASS-WITH-FINDINGS at bcc9f393d (impl-eval.md, 1772dfdf9) — unchanged
Scope Amendment commits 29c9e40aa, 7b0024967 only. Not a second IMPL-EVAL.
Reviewer Claude Fable 5 · medium, fresh native session, own detached worktree
Generator Codex gpt-5.6-sol, thread 01a006f3

Verdict

ACCEPT-WITH-FINDINGS. F1 is closed to the standard plan.md:251 set (consumer-visible
declaration + migration, in both pages, PR body, and a !/BREAKING CHANGE commit). F3/F5 are
closed by #1693. F4 is documented as a characteristic. Two under-claims remain in the docs tables
(A1, A2) and two precision defects (A3, A4); none re-opens F1, all are page-text fixes.

Head and scope verification

git rev-parse HEAD                               → 7b00249673bf1eaac5af14f000869e378b999c71
git ls-remote origin fix/sdk-typed-error-channel → 7b00249673bf1eaac5af14f000869e378b999c71
gh pr view 1692 headRefOid / isDraft             → 7b0024967… / draft=true
git diff --name-only 1772dfdf9 HEAD -- packages/ plugins/ | wc -l   → 0
git diff --quiet bcc9f393d HEAD -- packages/ plugins/               → exit 0 (byte-identical)
git diff --name-status 1772dfdf9 HEAD → 3 run artifacts + sdk.md + discover-services.md

The product tree is byte-identical to the evaluated S6 head, so the original product gate results
(impl-eval.md gate table) describe this head exactly.

Receipts re-run at this head

Command Result Exit
deno task check:mcp-export-corpus sha256 a8f0779228987ed7e304dc032d45d1488b0cfb651b088d563c1e17fbafa2fb0b (== S6) 0
deno task docs:exports-drift PASS 0
deno task docs:links docs=103 broken-links=0 broken-anchors=0 0
deno task docs:accuracy PASS 0
deno task docs:snippets 0 failures (2 informational partial-snippet notes, unrelated pages) 0

Markdown fmt of docs/site — not gated; not claimed by the supervisor; not claimed here.

Item-by-item

1. F1 closure — CLOSED, with two under-claims

Both pages carry a "Migrating … to 0.0.7" section (sdk.md:265-282, discover-services.md:178-195)
with identical five-row tables. Coverage of the six required points:

Required point sdk.md discover-services.md
payload null → undefined, tuple slot and data row 1 row 1
default TError unknown → Error row 2 row 2
ServiceClientMethod gains TError + __error marker row 3 row 3
safe() PromiseLike → Promise, TS2345, Promise.resolve remedy row 4 row 4
tuple → discriminated migration row 5 row 5 (→ Step 4, heading exists at line 137)
pre-1.0 intentional break / not patch-compatible lead sentence lead sentence

Over-claim check: both pages state "The tuple form has not been removed … destructuring still
works." Correct — every arm in errors.ts is […] & {…}. No over-claim.

PR body: "⚠️ Breaking change — not patch-level" section with a six-row table, migration paragraph,
and the surface:diff false-negative caveat. Present.

A consumer reading only these pages is warned about the five listed surfaces. They are not warned
about two changes that plan.md §"Breaking-change verdict" and the PR body itself enumerate — see
A1 and A2.

2. F4 closure — CLOSED, one precision defect

sdk.md:251-262 "Bare promises and the defined-error arm": states TError falls back to Error,
the isDefined: true arm types error as never, the arm is runtime-reachable when a
defined: true ORPCError rejects a bare promise, calls it "a deliberate characteristic", and gives
the practical remedy (pass a promise carrying contract error typing). Matches errors.ts:141-148
and _PlainErrorRejectedFromDefinedArm. Not framed as a bug. See A3 on naming.

3. F3 + F5 closure — CLOSED

gh issue view 1693 → OPEN, "sdk/contracts: record the ThrowableError substitution decision and
back the deferred bench-prose debt", type:chore, status:triage, priority:p3, area:sdk, milestone
Backlog / Triage. drift.md now points at #1693 in both the "tracked" sentence and the
former "no debt entry was created" sentence; the :25 vs :35-36 contradiction is resolved (the
"tracked" claim is now backed by an issue). Commit 29c9e40aa carries Refs #1693.

4. Commit hygiene — SUFFICIENT

git log -1 --format=%B 29c9e40aa: subject docs(sdk)!: …, body contains a
BREAKING CHANGE: footer naming payload null → undefined, default unknown → Error, and the
thenable rejection, plus "Pre-1.0 intentional break; not patch-compatible." With the PR body table,
a squash or a changelog generator keyed on !/BREAKING CHANGE will surface the break. Leaving the
twelve earlier fix(...) commits unrewritten is acceptable under that ruling; the branch-level
signal exists once, which is what conventional-commit tooling needs.

Findings (amendment text only)

ID Severity Finding Evidence
A1 Low (under-claim) Neither docs table lists the SafeFailure arm change (single arm with isDefined: boolean → two literal-discriminated arms). The PR body has this row; the pages do not. A consumer who typed failure.isDefined as boolean or narrowed on a single arm gets no page-level warning. git diff 1772dfdf9 HEAD -- docs/site — no row mentions isDefined: boolean; PR body row 3 does
A2 Low (under-claim) Neither page nor the PR body lists the baseContract key-space tightening — plan.md:110-112: "intentionally rejects consumers that treated undeclared codes as valid." Consumers comparing error.code against an undeclared string now get a TS error; this is a deliberate break the plan named and the disclosure omits. plan.md:105-114; grep -n "undeclared" docs/site/services-sdk/*.md docs/site/services-sdk/how-to/*.md → 0
A3 Low (precision) sdk.md:254-257 names DefinedErrorLike and createSafeFailure, neither of which is exported (grep DefinedErrorLike|createSafeFailure packages/sdk/mod.ts packages/sdk/src/client/mod.ts → 0), and cites a test file path. A consumer cannot resolve these names; the explanation should be in terms of the published SafeFailure arms. grep above
A4 Info (precision) Docs row 2 says safe "defaulted TError to unknown" — at base safe<TOutput> had no TError parameter at all (git show 61bfd858d:packages/sdk/src/client/errors.ts); the unknown came from SafeResult's default. PR body row 6 says the old isDefinedError return was error is DefinedError; it was error is Extract<T, DefinedError> (same file, line 75). Both are "before" descriptions that are slightly wrong in the direction of overstating the change. git show 61bfd858d:packages/sdk/src/client/errors.ts lines 75, 86

Not done

No product, test, or docs edits; no merge, label, checkbox, readiness, #1348/#1466 mutation, or
runtime lease. This file is the only change in my worktree.

@rickylabs rickylabs added ci:full breaking Introduces a breaking change and removed ci:full labels Aug 23, 2026
Add the SafeFailure literal-arm and baseContract key-space breaks, correct the historical safe signature, and express bare-Promise behavior only through exported SDK vocabulary.

BREAKING CHANGE: SafeFailure now has literal defined and non-defined arms, and baseContract rejects error codes outside its six declared literals. This extends the documented 0.0.7 pre-1.0 migration; it is not patch-compatible. See PR #1692.

Refs #1693
@rickylabs

Copy link
Copy Markdown
Owner Author

[PHASE: IMPL] S8 — amendment-review prose corrections A1–A4

S8 is complete and pushed. Exact branch head: 7a880c01804d566c28424f3b70254a296fdd3f15. The breaking-marked immutable content head tested by every gate is 8e568e49f3b4cff21ead698591abce2db0ec5f5c; the following commit changes only existing run artifacts.

Corrections:

  • A1: both migration tables now disclose the change from one SafeFailure arm with isDefined: boolean to literal false and true arms, including the required consumer branching migration.
  • A2: both tables now disclose the intentional baseContract tightening to exactly NOT_FOUND | VALIDATION_ERROR | UNAUTHORIZED | FORBIDDEN | RATE_LIMITED | SERVICE_UNAVAILABLE; undeclared comparisons are now type errors.
  • A3: the bare-promise characteristic now uses only exported SafeFailure, safe, isDefinedError, and DefinedError vocabulary. Private names and the test path are gone.
  • A4: both tables now state precisely that old safe<TOutput> had no TError parameter and inherited unknown from SafeResult<TOutput>.

The exact sentence “The tuple form has not been removed” remains on both pages. The docs commit is docs(sdk)!: and carries the required BREAKING CHANGE: footer plus Refs #1693.

Structured verdicts at gitHead == actualGitHead == 8e568e49f3b4cff21ead698591abce2db0ec5f5c, with no waiver:

{"gateId":"check:mcp-export-corpus","outcome":"PASS","exitCode":0,"unchanged":true,"sha256":"a8f0779228987ed7e304dc032d45d1488b0cfb651b088d563c1e17fbafa2fb0b","packageCount":35,"subpathCount":270,"symbolCount":7611}
{"gateId":"s8-packages-plugins-scope","outcome":"PASS","exitCode":0,"paths":[],"denoLock":"BYTE_IDENTICAL","exportCorpusGeneratedFile":"BYTE_IDENTICAL"}
{"gateId":"docs:snippets","outcome":"PASS","exitCode":0,"scanned":581,"tier1":36,"checked":22,"exempt":14,"malformed":0}
{"gateId":"docs:accuracy","outcome":"PASS","exitCode":0,"invocationId":"sdk-typed-error-s8-docs-accuracy","durationMs":8275,"requestHash":"248e287e45996f0342949331ff5c4dc2bc3869f435fd6e5e4f49dbf6ba62a36e","summary":"199 published source pages; 91/91 root/direct public commands from 149 recursive paths"}
{"gateId":"docs:links","outcome":"PASS","exitCode":0,"docs":103,"brokenLinks":0,"brokenAnchors":0,"orphans":0}
{"gateId":"docs:exports-drift","outcome":"PASS","exitCode":0,"summary":"Exports & Symbols drift check: PASS"}

docs:accuracy also emitted the existing non-blocking peer warning: @tanstack/ai-preact expects @tanstack/ai ^0.41.0, resolved 0.39.1; it is not attributed to this docs-only slice.

Base-to-head mutation is exactly the two authorized docs pages plus existing worklog.md, context-pack.md, and drift.md. packages/ and plugins/ are empty in the S8 diff; deno.lock and the generated corpus are byte-identical. No PR metadata, supervisor prose, issue, runtime, evaluator, readiness, or merge action was touched.

Stopping for the coordinator-owned opposite-family A1–A4 delta re-review.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@rickylabs

Copy link
Copy Markdown
Owner Author

Amendment delta review (A1–A4) — PASS

Head reviewed: 7a880c01804d566c28424f3b70254a296fdd3f15 · packages/+plugins/+deno.lock unchanged since 34eb1f524 and byte-identical to bcc9f393d (verified) · prior verdicts unchanged.
Reviewer: Claude Fable 5 · medium. Artifact commit 587ade9f3 (artifact-only, pushed).

Full delta review (verbatim artifact)

Amendment review delta — PR #1692, A1–A4 prose repair (S8)

Field Value
Head reviewed 7a880c01804d566c28424f3b70254a296fdd3f15
Scope A1–A4 from amendment-review.md only. F1/F3/F4/F5 and the IMPL-EVAL verdict are not re-opened.
Reviewer Claude Fable 5 · medium, own detached worktree. Generator: Codex gpt-5.6-sol thread 01a006f3.

Verdict

PASS on A1, A2, A3, A4. No over-claim or under-claim found in the corrected text. No new finding.

Head and scope

git rev-parse HEAD / git ls-remote origin fix/sdk-typed-error-channel / PR headRefOid
                                                        → 7a880c018… (all three), draft=true
git diff --name-only 34eb1f524 HEAD -- packages/ plugins/ deno.lock | wc -l   → 0
git diff --quiet bcc9f393d HEAD -- packages/ plugins/ deno.lock                → exit 0
git diff --name-status 34eb1f524 HEAD → 3 run artifacts + sdk.md + discover-services.md

Receipts re-run at this head, all exit 0: check:mcp-export-corpus sha256
a8f0779228987ed7e304dc032d45d1488b0cfb651b088d563c1e17fbafa2fb0b (unchanged since S6);
docs:exports-drift PASS; docs:links broken-links=0 broken-anchors=0; docs:accuracy PASS;
docs:snippets exit 0. Markdown fmt of docs/site not gated, not claimed.

A1 — SafeFailure arm change — PASS

Both tables (sdk.md "Migrating to 0.0.7", discover-services.md "Migrating typed-error handling
to 0.0.7") gained the row SafeFailure arms: before = "one failure arm with isDefined: boolean";
after = "two literal-discriminated arms, isDefined: false and isDefined: true", with the
consumer consequence "code that typed the property as a general boolean or treated failure as one
undifferentiated arm must branch on the literal". Base anchor checked:
git show 61bfd858d:packages/sdk/src/client/errors.ts line 39 — [TError, null, boolean, false].
Accurate.

A2 — baseContract key-space tightening — PASS

Both tables gained the row baseContract error codes. Six literals in the page match the
commonErrorMap keys derived from contract-primitives.ts by awk:
NOT_FOUND,VALIDATION_ERROR,UNAUTHORIZED,FORBIDDEN,RATE_LIMITED,SERVICE_UNAVAILABLE (identical
lists). Framed as both benefit ("intentional typo/undeclared-code protection") and break ("a
breaking tightening").

The "before" claim — "undeclared codes remained type-valid" — verified at base in a throwaway
worktree: const k: keyof typeof baseContract['~orpc']['errorMap'] = 'NOT_DECLARED'
deno check exit 0 at 61bfd858d. At head the same assignment is rejected (claim-1 probe in
impl-eval.md, Extract<'NOT_DECLARED', …> = never). Accurate.

A3 — exported vocabulary only — PASS

grep -c "DefinedErrorLike\|createSafeFailure\|readme-doctest\|_PlainErrorRejected\|NarrowDefined\|NonDefinedSafeFailure\|DefinedSafeFailure\|orpcIsDefinedError" → 0 in both pages (the
last four are the remaining private names in errors.ts; none was swapped in). The rewritten
passage names only SafeFailure, DefinedError, safe, isDefinedError — all exported from
packages/sdk/src/client/mod.ts:16-17. Substance retained: isDefined: true arm of
SafeFailure<Error> types error as never; runtime-reachable when a DefinedError rejects a
bare promise; remedy = pass a promise carrying contract error typing. Matches errors.ts:141-148.

A4 — historical signature precision — PASS

Both tables now read: "SafeFailure and SafeResult defaulted TError to unknown;
safe<TOutput> had no TError parameter and returned SafeResult<TOutput>, inheriting that
default." Base check: errors.ts at 61bfd858d line 39 (SafeFailure<TError = unknown>), line 49
(SafeResult<TOutput, TError = unknown>), line 86 (safe<TOutput>(…): Promise<SafeResult<TOutput>>).
Accurate. Neither page repeats the isDefinedError "before" wording (grep -c "error is DefinedError"
→ 0 in both); that half remains in the PR body, which the supervisor owns — not flagged here.

Preserved

grep -n "has \*\*not\*\* been removed"sdk.md:279, discover-services.md:193. Present.

Commit

8e568e49fdocs(sdk)!: subject; BREAKING CHANGE: footer names the literal-arm change and the
undeclared-code rejection; Refs #1693. Consistent with the page text.

Not done

No product/test/docs edits; no merge, label, checkbox, readiness, #1348/#1466 mutation, or runtime
lease. Throwaway base worktree /tmp/ns-base2 removed. This file is the only change.

rickylabs added a commit that referenced this pull request Aug 23, 2026
…ent rewritten

Delta re-review terminal PASS on A1-A4. All receipts re-executed at the exact
final head rather than carried over.

PR #1692 body rewritten completely and verified live: exactly one closing
keyword (Closes #1350), 9/9 DoD checked, 7 acceptance BOX entries citing real
comment ids, zero stale head references. Includes A4's second half, which was
this topic's to fix - base isDefinedError returned error is Extract<T,
DefinedError>.

#1671 comment 5304357008 rewritten in place: it pinned a rebased-away head,
recorded the refuted barrel-exposure ruling as adopted, and listed now-green
gates as NOT_RUN. Original preserved beneath a divider.

Evaluator asked to rewrite its own IMPL-EVAL comment in place, with the
closing-token trap stated explicitly.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XmfcnZVCo7NfkhWBuToAiV
@rickylabs rickylabs added impl-eval:skip Skip automatic ready-for-review IMPL-EVAL with attributed evidence status:ready-merge and removed status:impl labels Aug 23, 2026
@rickylabs
rickylabs marked this pull request as ready for review August 23, 2026 09:36
S7 and S8 changed the two SDK documentation pages consumed by the agent-docs prose bundle. Regenerate the canonical prose, provenance, CLI barrel, and publish assets; every changed file is generator output.
@rickylabs

Copy link
Copy Markdown
Owner Author

[PHASE: IMPL] S9 — regenerate the agent-docs generated cascade

S9 is complete and pushed. Exact branch head: 686bae07b2bc66353b2eec9dd56baa0779a63a20. Immutable generated-content head tested by every gate: 120172c466bf6a3d18da80012145347072377513; the following commit changes only existing run artifacts.

The coordinator-specified cascade ran twice in dependency order with no hand edits:

  1. deno task gen:agent-docs-prose
  2. deno task gen:assets-barrel
  3. deno task gen:publish-assets

Measured changed paths:

  • .llm/assets/agent-docs/prose.json.gz
  • .llm/assets/agent-docs/provenance.json
  • packages/cli/src/kernel/assets/agent-docs.generated.ts
  • packages/mcp/src/publish-assets.generated.ts

Determinism proof:

{"path":".llm/assets/agent-docs/prose.json.gz","pass1":"5082cf83b11ddfe64ac26f1c37c719074c55e244382ade26d310861b53348df0","pass2":"5082cf83b11ddfe64ac26f1c37c719074c55e244382ade26d310861b53348df0"}
{"path":".llm/assets/agent-docs/provenance.json","pass1":"fee682e73c243a207fd8e83557d5a96a62acf95f7ec1f3c14294e3908289e8b7","pass2":"fee682e73c243a207fd8e83557d5a96a62acf95f7ec1f3c14294e3908289e8b7"}
{"path":"packages/cli/src/kernel/assets/agent-docs.generated.ts","pass1":"b838cd7505b10ba0f24c0da3c8836ceed1a9ab1e975168d1fc0bbdd20b05246a","pass2":"b838cd7505b10ba0f24c0da3c8836ceed1a9ab1e975168d1fc0bbdd20b05246a"}
{"path":"packages/mcp/src/publish-assets.generated.ts","pass1":"5fec4b20254a3fa9fa7d1f0dad4bdad10b00d41e9737da96711a2956f5ca90c3","pass2":"5fec4b20254a3fa9fa7d1f0dad4bdad10b00d41e9737da96711a2956f5ca90c3"}

Structured verdicts at gitHead == actualGitHead == 120172c466bf6a3d18da80012145347072377513, with no waiver:

{"gateId":"agent-docs-prose","invocationId":"sdk-typed-error-s9-agent-docs-prose","outcome":"PASS","exitCode":0,"durationMs":12160,"requestHash":"9c24d015c0c7d72d724e0e4010be07cf3c7faae01ccbdd6c2c57e2d0549275a8","fresh":true,"stalePaths":[]}
{"gateId":"assets-barrel","invocationId":"sdk-typed-error-s9-assets-barrel","outcome":"PASS","exitCode":0,"durationMs":717,"requestHash":"57ec4456cfbca0a889aba6c5d395bf015da244e36140a98b93871567ee4c5a39"}
{"gateId":"publish-assets","invocationId":"sdk-typed-error-s9-publish-assets","outcome":"PASS","exitCode":0,"durationMs":315,"requestHash":"a10cf114c57501fc9d391b35a009d7beca76250784c361472f77f6ac0bf17f8b"}
{"gateId":"check:mcp-export-corpus","outcome":"PASS","exitCode":0,"unchanged":true,"sha256":"a8f0779228987ed7e304dc032d45d1488b0cfb651b088d563c1e17fbafa2fb0b","generatedFileSha256":"f7bbc8925481e8682f84f9057263387030838e6bc7ee366c56e98a9b2829f904","packageCount":35,"subpathCount":270,"symbolCount":7611}
{"gateId":"docs:exports-drift","outcome":"PASS","exitCode":0,"summary":"Exports & Symbols drift check: PASS"}
{"gateId":"contracts-sdk-tests","outcome":"PASS","exitCode":0,"durationMs":5601,"passed":78,"failed":0,"ignored":0,"totalResults":78}

deno.lock is unchanged at SHA-256 edfa0c24b70e0d830acce68aad6f5da42b66a88527aef4b80f3f82d989d1820c. The MCP export corpus did not move, so no regeneration or decoded delta was required. No docs source, tests, non-generated package source, metadata, issue, checkbox, label, readiness, merge, evaluator, or runtime action was performed.

At S9 start PR #1692 was externally observed as ready with sole status:ready-merge, despite the brief describing it as draft. S9 forbids readiness and label mutations, so this generator left that supervisor-owned state untouched.

Stopping for separate review and coordinator-owned CI/readiness handling.

@rickylabs
rickylabs merged commit c73d361 into main Aug 23, 2026
21 checks passed
@rickylabs
rickylabs deleted the fix/sdk-typed-error-channel branch August 23, 2026 09:59
rickylabs added a commit that referenced this pull request Aug 23, 2026
Merged 2026-08-23T09:58:53Z as c73d361 from
source head 686bae0. origin/main verified at the merge commit. #1350 CLOSED/
COMPLETED with 7/7 boxes; both #1350 and #1692 reconciled to a single
status:shipped label.

Keeps five lane lessons for the next run, including that a negated closing
keyword still closes a PR, and that two consecutive grep-precision near-misses
would each have filed a false finding against a correct author.

Worktrees and branches intentionally left in place - coordinator owns cleanup.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XmfcnZVCo7NfkhWBuToAiV
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:sdk packages/sdk breaking Introduces a breaking change impl-eval:skip Skip automatic ready-for-review IMPL-EVAL with attributed evidence priority:p1 High status:shipped type:fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[sdk-client S1] fix(sdk): preserve contract errors through safe() and isDefinedError

1 participant