@blamejs/exceptd-skills 0.10.2 → 0.11.0

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/CHANGELOG.md CHANGED
@@ -1,5 +1,119 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.11.0 — 2026-05-12
4
+
5
+ **Minor: architectural CLI redesign — 21 verbs collapsed to 11. Plus operator-reported items 31-46.**
6
+
7
+ ### New canonical surface
8
+
9
+ | New verb | Replaces |
10
+ |---|---|
11
+ | `brief [playbook]` | plan + govern + direct + look |
12
+ | `run [playbook]` | run + ingest (unchanged but with flat submission shape) |
13
+ | `ai-run <playbook>` | new — JSONL streaming variant for AI conversational flow |
14
+ | `attest <subverb> <sid>` | reattest + list-attestations (now `attest diff` + `attest list`) |
15
+ | `discover` | scan + dispatch (recommends playbooks based on cwd) |
16
+ | `doctor` | currency + verify + validate-cves + validate-rfcs + signing-status |
17
+ | `ci` | new — one-shot CI gate |
18
+ | `ask "<question>"` | new — plain-English routing to playbook(s) |
19
+ | `lint <playbook> <evidence>` | new — pre-flight submission shape check |
20
+ | `verify-attestation <sid>` | alias for `attest verify` |
21
+ | `run-all` | alias for `run --all` |
22
+
23
+ `exceptd` with no args now prints a welcome with two ways to start (`discover` / `ask`) plus common starting playbooks for code / Linux / AI service contexts.
24
+
25
+ ### Default output flip
26
+
27
+ Old default was JSON one-line; `--pretty` for humans. Reads weird for the operator audience. v0.11.0 flips:
28
+
29
+ - **Default: human-readable** (5-10 line summary per phase) for `discover` / `doctor` / `ci` / others.
30
+ - `--json` for machine consumption.
31
+ - `--json --pretty` for indented JSON.
32
+
33
+ Seven-phase verbs (`brief` / `run`) still emit JSON by default since their consumers are predominantly AI assistants and CI pipelines — switching them would break every existing script.
34
+
35
+ ### Flat submission shape
36
+
37
+ The runner now accepts a flatter submission shape — one row per observation, indicator inline:
38
+
39
+ ```json
40
+ {
41
+ "observations": {
42
+ "env-files": { "captured": true, "value": "none tracked", "indicator": "env-file-leak", "result": "no_hit" },
43
+ "repo-context": "ok"
44
+ },
45
+ "verdict": { "theater": "actual_security", "classification": "clean", "blast_radius": 0 }
46
+ }
47
+ ```
48
+
49
+ Nested v0.10.x shape (`artifacts` / `signal_overrides` / `signals` / `precondition_checks`) still works — the runner normalizes either shape internally.
50
+
51
+ ### Smart precondition auto-detect
52
+
53
+ Mechanically-answerable preconditions (`host.platform == 'linux'`, `cwd_readable`, `agent_has_command('uname')`) are now resolved by the runner itself. The AI only declares preconditions that require intent ("operator authorized this scan"). Reduces evidence-JSON friction by ~80% for typical runs.
54
+
55
+ ### Attestation root relocated
56
+
57
+ Default attestation root moved from cwd-relative `.exceptd/attestations/` to `~/.exceptd/attestations/<repo-or-host-tag>/`. Repo tag is derived from `git config --get remote.origin.url` + branch when in a git repo, else `host:<hostname>`. Means `attest list` works regardless of which directory you happened to run from.
58
+
59
+ Override via:
60
+ - `--attestation-root <path>` flag
61
+ - `EXCEPTD_HOME` env var (uses `$EXCEPTD_HOME/attestations/`)
62
+ - Legacy cwd-relative `.exceptd/` still scanned by `attest list` / `findSessionDir` so prior data isn't orphaned.
63
+
64
+ ### Bug fixes (operator-reported items 31-46)
65
+
66
+ - **#31 / #41 session-id collision** — Pre-0.11.0 a `--session-id` collision silently overwrote the prior attestation (data loss + tamper-evidence violation). Now refuses with exit 3 by default; `--force-overwrite` allows replacement and persists `prior_evidence_hash` + `prior_captured_at` so the audit chain survives.
67
+ - **#32 `--mode` validation** — was silently accepting any string. Now validates against `[self_service, authorized_pentest, ir_response, ctf, research, compliance_audit]`.
68
+ - **#33 `--session-key` hex validation** — was silently accepting any string. Now requires hex (0-9, a-f) and a minimum length of 16.
69
+ - **#34 reattest no artifact diff** — `attest diff <sid> --against <other-sid>` (or `reattest` default replay) now emits per-artifact diff: `{added, removed, changed, unchanged_count}` with value previews. Per-signal-override diff also included.
70
+ - **#35 validate-cves crash** — `sources/validators/` was missing from package.json `files` allowlist. Fixed in v0.10.3; still re-tested in v0.11.0.
71
+ - **#36 unsigned attestation warning** — Runs without `.keys/private.pem` now emit one stderr warning per process: "attestation will be written UNSIGNED — enable Ed25519 signing: node lib/sign.js generate-keypair". Suppress with `EXCEPTD_UNSIGNED_WARNED=1`.
72
+
73
+ ### Feature additions (operator items)
74
+
75
+ - **#38 `lint <playbook> <evidence>`** — Pre-flight check: detects missing required artifacts, unknown signal keys, unsupplied preconditions. Operators iterate on submission JSON before paying the phase-4-7 cost.
76
+ - **#39 `run --format summary`** — 5-line digest emit format for CI workflows (verdict + RWEP + blast + remediation).
77
+ - **#43 reattest cross-session compare** — `attest diff <a-sid> --against <b-sid>` now compares two sessions side-by-side instead of always replaying the same submission.
78
+ - **#46 plan / brief description always present** — Directive entries in plan output now always include a `description` field (falls back through `directive.description` → playbook `direct.threat_context` first sentence → `domain.name`).
79
+
80
+ ### Deprecation
81
+
82
+ v0.10.x verbs (`plan` / `govern` / `direct` / `look` / `ingest` / `reattest` / `list-attestations` / `scan` / `dispatch` / `currency` / `verify` / `validate-cves` / `validate-rfcs` / `watchlist` / `prefetch` / `build-indexes`) still work but emit a one-time deprecation banner per process pointing at the v0.11.0 replacement. Removed in v0.12.
83
+
84
+ Suppress the deprecation banner: `EXCEPTD_DEPRECATION_SHOWN=1`.
85
+
86
+ ## 0.10.3 — 2026-05-12
87
+
88
+ **Patch: 14 operator-reported items — 5 bugs + 9 features.**
89
+
90
+ ### Bugs
91
+
92
+ 1. **`exceptd validate-cves` crashed with `MODULE_NOT_FOUND`** in the installed npm package because `sources/` wasn't in the `files` allowlist. Two-part fix: (a) `sources/validators/` added to `package.json` `files`; (b) `runValidateCves` now wraps the require in the same try/catch graceful-fallback pattern `runValidateRfcs` was already using, so the command degrades to offline mode instead of crashing.
93
+ 2. **Inconsistent error shapes across verbs.** `exceptd <unknown>` and `exceptd skill <missing>` emitted plain stderr text while seven-phase verbs emitted structured JSON. Unified: every CLI verb now emits `{ok:false,error,hint,verb}` JSON on error so operators piping through `jq` get one shape.
94
+ 3. **`prefetch --no-network --quiet` was completely silent on success.** Now emits a one-line `prefetch summary: …` unconditionally; `--quiet` suppresses only the per-entry chatter.
95
+ 4. **`plan --directives` exposed `id + title + applies_to` only — no `description`.** Now also surfaces a `description` field (falls back through explicit `directive.description` → `phase_overrides.direct.threat_context` → playbook-level `direct.threat_context` first sentence → `domain.name`) plus a `threat_context_preview`. Operators / AIs get operator-facing prose, not just an ID + enum.
96
+ 5. **Analyst verbs (`scan`/`dispatch`/`currency`/`watchlist`/`report`) defaulted to human-readable text** while every seven-phase verb defaulted to JSON. Added `--json` flag passthrough across all analyst verbs. Operators scripting around both surfaces now have a consistent switch.
97
+
98
+ ### Features
99
+
100
+ 6. **`run --explain` dry-run** — emits preconditions, required + optional artifacts (with fallback notes), recognized signal keys with types + deterministic flags, and a `submission_skeleton` JSON the operator can fill in. No detect/analyze/validate/close happens. Lets operators preview before assembling evidence.
101
+ 7. **`attest <subverb> <session-id>`** — `attest export` emits redacted JSON for audit submission (strips raw artifact values, preserves evidence_hash + signature + classification + RWEP + remediation choice + residual risk acceptance). `--format csaf` wraps the export in a CSAF envelope. `attest verify` checks the `.sig` sidecar against `keys/public.pem` and reports tamper status. `attest show` emits the full unredacted attestation.
102
+ 8. **`run --signal-list`** — lighter than `--explain`; enumerates only the signal_overrides keys the detect phase recognizes plus the four valid `detection_classification` values. Closes the "agent submits a key and runner silently ignores it" gap (v0.10.1 bug #5).
103
+ 9. **Continuous-compliance: `run --evidence-dir <dir>`** — each `<playbook-id>.json` under the directory becomes that playbook's submission in a multi-playbook run. One cron job → full posture in one CSAF bundle. Pairs with `run --all`.
104
+ 10. **`validate-cves` + `validate-rfcs` gained `--since <ISO|YYYY-MM-DD>`** — scope-limit validation to entries whose `last_updated` / `cisa_kev_date` / `last_verified` / `published` is on or after the date. Cuts upstream calls for fleet operators running cron.
105
+ 11. **Ed25519-signed attestations** — every `attestation.json` now gets a `<file>.sig` sidecar. With `.keys/private.pem` present, the runner signs (matches the existing skill-signing convention). Without a private key, writes an `unsigned` marker file so downstream tooling can distinguish "operator declined signing" from "the .sig file was deleted by an attacker." `attest verify` cross-checks the signature against `keys/public.pem`.
106
+ 12. **`run --operator <name>`** — binds the attestation to a specific human or service identity. Persisted under `attestation.operator` for multi-operator audit-trail accountability.
107
+ 13. **`run --ack`** — explicit operator consent to the jurisdiction obligations surfaced by `govern`. Persisted under `attestation.operator_consent = { acked_at, explicit: true }`. Without `--ack`, the field is null (consent implicit / unverified).
108
+ 14. **`run --format <fmt>` repeatable** — emit the close.evidence_package in additional formats alongside the playbook-declared primary. Supported: `csaf-2.0` (primary), `sarif` (2.1.0 — GitHub Code Scanning / VS Code SARIF Viewer / Azure DevOps), `openvex` (0.2.0 — sigstore / in-toto / GUAC consumers), `markdown` (human review). Extras populate `close.evidence_package.bundles_by_format`.
109
+
110
+ ### Internal
111
+
112
+ - `lib/playbook-runner.js` `buildEvidenceBundle` now handles `csaf-2.0`, `sarif` (with per-CVE rules + properties), `openvex` (with status derived from active_exploitation + live_patch_available), and `markdown`.
113
+ - `bin/exceptd.js` `maybeSignAttestation` helper uses the same Ed25519 primitive as `lib/sign.js` against `.keys/private.pem`.
114
+ - CSAF envelope cvss_v3.base_score now reflects the catalog's real cvss_score (previously hardcoded 0).
115
+ - `submission.signals._bundle_formats` is the agent-side hook for requesting extra formats.
116
+
3
117
  ## 0.10.2 — 2026-05-12
4
118
 
5
119
  **Patch: v0.10.1 deferred set — framework-gap filter fix, VEX consumption, CI gating, drift mode, 2 new playbooks (13 total), feeds_into matrix.**