@event4u/agent-config 14.19.0 → 14.21.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.
Files changed (161) hide show
  1. package/.augment-plugin/marketplace.json +3 -3
  2. package/.augment-plugin/plugin.json +1 -1
  3. package/.claude-plugin/marketplace.json +1 -1
  4. package/CHANGELOG.md +351 -156
  5. package/README.md +1 -1
  6. package/agents/templates/.ai-council.yml.example +10 -0
  7. package/dist/agent-src/commands/agent-handoff.md +42 -41
  8. package/dist/agent-src/commands/analyze/inbox.md +1 -1
  9. package/dist/agent-src/commands/analyze/{reference-repo.md → repo.md} +247 -32
  10. package/dist/agent-src/commands/analyze/roadmap-repos.md +129 -0
  11. package/dist/agent-src/commands/analyze.md +12 -7
  12. package/dist/agent-src/commands/feature/plan.md +55 -16
  13. package/dist/agent-src/commands/feature/refactor.md +8 -3
  14. package/dist/agent-src/commands/humanize.md +48 -4
  15. package/dist/agent-src/contexts/execution/contract-decision-sheet.md +22 -1
  16. package/dist/agent-src/contexts/execution/host-capability-manifest.md +11 -2
  17. package/dist/agent-src/contexts/execution/roadmap-process-loop.md +35 -2
  18. package/dist/agent-src/contexts/execution/terminal-states.md +4 -1
  19. package/dist/agent-src/rules/evaluator-independence.md +4 -4
  20. package/dist/agent-src/rules/external-reference-deep-dive.md +2 -2
  21. package/dist/agent-src/rules/untrusted-input-defense.md +0 -2
  22. package/dist/agent-src/skills/competitive-positioning/SKILL.md +2 -2
  23. package/dist/agent-src/skills/evaluate-llm-feature/SKILL.md +1 -1
  24. package/dist/agent-src/skills/humanizer/references/anti-aiisms.md +27 -11
  25. package/dist/agent-src/skills/learning-to-rule-or-skill/SKILL.md +1 -1
  26. package/dist/agent-src/skills/markitdown/SKILL.md +2 -2
  27. package/dist/agent-src/skills/repomix-packer/SKILL.md +1 -1
  28. package/dist/agent-src/skills/skill-improvement-pipeline/SKILL.md +28 -6
  29. package/dist/agent-src/skills/technical-specification/SKILL.md +4 -0
  30. package/dist/agent-src/skills/test-driven-development/SKILL.md +1 -3
  31. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  32. package/dist/agent-src/templates/features.md +5 -0
  33. package/dist/agent-src/templates/roadmaps.md +29 -1
  34. package/dist/agent-src/templates/scripts/telemetry/mcp_lite.ts +213 -0
  35. package/dist/agent-src/templates/scripts/telemetry/report_renderer.ts +16 -0
  36. package/dist/agent-src/templates/scripts/telemetry_report.ts +22 -2
  37. package/dist/cli/mcp/dispatch.js +10 -0
  38. package/dist/cli/mcp/stdio.js +33 -2
  39. package/dist/cli/mcp/telemetry.js +227 -0
  40. package/dist/cli-delegate/{chunk-KPBWFOPZ.js → chunk-2FTMENJL.js} +194 -37
  41. package/dist/cli-delegate/{chunk-PMEKGDED.js → chunk-2TAQ2K4V.js} +166 -1
  42. package/dist/cli-delegate/{chunk-GZTMRYCN.js → chunk-643Z7FIC.js} +79 -12
  43. package/dist/cli-delegate/{chunk-CYH5SP6M.js → chunk-I6RHFQEG.js} +151 -16
  44. package/dist/cli-delegate/{chunk-IDHUQIXP.js → chunk-J3RFNKG4.js} +41 -5
  45. package/dist/cli-delegate/{chunk-7PRE6ZV2.js → chunk-YS6XTLEK.js} +199 -4
  46. package/dist/cli-delegate/chunk-ZVBOHSVF.js +1109 -0
  47. package/dist/cli-delegate/cmd_conformance.js +88 -110
  48. package/dist/cli-delegate/cmd_doctor.js +3 -3
  49. package/dist/cli-delegate/cmd_export.js +2 -2
  50. package/dist/cli-delegate/cmd_handoff.js +42 -12
  51. package/dist/cli-delegate/cmd_memory_get.js +1 -1
  52. package/dist/cli-delegate/cmd_prune.js +2 -2
  53. package/dist/cli-delegate/cmd_route_audit.js +1 -1
  54. package/dist/cli-delegate/cmd_session_recycle.js +59 -902
  55. package/dist/cli-delegate/cmd_settings_migrate.js +2 -2
  56. package/dist/cli-delegate/cmd_sync.js +2 -2
  57. package/dist/cli-delegate/cmd_uninstall.js +2 -2
  58. package/dist/cli-delegate/cmd_validate.js +2 -2
  59. package/dist/discovery/deprecation-report.md +1 -1
  60. package/dist/discovery/discovery-manifest.json +62 -31
  61. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  62. package/dist/discovery/discovery-manifest.summary.md +3 -3
  63. package/dist/discovery/dormancy-report.md +1 -1
  64. package/dist/discovery/orphan-report.md +1 -1
  65. package/dist/discovery/packs.json +7 -6
  66. package/dist/discovery/trust-report.md +2 -2
  67. package/dist/discovery/workspaces.json +6 -5
  68. package/dist/hooks/dispatch.js +3801 -2803
  69. package/dist/install/install.mjs +396 -168
  70. package/dist/mcp/registry-manifest.json +3 -3
  71. package/dist/mcp/server.json +2 -2
  72. package/dist/mcp/server.mjs +809 -180
  73. package/dist/scripts/ai_council/content_ceiling.js +63 -0
  74. package/dist/scripts/ai_council/seat_policy.js +106 -0
  75. package/dist/scripts/ai_council/transport_resolver.js +21 -0
  76. package/dist/scripts/mcp_server/telemetry.js +148 -0
  77. package/docs/guidelines/agent-infra/naming.md +1 -1
  78. package/docs/guidelines/agent-infra/security-lint-containment.md +46 -6
  79. package/docs/guidelines/agent-infra/self-improvement-pipeline.md +4 -4
  80. package/docs/guidelines/agent-infra/untrusted-input-spotlighting.md +1 -1
  81. package/docs/guidelines/redundancy-taxonomy.md +28 -0
  82. package/llms.txt +14 -14
  83. package/package.json +1 -1
  84. package/src/agent-src/templates/scripts/telemetry/mcp_lite.ts +213 -0
  85. package/src/agent-src/templates/scripts/telemetry/report_renderer.ts +16 -0
  86. package/src/agent-src/templates/scripts/telemetry_report.ts +22 -2
  87. package/src/config/assurance-capability-registry.json +9 -0
  88. package/src/config/gate-coverage.yml +55 -0
  89. package/src/config/gate-violation-baselines.json +18 -6
  90. package/src/config/release-gate-locality.yml +4 -3
  91. package/src/scripts/_cli/cmd_session_recycle.ts +51 -3
  92. package/src/scripts/_lib/audit_field_provenance.ts +44 -3
  93. package/src/scripts/_lib/blocked_by_marker.ts +189 -0
  94. package/src/scripts/_lib/host_capability.ts +76 -1
  95. package/src/scripts/_lib/install_reach_checks.ts +33 -1
  96. package/src/scripts/_lib/mcp_bridge.ts +222 -10
  97. package/src/scripts/_lib/mcp_consent_residual.ts +173 -0
  98. package/src/scripts/_lib/orchestration_record.ts +23 -1
  99. package/src/scripts/_lib/recycle_envelope_paths.ts +190 -0
  100. package/src/scripts/_lib/release_highlights.ts +19 -211
  101. package/src/scripts/_lib/release_material.ts +27 -77
  102. package/src/scripts/_lib/release_position.ts +96 -0
  103. package/src/scripts/_lib/review_skipped_record.ts +17 -1
  104. package/src/scripts/_lib/security_lint.ts +179 -7
  105. package/src/scripts/_lib/self_repair.ts +141 -6
  106. package/src/scripts/_lib/self_repair_store.ts +273 -7
  107. package/src/scripts/_lib/structured_ask.ts +117 -0
  108. package/src/scripts/_lib/subagent_capsule.ts +155 -3
  109. package/src/scripts/_lib/tty_prompt.ts +76 -0
  110. package/src/scripts/ai_council/api_transport.ts +163 -0
  111. package/src/scripts/ai_council/clients.ts +58 -63
  112. package/src/scripts/ai_council/config.ts +13 -0
  113. package/src/scripts/ai_council/content_ceiling.ts +79 -0
  114. package/src/scripts/ai_council/jury_aggregate.ts +178 -0
  115. package/src/scripts/ai_council/seat_policy.ts +137 -0
  116. package/src/scripts/ai_council/status_surface.ts +79 -0
  117. package/src/scripts/ai_council/transport_resolver.ts +59 -1
  118. package/src/scripts/ai_tells_rules.ts +446 -5
  119. package/src/scripts/ask_block_census.ts +499 -0
  120. package/src/scripts/bench_humanizer_eval.ts +264 -40
  121. package/src/scripts/bench_prose_tells_fp.ts +198 -0
  122. package/src/scripts/build_rule_trigger_matrix.ts +5 -0
  123. package/src/scripts/check_branch_work_committed.ts +234 -0
  124. package/src/scripts/check_mcp_doc_drift.ts +217 -0
  125. package/src/scripts/check_pack_size.ts +321 -3
  126. package/src/scripts/check_release_highlights.ts +0 -157
  127. package/src/scripts/council_cli.ts +18 -27
  128. package/src/scripts/detect_ai_tells.ts +142 -20
  129. package/src/scripts/handoff_context_hook.ts +54 -7
  130. package/src/scripts/harvest_reference_tokens.ts +698 -0
  131. package/src/scripts/hook_manifest.json +1 -1
  132. package/src/scripts/hook_manifest.yaml +31 -1
  133. package/src/scripts/hooks/concern_registry.ts +2 -0
  134. package/src/scripts/hooks/delegation_nudge_hook.ts +45 -1
  135. package/src/scripts/hooks/one_question_per_ask_hook.ts +191 -0
  136. package/src/scripts/hooks/session_eol_hook.ts +18 -7
  137. package/src/scripts/install-hooks.sh +52 -0
  138. package/src/scripts/install.ts +4 -4
  139. package/src/scripts/lint_agent_security.ts +316 -25
  140. package/src/scripts/lint_confusables.ts +42 -6
  141. package/src/scripts/lint_handoffs.ts +0 -132
  142. package/src/scripts/lint_hidden_unicode.ts +49 -7
  143. package/src/scripts/lint_instruction_smuggling.ts +42 -6
  144. package/src/scripts/lint_mcp_config_security.ts +42 -6
  145. package/src/scripts/lint_roadmap_blockers.ts +51 -1
  146. package/src/scripts/lint_roadmap_later_disposition.ts +217 -27
  147. package/src/scripts/lint_skill_frontmatter_safety.ts +43 -7
  148. package/src/scripts/mcp_server/resources.ts +41 -0
  149. package/src/scripts/mcp_server/telemetry.ts +19 -4
  150. package/src/scripts/migrate_command_suggestions.ts +1 -1
  151. package/src/scripts/orchestration_record.ts +12 -1
  152. package/src/scripts/probe_unblocked_ask.ts +135 -2
  153. package/src/scripts/release.ts +50 -95
  154. package/src/scripts/release_drill.ts +6 -10
  155. package/src/scripts/release_env.ts +1 -0
  156. package/src/scripts/release_publication.ts +40 -31
  157. package/src/scripts/self_repair_cli.ts +31 -1
  158. package/src/scripts/self_review_gate.ts +409 -15
  159. package/src/scripts/skill_scout.ts +69 -0
  160. package/dist/cli-delegate/chunk-2GNWGMAL.js +0 -172
  161. package/dist/cli-delegate/chunk-LPPWO5CE.js +0 -161
