@shrkcrft/cli 0.1.0-alpha.27 → 0.1.0-alpha.29

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.
Files changed (46) hide show
  1. package/dist/commands/baseline.command.d.ts +8 -0
  2. package/dist/commands/baseline.command.d.ts.map +1 -0
  3. package/dist/commands/baseline.command.js +542 -0
  4. package/dist/commands/changelog-data.d.ts.map +1 -1
  5. package/dist/commands/changelog-data.js +42 -0
  6. package/dist/commands/check.command.d.ts.map +1 -1
  7. package/dist/commands/check.command.js +147 -12
  8. package/dist/commands/command-catalog.d.ts.map +1 -1
  9. package/dist/commands/command-catalog.js +120 -0
  10. package/dist/commands/daily.commands.d.ts.map +1 -1
  11. package/dist/commands/daily.commands.js +11 -1
  12. package/dist/commands/gates.command.d.ts +16 -0
  13. package/dist/commands/gates.command.d.ts.map +1 -0
  14. package/dist/commands/gates.command.js +377 -0
  15. package/dist/commands/generated.command.d.ts +6 -0
  16. package/dist/commands/generated.command.d.ts.map +1 -0
  17. package/dist/commands/generated.command.js +544 -0
  18. package/dist/commands/help.command.d.ts.map +1 -1
  19. package/dist/commands/help.command.js +64 -2
  20. package/dist/commands/ingest.command.d.ts +11 -0
  21. package/dist/commands/ingest.command.d.ts.map +1 -1
  22. package/dist/commands/ingest.command.js +49 -23
  23. package/dist/commands/policy-lint.command.d.ts +37 -0
  24. package/dist/commands/policy-lint.command.d.ts.map +1 -1
  25. package/dist/commands/policy-lint.command.js +167 -8
  26. package/dist/commands/registry.command.d.ts.map +1 -1
  27. package/dist/commands/registry.command.js +70 -13
  28. package/dist/commands/wiring.command.d.ts.map +1 -1
  29. package/dist/commands/wiring.command.js +25 -0
  30. package/dist/exit-codes.d.ts +27 -7
  31. package/dist/exit-codes.d.ts.map +1 -1
  32. package/dist/exit-codes.js +47 -8
  33. package/dist/finish/run-finish.d.ts.map +1 -1
  34. package/dist/finish/run-finish.js +9 -3
  35. package/dist/gates/gate-envelope.d.ts +64 -0
  36. package/dist/gates/gate-envelope.d.ts.map +1 -0
  37. package/dist/gates/gate-envelope.js +26 -0
  38. package/dist/gates/gate-rule-view.d.ts +35 -0
  39. package/dist/gates/gate-rule-view.d.ts.map +1 -0
  40. package/dist/gates/gate-rule-view.js +81 -0
  41. package/dist/gates/rule-coverage.d.ts +53 -0
  42. package/dist/gates/rule-coverage.d.ts.map +1 -0
  43. package/dist/gates/rule-coverage.js +165 -0
  44. package/dist/main.d.ts.map +1 -1
  45. package/dist/main.js +27 -3
  46. package/package.json +33 -33
@@ -12,12 +12,19 @@
12
12
  * 0 VerifiedPass — checks ran over a NON-EMPTY scope and passed. Never
13
13
  * returned when zero units were evaluated.
14
14
  * 1 Failure — checks ran and found violations.
15
- * 2 NotVerified — indeterminate: empty evaluation scope, degraded
16
- * fallback, short-circuit, timeout, or "refused to run".
17
- * Distinct from both pass and fail so a chain can branch
18
- * on it (`|| handle-indeterminate`). This is also the
19
- * code the CLI already uses for usage errors — both mean
20
- * "did not produce a verified result".
15
+ * 2 NotVerified — indeterminate: empty evaluation scope, all rules
16
+ * skipped, degraded fallback, short-circuit, timeout, or
17
+ * "refused to run". Distinct from both pass and fail so a
18
+ * chain can branch on it (`|| handle-indeterminate`).
19
+ * 3 UsageError — the request itself was malformed: unloadable config, an
20
+ * unknown rule id, a bad flag value. Split out of `2` on
21
+ * the GATE verbs because the two demand different
22
+ * responses: `2` means "the gate ran but proved nothing"
23
+ * (investigate the rules), `3` means "the gate never
24
+ * started" (fix the invocation or the config). Non-gate
25
+ * verbs keep returning `2` for usage errors — widening the
26
+ * split across the whole CLI would churn a documented
27
+ * contract far beyond what it buys.
21
28
  *
22
29
  * The `gen --typecheck` pre-write gate already refuses-to-nonzero rather than
23
30
  * emit an unverified artifact; this generalizes that instinct across the gate
@@ -29,6 +36,7 @@ export var ExitCode;
29
36
  ExitCode[ExitCode["VerifiedPass"] = 0] = "VerifiedPass";
30
37
  ExitCode[ExitCode["Failure"] = 1] = "Failure";
31
38
  ExitCode[ExitCode["NotVerified"] = 2] = "NotVerified";
39
+ ExitCode[ExitCode["UsageError"] = 3] = "UsageError";
32
40
  })(ExitCode || (ExitCode = {}));
