DD-333 Phase F.4 (plugins) — domain_scope schema + AJV gate #16

Merged
piersdd merged 1 commit from feat/dd-333-phase-f4-domain-scope into main 2026-05-22 13:15:09 +00:00
piersdd commented 2026-05-22 13:11:04 +00:00 (Migrated from github.com)

Summary

Ships the stallari-plugins portion of DD-333 Phase F.4 — the 5th granularity: dimension (domain_scope: single | multi | non-conforming-explicit) plus the build-catalog procedural cross-field gate that surfaces S-DOM-002 findings when a tool's domain_scope=\"single\" declaration is contradicted by a user-domain-shaped scope/domain/domainName argument.

Cross-DD with DD-341 (domain substrate, all phases shipped 2026-05-22 in v0.99.26.0) and DD-338 (forthcoming A.2.dom blade _meta.domain_attribution substrate). Sister to F.1's non_conformance_rationale mechanism.

Changes

Schema — schemas/catalog-entry.schema.json:

  • granularity.domain_scope enum [single, multi, non-conforming-explicit]. Optional at F.4 (architect-lock #2 — promoted to required at F.4.b after A.2.dom blade backfill).
  • non_conformance_rationale.domain_scope_unspecified: array<string> — additive escape hatch listing tools that cannot yet declare domain_scope.

scripts/build-catalog.js — new enforceDomainScope(raw, filename) procedural pass invoked per plugin entry inside the build loop:

  1. Derivation — tools in domain_scope_unspecified without own declaration receive granularity.domain_scope=\"non-conforming-explicit\" in place (sister to existing scope_filtering derivation).
  2. Constraint A — every entry in domain_scope_unspecified must cross-reference an actual tools[].name; throws on mismatch.
  3. S-DOM-002 finding — for each tool with effective domain_scope=\"single\" advertising a user-domain-shaped argument matching /^(scope|domain|domains|domainName|domain_name)$/i with string-or-enum type, emit a warning-level finding. If tool.description contains a // scope-arg-disclaimer: <reason> annotation (architect-lock #5), downgrade to info.

Findings surface alongside Manifest UX warnings; severity .warning at F.4 ship (mirrors S-DOM-001 v1 posture per architect-lock #7; promotion to .error follows A.2.dom backfill via separate spec).

Fixtures — schemas/fixtures/catalog-entries/tool-domain-scope-*.json (6 new):

  • single-honest, multi-honest, single-with-scope-arg-violation, unspecified-derives, disclaimer, bogus-enum.

Example packs — examples/domain-scope-pack/ (3 new YAMLs):

  • Authoring-reference packs for the three authoring paths (honest-single, honest-multi, violation-with-fix-paths).

Tests — scripts/domain-scope.test.js (8 cases):

  • Covers all 6 spec acceptance criteria (acceptsHonestSingle / acceptsHonestMulti / rejectsUnknownEnumValue / derivesNonConformingForUnspecified / warnsOnSingleWithScopeArg / passesWithDisclaimerAnnotation) plus cross-reference mismatch + heuristic regex coverage + real-corpus smoke (zero findings on existing 11 packs + 59 plugin entries).

Verification

  • npm test — 178/178 green (incl. 8 new domain-scope cases; pre-existing 170 unaffected).
  • node scripts/build-catalog.js — clean against existing 11 packs + 59 plugin entries (zero new S-DOM-002 findings, zero new AJV rejections; no domain_scope: declared anywhere in the corpus yet).

Out of scope (per spec)

  • stallari-secops-scanner S-DOM-002 rule (separate subagent / separate PR).
  • stallari-pack-spec docs/CHANGELOG (separate subagent / separate PR).
  • Blade-side _meta.domain_attribution substrate (DD-338 A.2.dom).
  • Promoting domain_scope to required in granularity.required (F.4.b).
  • Promoting S-DOM-002 severity to .error (post-A.2.dom).
  • F.5 (assembler verdict logic consuming domain_scope).

Test plan

  • Architect-attended CI green on PR
  • Reviewer confirms zero S-DOM-002 findings on the existing live corpus (build-catalog.js output)
  • Reviewer scans the 6 fixture files for shape clarity (each documents one branch of the new procedural pass)
  • Reviewer confirms 3 example pack YAMLs serve as readable authoring references (not parsed by build — pure documentation)

Convention compliance

  • #17 commit trailers — exactly one Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>; commit ssh-signed by Piers.
  • #19 no phone-home — build-catalog runs offline.
  • #22 migration resilience — domain_scope optional; legacy corpus continues to validate.
  • #23 substrate-contract reader audit — F.4 adds a NEW reader contract (build-catalog.js as reader of tools[].arguments[] for scope-arg heuristic). Architect appends DD-333 reader-audit table extension post-merge.

🤖 Generated with Claude Code

## Summary Ships the **stallari-plugins** portion of DD-333 Phase F.4 — the 5th `granularity:` dimension (`domain_scope: single | multi | non-conforming-explicit`) plus the build-catalog procedural cross-field gate that surfaces `S-DOM-002` findings when a tool's `domain_scope=\"single\"` declaration is contradicted by a user-domain-shaped `scope`/`domain`/`domainName` argument. Cross-DD with DD-341 (domain substrate, all phases shipped 2026-05-22 in `v0.99.26.0`) and DD-338 (forthcoming A.2.dom blade `_meta.domain_attribution` substrate). Sister to F.1's `non_conformance_rationale` mechanism. ## Changes **Schema** — `schemas/catalog-entry.schema.json`: - `granularity.domain_scope` enum `[single, multi, non-conforming-explicit]`. Optional at F.4 (architect-lock #2 — promoted to required at F.4.b after A.2.dom blade backfill). - `non_conformance_rationale.domain_scope_unspecified: array<string>` — additive escape hatch listing tools that cannot yet declare `domain_scope`. **`scripts/build-catalog.js`** — new `enforceDomainScope(raw, filename)` procedural pass invoked per plugin entry inside the build loop: 1. **Derivation** — tools in `domain_scope_unspecified` without own declaration receive `granularity.domain_scope=\"non-conforming-explicit\"` in place (sister to existing `scope_filtering` derivation). 2. **Constraint A** — every entry in `domain_scope_unspecified` must cross-reference an actual `tools[].name`; throws on mismatch. 3. **S-DOM-002 finding** — for each tool with effective `domain_scope=\"single\"` advertising a user-domain-shaped argument matching `/^(scope|domain|domains|domainName|domain_name)$/i` with string-or-enum type, emit a `warning`-level finding. If `tool.description` contains a `// scope-arg-disclaimer: <reason>` annotation (architect-lock #5), downgrade to `info`. Findings surface alongside Manifest UX warnings; severity `.warning` at F.4 ship (mirrors S-DOM-001 v1 posture per architect-lock #7; promotion to `.error` follows A.2.dom backfill via separate spec). **Fixtures** — `schemas/fixtures/catalog-entries/tool-domain-scope-*.json` (6 new): - `single-honest`, `multi-honest`, `single-with-scope-arg-violation`, `unspecified-derives`, `disclaimer`, `bogus-enum`. **Example packs** — `examples/domain-scope-pack/` (3 new YAMLs): - Authoring-reference packs for the three authoring paths (honest-single, honest-multi, violation-with-fix-paths). **Tests** — `scripts/domain-scope.test.js` (8 cases): - Covers all 6 spec acceptance criteria (acceptsHonestSingle / acceptsHonestMulti / rejectsUnknownEnumValue / derivesNonConformingForUnspecified / warnsOnSingleWithScopeArg / passesWithDisclaimerAnnotation) plus cross-reference mismatch + heuristic regex coverage + real-corpus smoke (zero findings on existing 11 packs + 59 plugin entries). ## Verification - `npm test` — **178/178 green** (incl. 8 new domain-scope cases; pre-existing 170 unaffected). - `node scripts/build-catalog.js` — clean against existing 11 packs + 59 plugin entries (zero new S-DOM-002 findings, zero new AJV rejections; no `domain_scope:` declared anywhere in the corpus yet). ## Out of scope (per spec) - stallari-secops-scanner S-DOM-002 rule (separate subagent / separate PR). - stallari-pack-spec docs/CHANGELOG (separate subagent / separate PR). - Blade-side `_meta.domain_attribution` substrate (DD-338 A.2.dom). - Promoting `domain_scope` to required in `granularity.required` (F.4.b). - Promoting S-DOM-002 severity to `.error` (post-A.2.dom). - F.5 (assembler verdict logic consuming `domain_scope`). ## Test plan - [ ] Architect-attended CI green on PR - [ ] Reviewer confirms zero S-DOM-002 findings on the existing live corpus (build-catalog.js output) - [ ] Reviewer scans the 6 fixture files for shape clarity (each documents one branch of the new procedural pass) - [ ] Reviewer confirms 3 example pack YAMLs serve as readable authoring references (not parsed by build — pure documentation) ## Convention compliance - **#17 commit trailers** — exactly one `Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>`; commit ssh-signed by Piers. - **#19 no phone-home** — build-catalog runs offline. - **#22 migration resilience** — `domain_scope` optional; legacy corpus continues to validate. - **#23 substrate-contract reader audit** — F.4 adds a NEW reader contract (build-catalog.js as reader of `tools[].arguments[]` for scope-arg heuristic). Architect appends DD-333 reader-audit table extension post-merge. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Stallari/plugins!16
No description provided.