@@ -1502,6 +1502,7 @@ __export(resources_exports, {
1502
1502
  MIME_MARKDOWN: () => MIME_MARKDOWN,
1503
1503
  ResourceCache: () => ResourceCache,
1504
1504
  load_all_resources: () => load_all_resources,
1505
+ resourcePriority: () => resourcePriority,
1505
1506
  scan_contexts: () => scan_contexts,
1506
1507
  scan_guidelines: () => scan_guidelines,
1507
1508
  scan_rules: () => scan_rules,
@@ -1600,9 +1601,18 @@ function _load(p, options) {
1600
1601
  body: _rstrip2(text) + "\n",
1601
1602
  source: meta.source ?? "package",
1602
1603
  mime_type: MIME_MARKDOWN,
1603
- kind
1604
+ kind,
1605
+ ...meta.type === void 0 ? {} : { rule_type: meta.type.trim() },
1606
+ ..._mtimeIso(p) === null ? {} : { last_modified: _mtimeIso(p) }
1604
1607
  };
1605
1608
  }
1609
+ function _mtimeIso(p) {
1610
+ try {
1611
+ return fs5.statSync(p).mtime.toISOString();
1612
+ } catch {
1613
+ return null;
1614
+ }
1615
+ }
1606
1616
  function scan_rules(root) {
1607
1617
  const base = root ?? _project_root();
1608
1618
  const rules_root = path5.join(base, "dist/agent-src", "rules");
@@ -1684,12 +1694,23 @@ function _strCmp2(a, b) {
1684
1694
  }
1685
1695
  return 0;
1686
1696
  }
1697
+ function resourcePriority(resource) {
1698
+ if (resource.rule_type === "always") return 1;
1699
+ if (resource.rule_type === "auto") return 0.7;
1700
+ if (resource.rule_type === "manual") return 0.3;
1701
+ return resource.kind === "rule" ? 0.7 : resource.kind === "context" ? 0.5 : 0.3;
1702
+ }
1687
1703
  function to_mcp_resource_meta(resource) {
1688
1704
  return {
1689
1705
  uri: resource.uri,
1690
1706
  name: resource.name,
1691
1707
  description: resource.description,
1692
1708
  mimeType: resource.mime_type,
1709
+ // `audience` is the model, not the end user: these are governance
1710
+ // assets a host injects, never something a person reads in a client.
1711
+ audience: ["assistant"],
1712
+ priority: resourcePriority(resource),
1713
+ ...resource.last_modified === void 0 ? {} : { lastModified: resource.last_modified },
1693
1714
  _meta: { source: resource.source, kind: resource.kind }
1694
1715
  };
1695
1716
  }
@@ -9092,6 +9113,7 @@ var require_dist = __commonJS({
9092
9113
  });
9093
9114
 
9094
9115
  // src/scripts/_lib/security_lint.ts
9116
+ import { createHash as createHash2 } from "node:crypto";
9095
9117
  import * as fs6 from "node:fs";
9096
9118
  import * as path6 from "node:path";
9097
9119
  import { fileURLToPath as fileURLToPath3 } from "node:url";
@@ -9101,6 +9123,9 @@ function is_example_path(rel_path) {
9101
9123
  function path_weight(rel_path) {
9102
9124
  return is_example_path(rel_path) ? 0.25 : 1;
9103
9125
  }
9126
+ function source_identity(rel) {
9127
+ return rel.startsWith(PROJECTION_PREFIX) ? `src/${rel.slice(PROJECTION_PREFIX.length)}` : rel;
9128
+ }
9104
9129
  function _splitlines(text) {
9105
9130
  const out = [];
9106
9131
  let buf = "";
@@ -9176,11 +9201,18 @@ function scan_file(filePath) {
9176
9201
  }
9177
9202
  }
9178
9203
  const pragmas = {};
9204
+ const pragmaHashes = {};
9179
9205
  for (const text of lines) {
9180
9206
  _PRAGMA.lastIndex = 0;
9181
9207
  let m;
9182
9208
  while ((m = _PRAGMA.exec(text)) !== null) {
9183
- pragmas[m[1]] = m[2];
9209
+ const check = m[1];
9210
+ pragmas[check] = m[2];
9211
+ const hashes = (m[3] ?? "").match(/sha256:([0-9a-f]{64})/g) ?? [];
9212
+ pragmaHashes[check] = [
9213
+ ...pragmaHashes[check] ?? [],
9214
+ ...hashes.map((h) => h.slice("sha256:".length))
9215
+ ];
9184
9216
  if (m.index === _PRAGMA.lastIndex) {
9185
9217
  _PRAGMA.lastIndex += 1;
9186
9218
  }
@@ -9193,7 +9225,29 @@ function scan_file(filePath) {
9193
9225
  in_example,
9194
9226
  in_any,
9195
9227
  pragmas,
9196
- path_weight(rel)
9228
+ path_weight(rel),
9229
+ pragmaHashes
9230
+ );
9231
+ }
9232
+ function scan_path(filePath, base) {
9233
+ const sf = scan_file(filePath);
9234
+ let rel;
9235
+ const baseResolved = path6.resolve(base);
9236
+ const fileResolved = path6.resolve(filePath);
9237
+ if (fileResolved === baseResolved || fileResolved.startsWith(baseResolved + path6.sep)) {
9238
+ rel = path6.relative(baseResolved, fileResolved).split(path6.sep).join("/");
9239
+ } else {
9240
+ rel = path6.basename(filePath);
9241
+ }
9242
+ return new ScannedFile(
9243
+ sf.path,
9244
+ rel,
9245
+ sf.lines,
9246
+ sf.in_example_fence,
9247
+ sf.in_any_fence,
9248
+ sf.pragmas,
9249
+ path_weight(rel),
9250
+ sf.pragma_hashes
9197
9251
  );
9198
9252
  }
9199
9253
  function _rglobSorted(base) {
@@ -9229,9 +9283,9 @@ function _pathCmp(a, b) {
9229
9283
  if (pa.length > pb.length) return 1;
9230
9284
  return 0;
9231
9285
  }
9232
- function* iter_corpus(roots = DEFAULT_SCAN_ROOTS, exts = [".md"]) {
9286
+ function* iter_corpus(roots = DEFAULT_SCAN_ROOTS, exts = [".md"], scanBase = ROOT) {
9233
9287
  for (const root of roots) {
9234
- const base = path6.join(ROOT, root);
9288
+ const base = path6.join(scanBase, root);
9235
9289
  if (!fs6.existsSync(base)) {
9236
9290
  continue;
9237
9291
  }
@@ -9243,11 +9297,25 @@ function* iter_corpus(roots = DEFAULT_SCAN_ROOTS, exts = [".md"]) {
9243
9297
  continue;
9244
9298
  }
9245
9299
  if (st.isFile() && exts.includes(path6.extname(p))) {
9246
- yield scan_file(p);
9300
+ yield scan_path(p, scanBase);
9247
9301
  }
9248
9302
  }
9249
9303
  }
9250
9304
  }
9305
+ function legacy_pragma_finding(sf, check) {
9306
+ return new Finding(
9307
+ sf.rel,
9308
+ 0,
9309
+ LEGACY_PRAGMA_CHECK,
9310
+ "LOW",
9311
+ `unbound \`security-lint: allow ${check}\` pragma suppresses this whole file \u2014 it accepts whatever the matched text is later changed to say. Bind it with \`sha256:<hex>\` per accepted match.`,
9312
+ sf.weight
9313
+ );
9314
+ }
9315
+ function report_child_scanned(count) {
9316
+ process.stderr.write(`${CHILD_SCANNED_PREFIX}${String(count)}
9317
+ `);
9318
+ }
9251
9319
  function report(findings, opts) {
9252
9320
  const check_label = opts.check_label;
9253
9321
  if (findings.length === 0) {
@@ -9431,7 +9499,7 @@ function _pyJsonScalarAscii(value) {
9431
9499
  if (typeof value === "string") return _pyJsonStrAscii(value);
9432
9500
  return _pyJsonScalar(value);
9433
9501
  }
9434
- var _HERE, ROOT, EXAMPLE_FENCE_LANG, GUIDELINE, GUIDELINE_EPILOG, DEFAULT_SCAN_ROOTS, _EXAMPLE_PATH, _PRAGMA, _FENCE, SEVERITY_RANK, Finding, ScannedFile, PyFloat;
9502
+ var _HERE, ROOT, EXAMPLE_FENCE_LANG, GUIDELINE, GUIDELINE_EPILOG, DEFAULT_SCAN_ROOTS, _EXAMPLE_PATH, _PRAGMA, _FENCE, SEVERITY_RANK, Finding, PROJECTION_PREFIX, ScannedFile, LEGACY_PRAGMA_CHECK, CHILD_SCANNED_PREFIX, PyFloat;
9435
9503
  var init_security_lint = __esm({
9436
9504
  "src/scripts/_lib/security_lint.ts"() {
9437
9505
  "use strict";
@@ -9448,7 +9516,7 @@ var init_security_lint = __esm({
9448
9516
  "dist/agent-src"
9449
9517
  ];
9450
9518
  _EXAMPLE_PATH = /(^|\/)(docs|evals|tests?|fixtures?)(\/|$)|example|template|sample|\/_template/i;
9451
- _PRAGMA = /<!--\s*security-lint:\s*allow\s+([A-Za-z0-9_-]+)\s+"([^"]+)"\s*-->/g;
9519
+ _PRAGMA = /<!--\s*security-lint:\s*allow\s+([A-Za-z0-9_-]+)\s+"([^"]+)"((?:\s+sha256:[0-9a-f]{64})*)\s*-->/g;
9452
9520
  _FENCE = /^(\s*)(`{3,}|~{3,})\s*([A-Za-z0-9_-]*)\s*$/;
9453
9521
  SEVERITY_RANK = { LOW: 1, MED: 2, HIGH: 3 };
9454
9522
  Finding = class {
@@ -9488,6 +9556,7 @@ var init_security_lint = __esm({
9488
9556
  };
9489
9557
  }
9490
9558
  };
9559
+ PROJECTION_PREFIX = "dist/agent-src/";
9491
9560
  ScannedFile = class {
9492
9561
  path;
9493
9562
  // absolute or as-given path
@@ -9498,8 +9567,10 @@ var init_security_lint = __esm({
9498
9567
  in_any_fence;
9499
9568
  pragmas;
9500
9569
  // check id → reason
9570
+ /** check id → the sha256 fingerprints that pragma accepts. Empty = unbound. */
9571
+ pragma_hashes;
9501
9572
  weight;
9502
- constructor(pathArg, rel, lines, in_example_fence, in_any_fence, pragmas, weight) {
9573
+ constructor(pathArg, rel, lines, in_example_fence, in_any_fence, pragmas, weight, pragma_hashes = {}) {
9503
9574
  this.path = pathArg;
9504
9575
  this.rel = rel;
9505
9576
  this.lines = lines;
@@ -9507,10 +9578,74 @@ var init_security_lint = __esm({
9507
9578
  this.in_any_fence = in_any_fence;
9508
9579
  this.pragmas = pragmas;
9509
9580
  this.weight = weight;
9581
+ this.pragma_hashes = pragma_hashes;
9510
9582
  }
9511
9583
  pragma_allows(check) {
9512
9584
  return Object.prototype.hasOwnProperty.call(this.pragmas, check);
9513
9585
  }
9586
+ /**
9587
+ * Which form of pragma this file carries for `check`.
9588
+ *
9589
+ * `absent` — no pragma; scan normally.
9590
+ * `legacy` — a pragma with no fingerprint. Suppresses the whole file, as it
9591
+ * always did, and says so: a key lookup accepts whatever the
9592
+ * line is later changed to say, which is the defect being paid
9593
+ * down, not a mode anybody should choose.
9594
+ * `bound` — a pragma listing fingerprints. Suppresses exactly the matches
9595
+ * whose evidence hashes to one of them; anything else survives.
9596
+ */
9597
+ pragma_form(check) {
9598
+ if (!this.pragma_allows(check)) return "absent";
9599
+ return (this.pragma_hashes[check] ?? []).length > 0 ? "bound" : "legacy";
9600
+ }
9601
+ /**
9602
+ * The fingerprint one finding's evidence hashes to.
9603
+ *
9604
+ * WHAT IS HASHED, and each part earns its place:
9605
+ * check id — the same line may legitimately be accepted for one check
9606
+ * and not another.
9607
+ * rel path — the location IDENTITY. Not the line NUMBER: an unrelated
9608
+ * insert above would otherwise break every pragma in the
9609
+ * file, and a suppression that breaks on unrelated edits
9610
+ * gets deleted rather than re-derived. A `dist/agent-src/`
9611
+ * path folds to its `src/` original first, because the
9612
+ * projection is byte-exact by contract (ADR-201) and
9613
+ * carries the pragma verbatim — without the fold, every
9614
+ * migrated pragma would suppress the source and leave its
9615
+ * own copy flagged, which is a gate that reds on a file
9616
+ * nobody may edit.
9617
+ * matched line, — the evidence. ASCII whitespace runs collapse so a reflow
9618
+ * normalized does not invalidate the binding, `sha256:<hex>` tokens are
9619
+ * removed, and NOTHING else is stripped: the zero-width
9620
+ * characters this suite hunts are exactly what a wider
9621
+ * normalizer would erase.
9622
+ *
9623
+ * WHY THE HASH TOKENS COME OUT. A pragma's own reason string can be the
9624
+ * matched evidence — two in this tree are, because they quote the very
9625
+ * phrases their check detects in order to explain themselves. Without this
9626
+ * the fingerprint would have to be computed over a line that already
9627
+ * contains it, which has no fixed point: writing the hash changes the line,
9628
+ * which changes the hash. Stripping the tokens makes the fingerprint stable
9629
+ * under the act of recording it, and costs nothing elsewhere — a `sha256:`
9630
+ * token in ordinary prose is not evidence of anything a linter here checks.
9631
+ *
9632
+ * Deliberately NOT the whole file: incidental content elsewhere would make
9633
+ * every unrelated edit re-fire the pragma, which is the noise that produces
9634
+ * blanket suppressions.
9635
+ */
9636
+ evidence_fingerprint(finding) {
9637
+ const text = finding.line > 0 ? this.lines[finding.line - 1] ?? "" : "";
9638
+ const normalized = text.replace(/\s*sha256:[0-9a-f]{64}/g, "").replace(/[ \t]+/g, " ").trim();
9639
+ return createHash2("sha256").update(`${finding.check}
9640
+ ${source_identity(this.rel)}
9641
+ ${normalized}`, "utf-8").digest("hex");
9642
+ }
9643
+ /** Drop the findings this file's BOUND pragma for `check` accepts. */
9644
+ filter_bound_pragma(check, findings) {
9645
+ const accepted = new Set(this.pragma_hashes[check] ?? []);
9646
+ if (accepted.size === 0) return [...findings];
9647
+ return findings.filter((f) => !accepted.has(this.evidence_fingerprint(f)));
9648
+ }
9514
9649
  /** Yield [lineno, text] honouring the fence masks (mirrors iter_lines). */
9515
9650
  *iter_lines(opts = {}) {
9516
9651
  const skip_example_fence = opts.skip_example_fence ?? true;
@@ -9526,6 +9661,8 @@ var init_security_lint = __esm({
9526
9661
  }
9527
9662
  }
9528
9663
  };
9664
+ LEGACY_PRAGMA_CHECK = "legacy-pragma";
9665
+ CHILD_SCANNED_PREFIX = "scanned: ";
9529
9666
  PyFloat = class {
9530
9667
  constructor(value) {
9531
9668
  this.value = value;
@@ -9604,9 +9741,11 @@ function _cpName(cp) {
9604
9741
  return n !== void 0 ? n : "<unnamed>";
9605
9742
  }
9606
9743
  function _scan(sf) {
9607
- if (sf.pragma_allows(CHECK)) {
9608
- return [];
9744
+ const pragmaForm = sf.pragma_form(CHECK);
9745
+ if (pragmaForm === "legacy") {
9746
+ return [legacy_pragma_finding(sf, CHECK)];
9609
9747
  }
9748
+ const finish = (hits) => pragmaForm === "bound" ? sf.filter_bound_pragma(CHECK, hits) : hits;
9610
9749
  const out = [];
9611
9750
  for (const [lineno, text] of sf.iter_lines({ skip_example_fence: true })) {
9612
9751
  let vs_run = 0;
@@ -9644,7 +9783,7 @@ function _scan(sf) {
9644
9783
  );
9645
9784
  }
9646
9785
  }
9647
- return out;
9786
+ return finish(out);
9648
9787
  }
9649
9788
  function _isGenerated(rel) {
9650
9789
  return _GENERATED_PREFIXES.some((p) => rel.startsWith(p));
@@ -9728,7 +9867,7 @@ function _sanitize(filePath) {
9728
9867
  return out;
9729
9868
  }
9730
9869
  function _argError(msg) {
9731
- process.stderr.write("usage: lint_hidden_unicode [-h] [--json] [--fix]\n");
9870
+ process.stderr.write("usage: lint_hidden_unicode [-h] [--json] [--fix] [--root DIR]\n");
9732
9871
  process.stderr.write(`lint_hidden_unicode: error: ${msg}
9733
9872
  `);
9734
9873
  process.exit(2);
@@ -9736,14 +9875,27 @@ function _argError(msg) {
9736
9875
  function parse_args(argv) {
9737
9876
  const out = { json: false, fix: false };
9738
9877
  const extra = [];
9878
+ let rootPending = false;
9739
9879
  for (const a of argv) {
9880
+ if (rootPending) {
9881
+ out.root = a;
9882
+ rootPending = false;
9883
+ continue;
9884
+ }
9740
9885
  if (a === "-h" || a === "--help") {
9741
- process.stdout.write("usage: lint_hidden_unicode [-h] [--json] [--fix]\n");
9886
+ process.stdout.write("usage: lint_hidden_unicode [-h] [--json] [--fix] [--root DIR]\n");
9742
9887
  process.exit(0);
9743
9888
  } else if (a === "--json") {
9744
9889
  out.json = true;
9745
9890
  } else if (a === "--fix") {
9746
9891
  out.fix = true;
9892
+ } else if (a === "--root" || a.startsWith("--root=")) {
9893
+ const eq = a.indexOf("=");
9894
+ if (eq !== -1) {
9895
+ out.root = a.slice(eq + 1);
9896
+ } else {
9897
+ rootPending = true;
9898
+ }
9747
9899
  } else {
9748
9900
  extra.push(a);
9749
9901
  }
@@ -9755,10 +9907,11 @@ function parse_args(argv) {
9755
9907
  }
9756
9908
  function main(argv = null) {
9757
9909
  const args = parse_args(argv ?? process.argv.slice(2));
9910
+ const scanBase = args.root === void 0 ? ROOT : path7.resolve(args.root);
9758
9911
  const findings = [];
9759
9912
  const flagged = /* @__PURE__ */ new Set();
9760
9913
  let corpusFiles = 0;
9761
- for (const sf of iter_corpus()) {
9914
+ for (const sf of iter_corpus(DEFAULT_SCAN_ROOTS, [".md"], scanBase)) {
9762
9915
  corpusFiles += 1;
9763
9916
  const hits = _scan(sf);
9764
9917
  for (const h of hits) {
@@ -9783,7 +9936,7 @@ function main(argv = null) {
9783
9936
  }
9784
9937
  throw exc;
9785
9938
  }
9786
- const sourceFiles = _eligibleSourceFiles();
9939
+ const sourceFiles = args.root === void 0 ? _eligibleSourceFiles() : [];
9787
9940
  for (const h of _scanSourceControlBytes(sourceFiles)) {
9788
9941
  findings.push(h);
9789
9942
  }
@@ -9802,6 +9955,9 @@ function main(argv = null) {
9802
9955
  `);
9803
9956
  }
9804
9957
  }
9958
+ if (args.json) {
9959
+ report_child_scanned(corpusFiles + (sourceFiles === null ? 0 : sourceFiles.length));
9960
+ }
9805
9961
  if (args.json) {
9806
9962
  const payload = py_json_dumps_indent2(findings.map((f) => f.toDict()));
9807
9963
  process.stdout.write(payload + "\n");
@@ -11467,7 +11623,7 @@ var init_memory_fts_index = __esm({
11467
11623
  });
11468
11624
 
11469
11625
  // src/scripts/learning_sidecar.ts
11470
- import { createHash as createHash2 } from "node:crypto";
11626
+ import { createHash as createHash3 } from "node:crypto";
11471
11627
  import * as fs11 from "node:fs";
11472
11628
  import * as path11 from "node:path";
11473
11629
  import process5 from "node:process";
@@ -11477,7 +11633,7 @@ function _parseTsMs(ts) {
11477
11633
  return Number.isNaN(t) ? null : t;
11478
11634
  }
11479
11635
  function _bodyHash(body) {
11480
- return createHash2("sha256").update(body.trim().toLowerCase()).digest("hex").slice(0, 12);
11636
+ return createHash3("sha256").update(body.trim().toLowerCase()).digest("hex").slice(0, 12);
11481
11637
  }
11482
11638
  function _globSignalFiles(dir) {
11483
11639
  let names;
@@ -27740,6 +27896,171 @@ var init_runtime_wiring_checks = __esm({
27740
27896
  }
27741
27897
  });
27742
27898
 
27899
+ // src/scripts/_lib/host_capability.ts
27900
+ import process17 from "node:process";
27901
+ function asBool(value) {
27902
+ return value === true;
27903
+ }
27904
+ function normalizeHostManifest(input) {
27905
+ if (input === null || typeof input !== "object") {
27906
+ return { ...SAFE_DEFAULT };
27907
+ }
27908
+ const src = input;
27909
+ return {
27910
+ schema_version: 1,
27911
+ subagent_spawn: asBool(src.subagent_spawn),
27912
+ parallel_spawn: asBool(src.parallel_spawn),
27913
+ status_polling: asBool(src.status_polling),
27914
+ separate_quota_pool: asBool(src.separate_quota_pool),
27915
+ agent_teams: asBool(src.agent_teams),
27916
+ worker_respawn: asBool(src.worker_respawn),
27917
+ structured_ask: asBool(src.structured_ask),
27918
+ reads_project_mcp_config: asBool(src.reads_project_mcp_config),
27919
+ // Inverted coercion, matching the inverted default: only an explicit
27920
+ // `false` clears the residual, so an absent or malformed value keeps
27921
+ // the manual step visible instead of silently dropping it.
27922
+ mcp_needs_manual_activation: src.mcp_needs_manual_activation !== false
27923
+ };
27924
+ }
27925
+ function resolveHostCapabilities(hostId, override) {
27926
+ if (override !== void 0 && override !== null && typeof override === "object" && !Array.isArray(override)) {
27927
+ return normalizeHostManifest(override);
27928
+ }
27929
+ const row = hostId !== null && hostId !== void 0 ? HOST_CAPABILITY_REGISTRY[hostId] : void 0;
27930
+ if (row === void 0) {
27931
+ return { ...SAFE_DEFAULT };
27932
+ }
27933
+ return { ...SAFE_DEFAULT, ...row, schema_version: 1 };
27934
+ }
27935
+ function probeHostCapabilities(hostId) {
27936
+ const base = resolveHostCapabilities(hostId);
27937
+ const flag = process17.env.CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS;
27938
+ const probedAgentTeams = typeof flag === "string" && flag !== "";
27939
+ return { ...base, agent_teams: base.agent_teams || probedAgentTeams };
27940
+ }
27941
+ function describeHostCapabilities(hostId) {
27942
+ const manifest = probeHostCapabilities(hostId);
27943
+ const row = hostId !== null && hostId !== void 0 ? HOST_CAPABILITY_REGISTRY[hostId] : void 0;
27944
+ const flag = process17.env.CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS;
27945
+ const probedAgentTeams = typeof flag === "string" && flag !== "";
27946
+ const sources = {};
27947
+ for (const field of CAPABILITY_FIELDS) {
27948
+ if (row !== void 0 && typeof row[field] === "boolean") {
27949
+ sources[field] = "registry";
27950
+ } else if (field === "agent_teams" && probedAgentTeams) {
27951
+ sources[field] = "live-probe";
27952
+ } else {
27953
+ sources[field] = "default";
27954
+ }
27955
+ }
27956
+ return { manifest, sources };
27957
+ }
27958
+ var SAFE_DEFAULT, HOST_CAPABILITY_REGISTRY, CAPABILITY_FIELDS;
27959
+ var init_host_capability = __esm({
27960
+ "src/scripts/_lib/host_capability.ts"() {
27961
+ "use strict";
27962
+ SAFE_DEFAULT = {
27963
+ schema_version: 1,
27964
+ subagent_spawn: false,
27965
+ parallel_spawn: false,
27966
+ status_polling: false,
27967
+ separate_quota_pool: false,
27968
+ agent_teams: false,
27969
+ worker_respawn: false,
27970
+ structured_ask: false,
27971
+ reads_project_mcp_config: false,
27972
+ // `true` because the safe answer here is "there is still a step", not
27973
+ // "there is nothing to do" — see the field's own note.
27974
+ mcp_needs_manual_activation: true
27975
+ };
27976
+ HOST_CAPABILITY_REGISTRY = {
27977
+ claude: { subagent_spawn: true, parallel_spawn: true, structured_ask: false }
27978
+ };
27979
+ CAPABILITY_FIELDS = [
27980
+ "subagent_spawn",
27981
+ "parallel_spawn",
27982
+ "status_polling",
27983
+ "separate_quota_pool",
27984
+ "agent_teams",
27985
+ "worker_respawn",
27986
+ "structured_ask",
27987
+ "reads_project_mcp_config",
27988
+ "mcp_needs_manual_activation"
27989
+ ];
27990
+ }
27991
+ });
27992
+
27993
+ // src/scripts/_lib/mcp_consent_residual.ts
27994
+ function residualFor(hostId) {
27995
+ const { manifest, sources } = describeHostCapabilities(hostId);
27996
+ if (sources.mcp_needs_manual_activation === "registry" && !manifest.mcp_needs_manual_activation) {
27997
+ return null;
27998
+ }
27999
+ return SEEDED[hostId] ?? null;
28000
+ }
28001
+ function isRecorded(hostId) {
28002
+ const { sources } = describeHostCapabilities(hostId);
28003
+ return hostId in SEEDED || sources.mcp_needs_manual_activation === "registry";
28004
+ }
28005
+ function residualLine(hostId) {
28006
+ const r = residualFor(hostId);
28007
+ if (r !== null) {
28008
+ return {
28009
+ hostId,
28010
+ state: "residual",
28011
+ text: `${hostId}: ${r.residual} (source: ${r.source} \u2014 not observed here)`
28012
+ };
28013
+ }
28014
+ if (isRecorded(hostId)) {
28015
+ return {
28016
+ hostId,
28017
+ state: "cleared",
28018
+ text: `${hostId}: nothing left to do (source: observed)`
28019
+ };
28020
+ }
28021
+ return {
28022
+ hostId,
28023
+ state: "unrecorded",
28024
+ text: `${hostId}: no residual recorded \u2014 nobody checked this host, which is not the same as nothing to do`
28025
+ };
28026
+ }
28027
+ function residualReport(toolIds) {
28028
+ const seen = /* @__PURE__ */ new Set();
28029
+ const out = [];
28030
+ for (const toolId of toolIds) {
28031
+ const hostId = TOOL_TO_HOST[toolId];
28032
+ if (hostId === void 0 || seen.has(hostId)) continue;
28033
+ seen.add(hostId);
28034
+ const line = residualLine(hostId);
28035
+ if (line.state !== "cleared") out.push(line);
28036
+ }
28037
+ return out;
28038
+ }
28039
+ var SEEDED, TOOL_TO_HOST;
28040
+ var init_mcp_consent_residual = __esm({
28041
+ "src/scripts/_lib/mcp_consent_residual.ts"() {
28042
+ "use strict";
28043
+ init_host_capability();
28044
+ SEEDED = {
28045
+ claude: {
28046
+ hostId: "claude",
28047
+ residual: "Approve the project-scoped `agent-config` server the first time the host prompts \u2014 the installer writes `.mcp.json` but does not pre-approve it.",
28048
+ source: "vendor-doc",
28049
+ cite: "Host documentation: a project-scope MCP server requires explicit approval, suppressible only through the user-global `enabledMcpjsonServers` key, which this package deliberately does not write (blocker `mcp-user-scope-approval-consent`)."
28050
+ }
28051
+ };
28052
+ TOOL_TO_HOST = {
28053
+ "claude-code": "claude",
28054
+ cursor: "cursor",
28055
+ "gemini-cli": "gemini",
28056
+ windsurf: "windsurf",
28057
+ cline: "cline",
28058
+ copilot: "copilot",
28059
+ augment: "augment"
28060
+ };
28061
+ }
28062
+ });
28063
+
27743
28064
  // src/scripts/_lib/install_reach_checks.ts
27744
28065
  import * as fs52 from "node:fs";
27745
28066
  import * as path53 from "node:path";
@@ -27928,17 +28249,33 @@ function checkOverrideSet(projectRoot) {
27928
28249
  remedy: "route it through the upstream-contribution path, never by changing a shipped default on one install"
27929
28250
  };
27930
28251
  }
28252
+ function checkMcpConsentResidual() {
28253
+ const id = "mcp-consent-residual";
28254
+ const lines = residualReport(Object.keys(TOOL_TO_HOST));
28255
+ if (lines.length === 0) {
28256
+ return { id, status: "ok", message: "no MCP consent residual recorded for any known host", remedy: "" };
28257
+ }
28258
+ const actionable = lines.filter((l) => l.state === "residual");
28259
+ return {
28260
+ id,
28261
+ status: "warn",
28262
+ message: lines.map((l) => l.text).join(" \xB7 "),
28263
+ remedy: actionable.length > 0 ? "complete the step named above on each host you use" : "record an observation for the unchecked hosts, or ignore if you do not use them"
28264
+ };
28265
+ }
27931
28266
  function reachRunners(opts) {
27932
28267
  return {
27933
28268
  "instruction-path-reach": () => checkInstructionPaths(opts.projectRoot),
27934
28269
  "version-axis": () => checkVersionAxis(opts.projectRoot, opts.resolvableVersion),
27935
- "override-set": () => checkOverrideSet(opts.projectRoot)
28270
+ "override-set": () => checkOverrideSet(opts.projectRoot),
28271
+ "mcp-consent-residual": () => checkMcpConsentResidual()
27936
28272
  };
27937
28273
  }
27938
28274
  var ROOT_INSTRUCTION_FILES, UNRESOLVABLE_REASONS, BACKTICKED, LINK_TARGET, EXTENSION, SETTINGS_PIN_FILES, PIN_RE, LOCK_VERSION_RE, OVERRIDE_LAYERS, KIND_DIRS, REACH_CHECK_IDS;
27939
28275
  var init_install_reach_checks = __esm({
27940
28276
  "src/scripts/_lib/install_reach_checks.ts"() {
27941
28277
  "use strict";
28278
+ init_mcp_consent_residual();
27942
28279
  ROOT_INSTRUCTION_FILES = [
27943
28280
  "AGENTS.md",
27944
28281
  "CLAUDE.md",
@@ -27981,7 +28318,7 @@ var init_install_reach_checks = __esm({
27981
28318
  { dir: "skills", kind: "skill" },
27982
28319
  { dir: "commands", kind: "command" }
27983
28320
  ];
27984
- REACH_CHECK_IDS = ["instruction-path-reach", "version-axis", "override-set"];
28321
+ REACH_CHECK_IDS = ["instruction-path-reach", "version-axis", "override-set", "mcp-consent-residual"];
27985
28322
  }
27986
28323
  });
27987
28324
 
@@ -28186,6 +28523,94 @@ var init_cli_agency_bounds = __esm({
28186
28523
  }
28187
28524
  });
28188
28525
 
28526
+ // src/scripts/ai_council/api_transport.ts
28527
+ import { spawnSync as spawnSync9 } from "node:child_process";
28528
+ function curlJsonPost(url, extraHeaders, body) {
28529
+ const args = ["-sS", "-X", "POST", url, "-H", "content-type: application/json"];
28530
+ for (const h of extraHeaders) {
28531
+ args.push("-H", h);
28532
+ }
28533
+ args.push("--connect-timeout", "30", "--max-time", "290");
28534
+ args.push("-w", "\n%{http_code}", "--data-binary", "@-");
28535
+ const r = spawnSync9("curl", args, {
28536
+ input: JSON.stringify(body),
28537
+ encoding: "utf8",
28538
+ maxBuffer: 64 * 1024 * 1024,
28539
+ timeout: 3e5
28540
+ });
28541
+ if (r.error) {
28542
+ throw new Error(`curl spawn failed: ${r.error.message}`);
28543
+ }
28544
+ if (r.status !== 0) {
28545
+ throw new Error(
28546
+ `curl exited ${r.status ?? "null"}: ${(r.stderr ?? "").toString().slice(0, 500)}`
28547
+ );
28548
+ }
28549
+ const out = (r.stdout ?? "").toString();
28550
+ const nl = out.lastIndexOf("\n");
28551
+ const httpCode = (nl >= 0 ? out.slice(nl + 1) : out).trim();
28552
+ const bodyText = nl >= 0 ? out.slice(0, nl) : out;
28553
+ if (!/^2\d\d$/.test(httpCode)) {
28554
+ throw new Error(`HTTP ${httpCode}: ${bodyText.slice(0, 500)}`);
28555
+ }
28556
+ return JSON.parse(bodyText);
28557
+ }
28558
+ function openAiCompatibleClient(baseUrl, apiKey, post = curlJsonPost) {
28559
+ const url = `${baseUrl.replace(/\/+$/, "")}/chat/completions`;
28560
+ return {
28561
+ chat: {
28562
+ completions: {
28563
+ create: (kwargs) => post(url, [`authorization: Bearer ${apiKey}`], kwargs)
28564
+ }
28565
+ }
28566
+ };
28567
+ }
28568
+ function geminiRestClient(apiKey, post = curlJsonPost, baseUrl = GEMINI_BASE_URL) {
28569
+ return {
28570
+ models: {
28571
+ generate_content: (kwargs) => {
28572
+ const model = String(kwargs["model"] ?? "");
28573
+ const cfg = kwargs["config"] ?? {};
28574
+ const url = `${baseUrl.replace(/\/+$/, "")}/models/${model}:generateContent`;
28575
+ const raw = post(
28576
+ url,
28577
+ [`x-goog-api-key: ${apiKey}`],
28578
+ {
28579
+ contents: [{ role: "user", parts: [{ text: String(kwargs["contents"] ?? "") }] }],
28580
+ generationConfig: { maxOutputTokens: cfg["max_output_tokens"] ?? null }
28581
+ }
28582
+ );
28583
+ return normaliseGeminiRest(raw);
28584
+ }
28585
+ }
28586
+ };
28587
+ }
28588
+ function normaliseGeminiRest(raw) {
28589
+ const env = raw ?? {};
28590
+ const candidates = Array.isArray(env["candidates"]) ? env["candidates"] : [];
28591
+ const first = candidates[0] ?? {};
28592
+ const content = first["content"] ?? {};
28593
+ const parts = Array.isArray(content["parts"]) ? content["parts"] : [];
28594
+ const text = parts.map((p) => String((p ?? {})["text"] ?? "")).join("");
28595
+ const usage = env["usageMetadata"] ?? {};
28596
+ const num = (v) => typeof v === "number" && Number.isFinite(v) ? v : 0;
28597
+ return {
28598
+ text,
28599
+ model_version: String(env["modelVersion"] ?? ""),
28600
+ usage_metadata: {
28601
+ prompt_token_count: num(usage["promptTokenCount"]),
28602
+ candidates_token_count: num(usage["candidatesTokenCount"])
28603
+ }
28604
+ };
28605
+ }
28606
+ var GEMINI_BASE_URL;
28607
+ var init_api_transport = __esm({
28608
+ "src/scripts/ai_council/api_transport.ts"() {
28609
+ "use strict";
28610
+ GEMINI_BASE_URL = "https://generativelanguage.googleapis.com/v1beta";
28611
+ }
28612
+ });
28613
+
28189
28614
  // src/scripts/_lib/session_role.ts
28190
28615
  function resolveSessionRole(env = process.env) {
28191
28616
  const raw = (env[SESSION_ROLE_ENV] ?? "").trim().toLowerCase();
@@ -28894,7 +29319,7 @@ __export(clients_exports, {
28894
29319
  record_cli_call: () => record_cli_call,
28895
29320
  reset_cli_call_counts: () => reset_cli_call_counts
28896
29321
  });
28897
- import { spawnSync as spawnSync9 } from "node:child_process";
29322
+ import { spawnSync as spawnSync10 } from "node:child_process";
28898
29323
  import * as fs56 from "node:fs";
28899
29324
  import * as os10 from "node:os";
28900
29325
  import * as path57 from "node:path";
@@ -29002,34 +29427,6 @@ function _getattr(obj, name, fallback) {
29002
29427
  }
29003
29428
  return fallback;
29004
29429
  }
29005
- function _curlJsonPost(url, extraHeaders, body) {
29006
- const args = ["-sS", "-X", "POST", url, "-H", "content-type: application/json"];
29007
- for (const h of extraHeaders) {
29008
- args.push("-H", h);
29009
- }
29010
- args.push("--connect-timeout", "30", "--max-time", "290");
29011
- args.push("-w", "\n%{http_code}", "--data-binary", "@-");
29012
- const r = spawnSync9("curl", args, {
29013
- input: JSON.stringify(body),
29014
- encoding: "utf8",
29015
- maxBuffer: 64 * 1024 * 1024,
29016
- timeout: 3e5
29017
- });
29018
- if (r.error) {
29019
- throw new Error(`curl spawn failed: ${r.error.message}`);
29020
- }
29021
- if (r.status !== 0) {
29022
- throw new Error(`curl exited ${r.status ?? "null"}: ${(r.stderr ?? "").toString().slice(0, 500)}`);
29023
- }
29024
- const out = (r.stdout ?? "").toString();
29025
- const nl = out.lastIndexOf("\n");
29026
- const httpCode = (nl >= 0 ? out.slice(nl + 1) : out).trim();
29027
- const bodyText = nl >= 0 ? out.slice(0, nl) : out;
29028
- if (!/^2\d\d$/.test(httpCode)) {
29029
- throw new Error(`HTTP ${httpCode}: ${bodyText.slice(0, 500)}`);
29030
- }
29031
- return JSON.parse(bodyText);
29032
- }
29033
29430
  function _cliCallsStatePath() {
29034
29431
  return write_target(CLI_CALLS_FILENAME);
29035
29432
  }
@@ -29391,6 +29788,7 @@ var init_clients = __esm({
29391
29788
  "use strict";
29392
29789
  init_spawn_env();
29393
29790
  init_cli_agency_bounds();
29791
+ init_api_transport();
29394
29792
  init_session_role();
29395
29793
  init_agent_settings();
29396
29794
  init_user_global_paths();
@@ -29530,7 +29928,7 @@ var init_clients = __esm({
29530
29928
  }
29531
29929
  this._client = {
29532
29930
  messages: {
29533
- create: (kwargs) => _curlJsonPost(
29931
+ create: (kwargs) => curlJsonPost(
29534
29932
  "https://api.anthropic.com/v1/messages",
29535
29933
  [`x-api-key: ${api_key}`, "anthropic-version: 2023-06-01"],
29536
29934
  kwargs
@@ -29654,7 +30052,7 @@ var init_clients = __esm({
29654
30052
  this._client = {
29655
30053
  chat: {
29656
30054
  completions: {
29657
- create: (kwargs) => _curlJsonPost(
30055
+ create: (kwargs) => curlJsonPost(
29658
30056
  "https://api.openai.com/v1/chat/completions",
29659
30057
  [`authorization: Bearer ${api_key}`],
29660
30058
  kwargs
@@ -29737,7 +30135,7 @@ ${user_prompt}` }
29737
30135
  "GeminiClient requires explicit api_key or injected client. Use `api_key_ref: env:GEMINI_API_KEY` in ~/.event4u/agent-config/settings/.ai-council.yml."
29738
30136
  );
29739
30137
  }
29740
- throw new Error("google-genai package not installed. `pip install google-genai`.");
30138
+ this._client = geminiRestClient(api_key, opts.transport ?? curlJsonPost);
29741
30139
  }
29742
30140
  ask(system_prompt, user_prompt, max_tokens = DEFAULT_MAX_TOKENS) {
29743
30141
  const t0 = _nowMs();
@@ -29799,7 +30197,11 @@ ${user_prompt}`;
29799
30197
  `${this.constructor.name} requires explicit api_key or injected client.`
29800
30198
  );
29801
30199
  }
29802
- throw new Error("openai package not installed. `pip install openai`.");
30200
+ this._client = openAiCompatibleClient(
30201
+ opts.base_url,
30202
+ api_key,
30203
+ opts.transport ?? curlJsonPost
30204
+ );
29803
30205
  }
29804
30206
  ask(system_prompt, user_prompt, max_tokens = DEFAULT_MAX_TOKENS) {
29805
30207
  const t0 = _nowMs();
@@ -29852,7 +30254,13 @@ ${user_prompt}`;
29852
30254
  name = "xai";
29853
30255
  base_url = XAI_BASE_URL;
29854
30256
  constructor(opts = {}) {
29855
- super({ model: opts.model ?? DEFAULT_XAI_MODEL, client: opts.client, api_key: opts.api_key });
30257
+ super({
30258
+ model: opts.model ?? DEFAULT_XAI_MODEL,
30259
+ client: opts.client,
30260
+ api_key: opts.api_key,
30261
+ transport: opts.transport,
30262
+ base_url: XAI_BASE_URL
30263
+ });
29856
30264
  }
29857
30265
  };
29858
30266
  PerplexityClient = class extends _OpenAICompatibleClient {
@@ -29862,7 +30270,9 @@ ${user_prompt}`;
29862
30270
  super({
29863
30271
  model: opts.model ?? DEFAULT_PERPLEXITY_MODEL,
29864
30272
  client: opts.client,
29865
- api_key: opts.api_key
30273
+ api_key: opts.api_key,
30274
+ transport: opts.transport,
30275
+ base_url: PERPLEXITY_BASE_URL
29866
30276
  });
29867
30277
  }
29868
30278
  };
@@ -30046,7 +30456,7 @@ ${user_prompt}`;
30046
30456
  if (stdinPayload !== null) {
30047
30457
  spawnOpts.input = stdinPayload;
30048
30458
  }
30049
- const r = spawnSync9(argv0, cmd.slice(1), spawnOpts);
30459
+ const r = spawnSync10(argv0, cmd.slice(1), spawnOpts);
30050
30460
  if (r.error) {
30051
30461
  const err = r.error;
30052
30462
  if (r.signal === "SIGTERM" || err.code === "ETIMEDOUT") {
@@ -30836,6 +31246,102 @@ Type your follow-up question, end with a line containing only: ${this._end_marke
30836
31246
  }
30837
31247
  });
30838
31248
 
31249
+ // src/scripts/ai_council/content_ceiling.ts
31250
+ function classifyContentClass(raw, fallback = DEFAULT_CONTENT_CLASS) {
31251
+ if (typeof raw === "string" && _SET.has(raw)) {
31252
+ return raw;
31253
+ }
31254
+ return fallback;
31255
+ }
31256
+ function admitsContent(seatCeiling, contentClass) {
31257
+ if (seatCeiling === "public-artifact" && contentClass === "project-content") {
31258
+ return {
31259
+ admitted: false,
31260
+ reason: "seat ceiling is 'public-artifact'; the payload is classified 'project-content' (consumer-supplied)"
31261
+ };
31262
+ }
31263
+ return { admitted: true, reason: null };
31264
+ }
31265
+ var CONTENT_CLASSES, DEFAULT_CONTENT_CLASS, DEFAULT_SEAT_CEILING, _SET;
31266
+ var init_content_ceiling = __esm({
31267
+ "src/scripts/ai_council/content_ceiling.ts"() {
31268
+ "use strict";
31269
+ CONTENT_CLASSES = ["public-artifact", "project-content"];
31270
+ DEFAULT_CONTENT_CLASS = "project-content";
31271
+ DEFAULT_SEAT_CEILING = "project-content";
31272
+ _SET = new Set(CONTENT_CLASSES);
31273
+ }
31274
+ });
31275
+
31276
+ // src/scripts/ai_council/seat_policy.ts
31277
+ function isPolicyExclusion(v) {
31278
+ return typeof v === "string" && _SET2.has(v);
31279
+ }
31280
+ function classifyPolicyExclusion(raw) {
31281
+ if (raw === void 0 || raw === null) {
31282
+ return null;
31283
+ }
31284
+ return isPolicyExclusion(raw) ? raw : "policy_unknown";
31285
+ }
31286
+ function policyExclusionReason(p, provider) {
31287
+ const who = provider === void 0 ? "this seat" : provider;
31288
+ switch (p) {
31289
+ case "policy_terms":
31290
+ return `${who} is excluded by policy: the route's terms forbid this use`;
31291
+ case "policy_privacy":
31292
+ return `${who} is excluded by policy: a privacy constraint forbids this route`;
31293
+ case "policy_unproven_cost":
31294
+ return `${who} is excluded by policy: the route's cost property is asserted, not proven`;
31295
+ case "policy_model_mismatch":
31296
+ return `${who} is excluded by policy: the route serves a model other than the one requested`;
31297
+ case "policy_content_ceiling":
31298
+ return `${who} is excluded by policy: the payload exceeds the seat's content ceiling`;
31299
+ case "policy_unknown":
31300
+ return `${who} is excluded by policy: an exclusion this build does not understand (failing closed)`;
31301
+ }
31302
+ }
31303
+ function parseSeatFields(name, raw) {
31304
+ const dr = raw["disabled_reason"];
31305
+ let disabled_reason = null;
31306
+ if (dr !== void 0 && dr !== null) {
31307
+ if (typeof dr !== "string" || dr.trim() === "") {
31308
+ return {
31309
+ error: `members.${name}.disabled_reason must be a non-empty string when set (got ${JSON.stringify(dr)}).`
31310
+ };
31311
+ }
31312
+ disabled_reason = dr.trim();
31313
+ }
31314
+ return {
31315
+ fields: {
31316
+ disabled_reason,
31317
+ policy_exclusion: classifyPolicyExclusion(raw["policy_exclusion"]),
31318
+ content_ceiling: classifyContentClass(raw["content_ceiling"], DEFAULT_SEAT_CEILING)
31319
+ }
31320
+ };
31321
+ }
31322
+ var POLICY_EXCLUSIONS, _SET2;
31323
+ var init_seat_policy = __esm({
31324
+ "src/scripts/ai_council/seat_policy.ts"() {
31325
+ "use strict";
31326
+ init_content_ceiling();
31327
+ POLICY_EXCLUSIONS = [
31328
+ /** The provider's terms forbid this use of the route. */
31329
+ "policy_terms",
31330
+ /** A privacy constraint forbids sending to this route. */
31331
+ "policy_privacy",
31332
+ /** The route's cost property is asserted rather than proven. */
31333
+ "policy_unproven_cost",
31334
+ /** The route serves a model other than the one requested. */
31335
+ "policy_model_mismatch",
31336
+ /** 2.2 — the payload's content class exceeds the seat's ceiling. */
31337
+ "policy_content_ceiling",
31338
+ /** The config named an exclusion this build does not understand. */
31339
+ "policy_unknown"
31340
+ ];
31341
+ _SET2 = new Set(POLICY_EXCLUSIONS);
31342
+ }
31343
+ });
31344
+
30839
31345
  // src/scripts/ai_council/fallback_config.ts
30840
31346
  function buildFallback(raw, d) {
30841
31347
  if (!d.isDict(raw)) return { api_on_quota: false };
@@ -31987,6 +32493,10 @@ function _build_member(name, cfg, default_mode = "auto", ignored = []) {
31987
32493
  }
31988
32494
  verified_at = coerced;
31989
32495
  }
32496
+ const seat = parseSeatFields(name, cfg);
32497
+ if ("error" in seat) {
32498
+ throw new CouncilConfigError(seat.error);
32499
+ }
31990
32500
  const prompt_cache_raw = _get(cfg, "prompt_cache", null);
31991
32501
  let prompt_cache_ttl = "5m";
31992
32502
  if (prompt_cache_raw !== null && prompt_cache_raw !== void 0 && !_isBool(prompt_cache_raw)) {
@@ -32014,7 +32524,8 @@ function _build_member(name, cfg, default_mode = "auto", ignored = []) {
32014
32524
  participate_low_impact: participate_raw,
32015
32525
  tier,
32016
32526
  prompt_cache_ttl,
32017
- verified_at
32527
+ verified_at,
32528
+ ...seat.fields
32018
32529
  };
32019
32530
  }
32020
32531
  function resolve_cli_call_caps(raw) {
@@ -32206,6 +32717,7 @@ var init_config = __esm({
32206
32717
  init_user_global_paths();
32207
32718
  init_cli_call_budget();
32208
32719
  init_clients();
32720
+ init_seat_policy();
32209
32721
  init_quorum();
32210
32722
  init_fallback_config();
32211
32723
  init_py_format();
@@ -32390,7 +32902,7 @@ var init_agentSwitchDetection = __esm({
32390
32902
  });
32391
32903
 
32392
32904
  // src/scripts/_lib/environment_detector.ts
32393
- import { spawnSync as spawnSync10 } from "node:child_process";
32905
+ import { spawnSync as spawnSync11 } from "node:child_process";
32394
32906
  import * as fs58 from "node:fs";
32395
32907
  import * as os12 from "node:os";
32396
32908
  import * as path59 from "node:path";
@@ -32418,7 +32930,7 @@ function homeOf(env) {
32418
32930
  function defaultProbeKeychain(service) {
32419
32931
  if (process.platform !== "darwin") return false;
32420
32932
  try {
32421
- const res = spawnSync10("security", ["find-generic-password", "-s", service], {
32933
+ const res = spawnSync11("security", ["find-generic-password", "-s", service], {
32422
32934
  timeout: VERSION_PROBE_TIMEOUT_MS,
32423
32935
  encoding: "utf-8",
32424
32936
  windowsHide: true,
@@ -32432,7 +32944,7 @@ function defaultProbeKeychain(service) {
32432
32944
  }
32433
32945
  function defaultProbeVersion(binary) {
32434
32946
  try {
32435
- const res = spawnSync10(binary, ["--version"], {
32947
+ const res = spawnSync11(binary, ["--version"], {
32436
32948
  timeout: VERSION_PROBE_TIMEOUT_MS,
32437
32949
  encoding: "utf-8",
32438
32950
  windowsHide: true,
@@ -32744,6 +33256,22 @@ function resolveTransport(opts) {
32744
33256
  const auth = strongestAuth(report2, provider);
32745
33257
  const authSource = auth?.source ?? null;
32746
33258
  const billing = classifyBilling(provider, authSource);
33259
+ const exclusion = opts.policyExclusion ?? null;
33260
+ if (exclusion !== null) {
33261
+ return unavailable(provider, billing, policyExclusionReason(exclusion, provider), exclusion);
33262
+ }
33263
+ const contentClass = opts.contentClass ?? null;
33264
+ if (contentClass !== null) {
33265
+ const verdict = admitsContent(opts.seatCeiling ?? DEFAULT_SEAT_CEILING, contentClass);
33266
+ if (!verdict.admitted) {
33267
+ return unavailable(
33268
+ provider,
33269
+ billing,
33270
+ `${provider}: ${verdict.reason ?? "content ceiling refused the payload"}`,
33271
+ "policy_content_ceiling"
33272
+ );
33273
+ }
33274
+ }
32747
33275
  if (mode === "manual") {
32748
33276
  return {
32749
33277
  available: true,
@@ -32822,7 +33350,10 @@ function resolveMemberTransport(opts) {
32822
33350
  // `exactOptionalPropertyTypes` rejects an explicit `undefined` for an
32823
33351
  // optional-boolean field, so the key is omitted entirely rather than
32824
33352
  // forwarded as `apiKeyPresent: undefined`.
32825
- ...opts.apiKeyPresent !== void 0 ? { apiKeyPresent: opts.apiKeyPresent } : {}
33353
+ ...opts.apiKeyPresent !== void 0 ? { apiKeyPresent: opts.apiKeyPresent } : {},
33354
+ policyExclusion: opts.policyExclusion ?? null,
33355
+ seatCeiling: opts.seatCeiling ?? null,
33356
+ contentClass: opts.contentClass ?? null
32826
33357
  });
32827
33358
  return { ...resolved, configuredMode };
32828
33359
  }
@@ -32920,6 +33451,8 @@ var init_transport_resolver = __esm({
32920
33451
  "use strict";
32921
33452
  init_environment_detector();
32922
33453
  init_modes();
33454
+ init_content_ceiling();
33455
+ init_seat_policy();
32923
33456
  VALID_TRANSPORT_MODES = /* @__PURE__ */ new Set([
32924
33457
  "api",
32925
33458
  "manual",
@@ -33220,7 +33753,7 @@ var init_detection_report = __esm({
33220
33753
  });
33221
33754
 
33222
33755
  // src/scripts/hooks/state_io.ts
33223
- import { createHash as createHash6 } from "node:crypto";
33756
+ import { createHash as createHash7 } from "node:crypto";
33224
33757
  import fs59 from "node:fs";
33225
33758
  import path61 from "node:path";
33226
33759
  function is_replay_mode() {
@@ -33418,7 +33951,7 @@ function has_stable_session_id(session_id) {
33418
33951
  return typeof session_id === "string" && session_id.trim() !== "";
33419
33952
  }
33420
33953
  function session_state_file(dir, session_id) {
33421
- const digest = createHash6("sha256").update(session_id, "utf8").digest("hex").slice(0, 32);
33954
+ const digest = createHash7("sha256").update(session_id, "utf8").digest("hex").slice(0, 32);
33422
33955
  return path61.join(dir, `${digest}.json`);
33423
33956
  }
33424
33957
  function restore_claimed_state(tomb, live, link = fs59.linkSync) {
@@ -34093,7 +34626,7 @@ import * as crypto6 from "node:crypto";
34093
34626
  import * as fs64 from "node:fs";
34094
34627
  import * as os14 from "node:os";
34095
34628
  import * as path65 from "node:path";
34096
- import process17 from "node:process";
34629
+ import process18 from "node:process";
34097
34630
  import { fileURLToPath as fileURLToPath31, pathToFileURL as pathToFileURL21 } from "node:url";
34098
34631
  function expanduser5(p) {
34099
34632
  if (p === "~") return os14.homedir();
@@ -34230,10 +34763,10 @@ function yamlSafeLoad2(text) {
34230
34763
  }
34231
34764
  }
34232
34765
  function print2(line = "") {
34233
- process17.stdout.write(line + "\n");
34766
+ process18.stdout.write(line + "\n");
34234
34767
  }
34235
34768
  function eprint2(line = "") {
34236
- process17.stderr.write(line + "\n");
34769
+ process18.stderr.write(line + "\n");
34237
34770
  }
34238
34771
  function _resolve_project_root(arg) {
34239
34772
  return resolve_project_root(arg);
@@ -34284,7 +34817,7 @@ function _detect_wrapper(project_root) {
34284
34817
  };
34285
34818
  }
34286
34819
  function _emit_trace_text(root, anchor, trace, origin) {
34287
- print2(` \u{1F4CD} start: ${process17.cwd()}`);
34820
+ print2(` \u{1F4CD} start: ${process18.cwd()}`);
34288
34821
  print2(` \u{1F4CD} origin: ${origin}`);
34289
34822
  if (trace.length > 0) {
34290
34823
  print2(" trace:");
@@ -34304,7 +34837,7 @@ function _emit_trace_text(root, anchor, trace, origin) {
34304
34837
  }
34305
34838
  function _emit_trace_json(root, anchor, trace, origin) {
34306
34839
  const payload = {
34307
- start: process17.cwd(),
34840
+ start: process18.cwd(),
34308
34841
  origin,
34309
34842
  resolved_root: root !== null ? String(root) : null,
34310
34843
  anchor,
@@ -34744,10 +35277,10 @@ function shutilWhich(name) {
34744
35277
  if (path65.dirname(name) !== "." && (name.includes("/") || name.includes("\\"))) {
34745
35278
  return isExecutableFile(name) ? name : null;
34746
35279
  }
34747
- const pathEnv = process17.env["PATH"] || "";
34748
- const sep16 = process17.platform === "win32" ? ";" : ":";
35280
+ const pathEnv = process18.env["PATH"] || "";
35281
+ const sep16 = process18.platform === "win32" ? ";" : ":";
34749
35282
  const dirs = pathEnv.split(sep16);
34750
- const exts = process17.platform === "win32" ? (process17.env["PATHEXT"] || ".COM;.EXE;.BAT;.CMD").split(";") : [""];
35283
+ const exts = process18.platform === "win32" ? (process18.env["PATHEXT"] || ".COM;.EXE;.BAT;.CMD").split(";") : [""];
34751
35284
  const seenDirs = /* @__PURE__ */ new Set();
34752
35285
  for (const dir of dirs) {
34753
35286
  const d = dir === "" ? "." : dir;
@@ -34770,7 +35303,7 @@ function isExecutableFile(p) {
34770
35303
  try {
34771
35304
  const st = fs64.statSync(p);
34772
35305
  if (!st.isFile()) return false;
34773
- if (process17.platform === "win32") return true;
35306
+ if (process18.platform === "win32") return true;
34774
35307
  fs64.accessSync(p, fs64.constants.X_OK);
34775
35308
  return true;
34776
35309
  } catch {
@@ -36236,8 +36769,8 @@ function _emit_detection_text(project_root, checks) {
36236
36769
  print2("");
36237
36770
  }
36238
36771
  function _argError9(msg) {
36239
- process17.stderr.write(USAGE2);
36240
- process17.stderr.write(`${PROG4}: error: ${msg}
36772
+ process18.stderr.write(USAGE2);
36773
+ process18.stderr.write(`${PROG4}: error: ${msg}
36241
36774
  `);
36242
36775
  throw new ArgparseExit4(2);
36243
36776
  }
@@ -36258,7 +36791,7 @@ function _parse3(argv) {
36258
36791
  while (i < argv.length) {
36259
36792
  const a = argv[i];
36260
36793
  if (a === "-h" || a === "--help") {
36261
- process17.stdout.write(USAGE2);
36794
+ process18.stdout.write(USAGE2);
36262
36795
  throw new ArgparseExit4(0);
36263
36796
  }
36264
36797
  const eq = a.startsWith("--") ? a.indexOf("=") : -1;
@@ -36316,14 +36849,14 @@ function argMetaName(flag) {
36316
36849
  return flag;
36317
36850
  }
36318
36851
  function _run_trace_root(opts) {
36319
- const start = process17.cwd();
36852
+ const start = process18.cwd();
36320
36853
  const [root, anchor, trace] = find_project_root_with_trace(start);
36321
36854
  let origin;
36322
- if (process17.env[ROOT_OVERRIDE_ENV] === "1" && process17.env[PROJECT_ROOT_ENV]) {
36855
+ if (process18.env[ROOT_OVERRIDE_ENV] === "1" && process18.env[PROJECT_ROOT_ENV]) {
36323
36856
  origin = "root-flag";
36324
36857
  } else if (opts.project) {
36325
36858
  origin = "explicit";
36326
- } else if (process17.env[PROJECT_ROOT_ENV]) {
36859
+ } else if (process18.env[PROJECT_ROOT_ENV]) {
36327
36860
  origin = "env";
36328
36861
  } else if (root !== null) {
36329
36862
  origin = anchor || "unknown";
@@ -36355,8 +36888,8 @@ function _run_context(opts) {
36355
36888
  origin,
36356
36889
  install_mode: mode,
36357
36890
  install_mode_source: mode_source,
36358
- env_pin: process17.env[PROJECT_ROOT_ENV] || null,
36359
- root_override: process17.env[ROOT_OVERRIDE_ENV] === "1",
36891
+ env_pin: process18.env[PROJECT_ROOT_ENV] || null,
36892
+ root_override: process18.env[ROOT_OVERRIDE_ENV] === "1",
36360
36893
  settings_layers: _settings_layer_chain(project_root),
36361
36894
  wrapper: _detect_wrapper(project_root)
36362
36895
  };
@@ -36376,7 +36909,7 @@ function _run_anatomy(opts) {
36376
36909
  try {
36377
36910
  economyReport = economy.buildReport({
36378
36911
  root: economy.DEFAULT_PROJECTS_ROOT,
36379
- auditDir: path65.join(process17.cwd(), economy.DEFAULT_AUDIT_DIR),
36912
+ auditDir: path65.join(process18.cwd(), economy.DEFAULT_AUDIT_DIR),
36380
36913
  maxAgeDays: 14
36381
36914
  });
36382
36915
  } catch (err) {
@@ -36442,7 +36975,7 @@ function _run_repair(opts) {
36442
36975
  return 2;
36443
36976
  }
36444
36977
  function main21(argv = null) {
36445
- const opts = _parse3(argv !== null ? Array.from(argv) : process17.argv.slice(2));
36978
+ const opts = _parse3(argv !== null ? Array.from(argv) : process18.argv.slice(2));
36446
36979
  validateStrictLevelOr(opts.strict_level, _argError9);
36447
36980
  if (opts.ci) {
36448
36981
  opts.json = true;
@@ -36518,21 +37051,21 @@ function _isCliEntry17() {
36518
37051
  if (bundled && !cliDelegate) {
36519
37052
  return false;
36520
37053
  }
36521
- if (process17.argv[1] === void 0) {
37054
+ if (process18.argv[1] === void 0) {
36522
37055
  return false;
36523
37056
  }
36524
37057
  if (cliDelegate) {
36525
- if (path65.basename(process17.argv[1], ".js") === "cmd_doctor") {
37058
+ if (path65.basename(process18.argv[1], ".js") === "cmd_doctor") {
36526
37059
  return true;
36527
37060
  }
36528
37061
  }
36529
- const argvUrl = pathToFileURL21(path65.resolve(process17.argv[1])).href;
37062
+ const argvUrl = pathToFileURL21(path65.resolve(process18.argv[1])).href;
36530
37063
  if (import.meta.url === argvUrl) {
36531
37064
  return true;
36532
37065
  }
36533
37066
  try {
36534
37067
  const here = fs64.realpathSync(fileURLToPath31(import.meta.url));
36535
- const argv = fs64.realpathSync(path65.resolve(process17.argv[1]));
37068
+ const argv = fs64.realpathSync(path65.resolve(process18.argv[1]));
36536
37069
  return here === argv;
36537
37070
  } catch {
36538
37071
  return false;
@@ -36693,12 +37226,12 @@ var init_cmd_doctor = __esm({
36693
37226
  "--check": "check",
36694
37227
  "--repair": "repair"
36695
37228
  };
36696
- if (_isCliEntry17() || process17.argv[1] === _HERE18) {
37229
+ if (_isCliEntry17() || process18.argv[1] === _HERE18) {
36697
37230
  try {
36698
- process17.exitCode = main21(process17.argv.slice(2));
37231
+ process18.exitCode = main21(process18.argv.slice(2));
36699
37232
  } catch (e) {
36700
37233
  if (e instanceof ArgparseExit4) {
36701
- process17.exitCode = e.code;
37234
+ process18.exitCode = e.code;
36702
37235
  } else {
36703
37236
  throw e;
36704
37237
  }
@@ -38963,6 +39496,25 @@ var init_before_complete_hook = __esm({
38963
39496
  }
38964
39497
  });
38965
39498
 
39499
+ // src/scripts/_lib/audit_field_provenance.ts
39500
+ function appliedIds(values) {
39501
+ const out = [];
39502
+ for (const raw of values ?? []) {
39503
+ const v = String(raw).trim();
39504
+ if (v === "" || out.includes(v)) continue;
39505
+ out.push(v);
39506
+ if (out.length >= MAX_APPLIED_IDS) break;
39507
+ }
39508
+ return out;
39509
+ }
39510
+ var MAX_APPLIED_IDS;
39511
+ var init_audit_field_provenance = __esm({
39512
+ "src/scripts/_lib/audit_field_provenance.ts"() {
39513
+ "use strict";
39514
+ MAX_APPLIED_IDS = 32;
39515
+ }
39516
+ });
39517
+
38966
39518
  // src/scripts/_lib/review_skipped_record.ts
38967
39519
  function isNonNegInt(n) {
38968
39520
  return typeof n === "number" && Number.isFinite(n) && Number.isInteger(n) && n >= 0;
@@ -38989,7 +39541,8 @@ function buildReviewSkippedLine(input) {
38989
39541
  risk_class: input.diff_lines >= HIGH_RISK_DIFF_LINES ? "high" : "medium",
38990
39542
  memory: { asks: 0, hits: 0 },
38991
39543
  verify: { claims: 0, first_try_passes: 0 },
38992
- rules_applied: ["delegation-policy"],
39544
+ // COMPUTED, never a producer constant.
39545
+ rules_applied: appliedIds(input.rules_applied),
38993
39546
  // MANDATORY on every audit line, same as the orchestration producer.
38994
39547
  privacy_class: PRODUCER_PRIVACY_CLASS,
38995
39548
  // `skills_applied` is OMITTED here, deliberately and not by oversight.
@@ -39010,6 +39563,7 @@ var PRODUCER_PRIVACY_CLASS, HIGH_RISK_DIFF_LINES;
39010
39563
  var init_review_skipped_record = __esm({
39011
39564
  "src/scripts/_lib/review_skipped_record.ts"() {
39012
39565
  "use strict";
39566
+ init_audit_field_provenance();
39013
39567
  PRODUCER_PRIVACY_CLASS = "ids-only";
39014
39568
  HIGH_RISK_DIFF_LINES = 200;
39015
39569
  }
@@ -39076,7 +39630,7 @@ var init_envelope = __esm({
39076
39630
  });
39077
39631
 
39078
39632
  // src/scripts/hooks/end_review_nudge_hook.ts
39079
- import { spawnSync as spawnSync11 } from "node:child_process";
39633
+ import { spawnSync as spawnSync12 } from "node:child_process";
39080
39634
  import * as crypto7 from "node:crypto";
39081
39635
  import * as fs68 from "node:fs";
39082
39636
  import * as os15 from "node:os";
@@ -39122,7 +39676,7 @@ function nonDocMutatedLines(rows) {
39122
39676
  }
39123
39677
  function gitNumstatRows(cwd) {
39124
39678
  try {
39125
- const r = spawnSync11("git", ["diff", "--numstat", "HEAD"], {
39679
+ const r = spawnSync12("git", ["diff", "--numstat", "HEAD"], {
39126
39680
  cwd,
39127
39681
  encoding: "utf8",
39128
39682
  maxBuffer: 16 * 1024 * 1024
@@ -39135,7 +39689,7 @@ function gitNumstatRows(cwd) {
39135
39689
  }
39136
39690
  function untrackedNonDocFiles(cwd) {
39137
39691
  try {
39138
- const r = spawnSync11("git", ["ls-files", "--others", "--exclude-standard"], {
39692
+ const r = spawnSync12("git", ["ls-files", "--others", "--exclude-standard"], {
39139
39693
  cwd,
39140
39694
  encoding: "utf8",
39141
39695
  maxBuffer: 16 * 1024 * 1024
@@ -40674,61 +41228,6 @@ var init_evidence_independence = __esm({
40674
41228
  }
40675
41229
  });
40676
41230
 
40677
- // src/scripts/_lib/host_capability.ts
40678
- import process18 from "node:process";
40679
- function asBool(value) {
40680
- return value === true;
40681
- }
40682
- function normalizeHostManifest(input) {
40683
- if (input === null || typeof input !== "object") {
40684
- return { ...SAFE_DEFAULT };
40685
- }
40686
- const src = input;
40687
- return {
40688
- schema_version: 1,
40689
- subagent_spawn: asBool(src.subagent_spawn),
40690
- parallel_spawn: asBool(src.parallel_spawn),
40691
- status_polling: asBool(src.status_polling),
40692
- separate_quota_pool: asBool(src.separate_quota_pool),
40693
- agent_teams: asBool(src.agent_teams),
40694
- worker_respawn: asBool(src.worker_respawn)
40695
- };
40696
- }
40697
- function resolveHostCapabilities(hostId, override) {
40698
- if (override !== void 0 && override !== null && typeof override === "object" && !Array.isArray(override)) {
40699
- return normalizeHostManifest(override);
40700
- }
40701
- const row = hostId !== null && hostId !== void 0 ? HOST_CAPABILITY_REGISTRY[hostId] : void 0;
40702
- if (row === void 0) {
40703
- return { ...SAFE_DEFAULT };
40704
- }
40705
- return { ...SAFE_DEFAULT, ...row, schema_version: 1 };
40706
- }
40707
- function probeHostCapabilities(hostId) {
40708
- const base = resolveHostCapabilities(hostId);
40709
- const flag = process18.env.CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS;
40710
- const probedAgentTeams = typeof flag === "string" && flag !== "";
40711
- return { ...base, agent_teams: base.agent_teams || probedAgentTeams };
40712
- }
40713
- var SAFE_DEFAULT, HOST_CAPABILITY_REGISTRY;
40714
- var init_host_capability = __esm({
40715
- "src/scripts/_lib/host_capability.ts"() {
40716
- "use strict";
40717
- SAFE_DEFAULT = {
40718
- schema_version: 1,
40719
- subagent_spawn: false,
40720
- parallel_spawn: false,
40721
- status_polling: false,
40722
- separate_quota_pool: false,
40723
- agent_teams: false,
40724
- worker_respawn: false
40725
- };
40726
- HOST_CAPABILITY_REGISTRY = {
40727
- claude: { subagent_spawn: true, parallel_spawn: true }
40728
- };
40729
- }
40730
- });
40731
-
40732
41231
  // src/scripts/_lib/auto_dispatch.ts
40733
41232
  function inSession(reason) {
40734
41233
  return { delegable: false, action: "in-session", mode: null, reason };
@@ -41129,6 +41628,12 @@ function buildNudgeLine(rung, classification, sliceCount, tier) {
41129
41628
  if (rung === 0.5) {
41130
41629
  return `<delegation-nudge>rung-0.5: ask, est. <1k tokens. This is a single bounded question \u2014 answer it via ONE completion (\`./scripts-run src/scripts/ask_transport "<question>"\`) instead of a subagent spawn (measured spawn floor: ~251k tokens) \u2014 ${classification.reason}.</delegation-nudge>`;
41131
41630
  }
41631
+ if (rung === 4) {
41632
+ return `<delegation-nudge>rung-4: council. This is contested judgment, not a slice to dispatch \u2014 route it to the council yourself via \`./scripts-run src/scripts/council_cli run --input <file>\` (check reachability first with \`agent-config council:status\`; the file path is the input, never an inline question). Not a spawn, and not run for you \u2014 ${classification.reason}.</delegation-nudge>`;
41633
+ }
41634
+ if (rung === 3) {
41635
+ return `<delegation-nudge>rung-3: team. These slices must see each other's state during the run, so a set of independent subagent spawns cannot express it \u2014 use the host teams primitive, or fall back to \`./scripts-run src/scripts/ask_transport "<question>"\` for a bounded sub-question. Not a spawn, and not run for you \u2014 ${classification.reason}.</delegation-nudge>`;
41636
+ }
41132
41637
  const modeLabel = classification.mode ?? "single-slice";
41133
41638
  return `<delegation-nudge>${rungLabel}: dispatch ${modeLabel} (${sliceCount} ${unit}, ${tier} tier recommended). Consider dispatching via subagent-orchestration instead of doing every slice in-session \u2014 ${classification.reason}.</delegation-nudge>`;
41134
41639
  }
@@ -41147,6 +41652,14 @@ function classifyPrompt(prompt, workspace_root, hostId) {
41147
41652
  agentTeams,
41148
41653
  insideSubagentSession: sessionRole !== "orchestrator"
41149
41654
  });
41655
+ if (ladder.verdict === "team" || ladder.verdict === "council") {
41656
+ return {
41657
+ classification: { delegable: false, action: "ask", mode: null, reason: ladder.reason },
41658
+ sliceCount: 0,
41659
+ tier: recommendSliceTier(downshift, separate_quota_pool),
41660
+ rung: ladder.rung
41661
+ };
41662
+ }
41150
41663
  if (ladder.verdict !== "subagent") {
41151
41664
  return null;
41152
41665
  }
@@ -41265,7 +41778,7 @@ var init_delegation_nudge_hook = __esm({
41265
41778
  });
41266
41779
 
41267
41780
  // src/scripts/conformance_scan.ts
41268
- import { createHash as createHash12 } from "node:crypto";
41781
+ import { createHash as createHash13 } from "node:crypto";
41269
41782
  import fs73 from "node:fs";
41270
41783
  import os16 from "node:os";
41271
41784
  import path75 from "node:path";
@@ -41636,7 +42149,7 @@ function measureDelivered(projectRulesDir, globalRulesDir) {
41636
42149
  };
41637
42150
  }
41638
42151
  function storeKey(store) {
41639
- return createHash12("sha256").update(path75.resolve(store)).digest("hex").slice(0, 12);
42152
+ return createHash13("sha256").update(path75.resolve(store)).digest("hex").slice(0, 12);
41640
42153
  }
41641
42154
  function scanStore(store, limit) {
41642
42155
  const files = fs73.readdirSync(store).filter((f) => f.endsWith(".jsonl")).map((f) => ({ f, m: fs73.statSync(path75.join(store, f)).mtimeMs })).sort((a, b) => b.m - a.m).slice(0, limit).map((x) => x.f);
@@ -43115,7 +43628,7 @@ import * as fs78 from "node:fs";
43115
43628
  import * as os21 from "node:os";
43116
43629
  import * as path80 from "node:path";
43117
43630
  import process22 from "node:process";
43118
- import { spawnSync as spawnSync12 } from "node:child_process";
43631
+ import { spawnSync as spawnSync13 } from "node:child_process";
43119
43632
  import { fileURLToPath as fileURLToPath45, pathToFileURL as pathToFileURL35 } from "node:url";
43120
43633
  function print3(s = "") {
43121
43634
  process22.stdout.write(`${s}
@@ -43272,7 +43785,7 @@ function _check_hook_dispatcher(projectRoot, packageRoot = PACKAGE_ROOT2, opts =
43272
43785
  ...event === "stop" ? { stop_reason: "conformance-smoke" } : { source: "startup" }
43273
43786
  });
43274
43787
  const argv = [...runner, "--platform", platform, "--event", event];
43275
- const proc = spawnSync12(argv[0], argv.slice(1), {
43788
+ const proc = spawnSync13(argv[0], argv.slice(1), {
43276
43789
  input: payload,
43277
43790
  cwd: projectRoot,
43278
43791
  encoding: "utf8",
@@ -44565,6 +45078,75 @@ var init_aggregator = __esm({
44565
45078
  }
44566
45079
  });
44567
45080
 
45081
+ // src/agent-src/templates/scripts/telemetry/mcp_lite.ts
45082
+ function _sorted(m) {
45083
+ return [...m.entries()].sort((a, b) => b[1] - a[1] || (a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0));
45084
+ }
45085
+ function render_mcp_lite_markdown(agg) {
45086
+ const lines = [];
45087
+ lines.push("## MCP lite surface");
45088
+ lines.push("");
45089
+ lines.push(`- calls recorded: **${agg.calls}**`);
45090
+ if (agg.earliest_ts && agg.latest_ts) {
45091
+ lines.push(`- ts range: \`${agg.earliest_ts}\` \u2192 \`${agg.latest_ts}\``);
45092
+ }
45093
+ lines.push("");
45094
+ if (agg.calls === 0) {
45095
+ lines.push(ZERO_NOTE);
45096
+ lines.push("");
45097
+ return `${lines.join("\n")}`;
45098
+ }
45099
+ lines.push("| tool | calls |");
45100
+ lines.push("|---|---:|");
45101
+ for (const [tool, n] of _sorted(agg.by_tool)) {
45102
+ check_id_redaction("mcp_lite.by_tool.id", tool);
45103
+ lines.push(`| ${tool} | ${n} |`);
45104
+ }
45105
+ lines.push("");
45106
+ lines.push("| host | calls |");
45107
+ lines.push("|---|---:|");
45108
+ for (const [host, n] of _sorted(agg.by_host)) {
45109
+ check_id_redaction("mcp_lite.by_host.id", host);
45110
+ lines.push(`| ${host} | ${n} |`);
45111
+ }
45112
+ lines.push("");
45113
+ return `${lines.join("\n")}`;
45114
+ }
45115
+ function mcp_lite_json(agg) {
45116
+ const by_tool = {};
45117
+ for (const [tool, n] of _sorted(agg.by_tool)) {
45118
+ check_id_redaction("mcp_lite.by_tool.id", tool);
45119
+ by_tool[tool] = n;
45120
+ }
45121
+ const by_host = {};
45122
+ for (const [host, n] of _sorted(agg.by_host)) {
45123
+ check_id_redaction("mcp_lite.by_host.id", host);
45124
+ by_host[host] = n;
45125
+ }
45126
+ const by_outcome = {};
45127
+ for (const [outcome, n] of _sorted(agg.by_outcome)) {
45128
+ by_outcome[outcome] = n;
45129
+ }
45130
+ return {
45131
+ log_path: agg.log_path,
45132
+ calls: agg.calls,
45133
+ skipped_lines: agg.skipped_lines,
45134
+ by_tool,
45135
+ by_host,
45136
+ by_outcome,
45137
+ earliest_ts: agg.earliest_ts,
45138
+ latest_ts: agg.latest_ts
45139
+ };
45140
+ }
45141
+ var ZERO_NOTE;
45142
+ var init_mcp_lite = __esm({
45143
+ "src/agent-src/templates/scripts/telemetry/mcp_lite.ts"() {
45144
+ "use strict";
45145
+ init_engagement();
45146
+ ZERO_NOTE = "_No calls recorded. The lite-surface emitter is default-off (`telemetry.artifact_engagement.enabled`), so a zero here says the instrument was off or unused on this machine \u2014 it is not a measurement of what consumers do._";
45147
+ }
45148
+ });
45149
+
44568
45150
  // src/agent-src/templates/scripts/telemetry/report_renderer.ts
44569
45151
  var report_renderer_exports = {};
44570
45152
  __export(report_renderer_exports, {
@@ -44674,6 +45256,9 @@ function render_markdown(aggregate3, opts = {}) {
44674
45256
  }
44675
45257
  lines.push("");
44676
45258
  }
45259
+ if (opts.mcp_lite) {
45260
+ lines.push(render_mcp_lite_markdown(opts.mcp_lite));
45261
+ }
44677
45262
  return `${_pyRStrip(lines.join("\n"))}
44678
45263
  `;
44679
45264
  }
@@ -44717,7 +45302,8 @@ function render_json2(aggregate3, opts = {}) {
44717
45302
  since_label
44718
45303
  },
44719
45304
  outcomes: outcomes_payload,
44720
- buckets: grouped
45305
+ buckets: grouped,
45306
+ ...opts.mcp_lite ? { mcp_lite: mcp_lite_json(opts.mcp_lite) } : {}
44721
45307
  };
44722
45308
  return `${_py_json_dumps_indent2_sorted(payload)}
44723
45309
  `;
@@ -44912,6 +45498,7 @@ var init_report_renderer = __esm({
44912
45498
  "use strict";
44913
45499
  init_aggregator();
44914
45500
  init_engagement();
45501
+ init_mcp_lite();
44915
45502
  QUARTILE_TOP_RATIO = 0.2;
44916
45503
  QUARTILE_BOTTOM_RATIO = 0.2;
44917
45504
  BUCKET_TOP = "essential";
@@ -45516,9 +46103,9 @@ var init_consensus = __esm({
45516
46103
  });
45517
46104
 
45518
46105
  // src/scripts/ai_council/blind_review.ts
45519
- import { createHash as createHash13 } from "node:crypto";
46106
+ import { createHash as createHash14 } from "node:crypto";
45520
46107
  function _sha256_hex(s) {
45521
- return createHash13("sha256").update(s, "utf-8").digest("hex");
46108
+ return createHash14("sha256").update(s, "utf-8").digest("hex");
45522
46109
  }
45523
46110
  function deterministic_shuffle_indices(seed, n) {
45524
46111
  const keyed = Array.from({ length: n }, (_, i) => ({ i, key: _sha256_hex(`${seed}\0${i}`) }));
@@ -46704,6 +47291,39 @@ var init_solo_dispatch = __esm({
46704
47291
  }
46705
47292
  });
46706
47293
 
47294
+ // src/scripts/ai_council/status_surface.ts
47295
+ function resolvedTransportFor(name, member, report2, contentClass) {
47296
+ return resolveMemberTransport({
47297
+ provider: name,
47298
+ report: report2 ?? detectEnvironment(),
47299
+ invocationMode: null,
47300
+ memberSettings: null,
47301
+ globalMode: "auto",
47302
+ binaryOverride: member.binary,
47303
+ policyExclusion: member.policy_exclusion ?? null,
47304
+ seatCeiling: member.content_ceiling ?? DEFAULT_SEAT_CEILING,
47305
+ contentClass: contentClass ?? null
47306
+ });
47307
+ }
47308
+ function disabledSeats(cfg) {
47309
+ if (cfg === null) {
47310
+ return {};
47311
+ }
47312
+ return Object.fromEntries(
47313
+ [...cfg.members.entries()].filter(([, m]) => !m.enabled).map(([n, m]) => [n, m.disabled_reason ?? NO_DISABLED_REASON])
47314
+ );
47315
+ }
47316
+ var NO_DISABLED_REASON;
47317
+ var init_status_surface = __esm({
47318
+ "src/scripts/ai_council/status_surface.ts"() {
47319
+ "use strict";
47320
+ init_environment_detector();
47321
+ init_content_ceiling();
47322
+ init_transport_resolver();
47323
+ NO_DISABLED_REASON = "disabled, no reason recorded";
47324
+ }
47325
+ });
47326
+
46707
47327
  // src/scripts/ai_council/quorum_wiring.ts
46708
47328
  function _quorum_setting_from(ai) {
46709
47329
  const raw = ai["quorum"];
@@ -51531,7 +52151,7 @@ __export(shadow_dispatch_exports, {
51531
52151
  slo_status: () => slo_status
51532
52152
  });
51533
52153
  import * as fs90 from "node:fs";
51534
- import { createHash as createHash14 } from "node:crypto";
52154
+ import { createHash as createHash15 } from "node:crypto";
51535
52155
  function should_shadow(sampleRate, opts = {}) {
51536
52156
  const rate = Math.max(0, Math.min(1, sampleRate));
51537
52157
  const rng = opts.rng ?? null;
@@ -51540,7 +52160,7 @@ function should_shadow(sampleRate, opts = {}) {
51540
52160
  }
51541
52161
  function _hashQuery(query) {
51542
52162
  const redacted = redact(query);
51543
- return createHash14("sha256").update(Buffer.from(redacted, "utf-8")).digest("hex").slice(0, 16);
52163
+ return createHash15("sha256").update(Buffer.from(redacted, "utf-8")).digest("hex").slice(0, 16);
51544
52164
  }
51545
52165
  function _privacyDropped(redacted) {
51546
52166
  const stripped = _strip8(redacted);
@@ -53894,18 +54514,8 @@ function _emit_shadow_slo_banner() {
53894
54514
  return;
53895
54515
  }
53896
54516
  }
53897
- function _resolvedTransportFor(name, member, report2) {
53898
- return resolveMemberTransport({
53899
- provider: name,
53900
- report: report2 ?? detectEnvironment(),
53901
- invocationMode: null,
53902
- memberSettings: null,
53903
- globalMode: "auto",
53904
- binaryOverride: member.binary
53905
- });
53906
- }
53907
54517
  function _posture(name, member) {
53908
- const t = _resolvedTransportFor(name, member);
54518
+ const t = resolvedTransportFor(name, member);
53909
54519
  const keyless = {
53910
54520
  anthropic: () => Boolean(load_anthropic_key()),
53911
54521
  openai: () => Boolean(load_openai_key())
@@ -53937,7 +54547,7 @@ function cmd_status(args, opts = {}) {
53937
54547
  const configured = cfg !== null && cfg.enabled && enabledMembers.length > 0;
53938
54548
  const probeStore = readProbeStore(REPO_ROOT11);
53939
54549
  const qualifications = enabledMembers.map(
53940
- ([name, m]) => qualifySeat(name, _resolvedTransportFor(name, m), m.model, probeStore)
54550
+ ([name, m]) => qualifySeat(name, resolvedTransportFor(name, m), m.model, probeStore)
53941
54551
  );
53942
54552
  if (_getattr3(args, "json", false)) {
53943
54553
  _stdout2(
@@ -53952,14 +54562,17 @@ function cmd_status(args, opts = {}) {
53952
54562
  member_names: enabledMembers.map(([n]) => n),
53953
54563
  transports: Object.fromEntries(
53954
54564
  enabledMembers.map(([n, m]) => {
53955
- const t = _resolvedTransportFor(n, m);
54565
+ const t = resolvedTransportFor(n, m);
53956
54566
  return [
53957
54567
  n,
53958
54568
  {
53959
54569
  available: t.available,
53960
54570
  transport: t.available ? t.transport : null,
53961
54571
  billing: t.available ? t.billing : null,
53962
- reason: t.reason
54572
+ reason: t.reason,
54573
+ absent_reason: t.absentReason,
54574
+ policy_exclusion: m.policy_exclusion,
54575
+ content_ceiling: m.content_ceiling
53963
54576
  }
53964
54577
  ];
53965
54578
  })
@@ -53970,6 +54583,7 @@ function cmd_status(args, opts = {}) {
53970
54583
  enabledMembers.map(([n, m]) => [n, _posture(n, m)])
53971
54584
  )
53972
54585
  },
54586
+ disabled_seats: disabledSeats(cfg),
53973
54587
  ignored_transport_keys: cfg?.ignored_transport_keys ?? [],
53974
54588
  qualification: qualificationJson(qualifications),
53975
54589
  qualified_members: countableSeats(qualifications),
@@ -54006,10 +54620,20 @@ function cmd_status(args, opts = {}) {
54006
54620
  `);
54007
54621
  }
54008
54622
  for (const [name, member] of enabledMembers) {
54009
- const t = _resolvedTransportFor(name, member);
54623
+ const t = resolvedTransportFor(name, member);
54010
54624
  const billing = t.available ? ` \xB7 ${t.billing}` : "";
54011
54625
  const detail = t.available ? t.transport : `unavailable \u2014 ${t.reason ?? "no usable transport"}`;
54012
54626
  _stdout2(` transport ${name}: ${detail}${billing}
54627
+ `);
54628
+ if (!t.available && t.absentReason !== null && t.absentReason.startsWith("policy_")) {
54629
+ _stdout2(` policy ${name}: ${t.absentReason}
54630
+ `);
54631
+ }
54632
+ _stdout2(` content ceiling ${name}: ${member.content_ceiling}
54633
+ `);
54634
+ }
54635
+ for (const [name, reason] of Object.entries(disabledSeats(cfg))) {
54636
+ _stdout2(` disabled seat ${name}: ${reason}
54013
54637
  `);
54014
54638
  }
54015
54639
  for (const line of renderPostureLines(
@@ -55288,7 +55912,7 @@ var init_council_cli = __esm({
55288
55912
  init_solo_dispatch();
55289
55913
  init_modes();
55290
55914
  init_transport_resolver();
55291
- init_transport_resolver();
55915
+ init_status_surface();
55292
55916
  init_quorum();
55293
55917
  init_quorum_wiring();
55294
55918
  init_qualification();
@@ -56568,7 +57192,7 @@ import { fileURLToPath as fileURLToPath48 } from "node:url";
56568
57192
  init_memory_lookup();
56569
57193
  init_agent_settings();
56570
57194
  init_hook_stdin();
56571
- import { createHash as createHash3 } from "node:crypto";
57195
+ import { createHash as createHash4 } from "node:crypto";
56572
57196
  import * as fs14 from "node:fs";
56573
57197
  import * as path13 from "node:path";
56574
57198
  import { fileURLToPath as fileURLToPath9, pathToFileURL as pathToFileURL5 } from "node:url";
@@ -56788,7 +57412,7 @@ function _now() {
56788
57412
  }
56789
57413
  function fingerprint(value) {
56790
57414
  const normalized = _strip2((value || "").replace(_WS_RE, " "));
56791
- return createHash3("sha256").update(normalized, "utf-8").digest("hex");
57415
+ return createHash4("sha256").update(normalized, "utf-8").digest("hex");
56792
57416
  }
56793
57417
  function derive_session_tag(session_id) {
56794
57418
  if (!session_id) {
@@ -57021,7 +57645,7 @@ function _atomic_write_text(target, text) {
57021
57645
  return;
57022
57646
  }
57023
57647
  const suffix = path13.extname(target);
57024
- const uniq = `${process.pid}.${createHash3("sha256").update(`${process.pid}:${Date.now()}:${Math.random()}`).digest("hex").slice(0, 8)}`;
57648
+ const uniq = `${process.pid}.${createHash4("sha256").update(`${process.pid}:${Date.now()}:${Math.random()}`).digest("hex").slice(0, 8)}`;
57025
57649
  const tmp = target.slice(0, target.length - suffix.length) + `${suffix}.${uniq}.tmp`;
57026
57650
  try {
57027
57651
  fs14.writeFileSync(tmp, text, { encoding: "utf-8" });
@@ -58748,22 +59372,27 @@ function _now_iso() {
58748
59372
  return (/* @__PURE__ */ new Date()).toISOString().replace(/\.\d{3}Z$/, "Z");
58749
59373
  }
58750
59374
  function build_record(options) {
58751
- const { tool_name, outcome, transport, client_id_hash_value, ts } = options;
58752
- return {
59375
+ const { tool_name, outcome, transport, client_id_hash_value, ts, host } = options;
59376
+ const record = {
58753
59377
  tool_name,
58754
59378
  client_id_hash: client_id_hash_value || hash_client_id(),
58755
59379
  ts: ts || _now_iso(),
58756
59380
  transport,
58757
59381
  outcome
58758
59382
  };
59383
+ if (typeof host === "string" && host !== "") {
59384
+ record.host = host;
59385
+ }
59386
+ return record;
58759
59387
  }
58760
59388
  function record_call(options) {
58761
- const { tool_name, outcome, transport, consumer_root, client_id_hash_value } = options;
59389
+ const { tool_name, outcome, transport, consumer_root, client_id_hash_value, host } = options;
58762
59390
  const record = build_record({
58763
59391
  tool_name,
58764
59392
  outcome,
58765
59393
  transport,
58766
- client_id_hash_value
59394
+ client_id_hash_value,
59395
+ host
58767
59396
  });
58768
59397
  const target = _resolve_log_path(consumer_root ?? void 0);
58769
59398
  try {