33
41
  /**
34
42
  * Promote a NotVerified (`2`) exit into a Failure-class nonzero (`1`) when the
@@ -116,6 +124,32 @@ export function isGateVerb(commandPath) {
116
124
  return true;
117
125
  return false;
118
126
  }
127
+ /**
128
+ * True when the argv carries the global `--no-hints` (before the `--`
129
+ * sentinel). Suppresses advisory one-liners like the piped-exit note while
130
+ * leaving every real diagnostic — and the `--exit-trailer` machine channel —
131
+ * untouched. For a caller that has already internalised the warning and just
132
+ * wants clean stderr in captured logs.
133
+ */
134
+ export function argvHasNoHints(argv) {
135
+ for (const t of argv) {
136
+ if (t === '--')
137
+ break;
138
+ if (t === '--no-hints')
139
+ return true;
140
+ }
141
+ return false;
142
+ }
143
+ /**
144
+ * Process-lifetime latch for the piped-exit hint. The note is advisory, so it
145
+ * pays rent once: a command that emits several gate verdicts in one process
146
+ * (or a `--watch` loop) should not repeat the same paragraph every cycle.
147
+ */
148
+ let pipeHintEmitted = false;
149
+ /** Reset the one-time hint latch. Test-only seam. */
150
+ export function resetPipeHintLatch() {
151
+ pipeHintEmitted = false;
152
+ }
119
153
  /**
120
154
  * Keep the honest `0`/`1`/`2` exit code READABLE through the shape agents reach
121
155
  * for first — the trailing pipe. `<gate> | head` reports `head`'s `$?`, so a true
@@ -136,9 +170,14 @@ export function emitPipeExitSignal(commandPath, code, opts) {
136
170
  if (!isGateVerb(commandPath))
137
171
  return;
138
172
  const write = opts.write ?? ((s) => void process.stderr.write(s));
139
- if (opts.piped && code !== 0) {
173
+ // Advisory, and therefore rationed: stderr only, only when a NON-zero verdict
174
+ // would actually be lost to the pipe, at most once per process, and never
175
+ // under `--no-hints`. The structured channel (`--exit-trailer`) is unaffected
176
+ // by all of these — it is opt-in and always emitted when asked.
177
+ if (opts.piped && code !== 0 && !opts.noHints && !pipeHintEmitted) {
178
+ pipeHintEmitted = true;
140
179
  write(`note: stdout is piped — $? reflects the downstream command, not shrk (exit ${code}); ` +
141
- `use PIPESTATUS[0] or --exit-trailer to read shrk's verdict.\n`);
180
+ `use PIPESTATUS[0] or --exit-trailer to read shrk's verdict (--no-hints silences this).\n`);
142
181
  }
143
182
  // The trailer is written LAST so it is the final stderr line a caller reads.
144
183
  if (opts.trailer)
@@ -1 +1 @@
1
- {"version":3,"file":"run-finish.d.ts","sourceRoot":"","sources":["../../src/finish/run-finish.ts"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,oBAAoB,EAC1B,MAAM,qBAAqB,CAAC;AAiB7B,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,eAAO,MAAM,aAAa,EAAG,sBAA+B,CAAC;AAQ7D,2FAA2F;AAC3F,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;AAE3D,8EAA8E;AAC9E,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,YAAY,GAAG,SAAS,GAAG,QAAQ,GAAG,YAAY,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC;IAClG,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC;IAClC,uEAAuE;IACvE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,oEAAoE;IACpE,QAAQ,CAAC,KAAK,EAAE,SAAS,WAAW,EAAE,CAAC;IACvC;;;;;;OAMG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IACvC,yEAAyE;IACzE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,MAAM,EAAE,OAAO,aAAa,CAAC;IACtC,QAAQ,CAAC,KAAK,EAAE;QACd,QAAQ,CAAC,IAAI,EAAE,UAAU,GAAG,QAAQ,GAAG,OAAO,GAAG,OAAO,CAAC;QACzD,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;QAClC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;KAC5B,CAAC;IACF,QAAQ,CAAC,KAAK,EAAE,SAAS,WAAW,EAAE,CAAC;IACvC,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;IAC/B;;;;;;;;OAQG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,cAAc,CAAC;IACnD,6EAA6E;IAC7E,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,mEAAmE;IACnE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,2EAA2E;IAC3E,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,IAAI,EAAE,UAAU,GAAG,QAAQ,GAAG,OAAO,GAAG,OAAO,CAAC;IACzD,QAAQ,CAAC,KAAK,EAAE,oBAAoB,CAAC;CACtC;AAmBD;;;;;;;;GAQG;AACH,wBAAsB,cAAc,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,aAAa,CAAC,CAmJnF"}
1
+ {"version":3,"file":"run-finish.d.ts","sourceRoot":"","sources":["../../src/finish/run-finish.ts"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,oBAAoB,EAC1B,MAAM,qBAAqB,CAAC;AAiB7B,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,eAAO,MAAM,aAAa,EAAG,sBAA+B,CAAC;AAQ7D,2FAA2F;AAC3F,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;AAE3D,8EAA8E;AAC9E,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,YAAY,GAAG,SAAS,GAAG,QAAQ,GAAG,YAAY,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC;IAClG,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC;IAClC,uEAAuE;IACvE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,oEAAoE;IACpE,QAAQ,CAAC,KAAK,EAAE,SAAS,WAAW,EAAE,CAAC;IACvC;;;;;;OAMG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IACvC,yEAAyE;IACzE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,MAAM,EAAE,OAAO,aAAa,CAAC;IACtC,QAAQ,CAAC,KAAK,EAAE;QACd,QAAQ,CAAC,IAAI,EAAE,UAAU,GAAG,QAAQ,GAAG,OAAO,GAAG,OAAO,CAAC;QACzD,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;QAClC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;KAC5B,CAAC;IACF,QAAQ,CAAC,KAAK,EAAE,SAAS,WAAW,EAAE,CAAC;IACvC,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;IAC/B;;;;;;;;OAQG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,cAAc,CAAC;IACnD,6EAA6E;IAC7E,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,mEAAmE;IACnE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,2EAA2E;IAC3E,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,IAAI,EAAE,UAAU,GAAG,QAAQ,GAAG,OAAO,GAAG,OAAO,CAAC;IACzD,QAAQ,CAAC,KAAK,EAAE,oBAAoB,CAAC;CACtC;AAmBD;;;;;;;;GAQG;AACH,wBAAsB,cAAc,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,aAAa,CAAC,CA2JnF"}
@@ -88,16 +88,22 @@ export async function runFinishGates(input) {
88
88
  const report = buildImportHygieneReport(cwd, { files: codeChanged });
89
89
  const errors = report.counts?.['error'] ?? (report.verdict === 'errors' ? report.findings.length : 0);
90
90
  const warnings = report.counts?.['warning'] ?? (report.verdict === 'warnings' ? report.findings.length : 0);
91
+ // Only the findings that actually DRIVE the verdict become "failing items".
92
+ // An allowlisted import is downgraded to `info` by design and is not what
93
+ // failed — listing it anyway pads the renderer's 15-item cap and can push a
94
+ // real error out of view, while its allowlist justification reads like a
95
+ // fix instruction. A fix-list that names non-failures is not a fix-list.
96
+ const driving = report.findings.filter((f) => report.verdict === 'errors' ? f.severity === 'error' : f.severity === 'warning');
91
97
  gates.push({
92
98
  name: 'imports',
93
99
  status: report.verdict === 'errors' ? 'fail' : 'pass',
94
- detail: `verdict=${report.verdict} (${report.findings.length} finding(s))`,
100
+ detail: `verdict=${report.verdict} (${driving.length} of ${report.findings.length} finding(s) drive it)`,
95
101
  errors,
96
102
  warnings,
97
- items: report.findings.map((f) => ({
103
+ items: driving.map((f) => ({
98
104
  file: f.file,
99
105
  line: f.line,
100
- message: `${f.kind}: ${f.suggestedFix || f.reason || f.snippet}`.trim(),
106
+ message: `[${f.severity}] ${f.kind}: ${f.suggestedFix || f.reason || f.snippet}`.trim(),
101
107
  })),
102
108
  });
103
109
  }
@@ -0,0 +1,64 @@
1
+ /**
2
+ * One machine-readable shape for every gate verb.
3
+ *
4
+ * `--json` has always been available on each plane, but each emitted its own
5
+ * schema (`sharkcraft.wiring/v1`, `sharkcraft.baseline/v1`, …), so a CI step or
6
+ * agent had to parse four shapes to answer one question: which rules ran, which
7
+ * failed, and why. This envelope is that answer, identical across planes.
8
+ *
9
+ * It is ADDITIVE. The per-plane payloads are published, documented, and asserted
10
+ * by tests; replacing them would break every existing consumer. The envelope
11
+ * rides along under a `gate` key, so `jq .gate` is the uniform read and nothing
12
+ * that worked before stops working.
13
+ */
14
+ export declare const GATE_ENVELOPE_SCHEMA: "sharkcraft.gate/v1";
15
+ /** Which data-defined plane produced a rule result. */
16
+ export type GateRuleType = 'wiring' | 'policy' | 'registry' | 'registration' | 'baseline' | 'generated';
17
+ /**
18
+ * Per-rule outcome, uniform across planes. `skipped` is deliberately a
19
+ * first-class status, not folded into `passed` — a rule that matched nothing
20
+ * enforced nothing.
21
+ */
22
+ export type GateRuleStatus = 'passed' | 'failed' | 'skipped' | 'error';
23
+ /** One violation, normalized. `id` is the offending token / entry / file. */
24
+ export interface IGateViolation {
25
+ readonly id: string;
26
+ readonly file?: string;
27
+ readonly line?: number;
28
+ readonly message?: string;
29
+ readonly hint?: string;
30
+ }
31
+ /** One rule's result in the shared envelope. */
32
+ export interface IGateRuleResult {
33
+ readonly id: string;
34
+ readonly type: GateRuleType;
35
+ readonly status: GateRuleStatus;
36
+ readonly severity: 'error' | 'warning';
37
+ /**
38
+ * Plane-appropriate match counts — e.g. `{declared, registered}` for wiring,
39
+ * `{committed, current}` for baseline, `{units, findings}` for policy. Always
40
+ * present so "what did this rule actually see?" is answerable uniformly.
41
+ */
42
+ readonly counts: Readonly<Record<string, number>>;
43
+ readonly violations: readonly IGateViolation[];
44
+ /** Why the rule checked nothing, when `status` is `skipped`. */
45
+ readonly skipReason?: string;
46
+ /** Set when the rule is misconfigured (`status: 'error'`). */
47
+ readonly error?: string;
48
+ }
49
+ /** The envelope emitted under the `gate` key of every gate verb's `--json`. */
50
+ export interface IGateEnvelope {
51
+ readonly schema: typeof GATE_ENVELOPE_SCHEMA;
52
+ /** The verb that produced this, space-joined (e.g. `check wiring`). */
53
+ readonly verb: string;
54
+ /** The exit code this run returns — the same number the process exits with. */
55
+ readonly exit: number;
56
+ readonly rules: readonly IGateRuleResult[];
57
+ /** Rules that ran a real comparison (status !== 'skipped'). */
58
+ readonly evaluated: number;
59
+ readonly skipped: number;
60
+ readonly failed: number;
61
+ }
62
+ /** Build the envelope from already-normalized per-rule results. */
63
+ export declare function buildGateEnvelope(verb: string, exit: number, rules: readonly IGateRuleResult[]): IGateEnvelope;
64
+ //# sourceMappingURL=gate-envelope.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gate-envelope.d.ts","sourceRoot":"","sources":["../../src/gates/gate-envelope.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,oBAAoB,EAAG,oBAA6B,CAAC;AAElE,uDAAuD;AACvD,MAAM,MAAM,YAAY,GACpB,QAAQ,GACR,QAAQ,GACR,UAAU,GACV,cAAc,GACd,UAAU,GACV,WAAW,CAAC;AAEhB;;;;GAIG;AACH,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,CAAC;AAEvE,6EAA6E;AAC7E,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,gDAAgD;AAChD,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAChC,QAAQ,CAAC,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;IACvC;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAClD,QAAQ,CAAC,UAAU,EAAE,SAAS,cAAc,EAAE,CAAC;IAC/C,gEAAgE;IAChE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,8DAA8D;IAC9D,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,+EAA+E;AAC/E,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,MAAM,EAAE,OAAO,oBAAoB,CAAC;IAC7C,uEAAuE;IACvE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,+EAA+E;IAC/E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,SAAS,eAAe,EAAE,CAAC;IAC3C,+DAA+D;IAC/D,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,mEAAmE;AACnE,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,SAAS,eAAe,EAAE,GAChC,aAAa,CAUf"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * One machine-readable shape for every gate verb.
3
+ *
4
+ * `--json` has always been available on each plane, but each emitted its own
5
+ * schema (`sharkcraft.wiring/v1`, `sharkcraft.baseline/v1`, …), so a CI step or
6
+ * agent had to parse four shapes to answer one question: which rules ran, which
7
+ * failed, and why. This envelope is that answer, identical across planes.
8
+ *
9
+ * It is ADDITIVE. The per-plane payloads are published, documented, and asserted
10
+ * by tests; replacing them would break every existing consumer. The envelope
11
+ * rides along under a `gate` key, so `jq .gate` is the uniform read and nothing
12
+ * that worked before stops working.
13
+ */
14
+ export const GATE_ENVELOPE_SCHEMA = 'sharkcraft.gate/v1';
15
+ /** Build the envelope from already-normalized per-rule results. */
16
+ export function buildGateEnvelope(verb, exit, rules) {
17
+ return {
18
+ schema: GATE_ENVELOPE_SCHEMA,
19
+ verb,
20
+ exit,
21
+ rules,
22
+ evaluated: rules.filter((r) => r.status !== 'skipped').length,
23
+ skipped: rules.filter((r) => r.status === 'skipped').length,
24
+ failed: rules.filter((r) => r.status === 'failed' || r.status === 'error').length,
25
+ };
26
+ }
@@ -0,0 +1,35 @@
1
+ import { type IBaselineRule, type IGeneratedArtifactRule, type IPolicyRule, type IRegistrationIdiom, type IRegistryDeclaration, type IRuleSelfTest, type IWiringRule } from '@shrkcrft/core';
2
+ /** Which data-defined plane a rule belongs to. */
3
+ export type GatePlane = 'wiring' | 'policy' | 'registry' | 'registration' | 'baseline' | 'generated';
4
+ /** Every plane, in the order `shrk gates list` prints them. */
5
+ export declare const GATE_PLANES: readonly GatePlane[];
6
+ /**
7
+ * One data-defined rule, normalized across planes.
8
+ *
9
+ * The trust layer's whole job is to answer "what did this rule actually match?"
10
+ * for ANY rule, so it needs one shape to iterate. The plane-specific rule object
11
+ * rides along in `raw` for the explain dispatch.
12
+ */
13
+ export interface IGateRuleView {
14
+ readonly id: string;
15
+ readonly plane: GatePlane;
16
+ readonly description?: string;
17
+ readonly severity: 'error' | 'warning';
18
+ /** True when a zero-match is a hard failure rather than a loud skip. */
19
+ readonly failOnEmpty: boolean;
20
+ readonly selfTest?: IRuleSelfTest;
21
+ /** The underlying rule, for the plane-specific explainer. */
22
+ readonly raw: IWiringRule | IPolicyRule | IRegistryDeclaration | IRegistrationIdiom | IBaselineRule | IGeneratedArtifactRule;
23
+ }
24
+ /** The config planes this view is built from. */
25
+ export interface IGatePlanes {
26
+ readonly wiringRules?: readonly IWiringRule[];
27
+ readonly policyRules?: readonly IPolicyRule[];
28
+ readonly registries?: readonly IRegistryDeclaration[];
29
+ readonly registrationGraph?: readonly IRegistrationIdiom[];
30
+ readonly baselines?: readonly IBaselineRule[];
31
+ readonly generatedArtifacts?: readonly IGeneratedArtifactRule[];
32
+ }
33
+ /** Flatten every declared rule across every plane into one iterable list. */
34
+ export declare function collectGateRules(planes: IGatePlanes): IGateRuleView[];
35
+ //# sourceMappingURL=gate-rule-view.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gate-rule-view.d.ts","sourceRoot":"","sources":["../../src/gates/gate-rule-view.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,aAAa,EAClB,KAAK,sBAAsB,EAC3B,KAAK,WAAW,EAChB,KAAK,kBAAkB,EACvB,KAAK,oBAAoB,EACzB,KAAK,aAAa,EAClB,KAAK,WAAW,EACjB,MAAM,gBAAgB,CAAC;AAExB,kDAAkD;AAClD,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,UAAU,GAAG,cAAc,GAAG,UAAU,GAAG,WAAW,CAAC;AAErG,+DAA+D;AAC/D,eAAO,MAAM,WAAW,EAAE,SAAS,SAAS,EAO3C,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;IACvC,wEAAwE;IACxE,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B,QAAQ,CAAC,QAAQ,CAAC,EAAE,aAAa,CAAC;IAClC,6DAA6D;IAC7D,QAAQ,CAAC,GAAG,EACR,WAAW,GACX,WAAW,GACX,oBAAoB,GACpB,kBAAkB,GAClB,aAAa,GACb,sBAAsB,CAAC;CAC5B;AAED,iDAAiD;AACjD,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,WAAW,EAAE,CAAC;IAC9C,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,WAAW,EAAE,CAAC;IAC9C,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,oBAAoB,EAAE,CAAC;IACtD,QAAQ,CAAC,iBAAiB,CAAC,EAAE,SAAS,kBAAkB,EAAE,CAAC;IAC3D,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,aAAa,EAAE,CAAC;IAC9C,QAAQ,CAAC,kBAAkB,CAAC,EAAE,SAAS,sBAAsB,EAAE,CAAC;CACjE;AAED,6EAA6E;AAC7E,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,WAAW,GAAG,aAAa,EAAE,CAqErE"}
@@ -0,0 +1,81 @@
1
+ import { failsWhenEmpty, } from '@shrkcrft/core';
2
+ /** Every plane, in the order `shrk gates list` prints them. */
3
+ export const GATE_PLANES = [
4
+ 'wiring',
5
+ 'policy',
6
+ 'registry',
7
+ 'registration',
8
+ 'baseline',
9
+ 'generated',
10
+ ];
11
+ /** Flatten every declared rule across every plane into one iterable list. */
12
+ export function collectGateRules(planes) {
13
+ const out = [];
14
+ for (const r of planes.wiringRules ?? []) {
15
+ out.push({
16
+ id: r.id,
17
+ plane: 'wiring',
18
+ ...(r.description ? { description: r.description } : {}),
19
+ severity: r.severity ?? 'error',
20
+ failOnEmpty: failsWhenEmpty(r),
21
+ ...(r.selfTest ? { selfTest: r.selfTest } : {}),
22
+ raw: r,
23
+ });
24
+ }
25
+ for (const r of planes.policyRules ?? []) {
26
+ out.push({
27
+ id: r.id,
28
+ plane: 'policy',
29
+ ...(r.description ? { description: r.description } : {}),
30
+ severity: r.severity ?? 'error',
31
+ failOnEmpty: failsWhenEmpty(r),
32
+ ...(r.selfTest ? { selfTest: r.selfTest } : {}),
33
+ raw: r,
34
+ });
35
+ }
36
+ for (const r of planes.registries ?? []) {
37
+ out.push({
38
+ id: r.name,
39
+ plane: 'registry',
40
+ ...(r.description ? { description: r.description } : {}),
41
+ // A registry is an inventory, not a gate — it never fails a build on its
42
+ // own, so it carries no severity of its own.
43
+ severity: 'warning',
44
+ failOnEmpty: false,
45
+ raw: r,
46
+ });
47
+ }
48
+ for (const r of planes.registrationGraph ?? []) {
49
+ out.push({
50
+ id: r.name,
51
+ plane: 'registration',
52
+ ...(r.description ? { description: r.description } : {}),
53
+ severity: 'warning',
54
+ failOnEmpty: false,
55
+ raw: r,
56
+ });
57
+ }
58
+ for (const r of planes.baselines ?? []) {
59
+ out.push({
60
+ id: r.id,
61
+ plane: 'baseline',
62
+ ...(r.description ? { description: r.description } : {}),
63
+ severity: r.severity ?? 'error',
64
+ failOnEmpty: failsWhenEmpty(r),
65
+ ...(r.selfTest ? { selfTest: r.selfTest } : {}),
66
+ raw: r,
67
+ });
68
+ }
69
+ for (const r of planes.generatedArtifacts ?? []) {
70
+ out.push({
71
+ id: r.id,
72
+ plane: 'generated',
73
+ ...(r.description ? { description: r.description } : {}),
74
+ severity: r.severity ?? 'error',
75
+ failOnEmpty: failsWhenEmpty(r),
76
+ ...(r.selfTest ? { selfTest: r.selfTest } : {}),
77
+ raw: r,
78
+ });
79
+ }
80
+ return out;
81
+ }
@@ -0,0 +1,53 @@
1
+ import type { IGateRuleView } from './gate-rule-view.js';
2
+ export declare const GATE_COVERAGE_SCHEMA: "sharkcraft.gate-coverage/v1";
3
+ /**
4
+ * Whether a rule is connected to anything at all.
5
+ *
6
+ * `empty` is the finding this whole surface exists for: a stale selector that
7
+ * matches nothing passes every gate forever, so the ONLY way to notice is to
8
+ * report the match count itself and flag zero. `failed-expectation` is the
9
+ * stronger form — the author wrote down what the rule should match, and it
10
+ * doesn't.
11
+ */
12
+ export type GateCoverageStatus = 'ok' | 'empty' | 'error' | 'failed-expectation';
13
+ export interface IGateCoverage {
14
+ readonly id: string;
15
+ readonly plane: IGateRuleView['plane'];
16
+ readonly description?: string;
17
+ readonly status: GateCoverageStatus;
18
+ /** Files the rule's primary selector matched. */
19
+ readonly filesMatched: number;
20
+ /** Ids/units the rule extracted (findings scanned, for the policy plane). */
21
+ readonly unitsMatched: number;
22
+ /** What "units" means for this plane, for honest reporting. */
23
+ readonly unitLabel: string;
24
+ /** A few of the extracted ids, so the author can eyeball correctness. */
25
+ readonly sampleIds: readonly string[];
26
+ /** True when a zero match is a hard failure for this rule. */
27
+ readonly failOnEmpty: boolean;
28
+ readonly error?: string;
29
+ /** Unmet `selfTest` expectations, each a human-readable sentence. */
30
+ readonly expectationFailures: readonly string[];
31
+ }
32
+ export interface IGateCoverageReport {
33
+ readonly schema: typeof GATE_COVERAGE_SCHEMA;
34
+ readonly rules: readonly IGateCoverage[];
35
+ readonly total: number;
36
+ readonly empty: number;
37
+ readonly errored: number;
38
+ readonly expectationFailures: number;
39
+ /**
40
+ * `pass` — every rule matched something and met its expectations.
41
+ * `stale` — at least one rule matched nothing (or broke an expectation).
42
+ */
43
+ readonly verdict: 'pass' | 'stale';
44
+ }
45
+ /**
46
+ * Resolve every declared rule against the live tree and report what it matched.
47
+ *
48
+ * The `command`-compute baseline is the one rule kind that cannot be inspected
49
+ * without side effects; it is reported as un-inspected (never as `empty`), so
50
+ * the report never claims a fact it did not check.
51
+ */
52
+ export declare function buildGateCoverage(cwd: string, rules: readonly IGateRuleView[], excludeDirs?: readonly string[]): IGateCoverageReport;
53
+ //# sourceMappingURL=rule-coverage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule-coverage.d.ts","sourceRoot":"","sources":["../../src/gates/rule-coverage.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD,eAAO,MAAM,oBAAoB,EAAG,6BAAsC,CAAC;AAE3E;;;;;;;;GAQG;AACH,MAAM,MAAM,kBAAkB,GAAG,IAAI,GAAG,OAAO,GAAG,OAAO,GAAG,oBAAoB,CAAC;AAEjF,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;IACvC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,kBAAkB,CAAC;IACpC,iDAAiD;IACjD,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,6EAA6E;IAC7E,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,+DAA+D;IAC/D,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,yEAAyE;IACzE,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,8DAA8D;IAC9D,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,qEAAqE;IACrE,QAAQ,CAAC,mBAAmB,EAAE,SAAS,MAAM,EAAE,CAAC;CACjD;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,MAAM,EAAE,OAAO,oBAAoB,CAAC;IAC7C,QAAQ,CAAC,KAAK,EAAE,SAAS,aAAa,EAAE,CAAC;IACzC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;IACrC;;;OAGG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;CACpC;AAsHD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,SAAS,aAAa,EAAE,EAC/B,WAAW,GAAE,SAAS,MAAM,EAAO,GAClC,mBAAmB,CA4DrB"}
@@ -0,0 +1,165 @@
1
+ import { inspectSource, runPolicyLint, scanGeneratedFiles, wiringSourceSide, } from '@shrkcrft/boundaries';
2
+ export const GATE_COVERAGE_SCHEMA = 'sharkcraft.gate-coverage/v1';
3
+ /** Evaluate the author's declared expectations against what the rule extracted. */
4
+ function checkExpectations(selfTest, ids, unitsMatched) {
5
+ if (!selfTest)
6
+ return [];
7
+ const out = [];
8
+ if (selfTest.expectMatchesAtLeast !== undefined &&
9
+ unitsMatched < selfTest.expectMatchesAtLeast) {
10
+ out.push(`expected at least ${selfTest.expectMatchesAtLeast} match(es), got ${unitsMatched}`);
11
+ }
12
+ const present = new Set(ids);
13
+ for (const id of selfTest.expectIds ?? []) {
14
+ if (!present.has(id))
15
+ out.push(`expected id "${id}" was NOT extracted`);
16
+ }
17
+ for (const id of selfTest.expectNotIds ?? []) {
18
+ if (present.has(id))
19
+ out.push(`id "${id}" was extracted but is listed in expectNotIds`);
20
+ }
21
+ return out;
22
+ }
23
+ function matchWiring(cwd, rule, excludeDirs) {
24
+ const side = wiringSourceSide(rule);
25
+ if (!side)
26
+ return { filesMatched: 0, unitsMatched: 0, unitLabel: 'ids', ids: [], error: 'rule sets no source side' };
27
+ const insp = inspectSource(cwd, side, excludeDirs);
28
+ return {
29
+ filesMatched: insp.filesScanned,
30
+ unitsMatched: insp.ids.length,
31
+ unitLabel: 'ids',
32
+ ids: insp.ids,
33
+ ...(insp.error ? { error: insp.error } : {}),
34
+ };
35
+ }
36
+ function matchPolicy(cwd, rule, excludeDirs) {
37
+ const report = runPolicyLint(cwd, [rule], { excludeDirs });
38
+ const result = report.rules[0];
39
+ return {
40
+ // A policy rule's "files" and "units" differ only for inline templates.
41
+ filesMatched: result?.unitsScanned ?? 0,
42
+ unitsMatched: result?.unitsScanned ?? 0,
43
+ unitLabel: 'content units',
44
+ ids: [],
45
+ ...(result?.error ? { error: result.error } : {}),
46
+ };
47
+ }
48
+ function matchRegistry(cwd, decl, excludeDirs) {
49
+ const insp = inspectSource(cwd, decl.source, excludeDirs);
50
+ return {
51
+ filesMatched: insp.filesScanned,
52
+ unitsMatched: insp.ids.length,
53
+ unitLabel: 'ids',
54
+ ids: insp.ids,
55
+ ...(insp.error ? { error: insp.error } : {}),
56
+ };
57
+ }
58
+ function matchRegistration(cwd, idiom, excludeDirs) {
59
+ const insp = inspectSource(cwd, idiom.declared, excludeDirs);
60
+ return {
61
+ filesMatched: insp.filesScanned,
62
+ unitsMatched: insp.ids.length,
63
+ unitLabel: 'declared tokens',
64
+ ids: insp.ids,
65
+ ...(insp.error ? { error: insp.error } : {}),
66
+ };
67
+ }
68
+ function matchBaseline(cwd, rule, excludeDirs) {
69
+ // Only the EXTRACTOR half can be inspected without spawning. A command
70
+ // compute is reported honestly as un-inspectable rather than guessed at —
71
+ // `shrk baseline explain --id X` runs it on purpose.
72
+ if (rule.compute.kind !== 'extractor' || !rule.compute.source) {
73
+ return {
74
+ filesMatched: 0,
75
+ unitsMatched: 0,
76
+ unitLabel: 'entries (command compute — not inspected)',
77
+ ids: [],
78
+ };
79
+ }
80
+ const insp = inspectSource(cwd, rule.compute.source, excludeDirs);
81
+ return {
82
+ filesMatched: insp.filesScanned,
83
+ unitsMatched: insp.ids.length,
84
+ unitLabel: 'entries',
85
+ ids: insp.ids,
86
+ ...(insp.error ? { error: insp.error } : {}),
87
+ };
88
+ }
89
+ function matchGenerated(cwd, rule, excludeDirs) {
90
+ const scan = scanGeneratedFiles(cwd, rule, excludeDirs);
91
+ const files = [...scan.generated.keys()];
92
+ return {
93
+ filesMatched: files.length,
94
+ unitsMatched: files.length,
95
+ unitLabel: 'generated files',
96
+ ids: files,
97
+ };
98
+ }
99
+ /**
100
+ * Resolve every declared rule against the live tree and report what it matched.
101
+ *
102
+ * The `command`-compute baseline is the one rule kind that cannot be inspected
103
+ * without side effects; it is reported as un-inspected (never as `empty`), so
104
+ * the report never claims a fact it did not check.
105
+ */
106
+ export function buildGateCoverage(cwd, rules, excludeDirs = []) {
107
+ const out = [];
108
+ for (const view of rules) {
109
+ let match;
110
+ switch (view.plane) {
111
+ case 'wiring':
112
+ match = matchWiring(cwd, view.raw, excludeDirs);
113
+ break;
114
+ case 'policy':
115
+ match = matchPolicy(cwd, view.raw, excludeDirs);
116
+ break;
117
+ case 'registry':
118
+ match = matchRegistry(cwd, view.raw, excludeDirs);
119
+ break;
120
+ case 'registration':
121
+ match = matchRegistration(cwd, view.raw, excludeDirs);
122
+ break;
123
+ case 'baseline':
124
+ match = matchBaseline(cwd, view.raw, excludeDirs);
125
+ break;
126
+ default:
127
+ match = matchGenerated(cwd, view.raw, excludeDirs);
128
+ break;
129
+ }
130
+ const expectationFailures = checkExpectations(view.selfTest, match.ids, match.unitsMatched);
131
+ const uninspected = match.unitLabel.includes('not inspected');
132
+ const status = match.error !== undefined
133
+ ? 'error'
134
+ : expectationFailures.length > 0
135
+ ? 'failed-expectation'
136
+ : match.unitsMatched === 0 && !uninspected
137
+ ? 'empty'
138
+ : 'ok';
139
+ out.push({
140
+ id: view.id,
141
+ plane: view.plane,
142
+ ...(view.description ? { description: view.description } : {}),
143
+ status,
144
+ filesMatched: match.filesMatched,
145
+ unitsMatched: match.unitsMatched,
146
+ unitLabel: match.unitLabel,
147
+ sampleIds: match.ids.slice(0, 5),
148
+ failOnEmpty: view.failOnEmpty,
149
+ ...(match.error ? { error: match.error } : {}),
150
+ expectationFailures,
151
+ });
152
+ }
153
+ const empty = out.filter((r) => r.status === 'empty').length;
154
+ const errored = out.filter((r) => r.status === 'error').length;
155
+ const expectationFailures = out.filter((r) => r.status === 'failed-expectation').length;
156
+ return {
157
+ schema: GATE_COVERAGE_SCHEMA,
158
+ rules: out,
159
+ total: out.length,
160
+ empty,
161
+ errored,
162
+ expectationFailures,
163
+ verdict: empty + errored + expectationFailures > 0 ? 'stale' : 'pass',
164
+ };
165
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":";AAEA,OAAO,EACL,eAAe,EAMhB,MAAM,uBAAuB,CAAC;AA8X/B,wBAAgB,aAAa,IAAI,eAAe,CAiY/C;AAED,wBAAsB,MAAM,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CA+CrE;AAwID;;;;;;;;;;;GAWG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAoDxE"}
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":";AAEA,OAAO,EACL,eAAe,EAMhB,MAAM,uBAAuB,CAAC;AA0Z/B,wBAAgB,aAAa,IAAI,eAAe,CAqZ/C;AAED,wBAAsB,MAAM,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAgDrE;AAwID;;;;;;;;;;;GAWG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAoDxE"}
package/dist/main.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { loadDotenv } from "./env/load-dotenv.js";
3
3
  import { CommandRegistry, extractGlobalCompress, extractGlobalCwd, extractGlobalExitTrailer, parseArgs, } from "./command-registry.js";
4
- import { argvHasExitTrailer, argvHasStrict, emitPipeExitSignal, promoteForStrict } from "./exit-codes.js";
4
+ import { argvHasExitTrailer, argvHasNoHints, argvHasStrict, emitPipeExitSignal, promoteForStrict, } from "./exit-codes.js";
5
5
  import { runCommandWithCompression } from "./output/output-compression.js";
6
6
  import { initCommand } from "./commands/init.command.js";
7
7
  import { inspectCommand } from "./commands/inspect.command.js";
@@ -34,7 +34,10 @@ import { archCommand } from "./commands/arch.command.js";
34
34
  import { frameworkCommand } from "./commands/framework.command.js";
35
35
  import { apiDiffCommand } from "./commands/api-diff.command.js";
36
36
  import { gateCommand } from "./commands/gate.command.js";
37
- import { policyLintCommand } from "./commands/policy-lint.command.js";
37
+ import { policyLintCommand, policyLintExplainCommand } from "./commands/policy-lint.command.js";
38
+ import { baselineCheckCommand, baselineCommand, baselineDiffCommand, baselineExplainCommand, baselineListCommand, baselineUpdateCommand, } from "./commands/baseline.command.js";
39
+ import { generatedCheckCommand, generatedExplainCommand, generatedListCommand, generatedUpdateCommand, } from "./commands/generated.command.js";
40
+ import { gatesCommand, gatesCoverageCommand, gatesExplainCommand, gatesListCommand, } from "./commands/gates.command.js";
38
41
  import { wiringCommand } from "./commands/wiring.command.js";
39
42
  import { reuseCommand } from "./commands/reuse.command.js";
40
43
  import { migrateCommand } from "./commands/migrate.command.js";
@@ -44,7 +47,7 @@ import { compressCommand, expandCommand } from "./commands/compress.command.js";
44
47
  import { alignCommand, unalignCommand } from "./commands/cache-align.command.js";
45
48
  import { reviewCommand } from "./commands/review.command.js";
46
49
  import { onboardCommand } from "./commands/onboard.command.js";
47
- import { contradictionsCommand, generatedCommand, ingestCommand, } from "./commands/ingest.command.js";
50
+ import { contradictionsCommand, generatedCommand, generatedProtectCommand, generatedReportCommand, ingestCommand, } from "./commands/ingest.command.js";
48
51
  import { contextBuildCommand, contextRefreshCommand, contextStatusCommand, understandTaskCommand, validateChangeCommand, } from "./commands/task-context.command.js";
49
52
  import { testCommand } from "./commands/test.command.js";
50
53
  import { planParentCommand, planReviewCommand } from "./commands/plan.command.js";
@@ -206,6 +209,26 @@ export function buildRegistry() {
206
209
  registry.register(apiDiffCommand);
207
210
  registry.register(gateCommand);
208
211
  registry.register(policyLintCommand);
212
+ registry.registerSubcommand('policy-lint', policyLintExplainCommand);
213
+ // The two shell-executing planes (baseline/generated) + the trust layer.
214
+ registry.register(baselineCommand);
215
+ registry.registerSubcommand('baseline', baselineListCommand);
216
+ registry.registerSubcommand('baseline', baselineCheckCommand);
217
+ registry.registerSubcommand('baseline', baselineDiffCommand);
218
+ registry.registerSubcommand('baseline', baselineUpdateCommand);
219
+ registry.registerSubcommand('baseline', baselineExplainCommand);
220
+ // `generated` already exists as the generated-code CLASSIFIER (report /
221
+ // protect). These add the drift GATE under the same noun.
222
+ registry.registerSubcommand('generated', generatedReportCommand);
223
+ registry.registerSubcommand('generated', generatedProtectCommand);
224
+ registry.registerSubcommand('generated', generatedListCommand);
225
+ registry.registerSubcommand('generated', generatedCheckCommand);
226
+ registry.registerSubcommand('generated', generatedUpdateCommand);
227
+ registry.registerSubcommand('generated', generatedExplainCommand);
228
+ registry.register(gatesCommand);
229
+ registry.registerSubcommand('gates', gatesListCommand);
230
+ registry.registerSubcommand('gates', gatesCoverageCommand);
231
+ registry.registerSubcommand('gates', gatesExplainCommand);
209
232
  registry.register(wiringCommand);
210
233
  registry.register(reuseCommand);
211
234
  registry.register(migrateCommand);
@@ -532,6 +555,7 @@ export async function runCli(argv) {
532
555
  emitPipeExitSignal(command, exitCode, {
533
556
  piped: !process.stdout.isTTY,
534
557
  trailer: argvHasExitTrailer(argv),
558
+ noHints: argvHasNoHints(argv),
535
559
  });
536
560
  }
537
561
  return exitCode;