@shrkcrft/cli 0.1.0-alpha.29 → 0.1.0-alpha.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/asset-preview/apply-asset-preview.js +1 -1
- package/dist/authoring/authoring-kit.d.ts +9 -1
- package/dist/authoring/authoring-kit.d.ts.map +1 -1
- package/dist/authoring/authoring-kit.js +26 -13
- package/dist/bootstrap/unlinked-workspace-dependency.d.ts +11 -0
- package/dist/bootstrap/unlinked-workspace-dependency.d.ts.map +1 -0
- package/dist/bootstrap/unlinked-workspace-dependency.js +99 -0
- package/dist/command-registry.d.ts +100 -1
- package/dist/command-registry.d.ts.map +1 -1
- package/dist/command-registry.js +130 -3
- package/dist/commands/api-diff.command.d.ts.map +1 -1
- package/dist/commands/api-diff.command.js +12 -0
- package/dist/commands/apply.command.d.ts.map +1 -1
- package/dist/commands/apply.command.js +3 -0
- package/dist/commands/arch.command.d.ts.map +1 -1
- package/dist/commands/arch.command.js +26 -7
- package/dist/commands/architecture.command.d.ts.map +1 -1
- package/dist/commands/architecture.command.js +8 -2
- package/dist/commands/baseline.command.d.ts +76 -0
- package/dist/commands/baseline.command.d.ts.map +1 -1
- package/dist/commands/baseline.command.js +599 -75
- package/dist/commands/biome.command.d.ts.map +1 -1
- package/dist/commands/biome.command.js +20 -0
- package/dist/commands/boundaries.command.d.ts +9 -1
- package/dist/commands/boundaries.command.d.ts.map +1 -1
- package/dist/commands/boundaries.command.js +88 -20
- package/dist/commands/bundle.command.d.ts.map +1 -1
- package/dist/commands/bundle.command.js +57 -11
- package/dist/commands/cache-align.command.d.ts.map +1 -1
- package/dist/commands/cache-align.command.js +3 -1
- package/dist/commands/changelog-data.d.ts.map +1 -1
- package/dist/commands/changelog-data.js +164 -0
- package/dist/commands/changes.command.d.ts.map +1 -1
- package/dist/commands/changes.command.js +15 -0
- package/dist/commands/check.command.d.ts.map +1 -1
- package/dist/commands/check.command.js +1260 -324
- package/dist/commands/checks.command.d.ts.map +1 -1
- package/dist/commands/checks.command.js +188 -40
- package/dist/commands/ci.command.d.ts.map +1 -1
- package/dist/commands/ci.command.js +35 -2
- package/dist/commands/code-intel.command.d.ts.map +1 -1
- package/dist/commands/code-intel.command.js +8 -1
- package/dist/commands/command-catalog.d.ts +23 -1
- package/dist/commands/command-catalog.d.ts.map +1 -1
- package/dist/commands/command-catalog.js +152 -35
- package/dist/commands/commands.command.d.ts +21 -3
- package/dist/commands/commands.command.d.ts.map +1 -1
- package/dist/commands/commands.command.js +172 -27
- package/dist/commands/compress.command.d.ts.map +1 -1
- package/dist/commands/compress.command.js +4 -0
- package/dist/commands/constructs.command.d.ts.map +1 -1
- package/dist/commands/constructs.command.js +50 -12
- package/dist/commands/context.command.d.ts.map +1 -1
- package/dist/commands/context.command.js +40 -5
- package/dist/commands/contract-templates.command.d.ts.map +1 -1
- package/dist/commands/contract-templates.command.js +9 -1
- package/dist/commands/contract.command.d.ts.map +1 -1
- package/dist/commands/contract.command.js +35 -0
- package/dist/commands/conventions.command.d.ts.map +1 -1
- package/dist/commands/conventions.command.js +189 -29
- package/dist/commands/coverage.command.d.ts.map +1 -1
- package/dist/commands/coverage.command.js +9 -0
- package/dist/commands/daily.commands.d.ts +0 -1
- package/dist/commands/daily.commands.d.ts.map +1 -1
- package/dist/commands/daily.commands.js +12 -76
- package/dist/commands/dashboard.command.d.ts.map +1 -1
- package/dist/commands/dashboard.command.js +10 -0
- package/dist/commands/dev.command.d.ts.map +1 -1
- package/dist/commands/dev.command.js +45 -2
- package/dist/commands/diagnostics.command.d.ts +0 -2
- package/dist/commands/diagnostics.command.d.ts.map +1 -1
- package/dist/commands/diagnostics.command.js +5 -78
- package/dist/commands/diff-check.command.d.ts +6 -4
- package/dist/commands/diff-check.command.d.ts.map +1 -1
- package/dist/commands/diff-check.command.js +190 -103
- package/dist/commands/docs-references.command.d.ts +20 -0
- package/dist/commands/docs-references.command.d.ts.map +1 -0
- package/dist/commands/docs-references.command.js +520 -0
- package/dist/commands/doctor.command.d.ts.map +1 -1
- package/dist/commands/doctor.command.js +60 -5
- package/dist/commands/drift.command.d.ts.map +1 -1
- package/dist/commands/drift.command.js +17 -4
- package/dist/commands/eslint.command.d.ts.map +1 -1
- package/dist/commands/eslint.command.js +20 -0
- package/dist/commands/export.command.d.ts.map +1 -1
- package/dist/commands/export.command.js +23 -1
- package/dist/commands/feedback-dispatch.command.d.ts.map +1 -1
- package/dist/commands/feedback-dispatch.command.js +29 -0
- package/dist/commands/feedback.command.d.ts.map +1 -1
- package/dist/commands/feedback.command.js +6 -1
- package/dist/commands/finish.command.d.ts.map +1 -1
- package/dist/commands/finish.command.js +32 -8
- package/dist/commands/fix.command.d.ts.map +1 -1
- package/dist/commands/fix.command.js +19 -0
- package/dist/commands/gate.command.d.ts +6 -1
- package/dist/commands/gate.command.d.ts.map +1 -1
- package/dist/commands/gate.command.js +50 -124
- package/dist/commands/gates.command.d.ts +54 -0
- package/dist/commands/gates.command.d.ts.map +1 -1
- package/dist/commands/gates.command.js +1314 -64
- package/dist/commands/gen.command.d.ts.map +1 -1
- package/dist/commands/gen.command.js +4 -0
- package/dist/commands/generated.command.d.ts +62 -0
- package/dist/commands/generated.command.d.ts.map +1 -1
- package/dist/commands/generated.command.js +639 -156
- package/dist/commands/graph-code-subverbs.d.ts +15 -0
- package/dist/commands/graph-code-subverbs.d.ts.map +1 -1
- package/dist/commands/graph-code-subverbs.js +203 -25
- package/dist/commands/graph.command.d.ts.map +1 -1
- package/dist/commands/graph.command.js +79 -37
- package/dist/commands/help.command.d.ts +30 -6
- package/dist/commands/help.command.d.ts.map +1 -1
- package/dist/commands/help.command.js +323 -199
- package/dist/commands/helper.command.d.ts +1 -0
- package/dist/commands/helper.command.d.ts.map +1 -1
- package/dist/commands/helper.command.js +195 -56
- package/dist/commands/impact.command.d.ts.map +1 -1
- package/dist/commands/impact.command.js +115 -12
- package/dist/commands/infer.command.d.ts.map +1 -1
- package/dist/commands/infer.command.js +20 -45
- package/dist/commands/ingest.command.d.ts +0 -1
- package/dist/commands/ingest.command.d.ts.map +1 -1
- package/dist/commands/ingest.command.js +25 -41
- package/dist/commands/knowledge-author.command.d.ts +0 -3
- package/dist/commands/knowledge-author.command.d.ts.map +1 -1
- package/dist/commands/knowledge-author.command.js +10 -23
- package/dist/commands/knowledge.command.d.ts.map +1 -1
- package/dist/commands/knowledge.command.js +469 -129
- package/dist/commands/languages.command.d.ts.map +1 -1
- package/dist/commands/languages.command.js +27 -0
- package/dist/commands/lint.command.d.ts.map +1 -1
- package/dist/commands/lint.command.js +3 -0
- package/dist/commands/mcp.command.d.ts +18 -0
- package/dist/commands/mcp.command.d.ts.map +1 -1
- package/dist/commands/mcp.command.js +33 -8
- package/dist/commands/onboard.command.d.ts.map +1 -1
- package/dist/commands/onboard.command.js +20 -0
- package/dist/commands/owners.command.d.ts.map +1 -1
- package/dist/commands/owners.command.js +14 -2
- package/dist/commands/packs-new.d.ts +13 -1
- package/dist/commands/packs-new.d.ts.map +1 -1
- package/dist/commands/packs-new.js +500 -335
- package/dist/commands/packs.command.d.ts.map +1 -1
- package/dist/commands/packs.command.js +378 -36
- package/dist/commands/paths.command.d.ts.map +1 -1
- package/dist/commands/paths.command.js +9 -1
- package/dist/commands/pipelines.command.d.ts.map +1 -1
- package/dist/commands/pipelines.command.js +7 -1
- package/dist/commands/plan-check.command.d.ts.map +1 -1
- package/dist/commands/plan-check.command.js +3 -0
- package/dist/commands/plan.command.d.ts.map +1 -1
- package/dist/commands/plan.command.js +3 -0
- package/dist/commands/playbooks.command.d.ts.map +1 -1
- package/dist/commands/playbooks.command.js +7 -2
- package/dist/commands/policy-lint.command.d.ts +19 -2
- package/dist/commands/policy-lint.command.d.ts.map +1 -1
- package/dist/commands/policy-lint.command.js +224 -65
- package/dist/commands/policy.command.d.ts.map +1 -1
- package/dist/commands/policy.command.js +6 -1
- package/dist/commands/pr.command.d.ts.map +1 -1
- package/dist/commands/pr.command.js +14 -0
- package/dist/commands/presets.command.d.ts.map +1 -1
- package/dist/commands/presets.command.js +12 -27
- package/dist/commands/profiles.command.d.ts.map +1 -1
- package/dist/commands/profiles.command.js +94 -26
- package/dist/commands/provenance.command.js +1 -1
- package/dist/commands/quality.command.d.ts.map +1 -1
- package/dist/commands/quality.command.js +129 -33
- package/dist/commands/recommend.command.d.ts +20 -4
- package/dist/commands/recommend.command.d.ts.map +1 -1
- package/dist/commands/recommend.command.js +172 -278
- package/dist/commands/registrations.command.d.ts.map +1 -1
- package/dist/commands/registrations.command.js +138 -13
- package/dist/commands/registry-lifecycle-run.d.ts +14 -0
- package/dist/commands/registry-lifecycle-run.d.ts.map +1 -0
- package/dist/commands/registry-lifecycle-run.js +336 -0
- package/dist/commands/registry.command.d.ts.map +1 -1
- package/dist/commands/registry.command.js +235 -62
- package/dist/commands/release.command.d.ts.map +1 -1
- package/dist/commands/release.command.js +99 -20
- package/dist/commands/report.command.d.ts.map +1 -1
- package/dist/commands/report.command.js +38 -2
- package/dist/commands/reuse-coverage.command.d.ts +23 -0
- package/dist/commands/reuse-coverage.command.d.ts.map +1 -0
- package/dist/commands/reuse-coverage.command.js +536 -0
- package/dist/commands/reuse.command.d.ts +3 -18
- package/dist/commands/reuse.command.d.ts.map +1 -1
- package/dist/commands/reuse.command.js +395 -244
- package/dist/commands/review.command.d.ts.map +1 -1
- package/dist/commands/review.command.js +33 -1
- package/dist/commands/rounds.command.d.ts.map +1 -1
- package/dist/commands/rounds.command.js +5 -0
- package/dist/commands/safety.command.d.ts.map +1 -1
- package/dist/commands/safety.command.js +9 -0
- package/dist/commands/scaffolds.command.d.ts.map +1 -1
- package/dist/commands/scaffolds.command.js +97 -25
- package/dist/commands/search.command.d.ts +0 -8
- package/dist/commands/search.command.d.ts.map +1 -1
- package/dist/commands/search.command.js +136 -28
- package/dist/commands/self-config-xrefs.command.d.ts +24 -0
- package/dist/commands/self-config-xrefs.command.d.ts.map +1 -0
- package/dist/commands/self-config-xrefs.command.js +170 -0
- package/dist/commands/self-config.command.d.ts.map +1 -1
- package/dist/commands/self-config.command.js +261 -65
- package/dist/commands/smart-context.command.d.ts.map +1 -1
- package/dist/commands/smart-context.command.js +39 -3
- package/dist/commands/spec.command.d.ts.map +1 -1
- package/dist/commands/spec.command.js +3 -0
- package/dist/commands/stats.command.d.ts.map +1 -1
- package/dist/commands/stats.command.js +3 -0
- package/dist/commands/surface.command.d.ts +6 -1
- package/dist/commands/surface.command.d.ts.map +1 -1
- package/dist/commands/surface.command.js +256 -54
- package/dist/commands/task-context.command.js +1 -1
- package/dist/commands/task.command.d.ts.map +1 -1
- package/dist/commands/task.command.js +22 -1
- package/dist/commands/templates.command.d.ts +4 -0
- package/dist/commands/templates.command.d.ts.map +1 -1
- package/dist/commands/templates.command.js +109 -22
- package/dist/commands/test.command.d.ts.map +1 -1
- package/dist/commands/test.command.js +161 -33
- package/dist/commands/tests.command.d.ts.map +1 -1
- package/dist/commands/tests.command.js +29 -3
- package/dist/commands/trace.command.d.ts.map +1 -1
- package/dist/commands/trace.command.js +29 -4
- package/dist/commands/watch.command.d.ts.map +1 -1
- package/dist/commands/watch.command.js +3 -0
- package/dist/commands/why.command.d.ts.map +1 -1
- package/dist/commands/why.command.js +3 -0
- package/dist/commands/wiring.command.d.ts +18 -4
- package/dist/commands/wiring.command.d.ts.map +1 -1
- package/dist/commands/wiring.command.js +362 -74
- package/dist/dashboard/code-intelligence-data.js +4 -4
- package/dist/diff/deleted-orphan-coverage.d.ts +32 -0
- package/dist/diff/deleted-orphan-coverage.d.ts.map +1 -0
- package/dist/diff/deleted-orphan-coverage.js +107 -0
- package/dist/diff/deleted-orphan-scope-notes.d.ts +23 -0
- package/dist/diff/deleted-orphan-scope-notes.d.ts.map +1 -0
- package/dist/diff/deleted-orphan-scope-notes.js +49 -0
- package/dist/diff/deleted-orphans.d.ts +32 -0
- package/dist/diff/deleted-orphans.d.ts.map +1 -1
- package/dist/diff/deleted-orphans.js +42 -2
- package/dist/dispatch/closest-match.d.ts +15 -0
- package/dist/dispatch/closest-match.d.ts.map +1 -0
- package/dist/dispatch/closest-match.js +47 -0
- package/dist/dispatch/global-flags.d.ts +94 -0
- package/dist/dispatch/global-flags.d.ts.map +1 -0
- package/dist/dispatch/global-flags.js +123 -0
- package/dist/dispatch/guard-invocation-input.d.ts +24 -0
- package/dist/dispatch/guard-invocation-input.d.ts.map +1 -0
- package/dist/dispatch/guard-invocation-input.js +1 -0
- package/dist/dispatch/guard-invocation.d.ts +33 -0
- package/dist/dispatch/guard-invocation.d.ts.map +1 -0
- package/dist/dispatch/guard-invocation.js +183 -0
- package/dist/dispatch/help-intercept.d.ts +22 -0
- package/dist/dispatch/help-intercept.d.ts.map +1 -0
- package/dist/dispatch/help-intercept.js +42 -0
- package/dist/dispatch/i-declared-invocation.d.ts +17 -0
- package/dist/dispatch/i-declared-invocation.d.ts.map +1 -0
- package/dist/dispatch/i-declared-invocation.js +1 -0
- package/dist/dispatch/i-unknown-flag-refusal-input.d.ts +28 -0
- package/dist/dispatch/i-unknown-flag-refusal-input.d.ts.map +1 -0
- package/dist/dispatch/i-unknown-flag-refusal-input.js +1 -0
- package/dist/dispatch/invocation-rejection-kind.d.ts +15 -0
- package/dist/dispatch/invocation-rejection-kind.d.ts.map +1 -0
- package/dist/dispatch/invocation-rejection-kind.js +15 -0
- package/dist/dispatch/invocation-rejection.d.ts +18 -0
- package/dist/dispatch/invocation-rejection.d.ts.map +1 -0
- package/dist/dispatch/invocation-rejection.js +1 -0
- package/dist/dispatch/judge-invocation.d.ts +24 -0
- package/dist/dispatch/judge-invocation.d.ts.map +1 -0
- package/dist/dispatch/judge-invocation.js +50 -0
- package/dist/dispatch/positional-mode.d.ts +18 -0
- package/dist/dispatch/positional-mode.d.ts.map +1 -0
- package/dist/dispatch/positional-mode.js +18 -0
- package/dist/dispatch/read-tracking-map.d.ts +28 -0
- package/dist/dispatch/read-tracking-map.d.ts.map +1 -0
- package/dist/dispatch/read-tracking-map.js +58 -0
- package/dist/dispatch/refuse-sibling-valve-flags.d.ts +30 -0
- package/dist/dispatch/refuse-sibling-valve-flags.d.ts.map +1 -0
- package/dist/dispatch/refuse-sibling-valve-flags.js +65 -0
- package/dist/dispatch/subverb-spec.d.ts +26 -0
- package/dist/dispatch/subverb-spec.d.ts.map +1 -0
- package/dist/dispatch/subverb-spec.js +1 -0
- package/dist/dispatch/undocumented-flag-reads.d.ts +22 -0
- package/dist/dispatch/undocumented-flag-reads.d.ts.map +1 -0
- package/dist/dispatch/undocumented-flag-reads.js +283 -0
- package/dist/dispatch/unknown-flag-refusal-mode.d.ts +13 -0
- package/dist/dispatch/unknown-flag-refusal-mode.d.ts.map +1 -0
- package/dist/dispatch/unknown-flag-refusal-mode.js +13 -0
- package/dist/dispatch/unknown-flag-refusal.d.ts +22 -0
- package/dist/dispatch/unknown-flag-refusal.d.ts.map +1 -0
- package/dist/dispatch/unknown-flag-refusal.js +57 -0
- package/dist/dispatch/unread-flags.d.ts +152 -0
- package/dist/dispatch/unread-flags.d.ts.map +1 -0
- package/dist/dispatch/unread-flags.js +295 -0
- package/dist/dispatch/verdict-valve-flag.d.ts +21 -0
- package/dist/dispatch/verdict-valve-flag.d.ts.map +1 -0
- package/dist/dispatch/verdict-valve-flag.js +21 -0
- package/dist/dispatch/walk-declared-subverbs.d.ts +14 -0
- package/dist/dispatch/walk-declared-subverbs.d.ts.map +1 -0
- package/dist/dispatch/walk-declared-subverbs.js +28 -0
- package/dist/exit-codes.d.ts +41 -3
- package/dist/exit-codes.d.ts.map +1 -1
- package/dist/exit-codes.js +153 -14
- package/dist/finish/run-finish.d.ts +72 -5
- package/dist/finish/run-finish.d.ts.map +1 -1
- package/dist/finish/run-finish.js +453 -104
- package/dist/gates/accepted-empty-note.d.ts +10 -0
- package/dist/gates/accepted-empty-note.d.ts.map +1 -0
- package/dist/gates/accepted-empty-note.js +11 -0
- package/dist/gates/allow-empty.d.ts +25 -0
- package/dist/gates/allow-empty.d.ts.map +1 -0
- package/dist/gates/allow-empty.js +27 -0
- package/dist/gates/asset-doctor-failing-units.d.ts +16 -0
- package/dist/gates/asset-doctor-failing-units.d.ts.map +1 -0
- package/dist/gates/asset-doctor-failing-units.js +14 -0
- package/dist/gates/asset-doctor-failure-line.d.ts +16 -0
- package/dist/gates/asset-doctor-failure-line.d.ts.map +1 -0
- package/dist/gates/asset-doctor-failure-line.js +28 -0
- package/dist/gates/empty-rule-advice-lines.d.ts +15 -0
- package/dist/gates/empty-rule-advice-lines.d.ts.map +1 -0
- package/dist/gates/empty-rule-advice-lines.js +20 -0
- package/dist/gates/gate-envelope.d.ts +85 -8
- package/dist/gates/gate-envelope.d.ts.map +1 -1
- package/dist/gates/gate-envelope.js +56 -7
- package/dist/gates/gate-rule-globs.d.ts +67 -0
- package/dist/gates/gate-rule-globs.d.ts.map +1 -0
- package/dist/gates/gate-rule-globs.js +139 -0
- package/dist/gates/gate-rule-view.d.ts +25 -6
- package/dist/gates/gate-rule-view.d.ts.map +1 -1
- package/dist/gates/gate-rule-view.js +105 -77
- package/dist/gates/i-coverage-dead-glob.d.ts +19 -0
- package/dist/gates/i-coverage-dead-glob.d.ts.map +1 -0
- package/dist/gates/i-coverage-dead-glob.js +1 -0
- package/dist/gates/i-coverage-negation.d.ts +13 -0
- package/dist/gates/i-coverage-negation.d.ts.map +1 -0
- package/dist/gates/i-coverage-negation.js +1 -0
- package/dist/gates/i-registration-query-settle-input.d.ts +18 -0
- package/dist/gates/i-registration-query-settle-input.d.ts.map +1 -0
- package/dist/gates/i-registration-query-settle-input.js +1 -0
- package/dist/gates/i-unit-state-note-row.d.ts +16 -0
- package/dist/gates/i-unit-state-note-row.d.ts.map +1 -0
- package/dist/gates/i-unit-state-note-row.js +1 -0
- package/dist/gates/i-unit-state-notes.d.ts +32 -0
- package/dist/gates/i-unit-state-notes.d.ts.map +1 -0
- package/dist/gates/i-unit-state-notes.js +1 -0
- package/dist/gates/incomplete-registry-inventory.d.ts +19 -0
- package/dist/gates/incomplete-registry-inventory.d.ts.map +1 -0
- package/dist/gates/incomplete-registry-inventory.js +63 -0
- package/dist/gates/measure-registration-roles.d.ts +10 -0
- package/dist/gates/measure-registration-roles.d.ts.map +1 -0
- package/dist/gates/measure-registration-roles.js +9 -0
- package/dist/gates/plane-verdict.d.ts +14 -0
- package/dist/gates/plane-verdict.d.ts.map +1 -0
- package/dist/gates/plane-verdict.js +22 -0
- package/dist/gates/qualify-clean-for-units.d.ts +12 -0
- package/dist/gates/qualify-clean-for-units.d.ts.map +1 -0
- package/dist/gates/qualify-clean-for-units.js +18 -0
- package/dist/gates/registration-graph-verdict.d.ts +34 -0
- package/dist/gates/registration-graph-verdict.d.ts.map +1 -0
- package/dist/gates/registration-graph-verdict.js +70 -0
- package/dist/gates/registration-roles.d.ts +9 -0
- package/dist/gates/registration-roles.d.ts.map +1 -0
- package/dist/gates/registration-roles.js +1 -0
- package/dist/gates/registry-liveness.d.ts +11 -0
- package/dist/gates/registry-liveness.d.ts.map +1 -0
- package/dist/gates/registry-liveness.js +13 -0
- package/dist/gates/rule-coverage.d.ts +225 -4
- package/dist/gates/rule-coverage.d.ts.map +1 -1
- package/dist/gates/rule-coverage.js +610 -43
- package/dist/gates/run-gate-planes.d.ts +58 -0
- package/dist/gates/run-gate-planes.d.ts.map +1 -0
- package/dist/gates/run-gate-planes.js +403 -0
- package/dist/gates/scaffold-selftest.d.ts +56 -0
- package/dist/gates/scaffold-selftest.d.ts.map +1 -0
- package/dist/gates/scaffold-selftest.js +119 -0
- package/dist/gates/seam-rejected-rules.d.ts +28 -0
- package/dist/gates/seam-rejected-rules.d.ts.map +1 -0
- package/dist/gates/seam-rejected-rules.js +95 -0
- package/dist/gates/self-test-check.d.ts +29 -0
- package/dist/gates/self-test-check.d.ts.map +1 -0
- package/dist/gates/self-test-check.js +1 -0
- package/dist/gates/self-test-subject.d.ts +28 -0
- package/dist/gates/self-test-subject.d.ts.map +1 -0
- package/dist/gates/self-test-subject.js +1 -0
- package/dist/gates/self-test.d.ts +20 -0
- package/dist/gates/self-test.d.ts.map +1 -0
- package/dist/gates/self-test.js +82 -0
- package/dist/gates/settle-verdict.d.ts +14 -0
- package/dist/gates/settle-verdict.d.ts.map +1 -0
- package/dist/gates/settle-verdict.js +13 -0
- package/dist/gates/settled-verdict.d.ts +8 -0
- package/dist/gates/settled-verdict.d.ts.map +1 -0
- package/dist/gates/settled-verdict.js +1 -0
- package/dist/gates/template-registry-coverage.d.ts +18 -0
- package/dist/gates/template-registry-coverage.d.ts.map +1 -0
- package/dist/gates/template-registry-coverage.js +24 -0
- package/dist/gates/unit-state-notes.d.ts +40 -0
- package/dist/gates/unit-state-notes.d.ts.map +1 -0
- package/dist/gates/unit-state-notes.js +71 -0
- package/dist/gates/verdict-line.d.ts +18 -0
- package/dist/gates/verdict-line.d.ts.map +1 -0
- package/dist/gates/verdict-line.js +40 -0
- package/dist/graph/graph-reuse-lookup.d.ts +10 -0
- package/dist/graph/graph-reuse-lookup.d.ts.map +1 -0
- package/dist/graph/graph-reuse-lookup.js +41 -0
- package/dist/graph/index-behind-hint.d.ts +11 -0
- package/dist/graph/index-behind-hint.d.ts.map +1 -0
- package/dist/graph/index-behind-hint.js +27 -0
- package/dist/knowledge/knowledge-stale-gate-flags.d.ts +3 -0
- package/dist/knowledge/knowledge-stale-gate-flags.d.ts.map +1 -0
- package/dist/knowledge/knowledge-stale-gate-flags.js +1 -0
- package/dist/knowledge/knowledge-stale-gate-input.d.ts +3 -0
- package/dist/knowledge/knowledge-stale-gate-input.d.ts.map +1 -0
- package/dist/knowledge/knowledge-stale-gate-input.js +1 -0
- package/dist/knowledge/knowledge-stale-gate-result.d.ts +3 -0
- package/dist/knowledge/knowledge-stale-gate-result.d.ts.map +1 -0
- package/dist/knowledge/knowledge-stale-gate-result.js +1 -0
- package/dist/knowledge/knowledge-stale-gate.d.ts +10 -0
- package/dist/knowledge/knowledge-stale-gate.d.ts.map +1 -0
- package/dist/knowledge/knowledge-stale-gate.js +9 -0
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +204 -83
- package/dist/output/failure-hints.d.ts.map +1 -1
- package/dist/output/failure-hints.js +11 -9
- package/dist/output/rejected-entries-note.d.ts +57 -0
- package/dist/output/rejected-entries-note.d.ts.map +1 -0
- package/dist/output/rejected-entries-note.js +103 -0
- package/dist/output/stdout-is-pipe.d.ts +13 -0
- package/dist/output/stdout-is-pipe.d.ts.map +1 -0
- package/dist/output/stdout-is-pipe.js +21 -0
- package/dist/packs/stale-build-warning.d.ts +11 -0
- package/dist/packs/stale-build-warning.d.ts.map +1 -0
- package/dist/packs/stale-build-warning.js +23 -0
- package/dist/quality/run-quality.d.ts +123 -0
- package/dist/quality/run-quality.d.ts.map +1 -0
- package/dist/quality/run-quality.js +442 -0
- package/dist/schemas/json-schemas.d.ts +184 -3
- package/dist/schemas/json-schemas.d.ts.map +1 -1
- package/dist/schemas/json-schemas.js +113 -2
- package/dist/shrk.d.ts +3 -0
- package/dist/shrk.d.ts.map +1 -0
- package/dist/shrk.js +30 -0
- package/dist/surface/audience-applicability.d.ts +26 -0
- package/dist/surface/audience-applicability.d.ts.map +1 -0
- package/dist/surface/audience-applicability.js +60 -0
- package/dist/surface/catalog-command-safety.d.ts +18 -0
- package/dist/surface/catalog-command-safety.d.ts.map +1 -0
- package/dist/surface/catalog-command-safety.js +62 -0
- package/dist/surface/cli-command-resolver.d.ts +21 -0
- package/dist/surface/cli-command-resolver.d.ts.map +1 -0
- package/dist/surface/cli-command-resolver.js +87 -0
- package/dist/surface/command-dispatch-kind.d.ts +20 -0
- package/dist/surface/command-dispatch-kind.d.ts.map +1 -0
- package/dist/surface/command-dispatch-kind.js +20 -0
- package/dist/surface/command-index-entry.d.ts +40 -0
- package/dist/surface/command-index-entry.d.ts.map +1 -0
- package/dist/surface/command-index-entry.js +1 -0
- package/dist/surface/command-index.d.ts +77 -0
- package/dist/surface/command-index.d.ts.map +1 -0
- package/dist/surface/command-index.js +323 -0
- package/dist/surface/i-command-index.d.ts +22 -0
- package/dist/surface/i-command-index.d.ts.map +1 -0
- package/dist/surface/i-command-index.js +1 -0
- package/dist/surface/i-command-string-context.d.ts +20 -0
- package/dist/surface/i-command-string-context.d.ts.map +1 -0
- package/dist/surface/i-command-string-context.js +1 -0
- package/dist/surface/i-surface-denial.d.ts +13 -0
- package/dist/surface/i-surface-denial.d.ts.map +1 -0
- package/dist/surface/i-surface-denial.js +1 -0
- package/dist/surface/load-surface-context.d.ts +17 -1
- package/dist/surface/load-surface-context.d.ts.map +1 -1
- package/dist/surface/load-surface-context.js +48 -10
- package/dist/surface/not-enabled-error.d.ts +38 -4
- package/dist/surface/not-enabled-error.d.ts.map +1 -1
- package/dist/surface/not-enabled-error.js +96 -6
- package/dist/surface/profiles.d.ts +7 -0
- package/dist/surface/profiles.d.ts.map +1 -1
- package/dist/surface/resolve-command-string.d.ts +10 -0
- package/dist/surface/resolve-command-string.d.ts.map +1 -0
- package/dist/surface/resolve-command-string.js +572 -0
- package/dist/surface/surface-config-writer.d.ts +7 -2
- package/dist/surface/surface-config-writer.d.ts.map +1 -1
- package/dist/surface/surface-config-writer.js +25 -6
- package/dist/surface/surface-layer.d.ts +11 -0
- package/dist/surface/surface-layer.d.ts.map +1 -0
- package/dist/surface/surface-layer.js +11 -0
- package/dist/surface/surface-refusal-reason.d.ts +16 -0
- package/dist/surface/surface-refusal-reason.d.ts.map +1 -0
- package/dist/surface/surface-refusal-reason.js +16 -0
- package/dist/surface/surface-selector.d.ts +26 -0
- package/dist/surface/surface-selector.d.ts.map +1 -0
- package/dist/surface/surface-selector.js +42 -0
- package/dist/surface/surface-summary.d.ts +61 -18
- package/dist/surface/surface-summary.d.ts.map +1 -1
- package/dist/surface/surface-summary.js +147 -60
- package/dist/surface/tier.d.ts +85 -22
- package/dist/surface/tier.d.ts.map +1 -1
- package/dist/surface/tier.js +132 -30
- package/dist/usage/usage-log.d.ts +6 -1
- package/dist/usage/usage-log.d.ts.map +1 -1
- package/dist/usage/usage-log.js +7 -2
- package/dist/validation/run-validation-loop.d.ts +9 -0
- package/dist/validation/run-validation-loop.d.ts.map +1 -1
- package/dist/validation/run-validation-loop.js +14 -11
- package/dist/validation/typecheck-emitted.d.ts +8 -9
- package/dist/validation/typecheck-emitted.d.ts.map +1 -1
- package/dist/validation/typecheck-emitted.js +17 -97
- package/package.json +34 -34
|
@@ -134,6 +134,32 @@ export const RELEASE_SURFACE_DELTAS = [
|
|
|
134
134
|
],
|
|
135
135
|
removed: [],
|
|
136
136
|
},
|
|
137
|
+
{
|
|
138
|
+
version: '0.1.0-alpha.30',
|
|
139
|
+
title: 'The engine taps the import graph, and reads its own prose',
|
|
140
|
+
added: [
|
|
141
|
+
'`shrk docs references check|explain|list` — the seventh rule plane (`docReferences[]`): ids cited in free-text PROSE (READMEs, docs, agent skill files) that no longer resolve. Markdown has no build, so these drift with zero signal. `requireContext` (default `backtick`), `exempt[]`, a per-line `<!-- ref-allow: why -->` marker, and a length-scaled `did you mean` keep it low-noise. Reads dot-directories a glob explicitly names, so `.claude/skills/**` works.',
|
|
142
|
+
'`shrk gates check` — every rule plane in ONE pass with one exit code (the CI / pre-commit primitive); `--changed-only` scopes by rule footprint, `--strict` promotes warning-severity findings to failures.',
|
|
143
|
+
'`shrk gates try --rule-file <f> [--full]` — dry-run a candidate rule against the tree without adding it to config. Dumps every captured token, so an over-matching `tokenPattern` is visible in one run instead of arriving as noise in CI.',
|
|
144
|
+
'`import-edges` extractor — the resolved dependency graph as a rule input (`emit: edge|symbol|from`, targetable by `to.module` / `to.modulePattern` / `to.files` / `to.match`). Existing planes now express adoption ledgers, orphan detection, deprecation ratchets and targeted fences. Alias-aware; no persisted index, so no staleness.',
|
|
145
|
+
'`filenames` extractor + `mode: parity` — companion-file invariants (every `X.ts` has an `X.test.ts`).',
|
|
146
|
+
'Shared extractors: a top-level `extractors` map plus `{ $use: "<id>" }` on any plane (local fields override). The planes describing one id set can no longer drift apart, and a typo\'d id fails the config load rather than silently matching nothing.',
|
|
147
|
+
'`generatedArtifacts[]` for MIXED trees: `sources[]` (N writers, each verifying its own sub-glob), `handMaintained[]` (literal filenames only, so the exemption cannot silently widen) and `handMaintainedMarker` for an in-file bless. A file under the tree owned by neither is an `unclassified` finding.',
|
|
148
|
+
'`expectEmpty: true` on `baselines[]` — a fence that fails the moment the edge set becomes non-empty.',
|
|
149
|
+
'`shrk check wiring --fix` now adds the missing IMPORT alongside the array member when the specifier is a pure function of the member name AND resolves to the declaring file; otherwise it refuses with `needs-import`.',
|
|
150
|
+
],
|
|
151
|
+
changed: [
|
|
152
|
+
'FIXED (P1): `--fix --write` could green the wiring gate over a file that no longer compiles. The common registry shape IMPORTS its array members, and appending the token alone left `TS2304: Cannot find name`. It now writes both edits or refuses.',
|
|
153
|
+
'FIXED (P1): reference resolution ran in THREE modules — the prose linter and both self-config doctors — each from its own sources, agreeing only by coincidence. The self-config doctor reported 17 of shrk\'s own correctly-registered ids as unknown (its hand-written "known ids" union omitted policies, decisions, scaffold patterns and paths). One resolver now answers for every kind, and each kind reads the source its `list` verb reads.',
|
|
154
|
+
'FIXED (P2): `shrk graph status` judged index freshness by working-tree DIVERGENCE while `shrk code-intel` judged it by wall-clock age — contradictory verdicts on the same index in the same second, with every arch/cycle count derived from it inheriting the staleness unmarked. Divergence is now the single verdict; age is a display detail (`current (indexed 5d ago)` / `STALE — N file(s) changed since index`).',
|
|
155
|
+
'A finding DERIVED from a stale graph index is reported `NOT VERIFIED` rather than as a count — the loud-skip contract the rule planes already honour, extended to the graph-derived surfaces. An unmeasured verdict is never a pass.',
|
|
156
|
+
'An ERRORED rule is no longer counted as `evaluated` by `gates check` / `docs references check`, so a warning-severity rule that could not run exits `2` instead of printing "not blocking" above exit `0`.',
|
|
157
|
+
'A doc-reference rule whose registries are ALL empty refuses loudly instead of reporting every id as unresolved — a gate that confidently flags correct usage is worse than no gate.',
|
|
158
|
+
'`detectGraphFreshness` no longer throws on a store whose `meta.json` exists but whose remaining parts do not (an interrupted index); it reports "could not measure", which reads as not-verified.',
|
|
159
|
+
'`shrk graph status` labels its snapshot size `files indexed` — it deliberately does not move when a new file appears on disk; that shows up on the `drift` line.',
|
|
160
|
+
],
|
|
161
|
+
removed: [],
|
|
162
|
+
},
|
|
137
163
|
{
|
|
138
164
|
version: '0.1.0-alpha.29',
|
|
139
165
|
title: 'The exit code has to agree with the sentence',
|
|
@@ -154,4 +180,142 @@ export const RELEASE_SURFACE_DELTAS = [
|
|
|
154
180
|
],
|
|
155
181
|
removed: [],
|
|
156
182
|
},
|
|
183
|
+
{
|
|
184
|
+
version: '0.1.0-alpha.31',
|
|
185
|
+
title: 'Checks that cannot pass over what they did not examine, and a dispatcher that refuses what it does not know',
|
|
186
|
+
added: [
|
|
187
|
+
'Coverage on every verdict: each `gate` envelope rule and the run carry `coverage` (`IVerdictCoverage` in `@shrkcrft/core`: `expected` vs `examined`, `capped`, `unexamined`, `acceptedBy`) plus `shortfalls` / `accepted`, and a rule that passed over only part of its scope reads `partial`. `settleVerdict` (core) is the one guard that turns a proposed `0` into `2` on any shortfall; `verdictLine` is the one way a verb prints its ✓. See docs/exit-codes.md.',
|
|
188
|
+
'Explicit, printed valves for a gap: `--allow-empty` (an empty request: no rules, nothing in scope, nothing deleted, nothing configured) on `check wiring|boundaries|orphans|registry-lifecycle`, `registry lifecycle`, `policy-lint`, `gates check`, `finish`, `diff-check`, `impact --deleted`, `knowledge stale-check|verify`, `reuse coverage`, `test agent|context` and the helper / templates / packs / checks / conventions / registrations / scaffolds / search tuning doctors; `registeredExtras` (literal ids, or `"allow"`) on a subset wiring rule; `--min-referenced <ratio>` / `knowledgeCheck.minReferenced` for knowledge entries with no checkable reference. A valve never accepts rules that exist but checked nothing, and never a load failure.',
|
|
189
|
+
'`shrk reuse coverage` — curated `reusePrimitives[]` against the real public export surface: dead curated entries, `importPath`s that do not expose their symbol, and curation gaps (an exported name the lookup answers with a different curated entry). `--min-coverage <pct>`, `--package <name>`, `--include-types`, `--all`, `--allow-empty`; gate envelope, rule type `reuse`. Also `shrk reuse --curated-only` / `--include-types`, `reusePrimitives[].supersedes`, `GraphQueryApi.publicExportSurface()` / `resolveExportedName()` and the package-node `entryFile` (re-index to populate).',
|
|
190
|
+
'`shrk self-config resolve <id>` (every registry an id resolves in, plus every declared cross-reference pointing at it; did-you-mean when it resolves nowhere) and `shrk self-config xrefs [--source <kind>:<id>] [--dangling-only]`. Knowledge `seeAlso` / `supersededBy` (TS and Markdown): `shrk knowledge get` opens a superseded entry with a SUPERSEDED banner, renders `See also:` / `Related:` with each id namespace, and `--follow` renders the current entry. Construct facets may declare `resolvesAs: [<kind>]`.',
|
|
191
|
+
'Knowledge references can assert more: `contains` / `matches` (zoned by `scan`) and `count` (re-derived by the extraction DSL), `Owner.member` symbols and the `symbol:Name@path` grammar, a `verifiedOn` field, and `references[]` on boundary rules and policy checks (swept by the same check). `knowledge stale-check` gains `--require-references`, `--stale-after` / `--as-of`, and validated `--fail-on` categories `unverifiable | path-missing | anchor-missing | content | count | aged | implicit | invalid`; config `knowledgeCheck.minReferenced` / `requireReferences`.',
|
|
192
|
+
'Boundary rules: `exemptFiles`, `excludeTests`, `!` globs in `from`, `exceptions[{ path, target, reason }]` (suppressed violations are counted, never dropped; an exception that matches nothing is an error) and `forbiddenMatch: "exact"`. `shrk check boundaries --rule-file <path>` evaluates a candidate rule file; `--diff-against <path>` is a dry run of the violations a candidate set would add or remove; plus `--include-comments`, `--fail-on-dead-units` and `--no-rule-escalation`.',
|
|
193
|
+
'The audience gate and a deny list: commands that maintain SharkCraft itself are tagged `tool-maintenance`; `surface.disabled` (config and profiles) refuses a command, and `"<group> *"` selectors work in `hidden`, `enabled` and `disabled`. New `shrk surface deny <selector>` / `shrk surface allow <selector>` (preview-first). `surface list` gains an audience column and a host line.',
|
|
194
|
+
'One command index: `shrk surface list` lists every dispatchable verb, subverb and meta flag, not only catalog rows (`sharkcraft.surface.v2`); `surface explain` takes multi-word paths; handlers declare their `subverbs` / `positionals` / `flags`, which `help`, the dispatcher and the index all read. Command strings in assets (agent tests, routing and registration hints, pipelines, playbooks, constructs, presets, knowledge, decisions) are resolved against the index, the package.json scripts and the MCP tool names (`unknown-command`, with did-you-mean).',
|
|
195
|
+
'Packs: `--typecheck` on `packs test|doctor|release-check` (one in-process check, also behind `gen --typecheck`); `packs sign` records `signature.contentDigests`; `shrk helper doctor` and a real `helper --source`; templates declare `notScaffolded` / `manualSteps` (printed by gen / preview / get, checked by lint); scaffold strategies `className.stripSuffix:`, `filename.stripSuffix:`, `directoryName.pascal`, `directoryName.kebab`.',
|
|
196
|
+
'`shrk check registry-lifecycle` / `shrk registry lifecycle`: `--limit <n>` (`0` = uncapped), `--offset <n>`, `--budget-ms <n>`, `--allow-empty`. Candidates are sorted by path, so `--offset <nextOffset>` continues a capped, timed-out or interrupted scan where it stopped; MCP `get_registry_lifecycle_report` takes `offset` and returns `verdict` / `nextOffset`. `registryLifecycle.skipDirsAdd` extends the default skip set (`skipDirs` still replaces it, and dropping node_modules / dist / build / out / coverage / .sharkcraft is warned about).',
|
|
197
|
+
'`areaMap` config (`patterns[{ kind, match[], id? }]`, `replaceDefaults`, `minClassificationRate`); the area map reports `classificationRate` / `degraded` / `unclassifiedSample`, and `AreaKind` moved to `@shrkcrft/core`. `findBlankRunHazards` (@shrkcrft/boundaries) lints regexes that backtrack on a zone-blanked buffer; `gates coverage` shows it as the extractor hint.',
|
|
198
|
+
'Asset doctors: `search tuning doctor` lints every boost key and trigger (`target-missing`, `key-unprefixed`, `key-unknown-kind`, `boost-excluded-by-kind`, `duplicate-trigger`, `unreachable-trigger`, `cap-discards`, …); `registrations doctor` classifies each hint discovery as verified / ambiguous / dead / unverified; `scaffolds doctor` counts what each `matchPaths` glob matches. All take `--strict` / `--fail-on-dead-units` / `--allow-empty` (nothing declared is NOT VERIFIED unless accepted), and `--json` adds `coverage` / `deadUnits` / `exitCode` / `verdict`. MCP `get_self_config_doctor` takes `schema: "v1" | "v2"`.',
|
|
199
|
+
'Routing hints: `recommends.pipelines` / `rules` / `paths`, `match.mode: "tokens" | "substring"`, and load lints (`invalid-regex`, `empty-trigger`, `duplicate-trigger`, `unscored-match-criteria`, `ignored-match-criteria`, `unknown-recommends-key`); playbooks take `matchMode`. MCP `prepare_agent_task` returns `recommendedAssets`.',
|
|
200
|
+
'`shrk recommend --min-score <n>` (config `recommend.minScore`, MCP `recommend_commands` `minScore`) and `--require-confident` (exit 2 when nothing matched with confidence); config `recommend.scaffoldRequiresCreateIntent`. The report carries `confident` / `verdict` / `floor` / `bestScore`.',
|
|
201
|
+
'Rule authoring: `gates try` evaluates the candidate `selfTest` (every expectation held / FAILED / NOT EVALUABLE) and takes `--flags <f>`; `gates coverage --fail-on-dead-units` fails a glob that matched nothing inside a connected rule; `failOnEmpty` on `registries[]` and `registrationGraph[]`.',
|
|
202
|
+
'New `shrk quality` items: `gates-coverage` (a broken selfTest fails the gate, a stale selector is NOT VERIFIED), `cross-references` and `knowledge-stale`.',
|
|
203
|
+
'Round 12 (12.3): the builtin `workspace` profile kind — `shrk profiles list --kind workspace` / MCP `list_profiles {kind:"workspace"}` list every `WorkspaceProfile` id (`has-typescript`, `is-library`, …) with this repo\'s `detected` flag and evidence (reference kind `workspace-profile`, label table `describeWorkspaceProfile` in @shrkcrft/workspace). `REFERENCE_KIND_DECLARATIONS` / `isReferenceKindDeclarable` (@shrkcrft/inspector) record how every resolvable reference kind is declared (builtin, config key, local file, pack key), locked by a test that declares an id through every path; `PROBED_ID_FIELDS` is the one field → kind binding the self-config doctor probes. New self-config coverage records `conventions · applicability profile ids` and `templates · required ids`, and a `convention-profile-missing` (info) finding.',
|
|
204
|
+
'Round 12 (12.1 + the one change): `shrk packs contributions` is THE contributions report — a `By file:` section lists every contributed file (local and pack) with entries declared · accepted · rejected, each rejected entry with every reason (`\'conv.b\' (default[8]) — severity: …`), and the references it declares that cannot be checked because their kind\'s registry is empty or undeclarable; `--json` / MCP `get_pack_contributions` add `report: { files[], totals, referenceCoverage? }` and `rejections[]`. Every list verb (`knowledge`, `templates`, `pipelines`, `presets`, `boundaries`, `scaffolds`, `policy`, `constructs`, `playbooks`, `search tuning`, `feedback rules`, `contract template`, `profiles`, `conventions`, `helper`, `registrations`) prints `⚠ N entr(y|ies) rejected from <file>: …` after its list (exit unchanged; `--json` writes a one-line stderr `note:`). `packs list` / `packs get` / MCP `list_packs` / `get_pack` show per-kind accepted / REJECTED entries (`entryCounts`, `REJECTED-ENTRIES`) and every declared slot. New exports: `IRejectedEntry` / `RejectionCause` / `readContributionExport` (@shrkcrft/core); `collectRegistryOutcomes`, `collectContributionRejections`, `collectKindRejections`, `formatEntryRejection`, `validateContributionFile`, `buildContributionsReport`, `collectUnresolvableReferences`, `packEntryCounts` and one `<kind>RejectionReasons` predicate per kind (@shrkcrft/inspector); `frameworkExtractorExports` / `frameworkExtractorRejectionReasons` (@shrkcrft/plugin-api); `DelegateRecipeSchema` (@shrkcrft/config).',
|
|
205
|
+
'Round 13 (keystone — an empty result can be the intended one; `docs/intended-empty.md`): `@shrkcrft/core` gains the liveness module. `normalizeUnitList` / `normalizeUnitScalar` / `normalizeUnitMap` are the one parser for `string | { pattern, expectEmpty: true, reason? }` entries and `number | { weight, expectEmpty: true, reason? }` boost values — loaded lists stay plain strings plus an `expectEmptyUnits` ledger, every malformed marker is refused with a `<list>[i]: …` problem (did-you-mean included), and `stampUnitMarks` records the contributing pack. `settleUnitLiveness` is the one settle for selector units (live / dead / intended-empty / went-live / unproven; one coverage shortfall record over Coverage-weight units and one `acceptedBy: expectEmpty` acceptance record labelled with what was observed); `settleRuleEmptiness` is the one answer for a rule that matched nothing (accepted only when its primary list matched no file and every inclusion unit is intended-empty — never "0 units out of live files"; the baselines fence holds only over live or intended-empty inputs); `selectorUnitFails` is the one `--fail-on-dead-units` predicate (a pack marker that went live is INFO and never fails); `formatUnitLiveness`, `DEAD_SELECTOR_CAUSES` and `EMPTY_RULE_ADVICE` are the one wording; `MARKABLE_UNIT_LISTS` is the table of every markable list. The `gate` envelope rule gains optional `unitAcceptance` (folded into the one verdict settle, so an acceptance is printed in `gate.accepted` at exit 0) and `units` (`dead` / `intendedEmpty` / `wentLive`); no always-present envelope key is added.',
|
|
206
|
+
'Round 13 (lane G): the authored gate-plane types — `IWiringSourceInput`, `IWiringRuleInput`, `IRegistryDeclarationInput`, `IRegistrationIdiomInput`, `IPolicyRuleInput`, `IBaselineRuleInput` / `IBaselineComputeInput`, `IGeneratedArtifactRuleInput`, `IDocReferenceRuleInput` (`@shrkcrft/core`) and `ISharkCraftConfigInput` (`@shrkcrft/config`, taken by `defineSharkCraftConfig`) — widen only the markable lists to `string | { pattern, expectEmpty: true, reason? }`; the loaded types keep plain lists plus `expectEmptyUnits`. One normaliser per shape — `normalizeWiringSource`, `normalizeWiringRule`, `normalizeRuleList` (core) and `normalizePlaneRule`, `normalizePlaneConfig` (config) — serves the config loader, the pack merge seam (which stamps the contributing pack on every marker) and `gates try`, and the engine entries (`inspectSource`, `readGlobListUnits`, `runPolicyLint` / `evaluatePolicy`, `runWiring` / `evaluateWiring`, `checkDocReferences`, the baseline and generated evaluators) normalise idempotently, so a hand-built rule never crashes and never silently ignores a marker. `@shrkcrft/boundaries` gains THE gate-plane glob observation predicate (`globListLivenessInput`), its settle (`settleGlobLists`, `readGlobListLiveness`), the per-source request (`sourceLivenessRequest`) and the wiring side labels (`wiringLabeledSources`).',
|
|
207
|
+
'Round 13 (13.2 — a green build is a runnable build): `scripts/lib/workspace-links.ts` is the one workspace-link check (`bun run scripts/lib/workspace-links.ts`). Every `workspace:` pin in `dependencies` / `peerDependencies` / `optionalDependencies` of every packages/* package (private ones and dashboard included) must resolve, from that package, to the workspace package itself — a `createRequire(…).resolve.paths` walk plus realpath (`require.resolve(dep + "/package.json")` fails every pin under Node, and `Bun.resolveSync` / `resolve(dep)` are masked by tsconfig paths). Every bare import of a workspace package in non-test src (static, `import type`, `export … from`, literal dynamic `import()`, `require()`, `typeof import()`; a full TypeScript parse) must be declared in `dependencies` / `peerDependencies` / `optionalDependencies`; a link no manifest declares is a warning. `scripts/node-dist-smoke.ts` runs the emitted CLI and MCP entries (and both bin bootstraps) under node. `@shrkcrft/mcp-server` gains a `shrk-mcp` bin (`dist/shrk-mcp.js`). `compat-node --runtime --cli` and the install smoke test also probe the `shrk` bin bootstrap.',
|
|
208
|
+
'Round 13 (lane B — spec 13.1, the pre-emptive boundary fence; `docs/intended-empty.md`): boundary rules take a per-pattern `expectEmpty` marker — `forbiddenImports: [\'@scope/kernel-*\', { pattern: \'@scope/plugin-react\', expectEmpty: true, reason: \'ADR-7\' }]` — on `from` (inclusions and `!` exemptions), `exemptFiles`, `forbiddenImports` and `allowedImports` (authored `IBoundaryRuleInput`; the loaded `IBoundaryRule` keeps plain string lists plus one `expectEmptyUnits` ledger, each mark stamped with its contributing pack). A marked unit whose target does not exist yet is intended-empty: never dead, never a failure, printed `accepted by expectEmpty: …` under the ✓ — so a planned `from` glob beside a live one no longer makes its rule partial (2 → 0), and a rule whose only `from` glob is planned is accepted rather than a failOnEmpty failure (1 → 0). When the target appears — a workspace package name, a dependency, a tsconfig alias, a file or an import — the marker went live: `expectEmpty is stale: … — the fence went live; remove expectEmpty`, ✓ withheld; `--fail-on-dead-units` (and `--strict`, the warning promoter on this verb) fail on a local went-live marker, while a pack\'s is INFO and never fails. Every boundary unit settles through ONE boundary settle (`settleBoundaryRule`, over core `settleUnitLiveness` / `settleRuleEmptiness`). `check boundaries --json`, `--diff-against --json` and MCP `check_boundaries` gain `intendedEmpty`, `wentLive`, `failingUnits`, `accepted` and a `state` on every `coverage[].fromGlobs` / `forbidden` / `allowed` / `exemptions` row (and `coverage[].unitLiveness`); MCP `check_boundaries` takes `failOnDeadUnits`; `boundaries explain`, `boundaries get`, MCP `get_boundary_rule` and `list_boundary_rules` show `expectEmptyUnits` (one `intended empty: <list> <unit> — <reason>` line each); `shrk explain <ruleId>` resolves a boundary rule id (it used to fall through to a knowledge topic search).',
|
|
209
|
+
'Round 13 (lane A — intended-empty asset units; `docs/intended-empty.md`): registration hints (`discovery.targetGlobs` entries and `discovery.targetFile`), scaffold patterns (`matchPaths`) and search tuning (`boostIds` / `taskHints[].boostIds` VALUES: `{ weight, expectEmpty: true, reason? }`, the unit is the key) take the `expectEmpty` marker — authored types `IRegistrationHintInput` / `IRegistrationHintDiscoveryInput`, `IScaffoldPatternInput`, `ISearchTuningInput` / `ISearchTaskHintInput` and generic `defineRegistrationHint(s)` / `defineScaffoldPattern(s)` / `defineSearchTuning` (@shrkcrft/plugin-api); the loaders normalise to plain values plus an `expectEmptyUnits` ledger (`normalizeRegistrationHint`, `normalizeScaffoldPattern`) stamped with the contributing pack, and a boost marker keeps its weight. Each asset doctor settles its units through core `settleUnitLiveness`: a marked unit whose target does not exist yet is intended-empty — accepted and printed (`accepted by expectEmpty: …`; `--json` `accepted` plus `units: { dead, intendedEmpty, wentLive }`), a registration hint reads `intended-empty` (`totals.intendedEmpty`), and a planned scaffold glob is ONE acceptance (the derived pattern-level unit is left out); a marked unit whose target appears went live (`discovery-went-live` / `matchPaths-went-live` / `expect-empty-went-live`, info; ✓ withheld). `assetDoctorProposedExit` is the one proposal of every asset doctor and its MCP twin (`--fail-on-dead-units` through `selectorUnitFails`: a stale LOCAL marker fails, a pack\'s is INFO). New in @shrkcrft/inspector: `buildScaffoldPatternDoctorReport`, `searchTuningKeyProbes`, `settledUnitStates`, `assetDoctorProposedExit`, `ISelfConfigDoctorReportV2.selectorUnits`; `scaffold-pattern.schema.json` accepts the marker in `matchPaths`.',
|
|
210
|
+
'Round 13 (lane P — plane consumers, the doc-reference pack slot, the dispatcher): `docReferenceFiles` is a declared pack contribution slot (`CONTRIBUTION_FILE_KEYS`, `ContributionKind.DocReference`, a gate-plane row in the seam, a `doc-reference` self-config finding kind) — so a pack doc-reference rule travels the round-12 rejection channel like every other gate plane. `measureRegistrationRoles` / `IRegistrationRoles` moved to `@shrkcrft/boundaries` (the CLI gates path re-exports them; `IRegistrationRoles` gains the `unitAcceptance?` carrier) with the new `measureIdiomRoleCoverage` / `IIdiomRoleCoverage`, and `registrationUnprovidedVerdict` / `registrationOrphansVerdict` take the idioms\' role coverage (required). CLI: `unknownFlagRefusal` / `UnknownFlagRefusalMode` (THE refused-flag wording), `invocationFlagDocumentation` / `siblingsDocumenting` (per-subverb flag documentation), `isStdoutPipe`; the gate envelope\'s rule type gains `convention`.',
|
|
211
|
+
],
|
|
212
|
+
changed: [
|
|
213
|
+
'BEHAVIOUR CHANGE (exits 0 → 2): a verdict over a scope it did not fully examine is `2` NOT VERIFIED, never `0` — the shortfall is on the verdict line and in `--json` `shortfalls`. This flips `check wiring` / `policy-lint` / `gates check` with no rules; `check orphans` with nothing deleted or over a stale index; `check boundaries` with zero rules, a dead scope glob or an ungoverned change; `diff-check` over an empty diff; `finish` and `shrk gate` over a rule that examined nothing; `impact --deleted` over a stale index; a capped, timed-out or over-budget lifecycle scan; `registry <name> list|exists|where|duplicates` over an empty or unread inventory; bare `shrk check` over a doctor shortfall; `reuse coverage` over a stale index; `wiring unprovided|orphans|chain` with no `registrationGraph[]` declared; `check packs|templates|knowledge|pipelines` asked for alone over zero of them (the answer `packs doctor` / `templates doctor` give); and every doctor and test runner with nothing to examine. Accept an empty scope explicitly with `--allow-empty`.',
|
|
214
|
+
'BEHAVIOUR CHANGE: a subset wiring rule whose registered side holds tokens its declared selector never produced is `partial` (exit 2) on `check wiring`, `gates check` and `gates coverage` — it passed by construction before — and an accidental skip in `quality`. The tokens are named on the verdict line; accept known extras with `registeredExtras`, or use `mode: "parity"` to make them violations.',
|
|
215
|
+
'BEHAVIOUR CHANGE: `knowledge stale-check` / `knowledge verify` are strict by default. An entry with no checkable reference is UNVERIFIABLE and the run is `2` unless `--min-referenced <ratio>` (or `knowledgeCheck.minReferenced`) accepts it, printed. Loading 0 entries, a knowledge file that failed to load, or a malformed reference (outcome `invalid`) is `2` too; an unknown `--fail-on` category or a malformed ratio is `3`. The output leads with the verified / stale / unverifiable buckets; `--fail-on all` keeps its meaning, and the check reads `knowledgeCheck.failOn` / `strict` when no flag is given.',
|
|
216
|
+
'BEHAVIOUR CHANGE: a glob-matched file the reader did not read (over the 1MB read cap, or unreadable) is named in the rule coverage and makes the rule `partial` (2) on every plane — policy-lint, check wiring, gates, baseline, generated, docs references, the registry verbs, wiring unprovided / orphans (an absence there is `unproven`), quality, finish and `shrk gate` — never `examined 1 of 1 ✓`, and never the `failOnEmpty` 1. Every plane walk, in a verb or an aggregate, prunes the same directories.',
|
|
217
|
+
'BEHAVIOUR CHANGE: the dispatcher refuses a wrong invocation instead of running something else. An unknown subcommand, a bare token under a command group, a verb-shaped token that is neither a subverb nor a file, or a flag outside a declared set is refused before any body runs, naming the closest match — exit `3` on a verdict verb, `2` elsewhere (`check rules --tag auth` printed a green sweep at 0; it is now 3). A flag no documentation of the command names is refused before the body runs, too (`baseline update --dry-rn` used to perform the bless write first; `check --tag auth` printed a whole sweep), and the command-string resolver runs the same judgement, so a doc, asset or guidance string it certifies is one the dispatcher runs. `--help` / `-h` anywhere before `--` prints help and never runs a body (`graph index --help` used to build the store). Global flags work leading, in-path or trailing (`shrk --no-hints scaffolds list`); `doctor --strict <level>` still reads its level.',
|
|
218
|
+
'BEHAVIOUR CHANGE (consumer repos): commands that maintain SharkCraft itself — `docs check`, `examples check`, `self audit`, `install smoke`, `release readiness|smoke`, `commands doctor|docs-check|retirement-plan|ux-check|overlaps|legacy|machine` (and `ci scaffold --with-command-doctor`, whose step would fail every consumer CI run, is refused there; `recommend` / `context` never recommend them, nor offer to enable them), `rounds capture|list|show`, `diff rounds` — are hidden from `--help` outside the SharkCraft repository and exit `78` through the surface gate ("not a check failure"; they used to run, and fail on a healthy repo). `surface.enabled` is the escape hatch. The MCP gate refuses the matching tools; `--full-help` and the start screen now honour `surface.hidden`, profiles and the deny list.',
|
|
219
|
+
'BEHAVIOUR CHANGE: every pack signature made before this release has no `contentDigests` and reads `unverified` (`packs signature-status` exits 2, and pack-pending lists it) until it is re-signed once with `packs sign` (`--if-needed`). Freshness is judged by content, never by mtime: a compiled `dist/*.js` built from an older source is flagged (`packs list` STALE-BUILD, a `shrk doctor` warning, a one-line CLI startup warning).',
|
|
220
|
+
'BEHAVIOUR CHANGE: `shrk generated update` regenerates into a temp dir and writes the aligned files over their committed paths, in place — the same regen and alignment `generated check` uses. It used to substitute `{TMP}` with the project root, so a flat regen wrote every file at the repo root. It never writes an output it could not read, reports (never deletes) committed files the regen no longer produces, and exits 1 when the tree is not in sync.',
|
|
221
|
+
'BEHAVIOUR CHANGE: `shrk quality --json` (`verdict`), MCP `get_quality_report` / `get_dashboard_summary`, the dashboard and the report site read `not-verified` over a partial or unrun gate — `overall` gained the state (fail > not-verified > warn > pass), plus `coverage` / `shortfalls`. A zero-subject gate is skipped, never passed; the text tags a partial gate `PART`.',
|
|
222
|
+
'BEHAVIOUR CHANGE (boundaries): imports are read from code only — a commented-out import, a doc-comment fence or an import inside a string is no longer an edge (`--include-comments` restores the raw reading), and import line numbers are no longer one line early; `import-edges` follows the same reading. A bare forbidden pattern covers its subpaths (`@scope/pkg` catches `@scope/pkg/sub`; `forbiddenMatch: "exact"` opts out). A changed-only run escalates a rule whose definition the changeset touched (rule file, config, tsconfig, pack manifest), so a rule edit is never filed as legacy. An invalid or missing rule file is an errored rule (1), not silently dropped; an unset severity reads `error` everywhere.',
|
|
223
|
+
'BEHAVIOUR CHANGE (recommender): `recommend`, MCP `recommend_commands` and `shrk context` render one ranked list with one confidence vocabulary. Routing-hint keywords, playbook tags, recipes and change-intent domains match whole terms (`ci` no longer matches "pricing"; `match.mode: "substring"` opts back); a source-writing scaffold is never recommended for a repair or diagnose query; a ranker template or pipeline needs 2 matched terms. When nothing clears the floor the output says "No confident match" and withholds writes-source rows.',
|
|
224
|
+
'BEHAVIOUR CHANGE (ranking): search-tuning boost keys are `<kind>:<id>` — a bare id never fired, and the SharkCraft repo tuning was migrated, so it boosts documents for the first time. One trigger tokenizer serves `search`, `task`, `context` and `why`, so hyphenated and two-letter triggers fire everywhere; `why` / MCP `explain_ranker` report the tuning the rankers actually apply, and the ±10 total cap is reported (`capped`, a `tuning-cap:` reason).',
|
|
225
|
+
'BEHAVIOUR CHANGE: `baseline update` refuses to bless a value computed from an incomplete read (exit 2, nothing written for that rule), and `gates scaffold-selftest` refuses to scaffold from one. Selectors are required: `tests missing|impact`, `owners impact` and `impact` with no input exit 3 (they printed nothing at 0), and a selector that resolves to 0 files is 2; `knowledge|templates|paths search` with no query exit 3.',
|
|
226
|
+
'BEHAVIOUR CHANGE (packs and templates): `packs contributions` exits 1 on a contribution file that failed to load (its regex-scraped ids read `error`, never ok) or a duplicate id. `packs doctor` is 2 over zero packs or a compiled artifact with no build record (1 under `--strict` / `--release`); `templates doctor` fails on a `templates lint` error and is 2 over zero templates; `shrk doctor` exits 1 on unregistered entry exports and is never ready over an unrecorded compiled build.',
|
|
227
|
+
'BEHAVIOUR CHANGE (gate planes): `gates try` exits 1 on a failed or unevaluable selfTest and 2 for a partial candidate (it exited 0 over impossible expectations). A registration idiom whose declared role extracted nothing is 1 with `failOnEmpty`, else 2, in both `gates check` and `gates coverage`. Policy selfTest `expectIds` / `expectNotIds` are real assertions over the pattern matches.',
|
|
228
|
+
'Renamed or reshaped output: the surface summary is `sharkcraft.surface.v2`; the pack-test diagnostic `missing-id` became `unknown-id` / `not-surfaced`; `check boundaries --json` `rulesEvaluated` and every `gate.evaluated` no longer count skipped or errored rules; knowledge `ci.exitNonZero` counts a 2; `packs doctor|release-check --json` `passed` equals `exitCode === 0`; a command-baseline selfTest that cannot be evaluated is status `error`.',
|
|
229
|
+
'FIXED (P1): `check registry-lifecycle` over more candidates than its 2000-file cap printed `missing removers 0` and exited 0 while a real missing remover sat in the files it never read. A capped, timed-out, interrupted or over-budget scan is now 2 with the `--offset` that reaches the remainder; a missing remover is 1 even in a partial scan; both lifecycle verbs share one body and the gate envelope. The budget is checked inside each file (an over-budget file is named), and the remover lookup is one linear pass.',
|
|
230
|
+
'FIXED (P1): one self-config doctor — `--schema v1`, MCP `get_self_config_doctor` and `fix preview --self-config` ran a second doctor with its own checks; v1 is now a projection of v2. Correctly prefixed search-tuning keys are no longer reported unknown (bare keys, which never fire, are). Dead units report as coverage: the self-config, registrations, scaffolds and search tuning doctors exit 2 over a dead selector or an unverifiable unit, and routing / registration loader issues finally reach the doctor.',
|
|
231
|
+
'FIXED (P2): cross-reference ids in declared asset fields were never resolved — every doctor printed ✓ over ids no registry had. One collector (`DECLARED_XREF_FIELDS`) resolves them: `self-config doctor` reports `xref-dangling` / `xref-wrong-kind` and errors on a dangling `supersededBy` or a supersession cycle, and `self-config broken-links|graph|report`, `packs doctor` and the new `cross-references` quality item read the same rows. `templates drift` no longer reports a real construct or boundary id as unresolved; `knowledge remove` refuses when any declared field points at the entry.',
|
|
232
|
+
'FIXED (P2): `shrk reuse` answered only from the curated index, so an exactly-named public export lost to a generic curated primitive. It now ranks the uncurated public export surface too (labelled, with a real import line); an exact or covering NAME outranks a metadata-only curated match, and a curated entry that names the construct still wins. `reuse coverage` is NOT VERIFIED over a package entry that diverged from the index (`packagesChanged`), which `graph status`, `shrk doctor` and the dashboard now count as stale; an empty intent exits 3.',
|
|
233
|
+
'Commands cited by the engine resolve: `knowledge stale-check` reports a dead `command` reference as STALE with did-you-mean; `shrk test agent` accepts a correct `expectedCommands` entry and checks `expectedRules` against the rule registry; pack tests evaluate `expectPlaybookIds` / `expectConstructIds`; `shrk trace` ranks commands against the index; and the guidance the CLI and inspector print (failure footers, agent contracts, role views, next-command hints) names only live commands.',
|
|
234
|
+
'The MCP boundary tools resolve tsconfig aliases and carry a verdict; `shrk impact` reports `areaCoverage` and `area-attribution-degraded` (report only) and attributes areas through the one classifier; a zoned `regex-capture` that runs over budget is a named error, not a quietly smaller token set; conventions and custom checks that can never run are dropped with a named error, and `checks list` names every dropped declaration.',
|
|
235
|
+
'BEHAVIOUR CHANGE (usage exits 2 → 3): more paths are verdict verbs (`GATE_VERB_PATHS`) — bare `check` (so every `check <group>` under it), `gates check|coverage|try|scaffold-selftest`, `quality`, `policy-lint`, `baseline check|update`, `generated check`, `docs references check`, `knowledge stale-check|verify`, `reuse coverage`, `packs doctor|release-check|signature-status|test`, `test agent|context`, `self-config doctor|broken-links`, `helper doctor`, `registrations doctor`, `scaffolds doctor`, `search tuning doctor`, `templates doctor`, `checks doctor` and `conventions doctor`. A usage or invocation error on them (an unknown subcommand or flag, a bad flag value) exits `3`, not `2`, and `--exit-trailer` (`shrk-exit: <code>`) and the piped-exit stderr note now cover them — the trailer printed nothing on the verbs most often piped in CI. `self-config broken-links` exits `2` when an id could not be looked up (it returned only 0 / 1).',
|
|
236
|
+
'BEHAVIOUR CHANGE (exits 1 → 3): a config that fails to load (or no `sharkcraft/` folder) is a usage error on `check wiring`, `registry <name> list|exists|where|duplicates` and `wiring unprovided|orphans|chain` — the rules they check live in that config, so the gate never started — as it already was on `policy-lint`, `gates check|coverage`, `baseline check`, `generated check`, `docs references check` and `reuse coverage`. It exited `1`, which a CI step could not tell from violations; `--json` carries `exitCode: 3`.',
|
|
237
|
+
'BEHAVIOUR CHANGE (exits 0 → 2): `boundaries suggest` over zero boundary rules (nothing was checked), and `test context` / `test agent` with zero tests configured (`--allow-empty` accepts that) — this repository\'s own `shrk test context` now exits 2.',
|
|
238
|
+
'BEHAVIOUR CHANGE (round 11 review — the index is a stale input): `graph cycles` over an index behind the working tree exits 2 NOT VERIFIED instead of "No runtime cycles … ✓"; `--json` gains `freshness`, `exitCode`, `verdict` and `shortfalls`. In `shrk gate` and MCP `get_quality_gate`, `graph-fresh` reads the one freshness authority (`detectGraphFreshness`), so a stale index is a `warn` that settles 2, and `arch`, `impact`, `graph-cycles` and `graph-unresolved` are skipped NOT VERIFIED over it. `graph unresolved` drops its ✓ over a stale index (its exit is unchanged).',
|
|
239
|
+
'BEHAVIOUR CHANGE (round 11 review — one boundary authority): every boundary consumer reads the boundary orchestrator. `drift` and `architecture violations` exit 2 over an unreadable governed file (they read `total 0` at 0); `architecture violations` exits 2 over zero rules; `drift` fails on an errored rule or a stale exception; the review packet, plan review and plan simulation name a governed target they could not read; `policy` adds `boundary:not-verified` and `boundary:load-error:*` checks; `bundle validate` fails a boundaries or drift step that is not a clean 0; the validation loop reports `boundaryVerdict` / `boundaryShortfalls`. A directory the walk cannot LIST is an unread entry (`unreadable-directory`) on every plane and in `check imports` — it used to be skipped in silence, a clean 0.',
|
|
240
|
+
'BEHAVIOUR CHANGE: `self-config broken-links` with nothing to examine (no file reference, no declared cross-reference id) exits 2, and takes `--allow-empty`; `--json` gains `coverage`, `verdict` and `accepted`. `check boundaries --diff-against` never prints its ✓ under a dead candidate pattern, and honours `--fail-on-dead-units`.',
|
|
241
|
+
'BEHAVIOUR CHANGE (usage exits 2 → 3): `boundaries suggest`, `packs contributions`, `self-config resolve`, `checks list`, `recommend`, `drift` and `architecture violations` are registered verdict verbs — a bad flag exits 3 (it collided with their own 2), and `--exit-trailer` covers them.',
|
|
242
|
+
'`shrk task` reads the one query-intent classifier (spec 2.3, as `recommend`): a diagnose / repair task gets no create/scaffold pipeline, no template and no source-writing command, and a suggested generation needs a create query. `templates get --json`, MCP `get_template`, `task --json` and MCP `get_task_packet` carry a template\'s `notScaffolded` / `manualSteps`. The quality report adds no `gate-planes` row for a repository with no `sharkcraft/` folder (only for a config that failed to load).',
|
|
243
|
+
'BEHAVIOUR CHANGE (round 12, 12.3 — `profileIds` resolve against the WorkspaceProfile vocabulary): a registration hint\'s `discovery.profileIds`, a convention\'s `appliesTo.profileIds` and a template\'s `metadata.requiredProfileIds` resolve against the builtin `workspace-profile` kind. They were checked against MIGRATION profiles, so `self-config doctor` sat at NOT VERIFIED (exit 2) forever with none declared, and called a real, detected workspace profile "not registered" once any was. Such a unit is now measured: exit 0 for a real profile, a `*-profile-missing` finding with a did-you-mean for a typo — and an id that named a MIGRATION profile there is now reported missing. Finding `targetKind` is always the kind resolved against: `workspace-profile` (was `profile`), and routing `recommends.profiles` / `recommends.paths` misses read `migration-profile` / `path-convention` (were the `profile` / `path` relabels); codes are unchanged, finding ids follow the target kind. The v1 `referencedKind` (the MCP `get_self_config_doctor` default shape) and the `totals.byTargetKind` key change with it — `profile` → `workspace-profile` / `migration-profile`, `path` → `path-convention` — for `registration-hint-profile-missing`, `template-profile-missing` and routing `recommends.profiles` / `recommends.paths` misses, and a coverage record\'s unexamined labels name the kind resolved against (`rt.mig → migration-profile mig.x`, was `→ profile`). `accepts: "any"` cross-reference fields (knowledge / template `related`) now also resolve the 23 workspace-profile ids.',
|
|
244
|
+
'BEHAVIOUR CHANGE (round 12, 12.3b — one probe path for template metadata): `requiredProfileIds`, `requiredConventionIds`, `requiredHelperIds` and `registrationHintIds` go through the same probe as every other reference. An id checked against an EMPTY registry (a `requiredConventionIds` with zero conventions) is an unexamined unit — NOT VERIFIED, exit 2 — instead of a `template-*-missing` warning (exit 0; 1 under `--strict`). A loud skip\'s reason names how to fill the empty kind (`… — declare migration-profile via pack key migrationProfileFiles · sharkcraft/migration-profiles.ts …`), and `*-missing` findings print the kind\'s list verb as `next:`.',
|
|
245
|
+
'Round 12 (12.3a/d): `shrk profiles list|get|search --kind <kind>` refuses an unknown kind (exit 2, naming `migration, workspace`) instead of silently listing every kind, and MCP `list_profiles` / `get_profile` validate `kind` as an enum (inputSchema and the wire validator). The empty state names the real declaration paths (it said "contribute via packs: migrationProfileFiles, etc."); `profiles get` suggests the nearest id. The `self-config doctor` exit-0 line no longer says "every checked probe resolved ✓" over an info-level unresolved reference — it counts them (`N unresolved reference(s) reported as info above`; exit unchanged). TS decisions (`sharkcraft/decisions.ts`, pack `decisionFiles`) are warmed with the other registries, so a declared decision resolves on every surface (it was visible only after an unrelated decision load).',
|
|
246
|
+
'BEHAVIOUR CHANGE (round 12, 12.4 — `unknown:` means "resolves nowhere"): a `self-config doctor` finding labels its target `unknown:` only when the id resolves in no registry. It was the fallback for any finding that carried no kind, so `search-tuning-cap-discards` read `tunes unknown:knowledge:gamma.entry` for a document the index built — and a resolvable bare boost key, a clamped tag, a `doc:` key, a finding code (`unknown:duplicate-trigger`), a facet value whose declared KIND was typo\'d, a pipeline step naming a construct and the command-probe summary of the doctor itself (source `unknown:self-config`) all read `unknown:`, while the one really missing id did not. Now a key or document the resolvers place reads `<kind>:<id>`; a registry-less document (`doc:README.md`) and the cap summary read `search-document:`; a declaration-shape finding reads `validates schema:<field>` (`taskHints[1].whenTokens`, `appliesToKinds`, `boostSources`, `boostTags.<tag>`, `facets.<name>[<facetId>]`); the probe summary is `self-config:command-probes`; and a pipeline step reference that resolves as another kind is the new `pipeline-reference-wrong-kind` (info, `next: shrk self-config resolve <id>`), so `pipeline-reference-missing` means it resolves nowhere. Exits, verdicts, severities and coverage are unchanged. Finding `id`s, `targetKind` / `targetId` / `relation`, `totals.byTargetKind` / `byRelation` / `bySourceKind`, and the v1 `referencedKind` / `referencingId` (MCP `get_self_config_doctor`) change for these codes; `unreachable-trigger` findings in different task hints of one entry are no longer merged into one ×N finding, so the warning count can rise. `search tuning doctor --json` issues gain `field`, `moreDocuments` and, on `cap-discards`, `referenceKind` + the bare `targetId`; `boost-clamped` gains `field`; the key resolution of a resolvable bare key carries its `referenceKind`. The exit-0 line counts an info-level wrong-kind reference instead of certifying that every probe resolved.',
|
|
247
|
+
'BEHAVIOUR CHANGE (round 12, 12.2a — a `!` glob now EXCLUDES on every gate plane): every gate plane silently ignored a leading `!` in its glob lists (it compiled to a literal glob that matched nothing), so the spec, draft and hand-written files an author excluded were measured all along — deleting the `!` changed nothing. A negation now subtracts, order-independently and from its own list only, in wiring / registry / registration / extractor-baseline sources (`$use` extractors and pack-contributed rules included), `import-edges` `to.files`, policy `files`, `watchFiles`, `generatedGlob` / `sources[].glob` / `outsideGlob` and doc-reference `files`. One parser (`parseGlobList`, @shrkcrft/core) and one scope test (`globListSelects`, @shrkcrft/boundaries) serve every plane; walks stay positive-only unions and selection is per list, so one rule\'s `!x` never removes x from another rule. An upgrader may see findings in excluded files disappear, an extractor ledger report LOST ids that only excluded files held (review with `shrk baseline diff`, re-bless with `shrk baseline update`), a wiring rule whose registered side lived partly in excluded files gain "not wired" violations, a `selfTest` pinned to an excluded id fail, a rule whose whole positive set is excluded read `empty`, and `--changed-only` skip a changeset that touches only excluded files. The boundary plane keeps its semantics: a `!` in `from` EXEMPTS (suppressed, counted). See docs/gate-rules.md "Negation globs".',
|
|
248
|
+
'BEHAVIOUR CHANGE (round 12, 12.2 / 12.2b — negation liveness and list shapes): `gates coverage` judges a negation by what it EXCLUDES — alive iff it removes at least one file from its own list — on every list it judges (extraction sources, policy `files`, `watchFiles`, and now a generated rule\'s `generatedGlob` and a doc-reference rule\'s `files`, which it never judged before: a dead glob there is a new advisory ⚠), and prints each live one (`excludes: !src/**/*.spec.ts (512 files)`; `--json` per-rule `negations` and `deadGlobUnits`), so `--fail-on-dead-units` no longer fails a load-bearing exclusion. A rule its own negations emptied reads `matched nothing after its own negations: every file its inclusion globs select is excluded (…)` (`--json` `excludedByNegations`; `policy-lint` and `shrk quality` say the same), never "the selector is probably stale"; exits are unchanged. `generated update` places a first-generation file by its `generatedGlob` inclusion globs only (a `!gen/…` entry used to make the target directory ambiguous and refuse the file). A dead unit names its reason (`matched 0 files`, `matches only files the list\'s negations exclude (N)`, `excludes nothing — none of the N file(s) the other globs select match it`) in the ⚠ line (now `⚠ N of M glob(s) dead: …`), the `--fail-on-dead-units` violation message and the `shrk quality` note (`advisory: N dead glob(s): …`). A bare `!`, a `!!x`, a negation-only glob list, and a `!` in an exemption list (policy `exemptFiles`, generated `handMaintained`, boundary `exemptFiles`) are config / validation errors on every plane and at the pack-plane merge seam — each used to load and select (or exempt) nothing, and a bare `!` in a boundary `from` was dropped silently.',
|
|
249
|
+
'BEHAVIOUR CHANGE (round 12, R12-5.2 — a boundary specifier pattern that cannot mean what it says is an errored rule): in `forbiddenImports`, `allowedImports` and `exceptions[].target`, an empty pattern, a `!`-prefixed one (negation is `from`-only syntax) and — under package semantics — a trailing-`/` one now fail validation, so the rule is an errored rule on every surface (`check boundaries`, `--changed-only`, `finish`, `diff-check`, the MCP boundary tools; local and pack rule files alike), exit 1. Each used to load and match nothing its author meant: `forbiddenImports: [\'@scope/pkg/\']` printed `Verdict: OK — no boundary violations. ✓` at exit 0 over imports of `@scope/pkg` (its dead-unit check called it resolvable through the known package), and a `!` entry was reported dead with "typo or retired target?" advice. The fix is one character — `pkg` (the package and every subpath, `pkg/` included) or `pkg/**` (subpaths only); `forbiddenMatch: "exact"` (and `allowedImports`, always exact) keeps a trailing-slash literal such as the `buffer/` polyfill idiom. A hand-built rule that bypasses the loader reports such a pattern as a dead unit naming the defect (`cause: "defect"`).',
|
|
250
|
+
'BEHAVIOUR CHANGE (round 12, R12-5.3 — an inert allowance is reported): forbidden is checked first and `allowedImports` never re-admits, so under package semantics an allowed subpath of a bare forbidden package (`forbiddenImports: [\'@scope/pkg\']` + `allowedImports: [\'@scope/pkg/public/**\']`) can never admit an import — a carve-out alpha.30 honoured, made inert by the round-11 subpath default without a word. It is now a dead unit (`shadowed by forbidden \'@scope/pkg\' — …`, `cause: "shadowed"`, coverage `allowed[].shadowedBy`): `--fail-on-dead-units` fails on it and the exit-0 verdict line names it instead of a ✓. Carve the subpath out with `exceptions[{ path, target, reason }]`, or set `forbiddenMatch: "exact"`. A dead unit proved from the rule alone (a shadowed allowance, a pattern defect) is no longer dropped when a governed file went unread.',
|
|
251
|
+
'Round 12 (R12-5.4 – R12-5.6, boundaries): the round-11 subpath default is strictly stricter (`*` still never crosses `/`; package semantics add the `<pattern>/**` half to any pattern with no `**` and no trailing `/`), so a local helper expanding `pkg` → `pkg` + `pkg/**` is now redundant — a forbidden pattern a sibling already covers is reported as INFO (`boundaries explain`: `redundant … safe to delete`; `check boundaries`: one `note:` line; `--json` coverage `forbidden[].subsumedBy`), never a dead unit and never a verdict change. MCP `list_boundary_rules` rows carry the effective `severity` (through `boundaryRuleSeverity` — it re-implemented the default inline) and `forbiddenMatch`; `get_boundary_rule` adds the effective `severity`, `forbiddenMatch`, `failOnEmpty`, `redundantForbidden` and `shadowedAllowed` to the rule as written (output only — no input change). `exceptions[].target` keeps the rule\'s forbidden-pattern semantics — a bare target also excuses its subpaths — now documented as a (path, target) pair, not "exactly one edge", and pinned by a test. New in @shrkcrft/boundaries: `importPatternDefect`, `importPatternSubsumes`, `boundaryPatternOverlaps`.',
|
|
252
|
+
'BEHAVIOUR CHANGE (round 12, 12.1 — a contributed entry its loader refuses is a failure, never silence; exits 0 → 1): `self-config doctor` reports every rejected entry as an ERROR, one finding per failing field (`<kind>-invalid` / `<kind>-duplicate-id` — a contract template, migration profile or search-tuning entry with no id rises from a loader warning to this error); `packs doctor` reports `contribution-entries-rejected` per file (`2 of 10 entries rejected — …`, with a `satisfies I<Kind>[]` / `--typecheck` pointer); `packs contributions` exits 1 on a rejected entry and 2 NOT VERIFIED when only references whose kind\'s registry is empty or undeclarable remain; `packs test --load` runs every slot\'s runtime loader and exits 1 on an `asset-entry-rejected` (no annotation needed — the old check saw only `id`). `routing-hint-invalid` / `-duplicate-id` and `registration-hint-invalid` / `-duplicate-id` keep their codes but are reported once, by the rejection family (an id-less entry\'s source reads `<file>:<export>[<i>]`); a `*-missing` finding whose target was declared but rejected says so in `suggestedFix`. `scaffolds doctor` counts a refused pattern as an error; `scaffolds list` replaces its per-entry `! …` warning strings with the note (`--json` adds `rejected`); `helper list`\'s `N helper file error(s)` line now counts only helper files that failed to load or are missing.',
|
|
253
|
+
'BEHAVIOUR CHANGE (round 12, 12.1c / 12.1d — an accepted entry is a usable one): a playbook without an array `steps` (it crashed `self-config doctor`), a scaffold pattern without a `high|medium|low` `confidence` (it crashed `scaffolds list`), a construct without a string `type` (it crashed `constructs list`), an id-less construct, TS decision, policy declaration, feedback rule or search-tuning entry, a context / agent test without a string `task`, a construct facet whose `constructId` names no loaded construct, and a pack delegate recipe failing the config loader\'s `DelegateRecipeSchema` are REFUSED — they were accepted or dropped with no signal. A template\'s missing `tags` / `scope` / `appliesWhen` / `variables` is normalised to `[]` (a missing `tags` crashed `templates list`). A knowledge / template / pipeline array member meant as an entry that fails its loader\'s predicate, and a different object reusing an id in one module (pipelines deduped silently), are rejected entries. Import failures that used to be swallowed (constructs, TS decisions, policy checks, feedback rules, context / agent tests, delegate recipes, gate-plane pack files) are load failures on `packs doctor` / `packs contributions`.',
|
|
254
|
+
'BEHAVIOUR CHANGE (round 12, 12.1b / 12.1e — the contributions inventory covers every loader-backed slot): new contribution kinds `registration-hint`, `construct-facet`, `delegate-recipe`, `framework-extractor`, `wiring-rule`, `registry`, `registration-idiom`, `policy-rule`, `reuse-primitive`, `baseline` and `generated-artifact`, and presets, boundary rules, scaffold patterns, constructs, search tuning, decisions, policy checks, feedback rules and tests are listed structurally — so `packs contributions` / MCP `get_pack_contributions` list entries they never listed or only scraped. A regex-scraped id is never `ok` (one matching a rejected entry is `error`, "rejected by the <kind> loader"); the inventory JSON gains `rejections[]` and `extractionTotals.rejected`. `packs list` appends every other declared slot to its `files:` line (`convention=1`) and adds an `entries:` line; `packs get` prints every declared slot. `ISelfConfigDoctorReportV2` (and MCP `get_self_config_doctor`) gains `unresolvableReferences`.',
|
|
255
|
+
'BEHAVIOUR CHANGE (round 12 review — a filter that selects nothing is never a pass; exits 0 → 3 / 0 → 2): `packs contributions` refuses an unknown `--kind` (not a contribution kind — `conventions` is a typo of `convention`) or `--pack` (no discovered pack) with exit 3, naming the known values and the nearest; the typo narrowed the view to nothing and printed "0 of 0 declared entries accepted … ✓" at 0, even over a project with rejected entries. A view holding no contributed file (an empty project, or a real filter selecting none) is `2` NOT VERIFIED; `--allow-empty` (new on this verb) accepts it explicitly, printed; `--json` gains `accepted`. MCP `get_pack_contributions` `kind` is the contribution-kind enum (inputSchema AND the strict wire validator), and an unknown `kind` or `pack` is `invalid-input` instead of an empty report.',
|
|
256
|
+
'FIXED (round 12 review): the contributions inventory never regex-scrapes a file a loader READ — a file whose every entry its loader refused was scraped, its refused ids counted in `By kind`, `totals` and the header, and two packs sharing one refused id raised a false error-level `duplicate-id-same-kind` (also `pack-conflict:duplicate-id-same-kind` on `self-config doctor`). An id that does not take effect (refused, or scraped from a file that failed to load) is never grouped into a duplicate. A knowledge module\'s NAMED helper array of `{ id, … }` lookup rows is no longer a rejected entry (it failed `self-config doctor` and `packs contributions` as `knowledge-invalid`); a named member is one only when it carries two of `id` / `title` / `content` or a knowledge-only field (`content` / `type` / `priority`). List verbs name a contribution file that failed to load (`⚠ <file> failed to load (<message>) — nothing in it is listed`; a stderr `note:` under `--json`; new `collectKindOutcomes` / `IKindOutcomes` in @shrkcrft/inspector), and `conventions list` no longer points at the failed file as the place to contribute. A boundary rule rejection reads `(default[1])` like every other kind (`IBoundaryRuleInvalid.exportName`).',
|
|
257
|
+
'BEHAVIOUR CHANGE (round 12 review, R12-X1 — a pack gate-plane rule the merge seam rejects is a rule that did not run; exits 0 → 1): a pack-contributed wiring / policy / registry / registration / baseline / generated rule that fails validation at the pack-plane merge seam (a negation-only `files`, a schema error, a vetoed shell command, an unresolvable `$use`) — or a pack plane file that fails to import — is an ERRORED row, `failed validation — NOT evaluated`, on `gates check`, `gates coverage`, `policy-lint`, `check wiring`, `baseline check`, `generated check`, `shrk quality` (a FAILED item and an errored coverage row) and `finish` (its sub-gate fails), counted in the run coverage — exactly as the boundary plane reports a rejected boundary rule, and as `packs contributions` / `packs doctor` already failed the same tree. It was dropped with an advisory `!` line under "Every declared rule ran and passed ✓" at exit 0. `registry <name> …` over a rejected pack registry exits 1 naming the reason (was "unknown registry", 3), `check wiring --explain <rejected id>` exits 1, `--only` / `--id` accept a rejected id, `gates list` / `baseline list` / `generated list` name the rejected rules, and every `--json` adds `rejected`. A `duplicate-id` collision (local wins) is not an errored row — the id it collided with runs. New: `seamRejectedRules` (cli gates), `withRejectedRules` (gate coverage).',
|
|
258
|
+
'BEHAVIOUR CHANGE (round 12 review, R12-X2 — one pack doctor; exits 0 → 1): MCP `doctor_packs` / `get_pack_doctor_release`, `shrk check packs` (and bare `shrk check`), the `packs` item of `shrk quality` / MCP `get_quality_report` and release readiness run THE async pack doctor `shrk packs doctor` runs, so a registry-backed rejection (conventions, helpers, hints, playbooks, gate-plane elements, …) is `contribution-entries-rejected` on every surface. They called the sync builder without the registry outcomes: a pack whose conventions were all refused read `passed: true, exitCode 0` on MCP and `OK packs errors=0` on `check packs` while `packs doctor` exited 1. A lock forbids a direct call of the sync `buildPackDoctorReport` outside pack-doctor.ts.',
|
|
259
|
+
'BEHAVIOUR CHANGE (round 12 review, R12-X3 — a `$use` pack source is judged on its merged shape): the pack-plane merge seam and `gates try` run THE post-resolution check the config loader runs on a local rule (`validateResolvedPlaneSources`, @shrkcrft/core), and the `$use` branch of the source schema rejects a locally spelled negation-only / bare-`!` `files` or `to.files` (so `packs test --load` catches it on the pack side). A pack rule overriding an extractor with `files: [\'!src/**/*.spec.ts\']` was ACCEPTED by `packs contributions` / `packs doctor` / `packs test --load` (✓, exit 0) while `check wiring` called it misconfigured; it is now a rejected entry on every surface (exit 1), and `gates try` refuses such a candidate (exit 3). `gates coverage` no longer footnotes a misconfigured rule with "matched nothing — the selector is probably stale".',
|
|
260
|
+
'Round 12 review (R12-X4, R12-X5, R12-DOC-1, R12-DOC-2): one loader-kind → contribution-kind table (`contributionKindOfLoader`, @shrkcrft/inspector) serves the rejection channel, the contributions report rows and `packs contributions --kind`. MCP `list_boundary_rules` carries THE rejection note in its text (`⚠ N entr(y|ies) rejected from <file>: \'<id>\' (default[i]) — <reason>`; the rows array is unchanged) and `get_boundary_rule` answers a rejected id with `error.code: "rejected"` and every reason instead of a bare not-found (output only — no input change). A `?`-led boundary pattern (`?!raw-loader!**`) that matches no import is a dead unit — it read `resolvable: true` through every known package; `?raw-loader!**` reaches a single-bang `!raw-loader!…` specifier (docs/boundaries.md). A wiring source emptied by its own negations skips with `matched nothing after its own negations: every file its inclusion globs select is excluded (…)` on `check wiring`, `gates check` and the NOT VERIFIED line (was "0 files matched the source globs"), and `gates check` no longer points such a rule at "stale selectors".',
|
|
261
|
+
'Round 13 (keystone): the one did-you-mean scorer (`levenshtein`, `nearestIds`) moved from `@shrkcrft/inspector` to `@shrkcrft/core`, so the lowest layer — the `expectEmpty` marker parser — can suggest a misspelled key without importing upward. `@shrkcrft/inspector` re-exports the same functions unchanged (the CLI\'s `editDistance` is still the same function object); no output changes.',
|
|
262
|
+
'BEHAVIOUR CHANGE (round 13, lane G — an empty result can be the intended one on every gate plane; `docs/intended-empty.md`): every gate-plane markable list — each extraction source\'s `files` and an import-edges `to.files`, `policyRules[].files`, `baselines[].watchFiles`, `generatedArtifacts[].generatedGlob`, `docReferences[].files`, and the top-level `extractors` — takes `{ pattern, expectEmpty: true, reason? }` entries. A rule whose primary selector matched no file because every inclusion unit is marked is ACCEPTED (exit 0, `accepted by expectEmpty: …` printed) by the plane verb, `gates check` and `gates coverage` alike — it was 1 (failOnEmpty) or 2 on `policy-lint`, `check wiring`, `registry <name> …`, the registration plane, `generated check` and `docs references check`. A marked unit that matches something reads went-live (`expectEmpty is stale: … — the fence went live; remove expectEmpty`): the ✓ is withheld, the exit unchanged, and `gates coverage --fail-on-dead-units` fails a LOCAL stale marker (a pack marker is INFO). Files that matched but yielded 0 units are never assertable. A malformed marker fails the local config load (3) and refuses a pack element through the round-12 rejection channel (an ERRORED row); `failOnEmpty: true` with every primary inclusion unit marked is refused at load.',
|
|
263
|
+
'BEHAVIOUR CHANGE (round 13, lane G — baselines): a fence (`expectEmpty: true`) whose compute source matched no file is FAILED (`expectEmpty asserts an empty output, but its input selector matched nothing …`) on `baseline check`, `gates check` and `gates coverage` — it used to be accepted (V2 f1d: 0 → 1). A `mode: \'ceiling\'` baseline over an extractor that measured nothing is a loud skip on all three (`FAILED — the compute produced nothing — a ceiling over an empty measurement proves nothing`, 1; 2 with `failOnEmpty: false`) — `baseline check` and `gates check` printed `✓ (0 at-most N)` because the empty test read the serialised text `[]` (P1: it now counts the extractor\'s units); `expectEmpty` on a ceiling stays legal and is honoured. The fence acceptance reads `the rule asserts an empty set` everywhere (`baseline check` said `the fence asserts an empty set`). `baseline check` and `generated check` print a rule that matched nothing and fails on it as `FAILED — <reason>`, never as DRIFT / regen output with a bless hint. `baseline list` and `generated list` report the EFFECTIVE `failOnEmpty` (an error rule is `true` by default; they read `false`).',
|
|
264
|
+
'BEHAVIOUR CHANGE (round 13, lane G — `to.files` and the unit reports): an import-edges `to.files` glob is judged for liveness — one that matches no file is an advisory dead unit in `gates coverage` (`--fail-on-dead-units` fails it), where a typo\'d fence target used to pass silently. `gates coverage` rows print `✓ asserted empty (expectEmpty): …` and `⚠ … expectEmpty is stale …` lines; `--json` rules gain `unitAcceptance`, `units` (`dead` / `intendedEmpty` / `wentLive`), `unitLiveness` and `emptiness`, and `gate.rules[]` carries `unitAcceptance` / `units`; `deadGlobs` / `deadGlobUnits` now hold UNMARKED dead units only. `gates try` text prints the dead globs and went-live markers its JSON reports and never says "connected over everything" over one, and normalises a candidate\'s markers exactly as the loader does. The import-edges barrel hint is no longer printed over a verified fence or an intended-empty rule. `quality` notes a went-live gate unit (advisory) and lists every acceptance.',
|
|
265
|
+
'BEHAVIOUR CHANGE (round 13, lane G — one advice sentence): `check wiring`, `wiring explain`, `gates coverage`, `policy-lint` (and `policy-lint explain`), `docs references check`, `baseline check` and `generated check` give a rule that matched nothing ONE advice — `Fix the selector — or, if its target does not exist yet, mark the unit { pattern, expectEmpty: true }` — adding `set failOnEmpty: true` only for a rule that does not already fail and `set failOnEmpty: false` only for one that does (the verbs used to advise opposite settings for the same rule). A registry and a registration idiom decide `failOnEmpty` through the one authority (`failsWhenEmpty`), and a doc-reference rule no longer re-derives it inline.',
|
|
266
|
+
'BEHAVIOUR CHANGE (round 13, lane G review — every wiring explain surface settles a planned rule as `check wiring` does; exits 1 / 2 → 0): the explain engine (`explainWiring`, behind `check wiring --explain`, `wiring explain`, `wiring test`, `gates explain` and `gates try` on the wiring plane) now normalises its rule at entry and hands the wiring engine the same `expectEmpty` settle `check wiring` runs. A rule whose every declared glob is marked explained as `! SKIPPED — 0 files matched the source globs … Verdict: errors` (`check wiring --explain` exit 1, `gates try` 2) while `check wiring` accepted it at 0; it now reads `passed` with `accepted by expectEmpty: …`, and a partially planned rule prints its acceptance (`--json` gains `unitAcceptance` / `units`). `wiring test` over a candidate carrying a `{ pattern, expectEmpty: true }` entry crashed (`Fatal: glob.startsWith is not a function`, exit 1); a malformed marker there is now a misconfigured rule (`status: "error"`), never a crash.',
|
|
267
|
+
'BEHAVIOUR CHANGE (round 13, lane G review — the registry verbs print the acceptance `gates check` prints): `registry <name> list | duplicates | exists | where` print a planned glob\'s `accepted by expectEmpty: …` line (and `--json` `accepted`) on every exit-0 answer — for a live inventory with a planned sibling glob, which `gates check` accepted in print while every registry verb was silent, and for `exists <id> --fail-if-taken` over an intended-empty inventory (a silent 0). Exits are unchanged.',
|
|
268
|
+
'BEHAVIOUR CHANGE (round 13, lane G review — `baseline update` refuses an empty bless by unit count, P1; exit 0 → 1): the empty-bless refusal read `computed.text.trim() === \'\'`, which an extractor (whose empty set serialises as `[]`) never satisfies — so `baseline update` wrote `[]` at exit 0 for a failOnEmpty ledger over a dead selector, the measurement `baseline check` then refuses. It now decides on the compute\'s unit count through THE rule-emptiness settle `baseline check` reads: a stale empty of a failOnEmpty rule is refused naming why (`refusing to write an EMPTY baseline for a \\`failOnEmpty\\` rule — the recompute produced no entries — its input selector matched nothing (compute.source.files: appZ/**/*.ts: matched 0 files) — fix the compute first`); a fence (`expectEmpty: true`) over live inputs, an intended-empty input and a soft rule are blessed as before — and a command-compute fence that prints nothing is now blessable (it was refused, exit 1 → 0).',
|
|
269
|
+
'BEHAVIOUR CHANGE (round 13, 13.2 — `bun run build` / `bun run build:dist` fail on an unlinked or undeclared workspace dependency; exit 0 → 1): tsc and Bun resolve every `@shrkcrft/*` import through tsconfig paths and never consult node_modules, so a tree built without re-running the install printed `[build] ok` / `[build-dist] ok` and emitted a complete dist that died under node at ESM load — on every verb, `--version` included, and in the MCP server — while every Bun-run check stayed green. Both builds now refuse first, naming the fix: `workspace dependency @shrkcrft/x (needed by @shrkcrft/y) is not linked — run \`bun install\` in <root>` (build-dist before anything is emitted or wiped). They also refuse a src import of a workspace package its `package.json` does not declare — including one declared only in `devDependencies`, which build-dist compiled through a leftover link and shipped as a bare runtime import.',
|
|
270
|
+
'BEHAVIOUR CHANGE (round 13, 13.2 — new exit `70`): the `shrk` bin now points at `dist/shrk.js` (was `dist/main.js`), a bootstrap that loads `dist/main.js` and imports node: builtins only; `@shrkcrft/mcp-server`\'s new `shrk-mcp` bin is the same bootstrap. When a workspace dependency of the installed tool is not linked, they print one line — `shrk: workspace dependency @shrkcrft/x (needed by @shrkcrft/y) is not linked — run \`bun install\` in <root>` — and exit `70` (EX_SOFTWARE: the tool\'s own install is broken; never a check verdict), instead of Node\'s raw `ERR_MODULE_NOT_FOUND` resolver stack at exit 1. Every other load error is rethrown unchanged. `dist/main.js` stays runnable and executable, so an existing link to it (a `bun link`ed global `shrk`) keeps working — re-link to get the bootstrap.',
|
|
271
|
+
'BEHAVIOUR CHANGE (round 13, 13.2 — two new REQUIRED release-preflight steps): `workspace-links` (first, before `typecheck` and `tests`) and `node-dist-smoke` (right after `build-dist`: `node packages/cli/dist/main.js --version` must exit 0 and print the version, the MCP entry run under node with stdin closed must not die with `ERR_MODULE_NOT_FOUND`, and both bin bootstraps must pass the same probes). The only node run of the emitted dist used to be the opt-in, non-blocking `compat-node-runtime`, so `release:preflight` could print "ready to tag" over a dist no node could load. CI runs node-dist-smoke after its build; `release:dry-run` runs it after build-dist.',
|
|
272
|
+
'FIXED (round 13): `buildRegistryWithPacks` (@shrkcrft/framework-scanners) discarded a `register()` failure — `diagnostics.concat(…)` threw its result away — so an extractor a concurrent caller had registered first vanished without a diagnostic. It is recorded now (`<framework>: register failed (…)`).',
|
|
273
|
+
'BEHAVIOUR CHANGE (round 13, lane B — boundary rule keys are validated; exit 0 → 1 for a rule that carried one): a rule-level `expectEmpty` / `allowDead` / `intendedEmpty` is refused (`expectEmpty is per pattern on a boundary rule: forbiddenImports: [{ pattern, expectEmpty: true }]`), and so is ANY key that is not a boundary-rule field (with a did-you-mean through the one scorer) — both used to load and be silently ignored. A marker on a defective, redundant or shadowed pattern, an object `exceptions[].target` (`exceptions take no expectEmpty — a stale exception is an error by design`) and `failOnEmpty: true` over an all-marked `from` are refused too. Each is an errored rule (`failed validation — NOT evaluated`, exit 1) on local rules, pack `boundaryFiles` (and `packs test --load`), `--rule-file` and `--diff-against`.',
|
|
274
|
+
'BEHAVIOUR CHANGE (round 13, lane B — the dead-selector wording): a boundary pattern that matches nothing now reads `… — typo, retired target, or a target that does not exist yet (see expectEmpty)` in text, `--json` `deadUnits[].reason` and MCP, from the one core constant `DEAD_SELECTOR_CAUSES`; the round-12 `typo or retired target?` question is gone. The `check boundaries` fail verdict reads `boundary check needs attention` when there is no violation (a stale exception, an errored rule, a dead unit under `--fail-on-dead-units`) and `boundary violations need attention` only when there is one.',
|
|
275
|
+
'BEHAVIOUR CHANGE (round 13, lane B — `--diff-against` unread parity, prerequisite P2): `check boundaries --diff-against` settles each candidate rule through the SAME unread re-settle as `check boundaries` (`boundaryUnitLiveness`, which replaces `withProvableDeadUnits`) and the same read scope: an unreadable governed file makes the diff NOT VERIFIED (it read exit 0), and a dead unit such a file could refute is unproven — no longer printed, and no longer a `--fail-on-dead-units` failure (1 → 2). On `check boundaries` such a unit is now reported `unproven` in `coverage[].unitLiveness` rather than dropped silently.',
|
|
276
|
+
'BEHAVIOUR CHANGE (round 13, lane B — boundary dead units reach every surface, advisory): `quality`\'s boundaries item and `finish`\'s boundaries sub-gate now name dead selector units and went-live `expectEmpty` markers as ADVISORY notes (finish: the gate `detail` and a new `notes` list — never `items`, which are envelope violations); neither ever changes a status. The dashboard boundary panel reports the orchestrator\'s verdict — violations, `summary`, `verdict`, `exitCode` — instead of a hard-coded "No active violations." over any state.',
|
|
277
|
+
'BEHAVIOUR CHANGE (round 13, lane B review — an acceptance is never silent, and a pack marker is INFO everywhere): a boundary `expectEmpty` acceptance is now printed on every surface that settles a boundary run — `quality`\'s boundaries item carries the settled `accepted: <rule>: accepted by expectEmpty: …` lines, `finish` settles each rule\'s acceptance as its own envelope row (`gate.accepted` and its verdict line carry it; the boundaries detail names `N expectEmpty unit(s) intended empty`), and `drift` / `architecture violations` print them under their verdict (`--json` `accepted`) — a planned `from` glob used to turn those 2 → 0 in silence. On `check boundaries` a PACK marker that went live is printed in its own INFO block and no longer withholds the ✓ or asks the consumer to remove it (the `gates coverage` / asset-doctor behaviour); a LOCAL one still does. A went-live reason quotes evidence only: a leading-`*` pattern reads `a leading wildcard could match any known package name, so it is never judged dead` (it used to name an unrelated builtin), a relative one `a relative pattern is never judged dead (…)`.',
|
|
278
|
+
'BEHAVIOUR CHANGE (round 13, lane A — a malformed asset entry is refused LOUDLY, never a crash or a silent clamp; exits 0/2 → 1): a registration hint whose `discovery.targetGlobs` entry or `targetFile` is neither a string nor a well-formed `{ pattern, expectEmpty: true, reason? }` marker is a rejected entry (`invalid-hint`, `discovery.targetGlobs[<i>]: …`) — an object used to be ACCEPTED and crash `registrations doctor` / `self-config doctor` (`glob.includes is not a function`); a scaffold pattern with such a `matchPaths` entry is rejected (it loaded as the glob `[object Object]`, matching nothing); a search-tuning entry with a boost value that is neither a number nor a well-formed marker — or a marker in `boostTags` / `boostSources` / `boostKinds`, a marker on a key that can never fire (unprefixed, an unknown kind, excluded by `appliesToKinds`), a non-array `taskHints`, non-string `whenTokens` — is rejected, an `invalid-entry` ERROR on `search tuning doctor` (the value used to be silently clamped to 0). An authored `expectEmptyUnits` is refused on all three (the loader derives it). One predicate per kind serves the loader, `packs test --load`, `packs contributions` / `packs list` and the self-config doctor.',
|
|
279
|
+
'BEHAVIOUR CHANGE (round 13, lane A — `self-config report` is a verdict verb; usage exits 2 → 3): it settles the self-config doctor verdict (`--strict` / `--fail-on-dead-units` honoured) and is now in `GATE_VERB_PATHS` — a bad flag exits 3 (it collided with its own NOT VERIFIED 2), `--exit-trailer` covers it, its help documents `--schema` / `--output` / `--strict` / `--fail-on-dead-units` / `--json` (it showed only `[--json]`, a flag it never read), and `--json` prints `{ written, schema, verdict, exitCode, settledVerdict, shortfalls, accepted }`. `self-config doctor --json` (both schemas) gains `accepted` and `settledVerdict` (`pass` / `fail` / `not-verified`, the sibling doctors\' `verdict` vocabulary), and MCP `get_self_config_doctor` gains `accepted`, `settledVerdict`, `exitCode` and `shortfalls`; the report\'s own `verdict` is unchanged. `--fail-on-dead-units` also fails a stale LOCAL `expectEmpty` marker; a stale local marker is counted in the exit-0 line instead of certified.',
|
|
280
|
+
'BEHAVIOUR CHANGE (round 13, lane A — the `search` group keeps the doctor\'s flags; exits 0 → 1/2): `--fail-on-dead-units`, `--strict` and `--json` are declared boolean on the group, so they no longer swallow the next word — `search --fail-on-dead-units tuning doctor` ran a universal search for "doctor" and `search tuning --fail-on-dead-units doctor` printed the listing, both at exit 0; both now run the doctor. `search tuning doctor --format json` prints JSON (it printed text); `--format markdown|html` — advertised, never rendered — is a usage error (3); `search tuning list --format json` prints JSON too.',
|
|
281
|
+
'BEHAVIOUR CHANGE (round 13, lane A — MCP `get_scaffold_pattern_doctor` ≡ `scaffolds doctor`): both read one report (`buildScaffoldPatternDoctorReport`) and propose through one rule, so the MCP tool now counts the patterns the loader REFUSED (`rejected`, each an error — it answered "errors: 0" where the CLI exited 1) and returns `verdict` / `exitCode` / `shortfalls` / `accepted` / `units`.',
|
|
282
|
+
'BEHAVIOUR CHANGE (round 13, lane A — `packs contributions` covers search tuning; exit 0 → 2): the unresolvable-reference scan (`collectUnresolvableReferences`, the self-config doctor\'s `unresolvableReferences`) includes search-tuning boost keys through the SAME key probes `search tuning doctor` judges (`searchTuningKeyProbes`): a contributed boost whose kind\'s registry is empty (`registry-empty`) or whose document kind has no id registry (`doc:`, `preset:`, … — kind `search-document`, `undeclarable-kind`) is an unresolvable reference of the tuning file, so `packs contributions` is 2 NOT VERIFIED where it printed ✓ while `search tuning doctor` exited 2 over the same key.',
|
|
283
|
+
'BEHAVIOUR CHANGE (round 13, lane A — knowledge stale-check never ✓s over a STALE row): under `--ci` / `--strict` / `--fail-on <categories>` a failing reference the mode waives (`required: false`, or outside the chosen categories) is printed as an acceptance (`accepted by required: false (--ci fails on required references only): …`, in `gate.accepted`; `shrk quality` folds it the same way through `settleKnowledgeStaleGate`), and the ✓ line names it (`N failing reference(s) listed above do not block this mode`) instead of claiming "no stale or missing references" under the row. Exits are unchanged.',
|
|
284
|
+
'Round 13 (lane A — wording and coverage records): the registration / scaffold / search-tuning dead-selector findings and the self-config next command add the third explanation — `… — typo, retired target, or a target that does not exist yet (see expectEmpty)` (the one core constant `DEAD_SELECTOR_CAUSES`); `self-config doctor`\'s dead-unit hint reads `Fix each dead unit (N) — …`. Routing hints that can never match settle through the same authority (unmarked, dead by shape). The `discovery selectors`, `matchPaths globs`, `patterns`, `boost keys`, `task hints` and routing `hints` records carry `reason` only over a gap (it was always present), and an unverifiable boost key is labelled `(unproven)` in them (was `(unverified)`). Exits are unchanged.',
|
|
285
|
+
'BEHAVIOUR CHANGE (round 13, lane A review — `search tuning list --format` is honest; exit 0 → 2): the list renders text or JSON, and its usage now says so (`[--format text|json]`; it advertised markdown / html); `--format markdown|html`, which printed the text listing at exit 0, is a usage error (2), as it is on the doctor (3).',
|
|
286
|
+
'Round 13 (lane A review — an ignored marker is never silent): a `{ weight, expectEmpty: true }` marker on a missing boost key that another declaration leaves unmarked is not honoured (the key stays dead: the unmarked declaration is a boost that never fires); the marked declaration\'s `target-missing` finding now says so and names the unmarked declarations (`Its expectEmpty marker is not honoured: the key is also declared unmarked (<tuning id> <map>) — mark every declaration, or drop the unmarked one.`). Exits are unchanged.',
|
|
287
|
+
'BEHAVIOUR CHANGE (round 13, lane P — P4, the registration-role coverage fold; exits 0 → 2): `wiring unprovided`, `wiring orphans`, finish\'s `unprovided` sub-gate and MCP `get_wiring_graph` fold every idiom\'s ROLE record from THE role authority `gates check` / `gates coverage` read (`measureRegistrationRoles`). An idiom whose declared / provided / consumed role matched no file printed `✓ Every declared/injected token has a provider. ✓` (and `✓ unprovided pass`, `verdict: "pass"` with `coverage: null`) at exit 0 while `gates check` said NOT VERIFIED on the same tree; it is now 2 NOT VERIFIED naming the role (`di: examined 2 of 3 roles … declared (0 files)`), a found token keeps its 1, and a role whose every glob is marked `expectEmpty` is accepted (printed). `wiring unprovided|orphans --json` now ALWAYS carries `coverage`, `exitCode`, `verdict`, `shortfalls`, `accepted` and the shared `gate` envelope (they appeared only over an unread file), and so do the no-idiom and empty-changed-scope answers; MCP `get_wiring_graph` always returns `coverage` and `accepted`.',
|
|
288
|
+
'BEHAVIOUR CHANGE (round 13, lane P — `conventions check` is a verdict verb; exits 0 → 2): it settles through the shared gate envelope — `2` NOT VERIFIED over an empty file scope (no working-tree change, an empty `--since` / `--staged` diff, not a git repository), no convention declared, or a convention file that never loaded; `--allow-empty` (new on this verb) accepts the first two explicitly, printed, never the third; `1` on an `error`-severity hit; `3` on a usage error (it is in `GATE_VERB_PATHS`, so `--exit-trailer` and the piped note cover it). It printed `ok — no violations.` at exit 0 over nothing. `--json` keeps `schema` / `filesScanned` / `hits` / `verdict` and adds `conventions`, `exitCode`, `shortfalls`, `accepted` and `gate`.',
|
|
289
|
+
'BEHAVIOUR CHANGE (round 13, lane P — a flag only a sibling subverb documents is refused; exits 0 / 2 → 3 on a verdict verb, 0 → 2 on an informational one):an invocation\'s flags are judged by ITS documentation — the usages along its declared-subverb walk and the command-index entries its path passes through — never a sibling\'s. `check --fail-on-dead-units` ran the whole sweep at exit 0 (only `check boundaries` documents the flag), `check templates|wiring --fail-on-dead-units`, `self-config broken-links --fail-on-dead-units` and `self-config doctor --allow-empty` ignored it. A flag only a sibling documents that the run did not read now refuses a verdict verb\'s result (`3`; a found `1` is kept) with `! \`shrk check\`: --fail-on-dead-units is not a flag of this command — only \`shrk check boundaries\` documents it.`, and refuses an informational verb\'s `0` the same way, like any dropped flag (`registrations list --fail-on-dead-units` → 2; round 13 review — it was only warned). A sibling-documented flag the run READ is never judged (a group\'s shared option), and a flag no documentation of the group names is still refused before anything runs.',
|
|
290
|
+
'BEHAVIOUR CHANGE (round 13, lane P — one refused-flag format): the declared-set guard (`gates check`, `graph cycles`, `smart-context`, …), the documentation refusal, the in-body allow-lists of `check boundaries` and `reuse coverage`, and the post-run judgement print ONE format — `! \`shrk <path>\`: --x is not a flag of this command. Did you mean --y?`, an `Accepts: …` line for a command that declares its complete flag set, and one closing sentence saying when (`Refused before anything ran — …`, `The run ignored --x, so its result is refused — …`, `The run ignored --x (exit N kept).`). The guard printed `Unknown flag "--x" for \`shrk gates check\`. Accepts: …`; the post-run line read `… is not a flag of this command and was ignored.` Exits are unchanged.',
|
|
291
|
+
'BEHAVIOUR CHANGE (round 13, lane P — P3, pack doc-reference rules take the rejection channel; exits 0 → 1): a pack doc-reference rule the merge seam refuses is a structured rejection — `packs contributions` names the file and the entry (exit 1), `packs list` / `packs get` count the `doc-reference` kind, `packs test --load` reports `asset-entry-rejected`, `self-config doctor` reports `doc-reference-invalid`, and `gates check` / `gates coverage` / `quality` carry it as an ERRORED row (`failed validation — NOT evaluated`). It was only a `! pack …: invalid docReference element … — skipped` diagnostic under a ✓. A VALID pack doc-reference file is listed by the contributions inventory (it said "no contributed file (local or pack) was discovered", exit 2).',
|
|
292
|
+
'BEHAVIOUR CHANGE (round 13, lane P — MCP `get_ci_prediction` never reads an unmeasured verdict as a pass): the self-config probe reads only `ok` as `pass`; `unverified` (what `self-config report` writes over a dead unit — the doctor exits 2, so the CI step fails) predicts `fail`, an unknown verdict `unknown`. It read everything but `errors` / `warnings` as `pass`. And any cached report that carries its own non-zero `exitCode` never predicts `pass` — nor `warn` (round 13 review: `self-config doctor --strict --json` exits 1 on a warning, and its `verdict: "warnings"` predicted a non-blocking warn) — whatever field its probe reads.',
|
|
293
|
+
'FIXED (round 13, lane P): the "stdout is piped" note fires only when stdout feeds another process (a pipe or a socket) — a plain file redirect (`… > log 2>&1`) wrote the note into the log although nothing was downstream. `quality`\'s cross-references item names `shrk self-config xrefs` as its repro — the verb that prints the same `buildDeclaredXrefReport` the item summarises; it named `shrk self-config doctor`, which computes a different report (on a tree with no declared id the item said "none declared" while the named repro exited 2 over dead units).',
|
|
294
|
+
'BEHAVIOUR CHANGE (round 13, lane P review — the plane verbs agree on a rejected pack doc-reference rule; exits 0 / 2 → 1): `docs references check` carries a pack doc-reference rule the merge seam refused as an ERRORED row and exits 1 (`--json` lists it under `rejected`; `--id` selects it) — it printed `Every id cited in prose resolves. ✓` at 0 with only a `! … — skipped` line (or "No doc-reference rules declared" at 2 when it was the only rule) while `gates check` exited 1 on the same tree. finish\'s `unprovided` sub-gate carries EVERY idiom\'s role record and expectEmpty acceptance (`gates[].extraCoverage`, one envelope row each): with two idioms it printed only the first idiom\'s acceptance and named only the first dead role. `conventions check --json` reads `verdict: "not-verified"` at 2 (it kept the engine\'s `clean` beside `exitCode: 2`).',
|
|
295
|
+
'BEHAVIOUR CHANGE (round 13, K1 — a verdict-valve flag the subverb does not document is refused BEFORE the run): `--fail-on-dead-units`, `--allow-empty`, `--min-referenced` and `--fail-on` (the closed enum `VerdictValveFlag`) are judged inside the one `judgeInvocation`, so the dispatcher and the command-string resolver refuse the same string. `shrk check --fail-on-dead-units` printed the whole sweep and only then exited 3; it now exits 3 with nothing printed, naming the subverbs that accept the flag (`— only \`shrk check boundaries\` documents it`). Likewise `self-config doctor|report --allow-empty`, `registrations list|get|preview --fail-on-dead-units` (2, informational) and every other sibling-only valve. The resolver now reports those strings `unknown-flag` (it certified them). Every other sibling-documented flag keeps the post-run judgement.',
|
|
296
|
+
'BEHAVIOUR CHANGE (round 13, K2 — every plane verb says what `gates coverage` and `check boundaries` say about a selector unit): `policy-lint`, `check wiring`, `baseline check`, `generated check`, `docs references check`, `registry <name> list|duplicates`, `gates check`, the policy and wiring explain views, and finish\'s wiring / policy sub-gates print ONE shared unit-state block (`unitStateNotes`): an unmarked dead unit of a rule that still matched (a dead import-edges `to.files` under an accepted fence included) under `Dead selector units (N)` with the causes once as a footer, a LOCAL `expectEmpty` marker whose target appeared under `expectEmpty markers that went live (N)`, and a PACK marker in its own INFO block. A dead or local went-live unit withholds the ✓ (the clean line names them, the rule row reads ⚠); the exit is unchanged.',
|
|
297
|
+
'BEHAVIOUR CHANGE (round 13 review — `wiring chain` settles like its siblings; exits 0 → 2): the chain folds every involved idiom\'s role record and expectEmpty acceptance (`measureIdiomRoleCoverage`) through the shared gate envelope, so a chain over a dead declared role is NOT VERIFIED instead of `declared (0)` … `✓ declared → provided → consumed.` at exit 0, an acceptance is printed under the ✓, and `--json` carries `coverage`, `exitCode`, `verdict`, `shortfalls`, `accepted` and `gate` (its r75 MATRIX row is `envelope`).',
|
|
298
|
+
'FIXED (round 13 review): `wiring unprovided|orphans --json` over an empty or unresolvable changed scope, and every registration query with no `registrationGraph[]`, carry `coverage` / `exitCode` / `verdict` / `shortfalls` / `accepted` next to `gate`, as documented — the scoped answers carried `gate` alone and the no-idiom answer lacked `coverage`.',
|
|
299
|
+
'BEHAVIOUR CHANGE (round 13 review — MCP `get_changed_boundary_report` carries the settled unit states): its `typescript` block adds `deadUnits`, `intendedEmpty`, `wentLive`, `failingUnits` and `accepted`, in the shapes `check_boundaries` returns. It answered a bare `pass` over a marked planned unit, and over a marker that went live, while `check boundaries --files …` printed the acceptance or withheld its ✓.',
|
|
300
|
+
'BEHAVIOUR CHANGE (round 13 review — a static rule view never claims a unit\'s state): `boundaries explain` / `boundaries get` / `shrk explain <boundary rule id>` print each marker as `expectEmpty marker <list> <unit> — <reason> (state: see \`shrk check boundaries\`)` (it read `intended empty` over a marker that went live), and MCP `get_boundary_rule` returns the same declarations as `expectEmptyMarkers` in place of `intendedEmpty`.',
|
|
301
|
+
'BEHAVIOUR CHANGE (round 13 review — the one per-unit wording on the gate planes): `gates coverage` and `gates try` print an intended-empty unit as its `formatUnitLiveness` line under a neutral bullet (`· <glob> — intended empty (expectEmpty) — …`), never a hand-built `✓ asserted empty (expectEmpty): …` row (it printed one under FAILED and SKIPPED rules). A dead gate-plane glob is followed once by `Dead selectors: typo, retired target, or a target that does not exist yet (see expectEmpty).`, and `quality`\'s dead-glob note carries the same sentence.',
|
|
302
|
+
'BEHAVIOUR CHANGE (round 13 review — the ONE empty-rule advice reaches every branch): `check wiring` and `policy-lint` (their 0-evaluated returns included), `gates coverage` (a failing failOnEmpty rule), `baseline check`, `generated check` and `docs references check` (K8: a soft skip) print `formatEmptyRuleAdvice` with each rule\'s REAL `fails` through one renderer (`emptyRuleAdviceLines`). Several branches printed no advice, and a failing rule was never advised.',
|
|
303
|
+
'BEHAVIOUR CHANGE (round 13 review — finish and quality carry every acceptance, and a pack marker is INFO everywhere): finish\'s `wiring` and `policy` sub-gates forward each rule\'s expectEmpty acceptance (`extraCoverage`: printed under the ✓ and in `gate.accepted` — a fully marked rule turned finish 1 → 0 with the acceptance printed nowhere) and list a dead unit or a went-live marker as a note. A PACK marker that went live is `[info]` in finish\'s boundaries notes (`N pack expectEmpty marker(s) went live (INFO)` in its detail) and `info:` in `quality`\'s boundary and gate-plane notes — never counted as advisory.',
|
|
304
|
+
'BEHAVIOUR CHANGE (round 13 review — an asset doctor that fails on a unit says so): `registrations doctor`, `scaffolds doctor`, `search tuning doctor` and `self-config doctor|report` print `Verdict: <doctor> needs attention — N dead unit(s) / N went-live expectEmpty unit(s) (--fail-on-dead-units)` and each unit when that is what exited 1 (the run ended on INFO lines; `self-config doctor`\'s header read `verdict OK`), and their `--json` carries `failingUnits` — one predicate, `assetDoctorFailingUnits`. `registrations doctor`\'s status column fits `intended-empty` (K11).',
|
|
305
|
+
'Round 13 (K7): `check boundaries --diff-against` does not apply `--strict` — its usage line and docs/boundaries.md now say so (the diff settles on error violations, dead candidate scopes and `--fail-on-dead-units`; behaviour unchanged).',
|
|
306
|
+
'BEHAVIOUR CHANGE (round 13, K9 — `baseline update` never proposes a ceiling from an empty measurement; exits 0 → 2 / 1): a `mode: \'ceiling\'` rule whose compute measured nothing is decided by THE rule-emptiness settle `baseline check` reads. Accepted (a fence, an intended-empty input), it is judged like any value; otherwise it is the loud skip — `– <id>: no ceiling proposed — <reason>`, `--json` `skipped`, exit 2 — and a failOnEmpty rule is refused (1), where it printed `edit config … ceiling: 0`.',
|
|
307
|
+
'BEHAVIOUR CHANGE (round 13, K10): `docs references list` lists the pack doc-reference rules the merge seam REJECTED (`rejected at the pack-plane merge seam — never checked`, `--json` `rejected`), and `docs references explain --id <rejected id>` names the rejection (exit 1) — it called the id unknown (3).',
|
|
308
|
+
'BEHAVIOUR CHANGE (round 13, K4 — a registration-hint marker is never dropped silently; `registrations doctor` / `self-config doctor` exits 0 → 1): a fixed `discovery.targetFile` wins over `discovery.targetGlobs` (THE discovery authority never walks the globs of such a hint), so an `expectEmpty` marker on one of its `targetGlobs` used to vanish — never intended-empty, never went-live. `validateRegistrationHint` (@shrkcrft/plugin-api) now refuses it — `discovery.targetGlobs[i]: a marker on a list this hint\'s discovery mode never judges — a fixed discovery.targetFile wins over discovery.targetGlobs, … mark discovery.targetFile instead, or drop targetFile so the globs are judged` — through the round-12 rejection channel: the loader rejects the hint (`invalid-hint`, error) and `packs test --load` names the same reason. Plain globs beside a fixed target stay legal.',
|
|
309
|
+
'BEHAVIOUR CHANGE (round 13, K5 — a boundary marker that could only read went-live is refused; `check boundaries` exits 0 → 1, an errored rule): a `{ pattern, expectEmpty: true }` marker on a `forbiddenImports` / `allowedImports` pattern the dead-unit judge can NEVER call dead — a relative pattern, a leading `*`, or one a runtime builtin module matches (`fs`, `node:*`) — is refused at load: `\'<pattern>\' is marked expectEmpty, but <why it is never judged dead> — a marker on it could only ever read went-live; write the plain pattern (it needs no expectEmpty)`. The judge\'s reach rules are shared, not re-derived: `importPatternNeverJudgedDead`, `couldMatchPackageName` (moved out of the evaluator), `RELATIVE_PATTERN_NEVER_DEAD` / `LEADING_WILDCARD_NEVER_DEAD` and `nodeBuiltinPackageNames` (the one builtin list `collectKnownPackages` now reads too) are new exports of @shrkcrft/boundaries.',
|
|
310
|
+
'BEHAVIOUR CHANGE (round 13, K6 — an intended-empty rule is accepted, never evaluated): a boundary rule whose every `from` inclusion is marked `expectEmpty` and that matched no file examined 0 files, so `rulesEvaluated` (`evaluateBoundaries`) and THE inspector count `boundaryRulesEvaluated` (`check boundaries --json`, `diff-check`, MCP `check_boundaries`) no longer count it; it is counted apart — `IEvaluateResult.rulesAcceptedEmpty`, `IBoundaryRuleCoverage.acceptedAsIntendedEmpty` (the `coverage[]` row of `check boundaries --json`) and `boundaryRuleAcceptedEmpty` / `boundaryRulesAcceptedEmpty` (@shrkcrft/inspector) — and printed `N evaluated, M accepted as intended-empty`. The policy and wiring engine reports gain `acceptedEmpty` beside `evaluated` (which keeps counting the accepted rule, so the verdict path\'s "nothing ran" guard never reads an accepted plan as a skip; the printed evaluated count is `evaluated − acceptedEmpty`), and their doc comments now say so.',
|
|
311
|
+
'BEHAVIOUR CHANGE (round 13, K6 — the gate envelope never counts an accepted intended-empty rule as evaluated): `gate.evaluated` (the shared `--json` envelope of every verdict verb — `policy-lint`, `check wiring`, `check boundaries`, `gates check`, `gates coverage`, `baseline check`, `generated check`, `docs references check`, …) no longer counts a rule accepted as intended-empty — one whose coverage IS its `expectEmpty` acceptance (every inclusion unit of its primary list marked, 0 files examined). It examined nothing, so it is counted apart in the NEW optional `gate.acceptedEmpty` (present only when non-zero; no always-present key). ONE predicate decides it for every verb, `ruleAcceptedAsIntendedEmpty` (@shrkcrft/core, beside `ruleVerdictRecords`), over the record the engines\' own settle put on the rule; a rule that examined live units beside a planned one (a registration idiom whose declared role is planned) and the baselines rule-level fence (`expectEmpty: true`) stay evaluated. The text counts follow, in one wording (`acceptedEmptyNote`): `policy-lint` and `check wiring` (`rules evaluated`, and check wiring\'s "not a full green" sentence) print the engine\'s `evaluated − acceptedEmpty`; `gates check`, `baseline check`, `generated check` and `docs references check` (`evaluated`) print `gate.evaluated` — each as `N of M, K accepted as intended-empty` (the plane payloads\' own top-level `evaluated` is unchanged). MCP `check_boundaries` adds `rulesAcceptedEmpty` beside `rulesEvaluated` (0 when no rule is configured), as `check boundaries --json` has. `gates explain` on a registry or a registration idiom now prints THE shared unit-state block (`unitStateNotes`) the wiring and policy explain views print — a dead glob, a went-live marker, a pack marker as INFO — and every explain view (`gates explain`, `wiring explain`, `check wiring --explain`, `wiring test`, `policy-lint explain`) lists each intended-empty unit as its one per-unit line (`· <rule id>: <formatUnitLiveness>`).',
|
|
312
|
+
'FIXED (round 13 review — the dashboard boundary panel says "accepted" only over an acceptance): the panel derived `N expectEmpty unit(s) accepted` from the intended-empty unit count, so a run failing on a violation (exit 1, `accepted: []`) still claimed an acceptance. It now reads the settle — `accepted` at exit 0 with settled acceptance lines, `N expectEmpty unit(s) intended empty` otherwise (the word finish\'s boundaries sub-gate uses).',
|
|
313
|
+
'Round 13 (K12 — the release tooling is typechecked): `tsconfig.base.json` excludes `scripts/**`, so no script — release-preflight, build-dist, the workspace-link gate, the node-dist smoke — was ever typechecked. New `tsconfig.scripts.json` (extends the base, includes `scripts/**/*.ts`) runs as a REQUIRED `typecheck-scripts` step right after `typecheck` in `release:preflight`, and in CI; its two findings are fixed (an unreachable private-package branch in check-publish-readiness, an unsound cast in publish-mode).',
|
|
314
|
+
'Docs (round 13 review): `docs/claude-code.md` documents the `shrk-mcp` bin `@shrkcrft/mcp-server` now ships (global install, or `bunx --package @shrkcrft/mcp-server shrk-mcp` / `npx -y --package …`) instead of a "future" `bunx -y @shrkcrft/mcp-server`; `docs/intended-empty.md` scopes "a malformed local marker is exit 3" to the verdict verbs whose rules live in the config (`check boundaries` and the asset doctors read the unloadable config as 2, `doctor` / `quality` / `finish` as 1), names the `state` of `check boundaries --json` per `coverage[]` sub-row, words the registry acceptance per answer that exits 0, and corrects the alpha.30 forward-compat claim (an object boundary entry LOADS there and matches nothing silently — it is not refused); `docs/exit-codes.md` lists `conventions check`, `self-config broken-links` and `packs contributions` under `--allow-empty`; `docs/registration-hints.md` shows the `· I intended-empty` header segment.',
|
|
315
|
+
],
|
|
316
|
+
removed: [
|
|
317
|
+
'`shrk commands` no longer advertises `commands suggest` / `commands explain` (deleted earlier; they now exit 2, list the `commands` subcommands and name the replacement) — use `shrk commands search "<partial>"` and `shrk help <cmd>`.',
|
|
318
|
+
'`shrk ci scaffold --with-baseline` no longer emits the removed `quality baseline-compare` step; it runs `shrk baseline check`.',
|
|
319
|
+
],
|
|
320
|
+
},
|
|
157
321
|
];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"changes.command.d.ts","sourceRoot":"","sources":["../../src/commands/changes.command.ts"],"names":[],"mappings":"AAiBA,OAAO,EAKL,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"changes.command.d.ts","sourceRoot":"","sources":["../../src/commands/changes.command.ts"],"names":[],"mappings":"AAiBA,OAAO,EAKL,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;AAsIhC,eAAO,MAAM,cAAc,EAAE,eAoC5B,CAAC"}
|
|
@@ -8,6 +8,9 @@ import { existsSync, mkdirSync, writeFileSync } from 'node:fs';
|
|
|
8
8
|
import * as nodePath from 'node:path';
|
|
9
9
|
import { buildAcceptanceReplay, buildChangesSummary, inspectSharkcraft, renderAcceptanceReplayMarkdown, renderAcceptanceReplayText, renderChangesSummaryMarkdown, ReplayProfile, } from '@shrkcrft/inspector';
|
|
10
10
|
import { flagBool, flagString, flagList, resolveCwd, } from "../command-registry.js";
|
|
11
|
+
import { PositionalMode } from "../dispatch/positional-mode.js";
|
|
12
|
+
/** The selection / render flags every `changes` subverb shares (the handler usage's tail). */
|
|
13
|
+
const CHANGES_FLAGS = '[files... | --files a,b,c] [--since <ref>] [--staged] [--round <name>] [--profile changed-only|standard|strict] [--format text|markdown|json] [--output <file>]';
|
|
11
14
|
import { asJson, header } from "../output/format-output.js";
|
|
12
15
|
async function runChangesSummary(args) {
|
|
13
16
|
const cwd = resolveCwd(args);
|
|
@@ -145,6 +148,18 @@ async function runChangesAcceptanceReplay(args) {
|
|
|
145
148
|
}
|
|
146
149
|
export const changesCommand = {
|
|
147
150
|
name: 'changes',
|
|
151
|
+
positionals: PositionalMode.None,
|
|
152
|
+
subverbs: [
|
|
153
|
+
{ name: 'summary', description: 'The grouped changes summary (the default).', usage: `shrk changes summary ${CHANGES_FLAGS}`, positionals: PositionalMode.Free },
|
|
154
|
+
{ name: 'report', description: 'The changes summary as a report.', usage: `shrk changes report ${CHANGES_FLAGS}`, positionals: PositionalMode.Free },
|
|
155
|
+
{ name: 'impact', description: 'The changes summary with impact.', usage: `shrk changes impact ${CHANGES_FLAGS}`, positionals: PositionalMode.Free },
|
|
156
|
+
{
|
|
157
|
+
name: 'acceptance-replay',
|
|
158
|
+
aliases: ['replay', 'acceptance'],
|
|
159
|
+
description: 'Replay the acceptance checks for a change set.',
|
|
160
|
+
usage: `shrk changes acceptance-replay ${CHANGES_FLAGS}`,
|
|
161
|
+
},
|
|
162
|
+
],
|
|
148
163
|
description: 'Changes summary — grouped diff over --since/--staged/--files. Supports --round label and `changes acceptance-replay`. Read-only.',
|
|
149
164
|
usage: 'shrk changes <summary|impact|report|acceptance-replay> [files... | --files a,b,c] [--since <ref>] [--staged] [--round <name>] [--profile changed-only|standard|strict] [--format text|markdown|json] [--output <file>]',
|
|
150
165
|
booleanFlags: new Set(['json', 'staged']),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"check.command.d.ts","sourceRoot":"","sources":["../../src/commands/check.command.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"check.command.d.ts","sourceRoot":"","sources":["../../src/commands/check.command.ts"],"names":[],"mappings":"AAoCA,OAAO,EAOL,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;AA2mEhC,eAAO,MAAM,YAAY,EAAE,eAsG1B,CAAC"}
|