Skip to content

[CLI] META-244 — consume published @workspacejson/spec declarations, remove ambient shadow - #2

Merged
qmarcelle merged 1 commit into
mainfrom
fix/meta-244-remove-spec-ambient-shadow
Jul 26, 2026
Merged

qmarcelle merged 1 commit into
mainfrom
fix/meta-244-remove-spec-ambient-shadow

Conversation

@qmarcelle

Copy link
Copy Markdown
Contributor

Removes the handwritten @workspacejson/spec ambient declarations so the CLI packages compile against the real published contract.

Linear: META-244. Follow-up to META-240, which migrated this file byte-identical because parity required preserving behavior, and recorded the shadow as a known follow-up.

Scope discipline: this is a type-visibility correction only. It implies nothing about the durable architecture of this repository. The migrated package layout (packages/agents-audit/, packages/cli/) remains a migration baseline and compatibility capsule pending the META-236 target-architecture ratification — per ADR-002, historical repository and package names are migration inputs and compatibility constraints, not the target architecture.

The defect

types/ambient.d.ts contained declare module '@workspacejson/spec' { … } restating that package's type surface. Ambient module declarations win over node_modules typings, so the stub shadowed the real published declarations even though the dependency is a registry-backed pin (0.4.4).

It was not merely redundant — it was stale, and hid the entire v0.4 contract:

Real published export In the removed stub?
WorkspaceJsonV4 (specVersion: '0.4', coChange, fragility, health extensions) absent
validateV4() absent
CoChangeEntry absent
FragilityEntry absent
validate() narrowed — stub data is WorkspaceJsonV3; real data is WorkspaceJsonV3 | WorkspaceJsonV4
version stub string; real literal "0.4.4"

WorkspaceJsonV3, FileIndexEntry, FrameworkEntry and WorkspaceJson were shape-identical, which is why nothing failed loudly — the repository simply could not see the newer half of the contract it depends on.

Full ambient inventory (22 module declarations + 1 global)

Declaration Imported by CLI code Classification Action
@workspacejson/spec 4 standard-owned contract shadow removed
node:fs, node:fs/promises, node:path, node:url, node:module, node:readline 8/11/18/3/2/1 node builtins; merge with the @types/node added in META-240 kept
node:child_process 0 node builtin, unused kept
commander, ora, picocolors, cli-table3, boxen, terminal-link, dedent, vitest 1–13 external-package shadows for real dependencies kept
fast-glob, simple-git, remark, remark-parse, ajv, ajv/dist/2020.js 0 dead — served packages/spec / packages/rules, which left kept, flagged
declare const process global local global shim, overlaps @types/node kept

