page:docs-specs-platform-gaps-phase1-pkg-01-exports
WP-PKG-01 record: exports maps for all 43 publishables + exactness verifier reference
Executed 2026-09-29 on branch phase1/rename-train of a5c-ai/fabric (base 3beee69a6, the WP-PKG-02 head; draft PR 4 open, CI on every push). Spec: docs/specs/platform-gaps/40-packaging.md §2.1 (exports-map program), §2.3 (publics documentation) and "WP-PKG-01" (objective, affected paths, acceptance criteria, test requirements); spec 15 §1.2 invariants and §5 rule 6 (exports maps ride the RN-1 train); intent 00-intent.md D10 (break freely, major bump — in-repo consumers migrated in the same effort). Builds on rn-05-rename.md (names), rn-06-bins.md (collision-free bin set, consumed here) and pkg-02-versioning.md (7.0.0 lockstep train).
WP-PKG-01 record: exports maps for all 43 publishables + exactness verifier
Executed 2026-09-29 on branch phase1/rename-train of a5c-ai/fabric (base 3beee69a6, the WP-PKG-02 head; draft PR #4 open, CI on every push). Spec: docs/specs/platform-gaps/40-packaging.md §2.1 (exports-map program), §2.3 (publics documentation) and "WP-PKG-01" (objective, affected paths, acceptance criteria, test requirements); spec 15 §1.2 invariants and §5 rule 6 (exports maps ride the RN-1 train); intent 00-intent.md D10 (break freely, major bump — in-repo consumers migrated in the same effort). Builds on rn-05-rename.md (names), rn-06-bins.md (collision-free bin set, consumed here) and pkg-02-versioning.md (7.0.0 lockstep train).
The public repository a5c-ai/babysitter was never written to: gh api repos/a5c-ai/babysitter --jq .pushed_at → 2026-09-16T19:59:50Z at start and end (only GET calls were issued); git remote -v → upstream no_push (push). Nothing was published to any registry, no tag was created, no PR was opened.
1. Policy (encoded once, in `scripts/lib/exports-map.cjs`)
Shared by the packed-artifact verifier (scripts/verify-release-artifacts.mjs, step exactness), the in-repo resolver check (scripts/ci/exports-exactness.cjs) and the publics page generator, so the PR gate and the release gate read the same map the same way:
| Rule | Meaning |
|---|---|
no-exports-map | a publishable without exports has an unbounded surface (every dist/ module deep-importable) |
wildcard-export | no * in any key or target ("./*" reproduces the unbounded surface with extra steps, spec 40 §2.1) |
root-missing | "." is required unless the package is bin-only (then the map is closed: only ./package.json) |
package-json-not-exported | ./package.json → ./package.json always (tooling reads manifests through the map; three in-repo imports do) |
types-not-first | types is the first condition wherever a conditions object carries one (TypeScript stops at the first match) |
legacy-field-mismatch | main/module must be targets of "."; types must equal the "." types target |
typesversions-wildcard / typesversions-not-exported | typesVersions maps only exported subpaths, never a pattern (the "*" version selector is the standard exception) |
target-missing | every declared target exists on disk (PR check) and in the packed tarball (release gate). CI triage round 1: the PR check runs in the publish-isolation job on an UNBUILT checkout (before npm ci), so build output that is absent altogether in a package with a build script is a counted deferral to the release gate (exports-exactness: N declared target(s) in M unbuilt package(s) deferred …), not a finding; a present-but-incomplete dist/, a package without a build script, or a target outside any directory is still refused on disk |
subpath-not-exported / root-not-exported | an in-repo import (from, import(), require(), require.resolve(), vitest/jest mock helpers) that a workspace package's map does not resolve |
publics-missing / publics-drift | docs/reference/package-publics.md must equal the rendering of the maps |
Node's resolution semantics are followed where they matter (exact subpath keys, condition objects in declaration order, arrays as fallbacks, null as a block); patterns are refused, never matched.
2. Surface table: package → exported subpaths → probe that must fail
Derived from evidence, never guessed: every @fabricstack/<pkg>/<subpath> string in an import context across packages/ apps/ library/ scripts/ e2e-tests/ plugins/ blueprints/ (3,303 workspace imports resolved by the scanner), the bins' own entry points, documented subpaths (docs/, package READMEs, JSDoc @examples) and the pre-existing typesVersions/main/module/types fields. The full per-package table (subpaths, the data-driven negative probe and the local matrix verdict) is generated from the verifier reports in §5; the decisions are:
| Family | Packages | Map | Evidence / decision |
|---|---|---|---|
| hooks (CJS) | 12 × @fabricstack/harness-hooks-* (core, cli, 10 adapters) | "." {types, require, default} + ./package.json | no in-repo consumer imports a subpath of any hooks package; the CLI's bin (dist/cli/main.js) is executed, not imported |
| extensions (ESM) | harness-extensions | "." {types, import, default} + ./package.json | root-only consumers; bin dist/cli.js executed; its own verify:release gate asserts main/types unchanged (kept) |
| orchestrator SDK (CJS) | orchestrator-sdk | ".", ./cli, ./config, ./runtime, ./testing, ./package.json (+ typesVersions for the four subpaths) | see §3 |
| bin-only | orchestrator, observer | closed: ./package.json only | no importable root exists (files = bin/ / dist/cli.js + Next app); the executable is the consumer surface; bin/ and dist/ are now unimportable (probed) |
| control-plane | control-plane | "." → ./src/index.js (kept) + ./package.json | no subpath consumers; bins import ../src relatively |
| already mapped | 19 packages (agent-runtime-*, catalog, console-*, harness-* others, model-gateway, operator, trust) | existing subpath sets kept; ./package.json added where missing | every existing subpath was checked against actual deep-import usage (e.g. catalog/catalog ×93, harness-core/kanban ×12, agent-runtime-core/trust ×15) — none was unused-but-harmful, none was missing |
| fixes on existing maps | harness-observability; catalog | types first (+ default); typesVersions["*"]["catalog/*"] removed | ordering rule; the wildcard mapping had no consumer (@fabricstack/catalog/catalog/<x> is imported nowhere; the private atlas/webui tsconfig paths entry maps to source and is unaffected) |
harness-sdk (the spec's "exports only ." example): checked against deep-import usage — the only subpath consumer was @fabricstack/harness-sdk/package.json (a test), now satisfied by the added ./package.json; no other subpath is used, so the map stays "." + ./package.json.
Storage/journal and breakpoint seams the spec mentions as examples (§2.1) are reachable through the SDK root (src/index.ts re-exports ./storage, ./breakpoints); no consumer or sibling spec imports them as subpaths, so they were **not** minted — adding a subpath is a one-line, guarded change when a WP cites one.
3. Deep imports of now-private paths: every site and its decision
| Site | Before | Decision |
|---|---|---|
packages/babysitter/bin/babysitter.js:8 (the orchestrator metapackage shim) | require("@fabricstack/orchestrator-sdk/dist/cli/main.js") | **made public deliberately** as ./cli (→ dist/cli/main.js, the SDK's own bin entry; mirrors agent-runtime-cli/cli and operator/cli). Shim requires @fabricstack/orchestrator-sdk/cli; its missing-SDK detection now matches the package name with either path separator, because a map-resolved missing file reports the absolute path (Cannot find module 'C:\…\orchestrator-sdk\dist\cli\main.js') while an absent package reports the bare specifier |
packages/babysitter/bin/__tests__/exit-codes.packaged.test.js | stub SDK written to node_modules/@a5c-ai/babysitter-sdk (rename miss: the shim's specifier never resolved there), no exports | stub moved to node_modules/@fabricstack/orchestrator-sdk with the real map shape (".", ./cli, ./package.json); cli-missing mode keeps the map and omits the file — the broken-install shape. Not runnable here (before hook: GNU tar reads the absolute C:\… as a remote host, pre-existing, test:babysitter-metapackage runs in CI) |
packages/genty/platform/src/harness/internal/createRun/orchestration/index.ts:128 and src/orchestration/defaultOrchestrationProvider.ts:45 | require.resolve("@fabricstack/orchestrator-sdk/dist/cli/main.js") to spawn the CLI | consumer fixed → require.resolve("@fabricstack/orchestrator-sdk/cli") (resolves through the map to the same file; the string is not typed, moduleResolution: node unaffected) |
packages/observer-dashboard/src/app/actions/approve-breakpoint.ts:9 | import { commitEffectResult } from "@fabricstack/orchestrator-sdk/dist/runtime/commitEffectResult" (kept the server graph small) | **made public deliberately** as ./runtime (→ dist/runtime/index.js, which re-exports commitEffectResult); observer imports @fabricstack/orchestrator-sdk/runtime; next.config.mjs already externalizes `^@fabricstack\/orchestrator-sdk(\/ |
packages/babysitter-sdk/src/config/index.ts:9 (JSDoc @example) and docs/cli-examples.md (…/testing ×3) | documented @fabricstack/orchestrator-sdk/config / /testing | **made public** as ./config and ./testing — documented subpaths are public by definition |
packages/genty/platform/src/harness/internal/createRun/planProcess/validation.ts:53, packages/babysitter-sdk/src/cli/__tests__/resolveDependencyBin.test.ts:16, library/proof-quality-convergence.test-runner.mjs:15 | …/package.json imports of orchestrator-sdk / harness-sdk | satisfied by ./package.json on every package |
packages/genty/platform/src/harness/internal/createRun/planProcess/recovery.ts:17 | 'from "@fabricstack/orchestrator-sdk/$1"' — a regex **replacement template** inside a rewriter | not an import; the scanner skips any specifier containing $ (a real specifier never does) |
Zero remaining findings: node scripts/ci/exports-exactness.cjs → 43 publishable manifest(s), 6379 source file(s), 18979 specifier(s), 3303 workspace import(s) resolved, 0 finding(s).
4. Verifier exactness (AC1, AC2) — `scripts/verify-release-artifacts.mjs`
New step exactness between typecheck and bins (so a platform bin-shim failure cannot hide it), **on by default**, --exactness explicit in the workflow, --no-exactness for triage only:
1. exportsMapProblems(manifest, { tarballFiles }) — the §1 policy over the *packed* manifest, every target must be in the tarball. 2. nonExportedProbes(manifest, tarballFiles) — a **data-driven** probe manifest generated from the tarball inventory: up to 3 real shipped .js/.cjs/.mjs/.json files that no subpath resolves to (dist/ first, shortest first — e.g. harness-hooks-core/dist/api.js, harness-core/dist/pty.js, fix011-good-package/cli.js, bin-only-metapackage/bin/fix011-bin-only.js), plus the spec's synthetic <pkg>/dist/internal-anything. Written to fix011-exactness-probes.json in the clean consumer; fix011-exactness-probe.mjs tries each with require() and import(); both must fail with ERR_PACKAGE_PATH_NOT_EXPORTED (RESOLVED, MODULE_NOT_FOUND or any other code is a failure). A map-less package therefore fails on its leaking file *and* on the synthetic probe. 3. Together with steps 6–7 (every declared runtime subpath imports; every typed subpath typechecks in the fresh consumer) the importable surface equals the map. The report records declaredSubpaths, tarballFileProbes and each probe's two outcomes.
Fixtures (scripts/__tests__/fixtures/fix011/): new exports-wildcard (healthy artifact with "./*" → fails [wildcard-export]), new exports-leaky (no map, internal.js shipped → require -> RESOLVED named, synthetic probe reported); bin-only-metapackage, failing-verify-release, bundler-runtime gained closed/complete maps because exactness is on by default. Tests added to scripts/__tests__/verify-release-artifacts.test.mjs (probe record on the healthy fixture, wildcard red, leaky red, --no-exactness skipped, workflow passes --exactness, bin-only closed map keeps bin/ unimportable).
**Verifier bug found and fixed on the way**: since the CI-triage fix 1117e6993 each package's clean consumer resolves internal dependencies from tarballs packed in this run, but verifyPackage deleted its working directory (including pack/) after every package — so in any multi-package run every dependent failed at install with ENOENT on the file: override (first seen as @fabricstack/orchestrator-sdk opening the already-removed harness-hooks-core tarball). The tarball is now copied to the shared internal-deps directory before cleanup; regression test "a selected dependency stays installable by a dependent verified later in the same run" (trust → harness-policy, both bin-less, real packages, built by the verifier itself) pins it. CI triage round 1 retargeted the test: it originally ran hooks-core → hooks-claude with --skip-build, which passed only on a checkout that had already been built — the Release tooling tests CI step runs before any workspace build, so the surfaces check found an empty dist/. The verifier now builds the pair like the other real-package suites do, and the trust/policy closure (trust, harness-tasks, harness-policy) does not touch the catalog build that the two hooks suites already run concurrently.
5. Local matrix (43 packages, `--skip-build --exactness`)
Command: node scripts/verify-release-artifacts.mjs --skip-build --exactness --report-dir <scratch>/matrix (one process, dependency order, checkout-packed internal deps). Windows limits of this machine (known from RN-05/RN-06, unrelated to exports): the bins step spawns npm's .cmd shim directly (spawnSync … ENOENT) for every bin-bearing package, and harness-core's own verify:release gate spawns bare npm (same ENOENT class). Both happen **after** the exactness step, so exactness is proven locally wherever the row says so; CI (ubuntu, release-artifact-verifier.yml) verifies the whole chain.
Outcome: the run was **stopped by the Claude Code session at 27/43 for critically low system memory** (not a verifier failure; per the session notice it was not restarted). Reports exist for 27 packages; the 16 rows marked NOT RUN were never reached and are verified by CI only. Counts over the 27 reports: exactness passed 27/27 (never skipped, never failed); 20 fully green (every step incl. bins where present); 6 bin-bearing packages stopped only at the Windows .cmd-shim bin smoke AFTER exactness passed; 1 (harness-core) stopped only at its own verify:release gate (bare npm spawn) AFTER exactness passed. Earlier single-package runs (harness-hooks-core, the verifier fixtures, the hooks-core→hooks-claude regression pair) are consistent. Raw counters: .
| Package | Exported subpaths | Negative probe (fails as required) | Matrix result on this machine |
|---|---|---|---|
| @fabricstack/agent-runtime-cli | — | — | NOT RUN |
| @fabricstack/agent-runtime-core | — | — | NOT RUN |
| @fabricstack/agent-runtime-engine | — | — | NOT RUN |
| @fabricstack/agent-runtime-platform | — | — | NOT RUN |
| @fabricstack/catalog | ., ./indexer, ./catalog, ./graph-index, ./package.json | <pkg>/dist/cli.js (3 file + synthetic; all ERR_PACKAGE_PATH_NOT_EXPORTED) | PASS through exactness; bins: Windows .cmd-shim spawn ENOENT (environmental, CI verifies) |
| @fabricstack/console-tui | — | — | NOT RUN |
| @fabricstack/console-ui | — | — | NOT RUN |
| @fabricstack/control-plane | — | — | NOT RUN |
| @fabricstack/harness-channels | — | — | NOT RUN |
| @fabricstack/harness-cli | ., ./bootstrap, ./package.json | <pkg>/dist/output.js (3 file + synthetic; all ERR_PACKAGE_PATH_NOT_EXPORTED) | PASS |
| @fabricstack/harness-codecs | ., ./package.json | <pkg>/dist/pi-adapter.js (3 file + synthetic; all ERR_PACKAGE_PATH_NOT_EXPORTED) | PASS |
| @fabricstack/harness-config | ., ./package.json | <pkg>/dist/auth.js (3 file + synthetic; all ERR_PACKAGE_PATH_NOT_EXPORTED) | PASS |
| @fabricstack/harness-core | ., ./browser, ./kanban, ./automation, ./package.json | <pkg>/dist/pty.js (3 file + synthetic; all ERR_PACKAGE_PATH_NOT_EXPORTED) | PASS through exactness; verifyRelease: package gate spawns bare npm (Windows ENOENT, environmental, CI verifies) |
| @fabricstack/harness-extensions | — | — | NOT RUN |
| @fabricstack/harness-gateway | ., ./package.json | <pkg>/dist/config.js (3 file + synthetic; all ERR_PACKAGE_PATH_NOT_EXPORTED) | PASS |
| @fabricstack/harness-hooks-agent-runtime | — | — | NOT RUN |
| @fabricstack/harness-hooks-antigravity | ., ./package.json | <pkg>/dist/adapter.js (3 file + synthetic; all ERR_PACKAGE_PATH_NOT_EXPORTED) | PASS |
| @fabricstack/harness-hooks-claude | ., ./package.json | <pkg>/dist/adapter.js (3 file + synthetic; all ERR_PACKAGE_PATH_NOT_EXPORTED) | PASS |
| @fabricstack/harness-hooks-cli | ., ./package.json | <pkg>/dist/cli/main.js (3 file + synthetic; all ERR_PACKAGE_PATH_NOT_EXPORTED) | PASS through exactness; bins: Windows .cmd-shim spawn ENOENT (environmental, CI verifies) |
| @fabricstack/harness-hooks-codex | ., ./package.json | <pkg>/dist/adapter.js (3 file + synthetic; all ERR_PACKAGE_PATH_NOT_EXPORTED) | PASS |
| @fabricstack/harness-hooks-copilot | ., ./package.json | <pkg>/dist/adapter.js (3 file + synthetic; all ERR_PACKAGE_PATH_NOT_EXPORTED) | PASS |
| @fabricstack/harness-hooks-core | ., ./package.json | <pkg>/dist/api.js (3 file + synthetic; all ERR_PACKAGE_PATH_NOT_EXPORTED) | PASS |
| @fabricstack/harness-hooks-cursor | ., ./package.json | <pkg>/dist/adapter.js (3 file + synthetic; all ERR_PACKAGE_PATH_NOT_EXPORTED) | PASS |
| @fabricstack/harness-hooks-gemini | ., ./package.json | <pkg>/dist/adapter.js (3 file + synthetic; all ERR_PACKAGE_PATH_NOT_EXPORTED) | PASS |
| @fabricstack/harness-hooks-hermes | ., ./package.json | <pkg>/dist/adapter.js (3 file + synthetic; all ERR_PACKAGE_PATH_NOT_EXPORTED) | PASS |
| @fabricstack/harness-hooks-oh-my-pi | ., ./package.json | <pkg>/dist/adapter.js (3 file + synthetic; all ERR_PACKAGE_PATH_NOT_EXPORTED) | PASS |
| @fabricstack/harness-hooks-openclaw | ., ./package.json | <pkg>/dist/adapter.js (3 file + synthetic; all ERR_PACKAGE_PATH_NOT_EXPORTED) | PASS |
| @fabricstack/harness-hooks-opencode | ., ./package.json | <pkg>/dist/adapter.js (3 file + synthetic; all ERR_PACKAGE_PATH_NOT_EXPORTED) | PASS |
| @fabricstack/harness-hooks-pi | ., ./package.json | <pkg>/dist/adapter.js (3 file + synthetic; all ERR_PACKAGE_PATH_NOT_EXPORTED) | PASS |
| @fabricstack/harness-launch | ., ./package.json | <pkg>/dist/types.js (3 file + synthetic; all ERR_PACKAGE_PATH_NOT_EXPORTED) | PASS |
| @fabricstack/harness-mock | — | — | NOT RUN |
| @fabricstack/harness-observability | ., ./package.json | <pkg>/dist/types.js (3 file + synthetic; all ERR_PACKAGE_PATH_NOT_EXPORTED) | PASS |
| @fabricstack/harness-policy | ., ./trust, ./config-manifest, ./proven-bridge, ./package.json | <pkg>/dist/argv-matcher.js (3 file + synthetic; all ERR_PACKAGE_PATH_NOT_EXPORTED) | PASS |
| @fabricstack/harness-sdk | ., ./package.json | <pkg>/dist/bin/adapters.js (1 file + synthetic; all ERR_PACKAGE_PATH_NOT_EXPORTED) | PASS through exactness; bins: Windows .cmd-shim spawn ENOENT (environmental, CI verifies) |
| @fabricstack/harness-tasks | ., ./backends, ./proven, ./mcp, ./harness, ./auth, ./config, ./package.json | <pkg>/dist/types.js (3 file + synthetic; all ERR_PACKAGE_PATH_NOT_EXPORTED) | PASS through exactness; bins: Windows .cmd-shim spawn ENOENT (environmental, CI verifies) |
| @fabricstack/harness-tools | — | — | NOT RUN |
| @fabricstack/harness-triggers | — | — | NOT RUN |
| @fabricstack/model-gateway | ., ./config, ./server, ./runtime, ./types, ./attestation, ./package.json | <pkg>/dist/codec.js (3 file + synthetic; all ERR_PACKAGE_PATH_NOT_EXPORTED) | PASS through exactness; bins: Windows .cmd-shim spawn ENOENT (environmental, CI verifies) |
| @fabricstack/observer | — | — | NOT RUN |
| @fabricstack/operator | — | — | NOT RUN |
| @fabricstack/orchestrator | — | — | NOT RUN |
| @fabricstack/orchestrator-sdk | ., ./cli, ./config, ./runtime, ./testing, ./package.json | <pkg>/dist/mcp/index.js (3 file + synthetic; all ERR_PACKAGE_PATH_NOT_EXPORTED) | PASS through exactness; bins: Windows .cmd-shim spawn ENOENT (environmental, CI verifies) |
| @fabricstack/trust | ., ./package.json | <pkg>/dist/chain.js (3 file + synthetic; all ERR_PACKAGE_PATH_NOT_EXPORTED) | PASS |
{"pass":20,"envBins":6,"envVerify":1,"other":16,"exactnessPassed":27,"exactnessNotReached":0}
6. In-repo check (AC3) — `scripts/ci/exports-exactness.cjs`
--self-test: 8 fixtures underscripts/ci/fixtures/exports-exactness/(@fabricstack/exx-*names, AR registry, outside the workspace globs — pass every other guard's scan):clean(0 findings, publics page in sync),wildcard-export,private-deep-import(packages/consumer/src/index.ts:12 @fabricstack/exx-lib/dist/internal.js),missing-subpath-file(./missing→dist/missing.jsabsent),no-exports-map(+ the consumer's/utilimport becomes unresolvable),bin-only-root-import,publics-drift,publics-missing→8/8 fixtures behaved (7 negative, 1 positive).- Repository scan (above): 0 findings.
scripts/ci/exports-exactness.test.mjsbehindnpm run test:exports-exactness→ 8/8: self-test, fixture matrix with diagnostics, repository scan, all 43 manifests policy-clean with no*anywhere (exports or typesVersions) and the synthetic probe unexported, the SDK's exact subpath set, specifier extraction over 11 import shapes (+ 4 non-imports ignored), publics generation deterministic/idempotent, CI wiring present.- Wired into
ci.ymljobpublish-isolation(dependency-free, beforenpm ci) as step "Exports exactness (WP-PKG-01)": self-test → repository scan →npm run test:exports-exactness.release-artifact-verifier.yml: new step "Exports-map exactness self-test and repository scan",--exactnesspassed to the matrix,pull_requestpaths extended with the new library and check.
7. Docs-site publics (AC5)
The repo has no generator of SDK reference pages from manifests (docs:* scripts generate process-library/CLI-example artifacts and run lint/snippets/links/freshness). Added docs/reference/package-publics.md, generated by npm run docs:publics (node scripts/ci/exports-exactness.cjs --write-publics): front matter the freshness gate requires (title, description, last_updated — restamped only when the body changes), one section per package with directory, bins and a table subpath | import specifier | runtime target | types; 43 sections. Drift is a finding of the CI check and of the node:test suite. Picked up by the docs-site automatically (sidebars.js autogenerates reference/). Gates: docs-style-check 7 rules / 0 issues, docs-link-check clean, markdownlint-cli2 0 errors over the page; docs-freshness-report fails only on four pre-existing stale generated docs (adapters/reference/04-agent-events.md, generated/cli-examples-verification.md, GAP-PROMPT-011.md, reference-repos/README.md, 71–114 days), untouched here.
8. Gates
| Gate | Result |
|---|---|
node scripts/ci/exports-exactness.cjs --self-test | 8/8 fixtures behaved (7 negative, 1 positive) |
node scripts/ci/exports-exactness.cjs (repository scan) | 43 publishable manifest(s), 6379 source file(s), 18979 specifier(s), 3303 workspace import(s) resolved, 0 finding(s) |
npm run test:exports-exactness | 8/8 |
node --test scripts/__tests__/verify-release-artifacts.test.mjs | 24 tests: the 5 new WP-PKG-01 tests and the tarball-retention regression pass; the 7 failures are all in the inherited pre-change failing set (Windows .cmd-shim bin smoke on the healthy/bin-only fixtures, publish.yml shape, WP-RN-07) |
node scripts/release-version.cjs verify-manifests --version 7.0.0 | All synchronized manifests are at release version 7.0.0. |
node scripts/ci/publish-isolation-guard.cjs --self-test | self-test passed; repository scan clean (127 files, 0 findings, 8 legacy-train notice(s)) |
node scripts/ci/no-double-rename.cjs --self-test | 10/10; repository scan 59 manifest(s), 0 findings |
node scripts/ci/public-push-guard.cjs | scanned 342 files, 0 finding(s) |
npm run verify:metadata | passed, publishable inventory 43 |
npm run guard:packages | package-integrity guard passed (lockfile sync, native bindings, metadata, arch boundaries) |
npm run test:publish-guards | 17/17 |
npm run test:binary-renames | 18 spec 15 §3.1 bins across 16 packages; G5 holds over 25 workspace bin names |
npm run test:verify-manifests | 8/8 |
tsc --noEmit -p packages/observer-dashboard | exit 0 (the observer resolves @fabricstack/orchestrator-sdk/runtime through the map) |
docs gates over docs/reference/package-publics.md | style 0 issues, links clean, markdownlint 0 errors; freshness: 4 pre-existing stale generated docs only |
| Build entrypoints of every changed manifest family | build:sdk, build:adapters, build:atlas, build:kip, build:kradle, build:cloud and the observer's build:cli all exit 0 (observer build:app cannot run here — lightningcss win32 binding; CI verifies) |
npm run test:release-tooling before → after | before (pristine tree): 157 tests, 120 pass, 37 fail (inherited FIX-010/FIX-011 workflow-shape + Windows bin/npm-stub set; names saved). After: 163 tests, 125 pass, 38 fail = the same 37 names + 1 that appears only in the parallel full run — hooks-atlas-ownership.test.mjs "a hooks leaf resolves Atlas through its OWN dependency…" failed with npm run build --workspace=@fabricstack/catalog racing another test file's rebuild of the same package (the PKG-02-documented flake); rerun of that file alone → the test passes (5/6; the one failure "the hooks CLI installs, imports and runs from its packed tarball…" is in the inherited list). Failing-name set after minus the flake == set before (comm → 0 new, 0 fixed). No test deleted or skipped |
Orchestrator gate, verbatim from C:/work/fabric | node scripts/release-version.cjs verify-manifests --version 7.0.0 && node scripts/ci/publish-isolation-guard.cjs --self-test && npm run test:binary-renames && npm run test:verify-manifests && npm run test:exports-exactness && echo PKG01-PASS → tail: # tests 8 / # pass 8 / # fail 0 / PKG01-PASS (exit 0) |
8a. Review round 1 (M4): a live target-missing gate on a built tree
The review found that no job proved the declared targets on a built tree: the publish-isolation job scans an unbuilt checkout (221 targets in 40 packages *deferred*, by design) and the packed-artifact gate (release-artifact-verifier.yml) is disabled_manually, so a target that went missing after build was caught by nothing on a PR. Fixed:
scripts/ci/exports-exactness.cjs --require-built(alias--strict):allowUnbuiltis off, nothing is deferred, every declared target of every publishable must exist on disk or it is atarget-missingfinding (exit 1). The report line saysexports-exactness (strict, built tree: no unbuilt deferral): ….scripts/ci/exports-exactness.test.mjsgained the test "--require-built: an unbuilt package is refused (target-missing), never deferred; the built real tree passes strictly" (theunbuilt-packagefixture: 4 findings, 0 deferred, CLI exit 1 with no deferral line; the tolerant scan of the same tree still exits 0; on the real treestrict findings == tolerant deferrals), and the CI-wiring test now also asserts the strict step sits after the last build step of thetestjob. Suite: 11/11..github/workflows/ci.ymltestjob: new step **"Build agent-runtime-cli and operator (strict exports gate inputs)"** (the two publishables no earlier step of that job builds;tsc --builddirectly for agent-runtime-cli because its own build script re-runsbuild:runtime) followed by **"Exports exactness on the built tree (strict, WP-PKG-01)"** =node scripts/ci/exports-exactness.cjs --require-built, placed after "Build babysitter-harness" and before the agent-runtime suites. The tolerant scan stays in the dependency-free publish-isolation job (unbuilt checkout).- Local proof on this (fully built) checkout:
exports-exactness (strict, built tree: no unbuilt deferral): 43 publishable manifest(s), 6385 source file(s), 19013 specifier(s), 3305 workspace import(s) resolved, 0 finding(s)(exit 0). CI proof: see "CI evidence" below once thetestjob reaches the step.
**Still pending (owner decision)**: the full 43-package *packed* matrix (AC1 negative probes + AC2 fresh-consumer typecheck inside each tarball) runs only in release-artifact-verifier.yml, which is owner-disabled (workflow id 352401988); the local run reached 27/43 (§5). Re-enabling that workflow — or a dispatched run of scripts/verify-release-artifacts.mjs --exactness over the matrix with its report attached — is required before 7.0.0 and is outside what this task may do (no workflow enabling). The strict on-disk gate above proves the *source* of every tarball target on every PR; it does not replace the packed proof.
9. Honesty / deferred
1. **Matrix coverage on this machine**: exactness is proven locally for the 27 packages the run reached (all 27 passed the exactness step); the 16 listed as NOT RUN (agent-runtime-cli/core/engine/platform, console-tui/ui, control-plane, harness-channels/extensions/hooks-agent-runtime/mock/tools/triggers, observer, operator, orchestrator) were never reached because the Claude Code session stopped the run at 27/43 for critically low system memory and instructed not to restart it. Their maps pass the same static policy (exports-exactness over the checked-in tree, target-missing against disk) and the same probe generator; CI's release-artifact-verifier.yml (with --exactness) proves them on the pushed commits. No package is claimed verified that was not. 2. **Windows limits (pre-existing, unrelated to exports)**: the bins step spawns npm's .cmd shim directly (spawnSync … ENOENT) and harness-core's own verify:release gate spawns bare npm — both after exactness. test:babysitter-metapackage cannot run here (its before hook feeds GNU tar an absolute C:\… path); the stub/consumer fix in that test was made by reading and mirrors the real map shape (./cli resolved through exports; verified by hand in a temp consumer: require('@fabricstack/orchestrator-sdk/cli') → MODULE_NOT_FOUND naming the absolute dist\cli\main.js when the file is missing, ERR_PACKAGE_PATH_NOT_EXPORTED for the old deep path). vitest suites (rolldown win32 binding absent) and observer build:app (lightningcss) still cannot run here; the observer was typechecked with tsc instead. 3. **Verifier defect fixed in scope**: the multi-package run of verify-release-artifacts.mjs was broken since 1117e6993 (dependents installed from a tarball already deleted with the dependency's working directory); fixed by retaining the tarball in internal-deps, with a regression test. Without this fix the full matrix could not run at all. 4. **Scope calls**: ./cli and ./runtime on the SDK are deliberate publics (a spawnable CLI entry and a small commit-path graph) rather than consumer rewrites to the root, because the root cannot provide either property; ./config/./testing are public because they are documented. No wildcard was added anywhere, no test was deleted or skipped, no map was widened to make a probe pass. The private atlas/webui tsconfig paths (@fabricstack/catalog/* → source) is compile-time only and out of exports scope. 5. **Private workspace members without a map** (e.g. @fabricstack/memory) are legacy-resolved and only counted by the in-repo check — extending the policy to private members is a follow-up, not an AC of this WP. 6. artifacts/docs-qa/freshness-report.json (tracked, generated) was rewritten by the local freshness run and restored; it is not part of this change.