@blamejs/exceptd-skills 0.15.43 → 0.15.45

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/bin/exceptd.js CHANGED
@@ -564,6 +564,31 @@ function main() {
564
564
  };
565
565
  }
566
566
 
567
+ // --quiet: suppress advisory stderr chatter — the "[exceptd] note:" and
568
+ // "[exceptd] tip:" lines, the deprecation banner, and the unsigned-
569
+ // attestation warning — while keeping the actual result on stdout and all
570
+ // errors on stderr. Narrower than --json-stdout-only, which silences ALL
571
+ // stderr and forces JSON output; --quiet preserves human-readable output and
572
+ // exit codes and only drops the non-essential advisories. Skipped when
573
+ // --json-stdout-only is also present (that flag already silenced everything
574
+ // and patched stderr first; double-wrapping would be redundant).
575
+ if (argv.includes("--quiet") && !argv.includes("--json-stdout-only")) {
576
+ global.__exceptdQuiet = true;
577
+ process.env.EXCEPTD_DEPRECATION_SHOWN = "1";
578
+ process.env.EXCEPTD_UNSIGNED_WARNED = "1";
579
+ const origStderrWrite = process.stderr.write.bind(process.stderr);
580
+ process.stderr.write = (chunk, encoding, cb) => {
581
+ // Drop only the advisory-prefixed lines. Contract-violation notes
582
+ // ("[exceptd run] ..."), error frames, and uncaught exceptions still
583
+ // surface so --quiet never hides why a run failed or exited non-zero.
584
+ if (typeof chunk === "string" && /^\[exceptd\] (note|tip):/.test(chunk)) {
585
+ if (typeof cb === "function") cb();
586
+ return true;
587
+ }
588
+ return origStderrWrite(chunk, encoding, cb);
589
+ };
590
+ }
591
+
567
592
  if (argv.length === 0) {
568
593
  printWelcome();
569
594
  process.exit(0);
@@ -752,7 +777,7 @@ function main() {
752
777
  // verbs that lack their own help handler, so spawns that do (refresh,
753
778
  // prefetch) keep their detailed usage.
754
779
  const SPAWN_HELP_USAGE = {
755
- skill: "exceptd skill <name> Show the full context document for one skill.",
780
+ skill: "exceptd skill <name> Show the full context document for one skill. Run `exceptd skill` with no arguments to list all skill IDs.",
756
781
  "framework-gap": "exceptd framework-gap <framework> <cve-or-scenario> One-framework gap analysis.",
757
782
  "framework-gap-analysis": "exceptd framework-gap <framework> <cve-or-scenario> One-framework gap analysis.",
758
783
  cve: "exceptd cve <CVE-ID> [--json] [--air-gap|--no-network] Resolve a CVE: published/rejected/disputed/fabricated/nonexistent (catalog -> cache -> NVD). Exit 2 when the citation won't stand up (rejected/fabricated/nonexistent/withdrawn).",
@@ -761,7 +786,7 @@ function main() {
761
786
  // to spawning the blocking daemon, hanging the operator's terminal.
762
787
  watch: "exceptd watch Long-running forward-watch daemon (blocks; Ctrl-C to stop). For a one-shot aggregator use `exceptd watchlist`.",
763
788
  watchlist: "exceptd watchlist [--alerts] [--org-scan --org <login>] [--by-skill] [--json] One-shot forward-watch aggregator across skills.",
764
- report: "exceptd report [executive] [--json] Structured posture report.",
789
+ report: "exceptd report [executive] [--json] Structured posture report. Markdown by default; pass --json for machine-readable output.",
765
790
  scan: "exceptd scan [--json] [legacy] Working-directory CVE/KEV scan (orchestrator). See `exceptd discover`.",
766
791
  dispatch: "exceptd dispatch [--json] [legacy] Scan + route findings to skills (orchestrator). See `exceptd discover`.",
767
792
  currency: "exceptd currency [--json] [legacy] Skill threat-currency report. See `exceptd doctor --currency`.",
@@ -981,7 +1006,7 @@ function asEvidenceObject(parsed) {
981
1006
  return parsed;
982
1007
  }
983
1008
 
984
- function readEvidence(evidenceFlag) {
1009
+ function readEvidence(evidenceFlag, opts = {}) {
985
1010
  if (!evidenceFlag) return {};
986
1011
  // v0.12.12: file-path branch enforces a max size to defend against an
987
1012
  // operator accidentally passing a multi-gigabyte file (binary, log, or
@@ -1017,11 +1042,20 @@ function readEvidence(evidenceFlag) {
1017
1042
  // certainly meant to pipe something. Don't change exit semantics;
1018
1043
  // the empty-payload path is still legitimately useful for posture-
1019
1044
  // only playbooks (govern + direct + look-only walks).
1020
- process.stderr.write(
1021
- `[exceptd] note: --evidence - read 0 bytes from stdin. Treating as empty evidence {}. ` +
1022
- `If you meant to pipe a submission, run \`exceptd brief <playbook>\` to see the expected shape; ` +
1023
- `if you wanted a posture-only walk, this message is informational and the run will proceed.\n`,
1024
- );
1045
+ //
1046
+ // Only nudge when `--evidence -` was EXPLICITLY requested. On the stdin
1047
+ // auto-promotion path (no --evidence flag, just a non-TTY handle such as
1048
+ // `run kernel </dev/null` or a CI runner) the operator never asked to
1049
+ // read stdin, so an empty read is not a mistake to flag — and emitting to
1050
+ // stderr there corrupted `run ... 2>&1 | jq` pipelines that worked at a
1051
+ // TTY but broke in CI.
1052
+ if (opts.explicit !== false) {
1053
+ process.stderr.write(
1054
+ `[exceptd] note: --evidence - read 0 bytes from stdin. Treating as empty evidence {}. ` +
1055
+ `If you meant to pipe a submission, run \`exceptd brief <playbook>\` to see the expected shape; ` +
1056
+ `if you wanted a posture-only walk, this message is informational and the run will proceed.\n`,
1057
+ );
1058
+ }
1025
1059
  return {};
1026
1060
  }
1027
1061
  return asEvidenceObject(JSON.parse(text));
@@ -1853,6 +1887,13 @@ function editDistance(a, b) {
1853
1887
 
1854
1888
  function printPlaybookVerbHelp(verb) {
1855
1889
  const cmds = {
1890
+ recipes: `recipes [<id>] — curated multi-skill workflows (use-case → ordered skill chain).
1891
+
1892
+ With no id: lists every recipe with its "when to use" guidance.
1893
+ With <id>: expands that recipe's ordered skill_chain and notes.
1894
+
1895
+ Flags:
1896
+ --json Machine-readable output.`,
1856
1897
  plan: `plan — list playbooks + directives, grouped by scope.
1857
1898
 
1858
1899
  Flags:
@@ -2884,7 +2925,8 @@ function cmdBrief(runner, args, runOpts, pretty) {
2884
2925
  lines.push(` ${p.id} (${p.on_fail}): ${pdesc.length > 80 ? pdesc.slice(0, 80) + "…" : pdesc}`);
2885
2926
  }
2886
2927
  }
2887
- lines.push(`\nRun: exceptd run ${obj.playbook_id} --evidence <file|-> --json`);
2928
+ lines.push(`\nCollect evidence: exceptd collect ${obj.playbook_id} | exceptd run ${obj.playbook_id} --evidence -`);
2929
+ lines.push(`Run with your own evidence: exceptd run ${obj.playbook_id} --evidence <file|-> --json`);
2888
2930
  lines.push(`Full structured doc: --json or --pretty`);
2889
2931
  return lines.join("\n");
2890
2932
  });
@@ -3223,6 +3265,19 @@ function cmdRun(runner, args, runOpts, pretty) {
3223
3265
  // Single-playbook path (existing behavior).
3224
3266
  const playbookId = positional;
3225
3267
  if (refuseInvalidPlaybookId("run", playbookId, pretty)) return;
3268
+ // --evidence-dir is a contract input: cmdRunMulti reads one
3269
+ // <playbook-id>.json per playbook in an --all / --scope run. With a single
3270
+ // named playbook it was silently ignored, so `run secrets --evidence-dir ./ev`
3271
+ // ran against EMPTY evidence and reported a clean "not_detected" verdict — a
3272
+ // falsely-reassuring result from a security tool. Refuse loudly and point the
3273
+ // operator at the flag that actually loads evidence for one playbook.
3274
+ if (args["evidence-dir"]) {
3275
+ return emitError(
3276
+ `run ${playbookId}: --evidence-dir applies to contract runs (exceptd run --all / --scope <type>), where it reads one <playbook-id>.json per playbook. For a single playbook, pass its evidence directly: exceptd collect ${playbookId} | exceptd run ${playbookId} --evidence - (or --evidence ${playbookId}.json).`,
3277
+ { playbook: playbookId, provided: "--evidence-dir", use_instead: "--evidence <file|->" },
3278
+ pretty
3279
+ );
3280
+ }
3226
3281
  const pb = runner.loadPlaybook(playbookId);
3227
3282
  const directiveId = args.directive || (pb.directives[0] && pb.directives[0].id);
3228
3283
  if (!directiveId) return refuseNoDirectives("run", playbookId, pretty);
@@ -3286,12 +3341,16 @@ function cmdRun(runner, args, runOpts, pretty) {
3286
3341
  // first, then falls back to a strict isTTY===false check only on Windows
3287
3342
  // (where fstat on a pipe is unreliable). MSYS-bash on win32 reports
3288
3343
  // isTTY === false for genuine piped input, so that path still works.
3289
- if (!args.evidence && hasReadableStdin()) {
3344
+ const autoStdin = !args.evidence && hasReadableStdin();
3345
+ if (autoStdin) {
3290
3346
  args.evidence = "-";
3291
3347
  }
3292
3348
  if (args.evidence) {
3293
3349
  try {
3294
- submission = readEvidence(args.evidence);
3350
+ // explicit:false on the auto-promotion path suppresses the empty-stdin
3351
+ // nudge (which otherwise writes to stderr and breaks `run ... 2>&1 | jq`
3352
+ // on every no-evidence CI run); an explicit `--evidence -` still nudges.
3353
+ submission = readEvidence(args.evidence, { explicit: !autoStdin });
3295
3354
  } catch (e) {
3296
3355
  return emitError(`run: failed to read evidence: ${e.message}`, { evidence: args.evidence }, pretty);
3297
3356
  }
@@ -3531,7 +3590,40 @@ function cmdRun(runner, args, runOpts, pretty) {
3531
3590
  // Set exitCode BEFORE emit(): emit's ok:false fallback only fires when
3532
3591
  // exitCode is not already set, so the BLOCKED override survives.
3533
3592
  process.exitCode = args.ci ? EXIT_CODES.BLOCKED : EXIT_CODES.GENERIC_FAILURE;
3534
- emit(result, pretty);
3593
+ emit(result, pretty, (obj) => {
3594
+ // Human renderer for a halted run. Without this, a blocked verdict
3595
+ // (preflight precondition unmet, mutex conflict, stale currency,
3596
+ // corrupt catalog) dumped the raw ok:false JSON envelope even in human
3597
+ // mode — so a non-Linux operator's first `run` against any Linux-gated
3598
+ // playbook was a wall of JSON instead of one line saying why it stopped
3599
+ // and what to do. --json / --pretty still return the full envelope.
3600
+ const v = obj.verdict || "error";
3601
+ const tag = v === "blocked" ? "[blocked]" : "[error]";
3602
+ const lines = [`${tag} ${obj.playbook_id || "run"}${obj.directive_id ? ` (${obj.directive_id})` : ""}`];
3603
+ // summary_line is already a complete sentence ("<pb>: blocked at
3604
+ // preflight (<cause>) — <reason>"); prefer it, else fall back to reason.
3605
+ const detail = obj.summary_line || obj.reason;
3606
+ if (detail) lines.push(` ${detail}`);
3607
+ // remediation is the engine's own actionable next step when it has one;
3608
+ // otherwise synthesize a hint from blocked_by so the operator never hits
3609
+ // a dead end. Hints reference only current verbs (plan/direct were
3610
+ // removed in v0.13.0; brief --all is the replacement listing verb).
3611
+ if (obj.remediation) {
3612
+ lines.push(` → ${obj.remediation}`);
3613
+ } else {
3614
+ const hints = {
3615
+ precondition: "→ Preconditions are not met on this host (often a platform gate, e.g. a Linux-only playbook). List playbooks that fit your platform: exceptd brief --all",
3616
+ mutex: "→ Another run holds this playbook's mutex. Wait for it to finish, then retry.",
3617
+ currency: "→ Threat intel is stale. Refresh sources (exceptd refresh) or re-run with --force-stale to override.",
3618
+ catalog_corrupt: "→ The CVE catalog failed to load. Reinstall the package or run: exceptd doctor",
3619
+ playbook_not_found: "→ Unknown playbook. List available playbooks: exceptd brief --all",
3620
+ directive_not_found: `→ Unknown directive for this playbook. See its directives: exceptd brief ${obj.playbook_id || "<playbook>"}`,
3621
+ };
3622
+ if (obj.blocked_by && hints[obj.blocked_by]) lines.push(` ${hints[obj.blocked_by]}`);
3623
+ }
3624
+ lines.push(" Full envelope: re-run with --json");
3625
+ return lines.join("\n");
3626
+ });
3535
3627
  return;
3536
3628
  }
3537
3629
 
@@ -6386,8 +6478,10 @@ function cmdDoctor(runner, args, runOpts, pretty) {
6386
6478
  "json", "pretty", "fix", "air-gap",
6387
6479
  "signatures", "currency", "cves", "rfcs", "registry-check",
6388
6480
  "ai-config", "collectors", "exit-codes", "shipped-tarball",
6389
- // Global flags the parser may inject regardless of verb.
6390
- "_", "json-stdout-only", "_jsonMode",
6481
+ // Global flags the parser may inject regardless of verb. Keep in sync
6482
+ // with VERB_FLAG_ALLOWLIST._global in lib/flag-suggest.js — quiet/verbose
6483
+ // are accepted on every verb, so doctor must not refuse them as typos.
6484
+ "_", "json-stdout-only", "_jsonMode", "quiet", "verbose",
6391
6485
  ]);
6392
6486
  const unknownFlags = Object.keys(args).filter(k => !KNOWN_DOCTOR_FLAGS.has(k));
6393
6487
  if (unknownFlags.length > 0) {
@@ -7285,7 +7379,7 @@ function cmdDoctor(runner, args, runOpts, pretty) {
7285
7379
  if (c.ahead) {
7286
7380
  return `npm registry: local v${c.local_version ?? "?"} AHEAD of published v${c.published_version ?? "?"} (unreleased / dev install)`;
7287
7381
  }
7288
- return `npm registry: check returned no comparison (raw exit=${c.exit_code ?? "?"})`;
7382
+ return "npm registry: could not compare versions (registry unreachable, offline, or no published version yet). Run `npm view @blamejs/exceptd-skills version` to see the latest, then `npm install -g @blamejs/exceptd-skills@latest` if you are behind.";
7289
7383
  });
7290
7384
  // v0.12.9 (P3 #10): surface shipped_tarball sub-check when --shipped-tarball was used.
7291
7385
  if (checks.signatures?.shipped_tarball) {
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "schema_version": "1.1.0",
3
- "generated_at": "2026-05-30T07:08:37.048Z",
3
+ "generated_at": "2026-05-30T16:43:35.543Z",
4
4
  "generator": "scripts/build-indexes.js",
5
5
  "source_count": 54,
6
6
  "source_hashes": {
7
- "manifest.json": "970c197defcefa117bffcd713b167e14c90f36506e496794485d7bcb2e1789b0",
7
+ "manifest.json": "0b52ef7f74953dd925a1a5e718c30e8d4c9b4bb0d43da3109e0e0276837cca68",
8
8
  "data/atlas-ttps.json": "878b4a08bb73c8d20396d85cf433a88f2bc5e7a8cbf7f6ab773ce7ede0a11251",
9
- "data/attack-techniques.json": "6255e929454291c9f2ab48b600bbedf68a1678c5eb04504e5323a2d6ff5f3e36",
10
- "data/cve-catalog.json": "6a081bf58b2aafc37b7c297b63edb8bca7db6ee93ec69014d34ab9fc764cbb98",
9
+ "data/attack-techniques.json": "84fad74c8497cab922ed64b814752f54aa4620c2a938cb06642ff1510e1c5cb3",
10
+ "data/cve-catalog.json": "7a5f4e31401505e53330cdc4b54b39f8a8b04459d6b9411676d291c583ae535f",
11
11
  "data/cwe-catalog.json": "0fd275c2a61754958d68cea03a92794a67cf1c1d4d609f81a5728334df013ee3",
12
12
  "data/d3fend-catalog.json": "9a54bccb9f24f84b32024216cc3f53819a053721ac8ab43c326859e68fc0ffaf",
13
13
  "data/dlp-controls.json": "d2406c482dddd30e49203879999dc4b3a7fd4d0494d6a61d86b91ee76415df19",
@@ -15,7 +15,7 @@
15
15
  "data/framework-control-gaps.json": "29e7b6aa841ddf2530ca5971bdb60d7a715684b2f6264141ad49f0de9a039d78",
16
16
  "data/global-frameworks.json": "9ba563a85f7f8d6c3c957de64945e20925a89d0ed6ea6fc561cf093811acf558",
17
17
  "data/rfc-references.json": "b21d03b948c41bc8a854e2f057948ecf844bd8c105848aeb141d1eadf8192c31",
18
- "data/zeroday-lessons.json": "5337ae234da930e89a31d185d739f081cd95086223006ae7b5121f1ab7674791",
18
+ "data/zeroday-lessons.json": "acf9b2b001844dd2cacf1d29c7175d60db49b103847c9fddd242d2a98087541d",
19
19
  "skills/kernel-lpe-triage/skill.md": "0f79c641cef6e5f4a942eb94f43c460562bf83dfb67ae112d146c39c6b320fb0",
20
20
  "skills/ai-attack-surface/skill.md": "2880499993e0e69e3897a9d02b5e83aa0462c86a4dd2c1988b9968e375704a1f",
21
21
  "skills/mcp-agent-trust/skill.md": "0752834acde0303d6d1e36be4b320eac3d34fde715bb8d71f3ad9e801d701482",
@@ -32,7 +32,7 @@
32
32
  "skills/skill-update-loop/skill.md": "16cd5a61ccd87c61901e9b209fff0e26ca6540c0cfcb8e231ac17917c50d56bb",
33
33
  "skills/security-maturity-tiers/skill.md": "de7a67b1f6ae79be490656939ac59b5772aa648dae4759733d80d6bf4595c278",
34
34
  "skills/researcher/skill.md": "9f1211d177c64e4c465407a45ad9e2901c5c6c0af410a0d0a51cc8fb780420d4",
35
- "skills/attack-surface-pentest/skill.md": "6174a20b777a82c83941ef64d27e8c7e4091649358930ac1ba564a0ad4d9399f",
35
+ "skills/attack-surface-pentest/skill.md": "8d1137c3270763f1c90a3fa8c1c19ab5dc769623c1a35d6a71859bdb8cca2a3e",
36
36
  "skills/fuzz-testing-strategy/skill.md": "07e2ee5f773a3f0e82bd21b8a7e8cf6d5b1a8bf3ac6f71602f16550561ade553",
37
37
  "skills/dlp-gap-analysis/skill.md": "89dedc6c062fa2afd2284e608f4a51effda819e9288fbf38ab16a7891ccd8a10",
38
38
  "skills/supply-chain-integrity/skill.md": "7c568ee9805f4c822c16c266348e35fa6f2d7a3c76135fa34b0cfa77f003a878",
@@ -44,7 +44,7 @@
44
44
  "skills/webapp-security/skill.md": "9dc8c0e51c78ad93ef9de91dd9054370dfebeea2161a87f909202ecacfad1504",
45
45
  "skills/ai-risk-management/skill.md": "3e116dc6f03f31e32f1ee885516d72d9c11d3ff67d2184108b13dcbdf5f417bf",
46
46
  "skills/sector-healthcare/skill.md": "148520af64959a60018a24f4368670925980db3e73aa09af73194f8ea61f1fcc",
47
- "skills/sector-financial/skill.md": "eb526fdd9fff84943fff951ca7762de4304adbf3212eb26c73521a8979bb776d",
47
+ "skills/sector-financial/skill.md": "ad33faa8dddbeb23fed88f464205c630e3fa50c669d3e1ba7ed54f23719efd55",
48
48
  "skills/sector-federal-government/skill.md": "870dead2eae1b2664b1e151dd73d8fa240a62a297bdbcddee37bd1cb60e5e5f4",
49
49
  "skills/sector-energy/skill.md": "432213dfc9ee271631ce3171daf62a103a010b27a51911dd1112bd5d8bc6c152",
50
50
  "skills/sector-telecom/skill.md": "4b80771e78a474e3f43227ecc730ddda1684bff98d7e6e53f5ec373e1e886f34",
@@ -56,7 +56,7 @@
56
56
  "skills/ransomware-response/skill.md": "d0f456f1c31ec2968bb4c2cea67eb628d5baf857f17650ab204cf7931b3317ef",
57
57
  "skills/email-security-anti-phishing/skill.md": "0965eca982e8fc633b85e70c0ba6becb8c0f5ee7bdd0be96ad73a9a222bb8816",
58
58
  "skills/age-gates-child-safety/skill.md": "6d4d29e54a115314c3c0ea9f5df47bdc2828f3b226fff4b5974d898b56c0cd73",
59
- "skills/cloud-iam-incident/skill.md": "5ec3800a0049b2123aff67bfab4ff28491a86d2daeb712283e5e88b10c3d5d7b",
59
+ "skills/cloud-iam-incident/skill.md": "6aab2e400d1e87df7ac2b6f0a17dac6aa99723b217258c4a7b446703d1521775",
60
60
  "skills/idp-incident-response/skill.md": "cb2f2c5b90de4592bfd66dcd55f9bf2004f370746d519cad577fcbaf36125878"
61
61
  },
62
62
  "skill_count": 42,
@@ -78,7 +78,7 @@
78
78
  "handoff_dag_nodes": 42,
79
79
  "summary_cards": 42,
80
80
  "section_offsets_skills": 42,
81
- "token_budget_total_approx": 418479,
81
+ "token_budget_total_approx": 418426,
82
82
  "recipes": 8,
83
83
  "jurisdiction_clocks": 29,
84
84
  "did_ladders": 8,
@@ -5,6 +5,14 @@
5
5
  "event_count": 54
6
6
  },
7
7
  "events": [
8
+ {
9
+ "date": "2026-05-30",
10
+ "type": "catalog_update",
11
+ "artifact": "data/cve-catalog.json",
12
+ "path": "data/cve-catalog.json",
13
+ "schema_version": "1.0.0",
14
+ "entry_count": 427
15
+ },
8
16
  {
9
17
  "date": "2026-05-27",
10
18
  "type": "catalog_update",
@@ -143,14 +151,6 @@
143
151
  "path": "skills/email-security-anti-phishing/skill.md",
144
152
  "note": "Email security + anti-phishing for mid-2026 — SPF/DKIM/DMARC/BIMI/ARC/MTA-STS/TLSRPT, AI-augmented phishing (vishing, deepfake video, hyperpersonalized email), Business Email Compromise, secure email gateways"
145
153
  },
146
- {
147
- "date": "2026-05-18",
148
- "type": "catalog_update",
149
- "artifact": "data/cve-catalog.json",
150
- "path": "data/cve-catalog.json",
151
- "schema_version": "1.0.0",
152
- "entry_count": 427
153
- },
154
154
  {
155
155
  "date": "2026-05-18",
156
156
  "type": "catalog_update",
@@ -53,7 +53,7 @@
53
53
  "path": "data/cve-catalog.json",
54
54
  "purpose": "Per-CVE record (CVSS, EPSS, CISA KEV, RWEP, AI-discovery, vendor advisories, framework gaps, ATLAS/ATT&CK mappings). Cross-validated against NVD + CISA KEV + FIRST EPSS via validate-cves.",
55
55
  "schema_version": "1.0.0",
56
- "last_updated": "2026-05-18",
56
+ "last_updated": "2026-05-30",
57
57
  "tlp": "CLEAR",
58
58
  "source_confidence_default": "A1",
59
59
  "freshness_policy": {
@@ -1865,7 +1865,7 @@
1865
1865
  },
1866
1866
  "attack-surface-pentest": {
1867
1867
  "path": "skills/attack-surface-pentest/skill.md",
1868
- "total_bytes": 33291,
1868
+ "total_bytes": 33158,
1869
1869
  "total_lines": 388,
1870
1870
  "frontmatter": {
1871
1871
  "line_start": 1,
@@ -1888,25 +1888,25 @@
1888
1888
  "normalized_name": "framework-lag-declaration",
1889
1889
  "line": 106,
1890
1890
  "byte_start": 6410,
1891
- "byte_end": 10973,
1892
- "bytes": 4563,
1891
+ "byte_end": 10953,
1892
+ "bytes": 4543,
1893
1893
  "h3_count": 0
1894
1894
  },
1895
1895
  {
1896
1896
  "name": "TTP Mapping (MITRE ATLAS v5.6.0 + MITRE ATT&CK v19.0)",
1897
1897
  "normalized_name": "ttp-mapping",
1898
1898
  "line": 124,
1899
- "byte_start": 10973,
1900
- "byte_end": 13208,
1901
- "bytes": 2235,
1899
+ "byte_start": 10953,
1900
+ "byte_end": 13162,
1901
+ "bytes": 2209,
1902
1902
  "h3_count": 0
1903
1903
  },
1904
1904
  {
1905
1905
  "name": "Exploit Availability Matrix",
1906
1906
  "normalized_name": "exploit-availability-matrix",
1907
1907
  "line": 143,
1908
- "byte_start": 13208,
1909
- "byte_end": 15663,
1908
+ "byte_start": 13162,
1909
+ "byte_end": 15617,
1910
1910
  "bytes": 2455,
1911
1911
  "h3_count": 0
1912
1912
  },
@@ -1914,17 +1914,17 @@
1914
1914
  "name": "Analysis Procedure",
1915
1915
  "normalized_name": "analysis-procedure",
1916
1916
  "line": 160,
1917
- "byte_start": 15663,
1918
- "byte_end": 25366,
1919
- "bytes": 9703,
1917
+ "byte_start": 15617,
1918
+ "byte_end": 25273,
1919
+ "bytes": 9656,
1920
1920
  "h3_count": 4
1921
1921
  },
1922
1922
  {
1923
1923
  "name": "Output Format",
1924
1924
  "normalized_name": "output-format",
1925
1925
  "line": 281,
1926
- "byte_start": 25366,
1927
- "byte_end": 29363,
1926
+ "byte_start": 25273,
1927
+ "byte_end": 29270,
1928
1928
  "bytes": 3997,
1929
1929
  "h3_count": 9
1930
1930
  },
@@ -1932,8 +1932,8 @@
1932
1932
  "name": "Compliance Theater Check",
1933
1933
  "normalized_name": "compliance-theater-check",
1934
1934
  "line": 363,
1935
- "byte_start": 29363,
1936
- "byte_end": 31679,
1935
+ "byte_start": 29270,
1936
+ "byte_end": 31586,
1937
1937
  "bytes": 2316,
1938
1938
  "h3_count": 0
1939
1939
  },
@@ -1941,9 +1941,9 @@
1941
1941
  "name": "Defensive Countermeasure Mapping (D3FEND)",
1942
1942
  "normalized_name": "defensive-countermeasure-mapping",
1943
1943
  "line": 377,
1944
- "byte_start": 31679,
1945
- "byte_end": 33291,
1946
- "bytes": 1612,
1944
+ "byte_start": 31586,
1945
+ "byte_end": 33158,
1946
+ "bytes": 1572,
1947
1947
  "h3_count": 0
1948
1948
  }
1949
1949
  ]
@@ -2984,7 +2984,7 @@
2984
2984
  },
2985
2985
  "sector-financial": {
2986
2986
  "path": "skills/sector-financial/skill.md",
2987
- "total_bytes": 50325,
2987
+ "total_bytes": 50285,
2988
2988
  "total_lines": 401,
2989
2989
  "frontmatter": {
2990
2990
  "line_start": 1,
@@ -3034,16 +3034,16 @@
3034
3034
  "normalized_name": "analysis-procedure",
3035
3035
  "line": 182,
3036
3036
  "byte_start": 26352,
3037
- "byte_end": 35108,
3038
- "bytes": 8756,
3037
+ "byte_end": 35068,
3038
+ "bytes": 8716,
3039
3039
  "h3_count": 10
3040
3040
  },
3041
3041
  {
3042
3042
  "name": "Output Format",
3043
3043
  "normalized_name": "output-format",
3044
3044
  "line": 271,
3045
- "byte_start": 35108,
3046
- "byte_end": 38515,
3045
+ "byte_start": 35068,
3046
+ "byte_end": 38475,
3047
3047
  "bytes": 3407,
3048
3048
  "h3_count": 15
3049
3049
  },
@@ -3051,8 +3051,8 @@
3051
3051
  "name": "Compliance Theater Check",
3052
3052
  "normalized_name": "compliance-theater-check",
3053
3053
  "line": 335,
3054
- "byte_start": 38515,
3055
- "byte_end": 42853,
3054
+ "byte_start": 38475,
3055
+ "byte_end": 42813,
3056
3056
  "bytes": 4338,
3057
3057
  "h3_count": 0
3058
3058
  },
@@ -3060,8 +3060,8 @@
3060
3060
  "name": "Defensive Countermeasure Mapping",
3061
3061
  "normalized_name": "defensive-countermeasure-mapping",
3062
3062
  "line": 370,
3063
- "byte_start": 42853,
3064
- "byte_end": 46572,
3063
+ "byte_start": 42813,
3064
+ "byte_end": 46532,
3065
3065
  "bytes": 3719,
3066
3066
  "h3_count": 0
3067
3067
  },
@@ -3069,8 +3069,8 @@
3069
3069
  "name": "Hand-Off / Related Skills",
3070
3070
  "normalized_name": "hand-off",
3071
3071
  "line": 385,
3072
- "byte_start": 46572,
3073
- "byte_end": 50325,
3072
+ "byte_start": 46532,
3073
+ "byte_end": 50285,
3074
3074
  "bytes": 3753,
3075
3075
  "h3_count": 0
3076
3076
  }
@@ -4112,7 +4112,7 @@
4112
4112
  },
4113
4113
  "cloud-iam-incident": {
4114
4114
  "path": "skills/cloud-iam-incident/skill.md",
4115
- "total_bytes": 44474,
4115
+ "total_bytes": 44433,
4116
4116
  "total_lines": 416,
4117
4117
  "frontmatter": {
4118
4118
  "line_start": 1,
@@ -4162,16 +4162,16 @@
4162
4162
  "normalized_name": "analysis-procedure",
4163
4163
  "line": 185,
4164
4164
  "byte_start": 22803,
4165
- "byte_end": 30428,
4166
- "bytes": 7625,
4165
+ "byte_end": 30423,
4166
+ "bytes": 7620,
4167
4167
  "h3_count": 12
4168
4168
  },
4169
4169
  {
4170
4170
  "name": "Output Format",
4171
4171
  "normalized_name": "output-format",
4172
4172
  "line": 275,
4173
- "byte_start": 30428,
4174
- "byte_end": 32626,
4173
+ "byte_start": 30423,
4174
+ "byte_end": 32621,
4175
4175
  "bytes": 2198,
4176
4176
  "h3_count": 15
4177
4177
  },
@@ -4179,8 +4179,8 @@
4179
4179
  "name": "Compliance Theater Check",
4180
4180
  "normalized_name": "compliance-theater-check",
4181
4181
  "line": 338,
4182
- "byte_start": 32626,
4183
- "byte_end": 37225,
4182
+ "byte_start": 32621,
4183
+ "byte_end": 37220,
4184
4184
  "bytes": 4599,
4185
4185
  "h3_count": 0
4186
4186
  },
@@ -4188,17 +4188,17 @@
4188
4188
  "name": "Defensive Countermeasure Mapping",
4189
4189
  "normalized_name": "defensive-countermeasure-mapping",
4190
4190
  "line": 374,
4191
- "byte_start": 37225,
4192
- "byte_end": 41301,
4193
- "bytes": 4076,
4191
+ "byte_start": 37220,
4192
+ "byte_end": 41260,
4193
+ "bytes": 4040,
4194
4194
  "h3_count": 0
4195
4195
  },
4196
4196
  {
4197
4197
  "name": "Hand-Off / Related Skills",
4198
4198
  "normalized_name": "hand-off",
4199
4199
  "line": 396,
4200
- "byte_start": 41301,
4201
- "byte_end": 44474,
4200
+ "byte_start": 41260,
4201
+ "byte_end": 44433,
4202
4202
  "bytes": 3173,
4203
4203
  "h3_count": 0
4204
4204
  }