@workspacejson/rules shadow: does not exist. @workspacejson/spec was the only @workspacejson/* ambient declaration. No other first-party contract is duplicated here.

The six dead declarations are deliberately not removed — they are a separate, evidence-backed cleanup, and bundling them would blur a contract-ownership fix into unrelated tidying.

The deliberate test

packages/agents-audit/src/spec-contract-visibility.test.ts (5 cases) imports validateV4, WorkspaceJsonV4, CoChangeEntry and FragilityEntry — every one of which exists only in the real published package and was absent from the removed stub. Its primary assertion is that it compiles at all.

Proven by perturbation — restoring a V3-only stub and re-running typecheck:

src/spec-contract-visibility.test.ts(2,20): error TS2724: '"@workspacejson/spec"' has no exported member named 'validateV4'
src/spec-contract-visibility.test.ts(3,15): error TS2305: Module '"@workspacejson/spec"' has no exported member 'CoChangeEntry'
src/spec-contract-visibility.test.ts(3,30): error TS2305: Module '"@workspacejson/spec"' has no exported member 'FragilityEntry'
src/spec-contract-visibility.test.ts(3,46): error TS2724: '"@workspacejson/spec"' has no exported member named 'WorkspaceJsonV4'
src/audit.ts(4,15):                          error TS2724: '"@workspacejson/spec"' has no exported member named 'WorkspaceJson'

That is the acceptance criterion "a changed published type is visible to the CLI compiler", demonstrated rather than asserted.

The suite also checks the opposite failure: v0.3 artifacts must still validate and must still be rejected by validateV4, so consuming real types did not widen or break the contract the producer emits today.

Regression guard

New shadowed-standard-types check in scripts/check-architecture.mjs rejects any ambient re-declaration of a @workspacejson/* package, with two red tests (spec and rules). Guard red tests: 13 → 15, all passing, including the baseline case proving an unmodified repository is still accepted.

The guard strips comments before matching — the note left in ambient.d.ts explaining the removal necessarily quotes the syntax it forbids. I hit that false positive during development and fixed the guard rather than reword the explanation, since the rule is about what the compiler sees.

Verification

typecheck                       2/2 packages
build                           2/2 packages
tests                           68 agents-audit (was 63; +5 new suite) + 6 shim
architecture guard              pass (63 files, 3 manifests)
architecture red tests          15/15 (was 13/13)
pack verification               pass, incl. registry-resolved generate smoke test
packed file inventory           IDENTICAL to published agents-audit@0.4.4
packed manifest                 IDENTICAL to the merged META-240 candidate
META-240 producer parity        29/29
META-240 DataHub shim parity    35/35

No runtime behavior changed — the packed artifact is byte-identical to the merged META-240 candidate, which is the strongest available evidence that a types-only change stayed types-only.

Not in scope

  • No package renamed. No package published. @workspacejson/cli remains private: true and absent from the registry.
  • No publish authority changed; the release workflow remains non-authoritative with no trigger, no publish step and no credential.
  • Does not implement META-195 or META-235, both of which remain gated on the META-236 architecture decision.
  • Does not endorse packages/agents-audit as the durable home of anything.

…244)

types/ambient.d.ts carried a handwritten `declare module '@workspacejson/spec'`
restating that package's type surface. Ambient module declarations win over
node_modules typings, so the stub shadowed the real published declarations even
though the dependency is a registry-backed pin — and it silently hid the entire
v0.4 contract from this repository's compiler:

  WorkspaceJsonV4   absent from the stub
  validateV4        absent from the stub
  CoChangeEntry     absent from the stub
  FragilityEntry    absent from the stub
  validate()        narrowed to `data is WorkspaceJsonV3`; the real declaration
                    is `data is WorkspaceJsonV3 | WorkspaceJsonV4`
  version           typed `string`; the real declaration is the literal "0.4.4"

workspacejson/standard owns that contract. This removes the second editable copy
and compiles both packages against the real declarations.

This is a type-visibility correction only. No producer behavior change, no
emission change, no schema change, nothing renamed, nothing published. It
implies nothing about the durable architecture of this repository — the
migrated package layout remains a migration baseline pending META-236.

Added: packages/agents-audit/src/spec-contract-visibility.test.ts. Every symbol
it imports exists only in the real package, so reintroducing the shadow breaks
it at compile time rather than at runtime. Verified by deliberately restoring a
V3-only stub and observing TS2305/TS2724 on validateV4, CoChangeEntry,
FragilityEntry and WorkspaceJsonV4.

Added: a `shadowed-standard-types` guard in check-architecture.mjs rejecting any
ambient re-declaration of a @workspacejson/* package, with two red tests (spec
and rules). The guard strips comments first, so the note explaining the removal
can quote the syntax it forbids.

Inventory recorded on META-244: 22 ambient module declarations plus one global.
Exactly one was a standard-owned contract shadow. No @workspacejson/rules shadow
exists. Six declarations (fast-glob, simple-git, remark, remark-parse, ajv,
ajv/dist/2020.js) are dead here — they served packages/spec and packages/rules,
which left for workspacejson/standard — and are deliberately NOT removed in this
change, which stays scoped to the contract-ownership defect.

Verification
- typecheck 2/2, build 2/2
- tests 68 (was 63; +5 from the new visibility suite) + 6 shim tests
- architecture guard red tests 15/15 (was 13)
- packed file inventory identical to published agents-audit@0.4.4
- packed manifest identical to the merged META-240 candidate
- META-240 producer parity harness 29/29
- META-240 DataHub shim parity harness 35/35
Copilot AI review requested due to automatic review settings July 26, 2026 03:28

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@qmarcelle
qmarcelle merged commit 18e3d6a into main Jul 26, 2026
2 checks passed
@qmarcelle
qmarcelle deleted the fix/meta-244-remove-spec-ambient-shadow branch July 27, 2026 03:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants