@event4u/agent-config 14.8.0 → 14.10.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 (170) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/CHANGELOG.md +214 -237
  3. package/README.md +1 -1
  4. package/agents/templates/.ai-council.yml.example +34 -4
  5. package/dist/agent-src/commands/pr/merge.md +9 -5
  6. package/dist/agent-src/commands/review/changes.md +95 -14
  7. package/dist/agent-src/commands/roadmap/process-full.md +2 -2
  8. package/dist/agent-src/contexts/execution/host-capability-manifest.md +77 -0
  9. package/dist/agent-src/contexts/execution/roadmap-execution-contract.md +36 -0
  10. package/dist/agent-src/contexts/execution/subagent-response-contract.md +80 -0
  11. package/dist/agent-src/rules/untrusted-input-defense.md +9 -3
  12. package/dist/agent-src/skills/async-python-patterns/SKILL.md +1 -1
  13. package/dist/agent-src/skills/code-refactoring/SKILL.md +1 -1
  14. package/dist/agent-src/skills/code-review/evals/evals.json +87 -46
  15. package/dist/agent-src/skills/condense-memory/SKILL.md +1 -1
  16. package/dist/agent-src/skills/conventional-commits-writing/SKILL.md +1 -1
  17. package/dist/agent-src/skills/design-review/SKILL.md +1 -1
  18. package/dist/agent-src/skills/discovery-interview/SKILL.md +1 -1
  19. package/dist/agent-src/skills/doc-coauthoring/SKILL.md +1 -1
  20. package/dist/agent-src/skills/docx-authoring/SKILL.md +1 -1
  21. package/dist/agent-src/skills/editorial-calendar/SKILL.md +1 -1
  22. package/dist/agent-src/skills/github-ci/SKILL.md +1 -1
  23. package/dist/agent-src/skills/humanizer/SKILL.md +39 -0
  24. package/dist/agent-src/skills/humanizer/evals/strip_fixtures.json +57 -0
  25. package/dist/agent-src/skills/humanizer/references/fixtures.md +54 -0
  26. package/dist/agent-src/skills/judge-artifact-completeness/SKILL.md +1 -1
  27. package/dist/agent-src/skills/judge-injection-defense/SKILL.md +1 -1
  28. package/dist/agent-src/skills/judge-spec-compliance/SKILL.md +154 -0
  29. package/dist/agent-src/skills/judge-synthesis/SKILL.md +45 -0
  30. package/dist/agent-src/skills/laravel-validation/SKILL.md +1 -1
  31. package/dist/agent-src/skills/legal-intake-triage/SKILL.md +1 -1
  32. package/dist/agent-src/skills/legal-practice-profile/SKILL.md +1 -1
  33. package/dist/agent-src/skills/messaging-architecture/SKILL.md +1 -1
  34. package/dist/agent-src/skills/migration-architect/SKILL.md +1 -1
  35. package/dist/agent-src/skills/module-detect-on-the-fly/SKILL.md +1 -1
  36. package/dist/agent-src/skills/module-management/SKILL.md +1 -1
  37. package/dist/agent-src/skills/motion-choreographer/SKILL.md +1 -1
  38. package/dist/agent-src/skills/onboarding-program/SKILL.md +1 -1
  39. package/dist/agent-src/skills/perf-feedback-craft/SKILL.md +1 -1
  40. package/dist/agent-src/skills/prompt-optimizer/SKILL.md +1 -1
  41. package/dist/agent-src/skills/receiving-code-review/SKILL.md +1 -1
  42. package/dist/agent-src/skills/roadmap-writing/SKILL.md +18 -18
  43. package/dist/agent-src/skills/scene-expander/SKILL.md +1 -1
  44. package/dist/agent-src/skills/secrets-management/SKILL.md +1 -1
  45. package/dist/agent-src/skills/using-git-worktrees/SKILL.md +1 -1
  46. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  47. package/dist/agent-src/templates/roadmaps.md +8 -0
  48. package/dist/cli/registry.js +2 -0
  49. package/dist/cli/registry.js.map +1 -1
  50. package/dist/cli-delegate/{chunk-MMSGVZKV.js → chunk-77GR3VD4.js} +65 -40
  51. package/dist/cli-delegate/{chunk-Q26HT4QT.js → chunk-E46KPN6K.js} +251 -150
  52. package/dist/cli-delegate/{chunk-EEJUMCDZ.js → chunk-PLSG6UL5.js} +1 -1
  53. package/dist/cli-delegate/cmd_conformance.js +89 -13
  54. package/dist/cli-delegate/cmd_doctor.js +3 -3
  55. package/dist/cli-delegate/cmd_handoff.js +2 -2
  56. package/dist/cli-delegate/cmd_memory_get.js +1 -1
  57. package/dist/cli-delegate/cmd_route_audit.js +1 -1
  58. package/dist/cli-delegate/cmd_settings_get.js +1 -1
  59. package/dist/cli-delegate/cmd_settings_set.js +1 -1
  60. package/dist/discovery/deprecation-report.md +1 -1
  61. package/dist/discovery/discovery-manifest.json +64 -42
  62. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  63. package/dist/discovery/discovery-manifest.summary.md +3 -3
  64. package/dist/discovery/dormancy-report.md +1 -1
  65. package/dist/discovery/orphan-report.md +1 -1
  66. package/dist/discovery/packs.json +6 -5
  67. package/dist/discovery/trust-report.md +2 -2
  68. package/dist/discovery/workspaces.json +5 -4
  69. package/dist/hooks/dispatch.js +562 -204
  70. package/dist/mcp/registry-manifest.json +3 -3
  71. package/dist/mcp/server.json +2 -2
  72. package/dist/mcp/server.mjs +808 -331
  73. package/dist/scripts/_lib/claude_plugin.js +162 -0
  74. package/dist/scripts/_lib/claude_plugin.js.map +1 -0
  75. package/dist/scripts/_lib/environment_detector.js +397 -0
  76. package/dist/scripts/_lib/environment_detector.js.map +1 -0
  77. package/dist/scripts/_lib/spawn_env.js +129 -0
  78. package/dist/scripts/_lib/spawn_env.js.map +1 -0
  79. package/dist/scripts/ai_council/modes.js +199 -0
  80. package/dist/scripts/ai_council/modes.js.map +1 -0
  81. package/dist/scripts/ai_council/transport_resolver.js +418 -0
  82. package/dist/scripts/ai_council/transport_resolver.js.map +1 -0
  83. package/dist/server/routes/wizard.js +3 -2
  84. package/dist/server/routes/wizard.js.map +1 -1
  85. package/dist/ui/assets/index-Cxgy63kz.js +26 -0
  86. package/dist/ui/assets/index-Cxgy63kz.js.map +1 -0
  87. package/dist/ui/index.html +1 -1
  88. package/docs/guidelines/agent-infra/traceability-field-mechanics.md +50 -0
  89. package/docs/guidelines/agent-infra/untrusted-input-spotlighting.md +17 -0
  90. package/package.json +7 -3
  91. package/src/config/estate-count-budget.json +13 -744
  92. package/src/config/evaluator-budgets.json +4 -4
  93. package/src/config/gate-coverage.yml +267 -9
  94. package/src/config/gate-violation-baselines.json +72 -72
  95. package/src/config/preamble-payload-budget.json +71 -67
  96. package/src/config/publish-surface.json +60 -0
  97. package/src/config/requirements-trace-budget.json +32 -0
  98. package/src/config/rule-stub-ceilings.json +8 -1
  99. package/src/scripts/_dispatch.bash +7 -0
  100. package/src/scripts/_lib/base_tree.ts +175 -0
  101. package/src/scripts/_lib/billing_grant.ts +165 -0
  102. package/src/scripts/_lib/billing_grant_cli.ts +123 -0
  103. package/src/scripts/_lib/council_fallback_posture.ts +53 -6
  104. package/src/scripts/_lib/council_fallback_wiring.ts +61 -1
  105. package/src/scripts/_lib/host_capability.ts +59 -5
  106. package/src/scripts/_lib/quota_parked.ts +133 -0
  107. package/src/scripts/_lib/retrieval_sanitize.ts +62 -0
  108. package/src/scripts/_lib/review_telemetry.ts +196 -0
  109. package/src/scripts/_lib/subagent_response.ts +92 -0
  110. package/src/scripts/adr/regenerate_index.ts +14 -7
  111. package/src/scripts/ai_council/clients.ts +12 -1
  112. package/src/scripts/ai_council/config.ts +72 -115
  113. package/src/scripts/ai_council/fallback_config.ts +19 -7
  114. package/src/scripts/ai_council/mid_flight_fallback.ts +88 -7
  115. package/src/scripts/ai_council/orchestrator.ts +2 -2
  116. package/src/scripts/ai_council/py_format.ts +124 -0
  117. package/src/scripts/ai_council/seating.ts +211 -0
  118. package/src/scripts/ai_council/transport_resolver.ts +65 -2
  119. package/src/scripts/audit_adr_coverage.ts +33 -6
  120. package/src/scripts/check_council_pin_staleness.ts +300 -0
  121. package/src/scripts/check_estate_count.ts +420 -293
  122. package/src/scripts/check_gate_coverage.ts +91 -0
  123. package/src/scripts/check_no_stub_inventory_table.ts +292 -0
  124. package/src/scripts/check_pack_passport_reconciliation.ts +274 -0
  125. package/src/scripts/check_pack_size.ts +234 -1
  126. package/src/scripts/check_publish_surface.ts +297 -0
  127. package/src/scripts/check_requirements_trace.ts +378 -0
  128. package/src/scripts/check_secret_leak.ts +166 -12
  129. package/src/scripts/code_graph/cli.ts +44 -5
  130. package/src/scripts/code_graph/extract.ts +87 -0
  131. package/src/scripts/council_cli.ts +12 -16
  132. package/src/scripts/detect_ai_tells.ts +87 -0
  133. package/src/scripts/dispatch_r2_reviewer.ts +42 -0
  134. package/src/scripts/generate_capabilities_index.ts +41 -0
  135. package/src/scripts/generate_pack_manifests.ts +78 -0
  136. package/src/scripts/git_authorization_hook.ts +54 -4
  137. package/src/scripts/hooks/block_unauthorized_git.ts +19 -1
  138. package/src/scripts/hooks/run_continuation_hook.ts +3 -1
  139. package/src/scripts/hooks/subagent_ledger_hook.ts +76 -11
  140. package/src/scripts/injection_scan_hook.ts +120 -10
  141. package/src/scripts/lint_adr_sweep_routing.ts +365 -0
  142. package/src/scripts/lint_workflow_security.ts +53 -10
  143. package/src/scripts/lint_workflow_security_allowlist.json +2 -18
  144. package/src/scripts/report_envelope_rate.ts +166 -0
  145. package/src/scripts/review_axis_report.ts +218 -0
  146. package/src/scripts/run_supervise.ts +46 -1
  147. package/src/scripts/schemas/evals.schema.json +5 -0
  148. package/src/scripts/schemas/pack.schema.json +62 -4
  149. package/src/scripts/schemas/skill.schema.json +2 -2
  150. package/src/scripts/sync_pr_branch.ts +14 -7
  151. package/src/scripts/tighten_skill_descriptions.ts +264 -0
  152. package/dist/cli/commands/commands.candidates.test.js +0 -257
  153. package/dist/cli/commands/commands.candidates.test.js.map +0 -1
  154. package/dist/cli/commands/profiles.test.js +0 -88
  155. package/dist/cli/commands/profiles.test.js.map +0 -1
  156. package/dist/cli/commands/recordTriggerEval.test.js +0 -113
  157. package/dist/cli/commands/recordTriggerEval.test.js.map +0 -1
  158. package/dist/cli/configRoot.test.js +0 -97
  159. package/dist/cli/configRoot.test.js.map +0 -1
  160. package/dist/cli/mcp/content.test.js +0 -54
  161. package/dist/cli/mcp/content.test.js.map +0 -1
  162. package/dist/cli/mcp/dispatch.test.js +0 -108
  163. package/dist/cli/mcp/dispatch.test.js.map +0 -1
  164. package/dist/server/writeRoot.test.js +0 -91
  165. package/dist/server/writeRoot.test.js.map +0 -1
  166. package/dist/shared/capabilities.test.js +0 -39
  167. package/dist/shared/capabilities.test.js.map +0 -1
  168. package/dist/ui/assets/index-C1pBRm1f.js +0 -26
  169. package/dist/ui/assets/index-C1pBRm1f.js.map +0 -1
  170. /package/dist/cli-delegate/{chunk-N7CDDGI3.js → chunk-CYH5SP6M.js} +0 -0
@@ -1841,17 +1841,17 @@ var require_visit = __commonJS({
1841
1841
  visit.BREAK = BREAK;
1842
1842
  visit.SKIP = SKIP;
1843
1843
  visit.REMOVE = REMOVE;
1844
- function visit_(key, node, visitor, path81) {
1845
- const ctrl = callVisitor(key, node, visitor, path81);
1844
+ function visit_(key, node, visitor, path83) {
1845
+ const ctrl = callVisitor(key, node, visitor, path83);
1846
1846
  if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
1847
- replaceNode(key, path81, ctrl);
1848
- return visit_(key, ctrl, visitor, path81);
1847
+ replaceNode(key, path83, ctrl);
1848
+ return visit_(key, ctrl, visitor, path83);
1849
1849
  }
1850
1850
  if (typeof ctrl !== "symbol") {
1851
1851
  if (identity.isCollection(node)) {
1852
- path81 = Object.freeze(path81.concat(node));
1852
+ path83 = Object.freeze(path83.concat(node));
1853
1853
  for (let i = 0; i < node.items.length; ++i) {
1854
- const ci = visit_(i, node.items[i], visitor, path81);
1854
+ const ci = visit_(i, node.items[i], visitor, path83);
1855
1855
  if (typeof ci === "number")
1856
1856
  i = ci - 1;
1857
1857
  else if (ci === BREAK)
@@ -1862,13 +1862,13 @@ var require_visit = __commonJS({
1862
1862
  }
1863
1863
  }
1864
1864
  } else if (identity.isPair(node)) {
1865
- path81 = Object.freeze(path81.concat(node));
1866
- const ck = visit_("key", node.key, visitor, path81);
1865
+ path83 = Object.freeze(path83.concat(node));
1866
+ const ck = visit_("key", node.key, visitor, path83);
1867
1867
  if (ck === BREAK)
1868
1868
  return BREAK;
1869
1869
  else if (ck === REMOVE)
1870
1870
  node.key = null;
1871
- const cv = visit_("value", node.value, visitor, path81);
1871
+ const cv = visit_("value", node.value, visitor, path83);
1872
1872
  if (cv === BREAK)
1873
1873
  return BREAK;
1874
1874
  else if (cv === REMOVE)
@@ -1889,17 +1889,17 @@ var require_visit = __commonJS({
1889
1889
  visitAsync.BREAK = BREAK;
1890
1890
  visitAsync.SKIP = SKIP;
1891
1891
  visitAsync.REMOVE = REMOVE;
1892
- async function visitAsync_(key, node, visitor, path81) {
1893
- const ctrl = await callVisitor(key, node, visitor, path81);
1892
+ async function visitAsync_(key, node, visitor, path83) {
1893
+ const ctrl = await callVisitor(key, node, visitor, path83);
1894
1894
  if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
1895
- replaceNode(key, path81, ctrl);
1896
- return visitAsync_(key, ctrl, visitor, path81);
1895
+ replaceNode(key, path83, ctrl);
1896
+ return visitAsync_(key, ctrl, visitor, path83);
1897
1897
  }
1898
1898
  if (typeof ctrl !== "symbol") {
1899
1899
  if (identity.isCollection(node)) {
1900
- path81 = Object.freeze(path81.concat(node));
1900
+ path83 = Object.freeze(path83.concat(node));
1901
1901
  for (let i = 0; i < node.items.length; ++i) {
1902
- const ci = await visitAsync_(i, node.items[i], visitor, path81);
1902
+ const ci = await visitAsync_(i, node.items[i], visitor, path83);
1903
1903
  if (typeof ci === "number")
1904
1904
  i = ci - 1;
1905
1905
  else if (ci === BREAK)
@@ -1910,13 +1910,13 @@ var require_visit = __commonJS({
1910
1910
  }
1911
1911
  }
1912
1912
  } else if (identity.isPair(node)) {
1913
- path81 = Object.freeze(path81.concat(node));
1914
- const ck = await visitAsync_("key", node.key, visitor, path81);
1913
+ path83 = Object.freeze(path83.concat(node));
1914
+ const ck = await visitAsync_("key", node.key, visitor, path83);
1915
1915
  if (ck === BREAK)
1916
1916
  return BREAK;
1917
1917
  else if (ck === REMOVE)
1918
1918
  node.key = null;
1919
- const cv = await visitAsync_("value", node.value, visitor, path81);
1919
+ const cv = await visitAsync_("value", node.value, visitor, path83);
1920
1920
  if (cv === BREAK)
1921
1921
  return BREAK;
1922
1922
  else if (cv === REMOVE)
@@ -1943,23 +1943,23 @@ var require_visit = __commonJS({
1943
1943
  }
1944
1944
  return visitor;
1945
1945
  }
1946
- function callVisitor(key, node, visitor, path81) {
1946
+ function callVisitor(key, node, visitor, path83) {
1947
1947
  if (typeof visitor === "function")
1948
- return visitor(key, node, path81);
1948
+ return visitor(key, node, path83);
1949
1949
  if (identity.isMap(node))
1950
- return visitor.Map?.(key, node, path81);
1950
+ return visitor.Map?.(key, node, path83);
1951
1951
  if (identity.isSeq(node))
1952
- return visitor.Seq?.(key, node, path81);
1952
+ return visitor.Seq?.(key, node, path83);
1953
1953
  if (identity.isPair(node))
1954
- return visitor.Pair?.(key, node, path81);
1954
+ return visitor.Pair?.(key, node, path83);
1955
1955
  if (identity.isScalar(node))
1956
- return visitor.Scalar?.(key, node, path81);
1956
+ return visitor.Scalar?.(key, node, path83);
1957
1957
  if (identity.isAlias(node))
1958
- return visitor.Alias?.(key, node, path81);
1958
+ return visitor.Alias?.(key, node, path83);
1959
1959
  return void 0;
1960
1960
  }
1961
- function replaceNode(key, path81, node) {
1962
- const parent = path81[path81.length - 1];
1961
+ function replaceNode(key, path83, node) {
1962
+ const parent = path83[path83.length - 1];
1963
1963
  if (identity.isCollection(parent)) {
1964
1964
  parent.items[key] = node;
1965
1965
  } else if (identity.isPair(parent)) {
@@ -2569,10 +2569,10 @@ var require_Collection = __commonJS({
2569
2569
  var createNode = require_createNode();
2570
2570
  var identity = require_identity();
2571
2571
  var Node = require_Node();
2572
- function collectionFromPath(schema, path81, value) {
2572
+ function collectionFromPath(schema, path83, value) {
2573
2573
  let v = value;
2574
- for (let i = path81.length - 1; i >= 0; --i) {
2575
- const k = path81[i];
2574
+ for (let i = path83.length - 1; i >= 0; --i) {
2575
+ const k = path83[i];
2576
2576
  if (typeof k === "number" && Number.isInteger(k) && k >= 0) {
2577
2577
  const a = [];
2578
2578
  a[k] = v;
@@ -2591,7 +2591,7 @@ var require_Collection = __commonJS({
2591
2591
  sourceObjects: /* @__PURE__ */ new Map()
2592
2592
  });
2593
2593
  }
2594
- var isEmptyPath = (path81) => path81 == null || typeof path81 === "object" && !!path81[Symbol.iterator]().next().done;
2594
+ var isEmptyPath = (path83) => path83 == null || typeof path83 === "object" && !!path83[Symbol.iterator]().next().done;
2595
2595
  var Collection = class extends Node.NodeBase {
2596
2596
  constructor(type, schema) {
2597
2597
  super(type);
@@ -2621,11 +2621,11 @@ var require_Collection = __commonJS({
2621
2621
  * be a Pair instance or a `{ key, value }` object, which may not have a key
2622
2622
  * that already exists in the map.
2623
2623
  */
2624
- addIn(path81, value) {
2625
- if (isEmptyPath(path81))
2624
+ addIn(path83, value) {
2625
+ if (isEmptyPath(path83))
2626
2626
  this.add(value);
2627
2627
  else {
2628
- const [key, ...rest] = path81;
2628
+ const [key, ...rest] = path83;
2629
2629
  const node = this.get(key, true);
2630
2630
  if (identity.isCollection(node))
2631
2631
  node.addIn(rest, value);
@@ -2639,8 +2639,8 @@ var require_Collection = __commonJS({
2639
2639
  * Removes a value from the collection.
2640
2640
  * @returns `true` if the item was found and removed.
2641
2641
  */
2642
- deleteIn(path81) {
2643
- const [key, ...rest] = path81;
2642
+ deleteIn(path83) {
2643
+ const [key, ...rest] = path83;
2644
2644
  if (rest.length === 0)
2645
2645
  return this.delete(key);
2646
2646
  const node = this.get(key, true);
@@ -2654,8 +2654,8 @@ var require_Collection = __commonJS({
2654
2654
  * scalar values from their surrounding node; to disable set `keepScalar` to
2655
2655
  * `true` (collections are always returned intact).
2656
2656
  */
2657
- getIn(path81, keepScalar) {
2658
- const [key, ...rest] = path81;
2657
+ getIn(path83, keepScalar) {
2658
+ const [key, ...rest] = path83;
2659
2659
  const node = this.get(key, true);
2660
2660
  if (rest.length === 0)
2661
2661
  return !keepScalar && identity.isScalar(node) ? node.value : node;
@@ -2673,8 +2673,8 @@ var require_Collection = __commonJS({
2673
2673
  /**
2674
2674
  * Checks if the collection includes a value with the key `key`.
2675
2675
  */
2676
- hasIn(path81) {
2677
- const [key, ...rest] = path81;
2676
+ hasIn(path83) {
2677
+ const [key, ...rest] = path83;
2678
2678
  if (rest.length === 0)
2679
2679
  return this.has(key);
2680
2680
  const node = this.get(key, true);
@@ -2684,8 +2684,8 @@ var require_Collection = __commonJS({
2684
2684
  * Sets a value in this collection. For `!!set`, `value` needs to be a
2685
2685
  * boolean to add/remove the item from the set.
2686
2686
  */
2687
- setIn(path81, value) {
2688
- const [key, ...rest] = path81;
2687
+ setIn(path83, value) {
2688
+ const [key, ...rest] = path83;
2689
2689
  if (rest.length === 0) {
2690
2690
  this.set(key, value);
2691
2691
  } else {
@@ -3426,16 +3426,16 @@ var require_merge = __commonJS({
3426
3426
  "use strict";
3427
3427
  var identity = require_identity();
3428
3428
  var Scalar = require_Scalar();
3429
- var MERGE_KEY2 = "<<";
3429
+ var MERGE_KEY = "<<";
3430
3430
  var merge = {
3431
- identify: (value) => value === MERGE_KEY2 || typeof value === "symbol" && value.description === MERGE_KEY2,
3431
+ identify: (value) => value === MERGE_KEY || typeof value === "symbol" && value.description === MERGE_KEY,
3432
3432
  default: "key",
3433
3433
  tag: "tag:yaml.org,2002:merge",
3434
3434
  test: /^<<$/,
3435
- resolve: () => Object.assign(new Scalar.Scalar(Symbol(MERGE_KEY2)), {
3435
+ resolve: () => Object.assign(new Scalar.Scalar(Symbol(MERGE_KEY)), {
3436
3436
  addToJSMap: addMergeToJSMap
3437
3437
  }),
3438
- stringify: () => MERGE_KEY2
3438
+ stringify: () => MERGE_KEY
3439
3439
  };
3440
3440
  var isMergeKey = (ctx, key) => (merge.identify(key) || identity.isScalar(key) && (!key.type || key.type === Scalar.Scalar.PLAIN) && merge.identify(key.value)) && ctx?.doc.schema.tags.some((tag) => tag.tag === merge.tag && tag.default);
3441
3441
  function addMergeToJSMap(ctx, map, value) {
@@ -5200,9 +5200,9 @@ var require_Document = __commonJS({
5200
5200
  this.contents.add(value);
5201
5201
  }
5202
5202
  /** Adds a value to the document. */
5203
- addIn(path81, value) {
5203
+ addIn(path83, value) {
5204
5204
  if (assertCollection(this.contents))
5205
- this.contents.addIn(path81, value);
5205
+ this.contents.addIn(path83, value);
5206
5206
  }
5207
5207
  /**
5208
5208
  * Create a new `Alias` node, ensuring that the target `node` has the required anchor.
@@ -5277,14 +5277,14 @@ var require_Document = __commonJS({
5277
5277
  * Removes a value from the document.
5278
5278
  * @returns `true` if the item was found and removed.
5279
5279
  */
5280
- deleteIn(path81) {
5281
- if (Collection.isEmptyPath(path81)) {
5280
+ deleteIn(path83) {
5281
+ if (Collection.isEmptyPath(path83)) {
5282
5282
  if (this.contents == null)
5283
5283
  return false;
5284
5284
  this.contents = null;
5285
5285
  return true;
5286
5286
  }
5287
- return assertCollection(this.contents) ? this.contents.deleteIn(path81) : false;
5287
+ return assertCollection(this.contents) ? this.contents.deleteIn(path83) : false;
5288
5288
  }
5289
5289
  /**
5290
5290
  * Returns item at `key`, or `undefined` if not found. By default unwraps
@@ -5299,10 +5299,10 @@ var require_Document = __commonJS({
5299
5299
  * scalar values from their surrounding node; to disable set `keepScalar` to
5300
5300
  * `true` (collections are always returned intact).
5301
5301
  */
5302
- getIn(path81, keepScalar) {
5303
- if (Collection.isEmptyPath(path81))
5302
+ getIn(path83, keepScalar) {
5303
+ if (Collection.isEmptyPath(path83))
5304
5304
  return !keepScalar && identity.isScalar(this.contents) ? this.contents.value : this.contents;
5305
- return identity.isCollection(this.contents) ? this.contents.getIn(path81, keepScalar) : void 0;
5305
+ return identity.isCollection(this.contents) ? this.contents.getIn(path83, keepScalar) : void 0;
5306
5306
  }
5307
5307
  /**
5308
5308
  * Checks if the document includes a value with the key `key`.
@@ -5313,10 +5313,10 @@ var require_Document = __commonJS({
5313
5313
  /**
5314
5314
  * Checks if the document includes a value at `path`.
5315
5315
  */
5316
- hasIn(path81) {
5317
- if (Collection.isEmptyPath(path81))
5316
+ hasIn(path83) {
5317
+ if (Collection.isEmptyPath(path83))
5318
5318
  return this.contents !== void 0;
5319
- return identity.isCollection(this.contents) ? this.contents.hasIn(path81) : false;
5319
+ return identity.isCollection(this.contents) ? this.contents.hasIn(path83) : false;
5320
5320
  }
5321
5321
  /**
5322
5322
  * Sets a value in this document. For `!!set`, `value` needs to be a
@@ -5333,13 +5333,13 @@ var require_Document = __commonJS({
5333
5333
  * Sets a value in this document. For `!!set`, `value` needs to be a
5334
5334
  * boolean to add/remove the item from the set.
5335
5335
  */
5336
- setIn(path81, value) {
5337
- if (Collection.isEmptyPath(path81)) {
5336
+ setIn(path83, value) {
5337
+ if (Collection.isEmptyPath(path83)) {
5338
5338
  this.contents = value;
5339
5339
  } else if (this.contents == null) {
5340
- this.contents = Collection.collectionFromPath(this.schema, Array.from(path81), value);
5340
+ this.contents = Collection.collectionFromPath(this.schema, Array.from(path83), value);
5341
5341
  } else if (assertCollection(this.contents)) {
5342
- this.contents.setIn(path81, value);
5342
+ this.contents.setIn(path83, value);
5343
5343
  }
5344
5344
  }
5345
5345
  /**
@@ -7299,9 +7299,9 @@ var require_cst_visit = __commonJS({
7299
7299
  visit.BREAK = BREAK;
7300
7300
  visit.SKIP = SKIP;
7301
7301
  visit.REMOVE = REMOVE;
7302
- visit.itemAtPath = (cst, path81) => {
7302
+ visit.itemAtPath = (cst, path83) => {
7303
7303
  let item = cst;
7304
- for (const [field, index] of path81) {
7304
+ for (const [field, index] of path83) {
7305
7305
  const tok = item?.[field];
7306
7306
  if (tok && "items" in tok) {
7307
7307
  item = tok.items[index];
@@ -7310,23 +7310,23 @@ var require_cst_visit = __commonJS({
7310
7310
  }
7311
7311
  return item;
7312
7312
  };
7313
- visit.parentCollection = (cst, path81) => {
7314
- const parent = visit.itemAtPath(cst, path81.slice(0, -1));
7315
- const field = path81[path81.length - 1][0];
7313
+ visit.parentCollection = (cst, path83) => {
7314
+ const parent = visit.itemAtPath(cst, path83.slice(0, -1));
7315
+ const field = path83[path83.length - 1][0];
7316
7316
  const coll = parent?.[field];
7317
7317
  if (coll && "items" in coll)
7318
7318
  return coll;
7319
7319
  throw new Error("Parent collection not found");
7320
7320
  };
7321
- function _visit(path81, item, visitor) {
7322
- let ctrl = visitor(item, path81);
7321
+ function _visit(path83, item, visitor) {
7322
+ let ctrl = visitor(item, path83);
7323
7323
  if (typeof ctrl === "symbol")
7324
7324
  return ctrl;
7325
7325
  for (const field of ["key", "value"]) {
7326
7326
  const token = item[field];
7327
7327
  if (token && "items" in token) {
7328
7328
  for (let i = 0; i < token.items.length; ++i) {
7329
- const ci = _visit(Object.freeze(path81.concat([[field, i]])), token.items[i], visitor);
7329
+ const ci = _visit(Object.freeze(path83.concat([[field, i]])), token.items[i], visitor);
7330
7330
  if (typeof ci === "number")
7331
7331
  i = ci - 1;
7332
7332
  else if (ci === BREAK)
@@ -7337,10 +7337,10 @@ var require_cst_visit = __commonJS({
7337
7337
  }
7338
7338
  }
7339
7339
  if (typeof ctrl === "function" && field === "key")
7340
- ctrl = ctrl(item, path81);
7340
+ ctrl = ctrl(item, path83);
7341
7341
  }
7342
7342
  }
7343
- return typeof ctrl === "function" ? ctrl(item, path81) : ctrl;
7343
+ return typeof ctrl === "function" ? ctrl(item, path83) : ctrl;
7344
7344
  }
7345
7345
  exports.visit = visit;
7346
7346
  }
@@ -8642,14 +8642,14 @@ var require_parser = __commonJS({
8642
8642
  case "scalar":
8643
8643
  case "single-quoted-scalar":
8644
8644
  case "double-quoted-scalar": {
8645
- const fs84 = this.flowScalar(this.type);
8645
+ const fs86 = this.flowScalar(this.type);
8646
8646
  if (atNextItem || it.value) {
8647
- map.items.push({ start, key: fs84, sep: [] });
8647
+ map.items.push({ start, key: fs86, sep: [] });
8648
8648
  this.onKeyLine = true;
8649
8649
  } else if (it.sep) {
8650
- this.stack.push(fs84);
8650
+ this.stack.push(fs86);
8651
8651
  } else {
8652
- Object.assign(it, { key: fs84, sep: [] });
8652
+ Object.assign(it, { key: fs86, sep: [] });
8653
8653
  this.onKeyLine = true;
8654
8654
  }
8655
8655
  return;
@@ -8777,13 +8777,13 @@ var require_parser = __commonJS({
8777
8777
  case "scalar":
8778
8778
  case "single-quoted-scalar":
8779
8779
  case "double-quoted-scalar": {
8780
- const fs84 = this.flowScalar(this.type);
8780
+ const fs86 = this.flowScalar(this.type);
8781
8781
  if (!it || it.value)
8782
- fc.items.push({ start: [], key: fs84, sep: [] });
8782
+ fc.items.push({ start: [], key: fs86, sep: [] });
8783
8783
  else if (it.sep)
8784
- this.stack.push(fs84);
8784
+ this.stack.push(fs86);
8785
8785
  else
8786
- Object.assign(it, { key: fs84, sep: [] });
8786
+ Object.assign(it, { key: fs86, sep: [] });
8787
8787
  return;
8788
8788
  }
8789
8789
  case "flow-map-end":
@@ -20454,6 +20454,22 @@ function _getStr(d, key, dflt) {
20454
20454
  }
20455
20455
  return String(v);
20456
20456
  }
20457
+ function _runtime_enforcement_lines() {
20458
+ return [
20459
+ "runtime_enforcement:",
20460
+ " # Four states, and no others: detects | warns | blocks | not-enforceable-on-host.",
20461
+ " # Derived from src/scripts/hook_manifest.yaml (fail_closed + severity), never",
20462
+ " # hand-written \u2014 a manifest row that gained teeth would have to change this one.",
20463
+ " - hook: injection-scan",
20464
+ " slot: post_tool_use",
20465
+ " state: warns",
20466
+ " default: off",
20467
+ " blocks_legal_on_any_host: false",
20468
+ " reason: " + _scalar(
20469
+ "fail_closed: false + severity: advisory in hook_manifest.yaml \u2014 it reports through the host and cannot refuse, so it warns and never blocks. Ships enabled: false; the detector was measured at 99.00% recall and a 0.85% false-positive rate over internal/bench/corpora/encoding-channels/ before any default flip is even discussable.<!-- claim:injection-scan-corpus-rates -->"
20470
+ )
20471
+ ];
20472
+ }
20457
20473
  function build() {
20458
20474
  const packs = _load_packs();
20459
20475
  const skillMap = _skill_packs();
@@ -20540,6 +20556,8 @@ function build() {
20540
20556
  }
20541
20557
  }
20542
20558
  lines.push("");
20559
+ lines.push(..._runtime_enforcement_lines());
20560
+ lines.push("");
20543
20561
  lines.push("gaps:");
20544
20562
  if (gaps.length > 0) {
20545
20563
  const sortedGaps = [...gaps].sort((a, b) => a.id < b.id ? -1 : a.id > b.id ? 1 : 0);
@@ -22068,8 +22086,8 @@ function lockfile_path(env) {
22068
22086
  }
22069
22087
  return write_target("installed.lock", { env: env ?? null });
22070
22088
  }
22071
- function read_lockfile(path81) {
22072
- const target = path81 ?? lockfile_path();
22089
+ function read_lockfile(path83) {
22090
+ const target = path83 ?? lockfile_path();
22073
22091
  let text;
22074
22092
  try {
22075
22093
  text = fs33.readFileSync(target, { encoding: "utf-8" });
@@ -22286,18 +22304,18 @@ function manifest_path(project_root, env) {
22286
22304
  }
22287
22305
  return fsPath.join(project_root, DEFAULT_MANIFEST_RELATIVE);
22288
22306
  }
22289
- function read_manifest(path81) {
22307
+ function read_manifest(path83) {
22290
22308
  let text;
22291
22309
  try {
22292
- text = require_read_text(path81);
22310
+ text = require_read_text(path83);
22293
22311
  } catch {
22294
22312
  return null;
22295
22313
  }
22296
22314
  const data = _parse_manual(text);
22297
22315
  return _normalise_v2_shape(data);
22298
22316
  }
22299
- function require_read_text(path81) {
22300
- return fs35.readFileSync(path81, { encoding: "utf-8" });
22317
+ function require_read_text(path83) {
22318
+ return fs35.readFileSync(path83, { encoding: "utf-8" });
22301
22319
  }
22302
22320
  function _normalise_v2_shape(data) {
22303
22321
  if (data["tools"] === void 0 || data["tools"] === null) {
@@ -22478,9 +22496,9 @@ function stable_sort(items, key) {
22478
22496
  return a.index - b.index;
22479
22497
  }).map((entry) => entry.item);
22480
22498
  }
22481
- function write_manifest(path81, version, tools, options = {}) {
22499
+ function write_manifest(path83, version, tools, options = {}) {
22482
22500
  const rendered = _render(version, tools, { deploy_roots: options.deploy_roots ?? null });
22483
- return write_atomic(path81, rendered);
22501
+ return write_atomic(path83, rendered);
22484
22502
  }
22485
22503
  function upsert_tool(existing, options) {
22486
22504
  const {
@@ -23092,9 +23110,9 @@ function defineScalarTag(tagName, options) {
23092
23110
  matchByTagPrefix: options.matchByTagPrefix ?? false,
23093
23111
  implicitFirstChars: options.implicitFirstChars ?? null,
23094
23112
  resolve: options.resolve,
23095
- identify: options.identify ?? null,
23113
+ identify: options.identify,
23096
23114
  represent: options.represent ?? ((data) => String(data)),
23097
- representTagName: options.representTagName ?? null
23115
+ representTagName: options.representTagName ?? (() => tagName)
23098
23116
  };
23099
23117
  }
23100
23118
  function defineSequenceTag(tagName, options) {
@@ -23108,9 +23126,9 @@ function defineSequenceTag(tagName, options) {
23108
23126
  addItem: options.addItem,
23109
23127
  finalize: options.finalize ?? ((carrier) => carrier),
23110
23128
  carrierIsResult,
23111
- identify: options.identify ?? null,
23129
+ identify: options.identify,
23112
23130
  represent: options.represent ?? ((data) => data),
23113
- representTagName: options.representTagName ?? null
23131
+ representTagName: options.representTagName ?? (() => tagName)
23114
23132
  };
23115
23133
  }
23116
23134
  function defineMappingTag(tagName, options) {
@@ -23127,9 +23145,9 @@ function defineMappingTag(tagName, options) {
23127
23145
  get: options.get,
23128
23146
  finalize: options.finalize ?? ((carrier) => carrier),
23129
23147
  carrierIsResult,
23130
- identify: options.identify ?? null,
23148
+ identify: options.identify,
23131
23149
  represent: options.represent ?? ((data) => data),
23132
- representTagName: options.representTagName ?? null
23150
+ representTagName: options.representTagName ?? (() => tagName)
23133
23151
  };
23134
23152
  }
23135
23153
  function parseYamlInteger$2(source) {
@@ -23397,11 +23415,10 @@ function simpleEscapeSequence(c) {
23397
23415
  return "";
23398
23416
  }
23399
23417
  }
23400
- var NOT_RESOLVED, MERGE_KEY, strTag, NULL_VALUES$1, nullCoreTag, nullJsonTag, NULL_VALUES, nullYaml11Tag, TRUE_VALUES$2, FALSE_VALUES$2, boolCoreTag, TRUE_VALUES$1, FALSE_VALUES$1, boolJsonTag, TRUE_VALUES, FALSE_VALUES, boolYaml11Tag, YAML_INTEGER_IMPLICIT_PATTERN$1, YAML_INTEGER_EXPLICIT_PATTERN$1, intCoreTag, YAML_INTEGER_IMPLICIT_PATTERN, YAML_INTEGER_EXPLICIT_PATTERN, intJsonTag, YAML_INTEGER_PATTERN, intYaml11Tag, YAML_FLOAT_PATTERN$1, YAML_FLOAT_SPECIAL_PATTERN$1, floatCoreTag, YAML_FLOAT_IMPLICIT_PATTERN, YAML_FLOAT_EXPLICIT_PATTERN, floatJsonTag, YAML_FLOAT_PATTERN, YAML_FLOAT_SPECIAL_PATTERN, floatYaml11Tag, mergeTag, BASE64_PATTERN, binaryTag, YAML_DATE_REGEXP, YAML_TIMESTAMP_REGEXP, timestampTag, seqTag, omapTag, pairsTag, mapTag, setTag, Schema, FAILSAFE_SCHEMA, JSON_SCHEMA, CORE_SCHEMA, YAML11_SCHEMA, realMapTag, legacyMapTag, simpleEscapeCheck, simpleEscapeMap, DEFAULT_TAG_HANDLERS, DEFAULT_CONSTRUCTOR_OPTIONS, NS_URI_CHAR, NS_TAG_CHAR, PATTERN_TAG_URI, PATTERN_TAG_SUFFIX, PATTERN_TAG_PREFIX, DEFAULT_PARSER_OPTIONS, DEFAULT_LOAD_OPTIONS, ESCAPE_SEQUENCES, DEFAULT_PRESENTER_OPTIONS, DEFAULT_DUMP_SCHEMA, DEFAULT_DUMP_OPTIONS;
23418
+ var NOT_RESOLVED, strTag, NULL_VALUES$1, nullCoreTag, nullJsonTag, NULL_VALUES, nullYaml11Tag, TRUE_VALUES$2, FALSE_VALUES$2, boolCoreTag, TRUE_VALUES$1, FALSE_VALUES$1, boolJsonTag, TRUE_VALUES, FALSE_VALUES, boolYaml11Tag, YAML_INTEGER_IMPLICIT_PATTERN$1, YAML_INTEGER_EXPLICIT_PATTERN$1, intCoreTag, YAML_INTEGER_IMPLICIT_PATTERN, YAML_INTEGER_EXPLICIT_PATTERN, intJsonTag, YAML_INTEGER_PATTERN, intYaml11Tag, YAML_FLOAT_PATTERN$1, YAML_FLOAT_SPECIAL_PATTERN$1, floatCoreTag, YAML_FLOAT_IMPLICIT_PATTERN, YAML_FLOAT_EXPLICIT_PATTERN, floatJsonTag, YAML_FLOAT_PATTERN, YAML_FLOAT_SPECIAL_PATTERN, floatYaml11Tag, mergeTag, BASE64_PATTERN, binaryTag, YAML_DATE_REGEXP, YAML_TIMESTAMP_REGEXP, timestampTag, seqTag, omapTag, pairsTag, mapTag, setTag, Schema, FAILSAFE_SCHEMA, JSON_SCHEMA, CORE_SCHEMA, YAML11_SCHEMA, DUMP_SCHEMA, realMapTag, legacyMapTag, EVENT_ID, SCALAR_STYLE, COLLECTION_STYLE, CHOMPING_MODE, simpleEscapeCheck, simpleEscapeMap, DEFAULT_TAG_HANDLERS, DEFAULT_CONSTRUCTOR_OPTIONS, NS_URI_CHAR, NS_TAG_CHAR, PATTERN_TAG_URI, PATTERN_TAG_SUFFIX, PATTERN_TAG_PREFIX, DEFAULT_PARSER_OPTIONS, DEFAULT_LOAD_OPTIONS, ESCAPE_SEQUENCES, DEFAULT_PRESENTER_OPTIONS, DEFAULT_DUMP_OPTIONS, EVENT_DOCUMENT, EVENT_SEQUENCE, EVENT_MAPPING, EVENT_SCALAR, EVENT_ALIAS, EVENT_POP, SCALAR_STYLE_PLAIN, SCALAR_STYLE_SINGLE_QUOTED, SCALAR_STYLE_DOUBLE_QUOTED, SCALAR_STYLE_LITERAL_BLOCK, SCALAR_STYLE_FOLDED_BLOCK, COLLECTION_STYLE_BLOCK, COLLECTION_STYLE_FLOW, CHOMPING_CLIP, CHOMPING_STRIP, CHOMPING_KEEP;
23401
23419
  var init_js_yaml = __esm({
23402
23420
  "node_modules/js-yaml/dist/js-yaml.mjs"() {
23403
23421
  NOT_RESOLVED = /* @__PURE__ */ Symbol("NOT_RESOLVED");
23404
- MERGE_KEY = /* @__PURE__ */ Symbol("MERGE_KEY");
23405
23422
  strTag = defineScalarTag("tag:yaml.org,2002:str", {
23406
23423
  resolve: (source) => source,
23407
23424
  identify: (data) => typeof data === "string"
@@ -23622,9 +23639,10 @@ var init_js_yaml = __esm({
23622
23639
  implicit: true,
23623
23640
  implicitFirstChars: ["<"],
23624
23641
  resolve: (source, isExplicit) => {
23625
- if (source === "<<" || isExplicit && source === "") return MERGE_KEY;
23642
+ if (source === "<<" || isExplicit && source === "") return "<<";
23626
23643
  return NOT_RESOLVED;
23627
- }
23644
+ },
23645
+ identify: () => false
23628
23646
  });
23629
23647
  BASE64_PATTERN = /^[A-Za-z0-9+/]*={0,2}$/;
23630
23648
  binaryTag = defineScalarTag("tag:yaml.org,2002:binary", {
@@ -23668,7 +23686,8 @@ var init_js_yaml = __esm({
23668
23686
  carrier.list.push(item);
23669
23687
  return "";
23670
23688
  },
23671
- finalize: (carrier) => carrier.list
23689
+ finalize: (carrier) => carrier.list,
23690
+ identify: () => false
23672
23691
  });
23673
23692
  pairsTag = defineSequenceTag("tag:yaml.org,2002:pairs", {
23674
23693
  create: () => [],
@@ -23684,7 +23703,8 @@ var init_js_yaml = __esm({
23684
23703
  if (keys.length !== 1) return "cannot resolve a pairs item";
23685
23704
  container.push([keys[0], object[keys[0]]]);
23686
23705
  return "";
23687
- }
23706
+ },
23707
+ identify: () => false
23688
23708
  });
23689
23709
  mapTag = defineMappingTag("tag:yaml.org,2002:map", {
23690
23710
  create: () => ({}),
@@ -23736,11 +23756,35 @@ var init_js_yaml = __esm({
23736
23756
  });
23737
23757
  Schema = class Schema2 {
23738
23758
  tags;
23759
+ /** @internal */
23739
23760
  implicitScalarTags;
23761
+ /**
23762
+ * Dispatch implicit scalar resolvers by `source.charAt(0)`. Each bucket holds
23763
+ * the resolvers that may match that key, in schema order; a key absent from
23764
+ * the map uses
23765
+ * {@link Schema.implicitScalarAnyFirstChar}
23766
+ * (resolvers that declared no first-char constraint, so they apply to any
23767
+ * first character).
23768
+ */
23740
23769
  implicitScalarByFirstChar;
23741
23770
  implicitScalarAnyFirstChar;
23771
+ /**
23772
+ * The default scalar tag (`!!str`), resolved once so the composer's fallback
23773
+ * for unresolved plain scalars avoids a keyed lookup per scalar.
23774
+ *
23775
+ * @internal
23776
+ */
23742
23777
  defaultScalarTag;
23778
+ /**
23779
+ * The default container tags (`!!seq` / `!!map`), used by the dumper: when a
23780
+ * value is identified by its default tag, the tag is implicit and not
23781
+ * printed. Undefined if the schema does not define them (then such values
23782
+ * can't be dumped).
23783
+ *
23784
+ * @internal
23785
+ */
23743
23786
  defaultSequenceTag;
23787
+ /** @internal */
23744
23788
  defaultMappingTag;
23745
23789
  exact;
23746
23790
  prefix;
@@ -23786,6 +23830,52 @@ var init_js_yaml = __esm({
23786
23830
  this.exact = exact;
23787
23831
  this.prefix = prefix;
23788
23832
  }
23833
+ /** @internal */
23834
+ lookupScalarTag(tagName) {
23835
+ const exactTag = this.exact.scalar[tagName];
23836
+ if (exactTag) return exactTag;
23837
+ for (const tag of this.prefix.scalar) if (tagName.startsWith(tag.tagName)) return tag;
23838
+ }
23839
+ /** @internal */
23840
+ lookupSequenceTag(tagName) {
23841
+ const exactTag = this.exact.sequence[tagName];
23842
+ if (exactTag) return exactTag;
23843
+ for (const tag of this.prefix.sequence) if (tagName.startsWith(tag.tagName)) return tag;
23844
+ }
23845
+ /** @internal */
23846
+ lookupMappingTag(tagName) {
23847
+ const exactTag = this.exact.mapping[tagName];
23848
+ if (exactTag) return exactTag;
23849
+ for (const tag of this.prefix.mapping) if (tagName.startsWith(tag.tagName)) return tag;
23850
+ }
23851
+ /** @internal */
23852
+ resolveImplicitScalarTag(source) {
23853
+ const candidates = this.implicitScalarByFirstChar.get(source.charAt(0)) ?? this.implicitScalarAnyFirstChar;
23854
+ for (const tag2 of candidates) {
23855
+ const value = tag2.resolve(source, false, tag2.tagName);
23856
+ if (value !== NOT_RESOLVED) return {
23857
+ value,
23858
+ tag: tag2
23859
+ };
23860
+ }
23861
+ const tag = this.defaultScalarTag;
23862
+ return {
23863
+ value: tag.resolve(source, false, tag.tagName),
23864
+ tag
23865
+ };
23866
+ }
23867
+ /**
23868
+ * Creates a new schema with the specified tags added. If a tag already
23869
+ * exists, it is replaced by the specified tag.
23870
+ *
23871
+ * @example
23872
+ *
23873
+ * ```javascript
23874
+ * import { CORE_SCHEMA, mergeTag, realMapTag } from 'js-yaml'
23875
+ *
23876
+ * const schema = CORE_SCHEMA.withTags(mergeTag, realMapTag)
23877
+ * ```
23878
+ */
23789
23879
  withTags(...tags) {
23790
23880
  let flatTags = [];
23791
23881
  for (const tag of tags) flatTags = flatTags.concat(tag);
@@ -23824,6 +23914,19 @@ var init_js_yaml = __esm({
23824
23914
  pairsTag,
23825
23915
  setTag
23826
23916
  ]);
23917
+ DUMP_SCHEMA = YAML11_SCHEMA.withTags({
23918
+ ...intYaml11Tag,
23919
+ resolve: (source, isExplicit, tagName) => {
23920
+ const result = intYaml11Tag.resolve(source, isExplicit, tagName);
23921
+ return result === NOT_RESOLVED ? intCoreTag.resolve(source, isExplicit, tagName) : result;
23922
+ }
23923
+ }, {
23924
+ ...floatYaml11Tag,
23925
+ resolve: (source, isExplicit, tagName) => {
23926
+ const result = floatYaml11Tag.resolve(source, isExplicit, tagName);
23927
+ return result === NOT_RESOLVED ? floatCoreTag.resolve(source, isExplicit, tagName) : result;
23928
+ }
23929
+ });
23827
23930
  realMapTag = defineMappingTag("tag:yaml.org,2002:map", {
23828
23931
  create: () => /* @__PURE__ */ new Map(),
23829
23932
  addPair: (container, key, value) => {
@@ -23873,6 +23976,30 @@ var init_js_yaml = __esm({
23873
23976
  return container[normalizedKey];
23874
23977
  }
23875
23978
  });
23979
+ EVENT_ID = {
23980
+ DOCUMENT: 1,
23981
+ SEQUENCE: 2,
23982
+ MAPPING: 3,
23983
+ SCALAR: 4,
23984
+ ALIAS: 5,
23985
+ POP: 6
23986
+ };
23987
+ SCALAR_STYLE = {
23988
+ PLAIN: 1,
23989
+ SINGLE_QUOTED: 2,
23990
+ DOUBLE_QUOTED: 3,
23991
+ LITERAL_BLOCK: 4,
23992
+ FOLDED_BLOCK: 5
23993
+ };
23994
+ COLLECTION_STYLE = {
23995
+ BLOCK: 1,
23996
+ FLOW: 2
23997
+ };
23998
+ CHOMPING_MODE = {
23999
+ CLIP: 1,
24000
+ STRIP: 2,
24001
+ KEEP: 3
24002
+ };
23876
24003
  simpleEscapeCheck = new Array(256);
23877
24004
  simpleEscapeMap = new Array(256);
23878
24005
  for (let i = 0; i < 256; i++) {
@@ -23933,28 +24060,31 @@ var init_js_yaml = __esm({
23933
24060
  forceQuotes: false,
23934
24061
  tagBeforeAnchor: false
23935
24062
  };
23936
- DEFAULT_DUMP_SCHEMA = YAML11_SCHEMA.withTags({
23937
- ...intYaml11Tag,
23938
- resolve: (source, isExplicit, tagName) => {
23939
- const result = intYaml11Tag.resolve(source, isExplicit, tagName);
23940
- return result === NOT_RESOLVED ? intCoreTag.resolve(source, isExplicit, tagName) : result;
23941
- }
23942
- }, {
23943
- ...floatYaml11Tag,
23944
- resolve: (source, isExplicit, tagName) => {
23945
- const result = floatYaml11Tag.resolve(source, isExplicit, tagName);
23946
- return result === NOT_RESOLVED ? floatCoreTag.resolve(source, isExplicit, tagName) : result;
23947
- }
23948
- });
23949
24063
  DEFAULT_DUMP_OPTIONS = {
23950
24064
  ...DEFAULT_PRESENTER_OPTIONS,
23951
- schema: DEFAULT_DUMP_SCHEMA,
24065
+ schema: DUMP_SCHEMA,
23952
24066
  skipInvalid: false,
23953
24067
  noRefs: false,
23954
24068
  flowLevel: -1,
23955
24069
  transform: () => {
23956
24070
  }
23957
24071
  };
24072
+ EVENT_DOCUMENT = EVENT_ID.DOCUMENT;
24073
+ EVENT_SEQUENCE = EVENT_ID.SEQUENCE;
24074
+ EVENT_MAPPING = EVENT_ID.MAPPING;
24075
+ EVENT_SCALAR = EVENT_ID.SCALAR;
24076
+ EVENT_ALIAS = EVENT_ID.ALIAS;
24077
+ EVENT_POP = EVENT_ID.POP;
24078
+ SCALAR_STYLE_PLAIN = SCALAR_STYLE.PLAIN;
24079
+ SCALAR_STYLE_SINGLE_QUOTED = SCALAR_STYLE.SINGLE_QUOTED;
24080
+ SCALAR_STYLE_DOUBLE_QUOTED = SCALAR_STYLE.DOUBLE_QUOTED;
24081
+ SCALAR_STYLE_LITERAL_BLOCK = SCALAR_STYLE.LITERAL_BLOCK;
24082
+ SCALAR_STYLE_FOLDED_BLOCK = SCALAR_STYLE.FOLDED_BLOCK;
24083
+ COLLECTION_STYLE_BLOCK = COLLECTION_STYLE.BLOCK;
24084
+ COLLECTION_STYLE_FLOW = COLLECTION_STYLE.FLOW;
24085
+ CHOMPING_CLIP = CHOMPING_MODE.CLIP;
24086
+ CHOMPING_STRIP = CHOMPING_MODE.STRIP;
24087
+ CHOMPING_KEEP = CHOMPING_MODE.KEEP;
23958
24088
  }
23959
24089
  });
23960
24090
 
@@ -27021,7 +27151,7 @@ var init_clients = __esm({
27021
27151
  ["gpt-5.1-codex", "2026-08-15"]
27022
27152
  ]);
27023
27153
  DEFAULT_OPENAI_CLI_MODEL = OPENAI_CLI_VENDOR_DEFAULT;
27024
- DEFAULT_ANTHROPIC_CLI_MODEL = "claude-sonnet-4-5";
27154
+ DEFAULT_ANTHROPIC_CLI_MODEL = "sonnet";
27025
27155
  DEFAULT_GEMINI_CLI_MODEL = "gemini-2.5-pro";
27026
27156
  XAI_BASE_URL = "https://api.x.ai/v1";
27027
27157
  PERPLEXITY_BASE_URL = "https://api.perplexity.ai";
@@ -28444,12 +28574,11 @@ function buildFallback(raw, d) {
28444
28574
  if (!d.isDict(raw)) return { api_on_quota: false };
28445
28575
  const v = raw["api_on_quota"];
28446
28576
  if (v === void 0) return { api_on_quota: false };
28447
- if (!d.isBool(v)) {
28448
- throw d.error(
28449
- `\`fallback.api_on_quota\`=${d.repr(v)} must be a boolean (got ${d.typeName(v)}).`
28450
- );
28451
- }
28452
- return { api_on_quota: v };
28577
+ if (d.isBool(v)) return { api_on_quota: v };
28578
+ if (d.isStr(v) && v === "ask") return { api_on_quota: "ask" };
28579
+ throw d.error(
28580
+ `\`fallback.api_on_quota\`=${d.repr(v)} must be \`false\`, \`true\` or \`'ask'\` (got ${d.typeName(v)}).`
28581
+ );
28453
28582
  }
28454
28583
  function buildSecondModel(entry, cls, locked, d) {
28455
28584
  if (!("second_model" in entry)) return null;
@@ -28479,24 +28608,7 @@ var init_fallback_config = __esm({
28479
28608
  }
28480
28609
  });
28481
28610
 
28482
- // src/scripts/ai_council/config.ts
28483
- var config_exports = {};
28484
- __export(config_exports, {
28485
- COUNCIL_CONFIG_ENV: () => COUNCIL_CONFIG_ENV,
28486
- COUNCIL_CONFIG_RELNAME: () => COUNCIL_CONFIG_RELNAME,
28487
- COUNCIL_CONFIG_USER_GLOBAL_REL: () => COUNCIL_CONFIG_USER_GLOBAL_REL,
28488
- CouncilConfigError: () => CouncilConfigError,
28489
- DEFAULT_CLI_CALLS_PER_DAY: () => DEFAULT_CLI_CALLS_PER_DAY2,
28490
- _RAW_KEY_PREFIXES: () => _RAW_KEY_PREFIXES,
28491
- _build_config: () => _build_config,
28492
- load_council_config: () => load_council_config,
28493
- resolve_api_key: () => resolve_api_key,
28494
- resolve_cli_call_caps: () => resolve_cli_call_caps,
28495
- resolve_config_path: () => resolve_config_path
28496
- });
28497
- import * as fs48 from "node:fs";
28498
- import * as os9 from "node:os";
28499
- import * as path48 from "node:path";
28611
+ // src/scripts/ai_council/py_format.ts
28500
28612
  function _pyReprStr(s) {
28501
28613
  const hasSingle = s.includes("'");
28502
28614
  const hasDouble = s.includes('"');
@@ -28583,6 +28695,37 @@ function _sortedListRepr(items) {
28583
28695
  function _pyOct(mode) {
28584
28696
  return `0o${mode.toString(8)}`;
28585
28697
  }
28698
+ var _Float;
28699
+ var init_py_format = __esm({
28700
+ "src/scripts/ai_council/py_format.ts"() {
28701
+ "use strict";
28702
+ _Float = class {
28703
+ constructor(value) {
28704
+ this.value = value;
28705
+ }
28706
+ value;
28707
+ };
28708
+ }
28709
+ });
28710
+
28711
+ // src/scripts/ai_council/config.ts
28712
+ var config_exports = {};
28713
+ __export(config_exports, {
28714
+ COUNCIL_CONFIG_ENV: () => COUNCIL_CONFIG_ENV,
28715
+ COUNCIL_CONFIG_RELNAME: () => COUNCIL_CONFIG_RELNAME,
28716
+ COUNCIL_CONFIG_USER_GLOBAL_REL: () => COUNCIL_CONFIG_USER_GLOBAL_REL,
28717
+ CouncilConfigError: () => CouncilConfigError,
28718
+ DEFAULT_CLI_CALLS_PER_DAY: () => DEFAULT_CLI_CALLS_PER_DAY2,
28719
+ _RAW_KEY_PREFIXES: () => _RAW_KEY_PREFIXES,
28720
+ _build_config: () => _build_config,
28721
+ load_council_config: () => load_council_config,
28722
+ resolve_api_key: () => resolve_api_key,
28723
+ resolve_cli_call_caps: () => resolve_cli_call_caps,
28724
+ resolve_config_path: () => resolve_config_path
28725
+ });
28726
+ import * as fs48 from "node:fs";
28727
+ import * as os9 from "node:os";
28728
+ import * as path48 from "node:path";
28586
28729
  function _pyInt2(value) {
28587
28730
  if (typeof value === "boolean") {
28588
28731
  return value ? 1 : 0;
@@ -29553,6 +29696,29 @@ function _build_member(name, cfg, default_mode = "auto", ignored = []) {
29553
29696
  }
29554
29697
  tier = tier_raw;
29555
29698
  }
29699
+ const verified_at_raw = _get(cfg, "verified_at", null);
29700
+ let verified_at = null;
29701
+ if (verified_at_raw !== null && verified_at_raw !== void 0) {
29702
+ if (verified_at_raw instanceof Date) {
29703
+ throw new CouncilConfigError(
29704
+ `members.${name}.verified_at must be QUOTED \u2014 write verified_at: "YYYY-MM-DD". Unquoted, YAML parses it as a date and silently rolls impossible values over (2026-13-45 becomes 2027-02-14), which would let a malformed stamp through.`
29705
+ );
29706
+ }
29707
+ const coerced = verified_at_raw;
29708
+ if (typeof coerced !== "string" || !/^\d{4}-\d{2}-\d{2}$/.test(coerced)) {
29709
+ throw new CouncilConfigError(
29710
+ `members.${name}.verified_at must be a 'YYYY-MM-DD' string when set (got ${_pyRepr6(verified_at_raw)}).`
29711
+ );
29712
+ }
29713
+ const [y, m, d] = coerced.split("-").map((x) => Number(x));
29714
+ const probe = new Date(Date.UTC(y, m - 1, d));
29715
+ if (probe.getUTCFullYear() !== y || probe.getUTCMonth() + 1 !== m || probe.getUTCDate() !== d) {
29716
+ throw new CouncilConfigError(
29717
+ `members.${name}.verified_at is not a real calendar date (got ${_pyRepr6(verified_at_raw)}).`
29718
+ );
29719
+ }
29720
+ verified_at = coerced;
29721
+ }
29556
29722
  const prompt_cache_raw = _get(cfg, "prompt_cache", null);
29557
29723
  let prompt_cache_ttl = "5m";
29558
29724
  if (prompt_cache_raw !== null && prompt_cache_raw !== void 0 && !_isBool(prompt_cache_raw)) {
@@ -29579,7 +29745,8 @@ function _build_member(name, cfg, default_mode = "auto", ignored = []) {
29579
29745
  model_ladder: ladder,
29580
29746
  participate_low_impact: participate_raw,
29581
29747
  tier,
29582
- prompt_cache_ttl
29748
+ prompt_cache_ttl,
29749
+ verified_at
29583
29750
  };
29584
29751
  }
29585
29752
  function resolve_cli_call_caps(raw) {
@@ -29763,7 +29930,7 @@ function _pyTruthy3(value) {
29763
29930
  }
29764
29931
  return Object.keys(value).length > 0;
29765
29932
  }
29766
- var import_yaml5, _VALID_PROVIDERS, _FALLBACK_DEPS, _RAW_KEY_PREFIXES, CouncilConfigError, _Float, _VALID_NECESSITY_MODES, _VALID_DISCLOSURE_MODES, _VALID_CHAIRMAN_MODES, COUNCIL_CONFIG_RELNAME, COUNCIL_CONFIG_USER_GLOBAL_REL, COUNCIL_CONFIG_ENV, _VALID_CRITIC_PROTOCOLS, _VALID_RESOLUTION_MODES, _IMPACT_CLASSES, _LOCKED_IMPACT_CLASSES, _DEFAULT_RESOLUTION_MODES, _VALID_MEMBER_MODES, _VALID_DISPATCH_MODES, DEFAULT_CLI_CALLS_PER_DAY2;
29933
+ var import_yaml5, _VALID_PROVIDERS, _FALLBACK_DEPS, _RAW_KEY_PREFIXES, CouncilConfigError, _VALID_NECESSITY_MODES, _VALID_DISCLOSURE_MODES, _VALID_CHAIRMAN_MODES, COUNCIL_CONFIG_RELNAME, COUNCIL_CONFIG_USER_GLOBAL_REL, COUNCIL_CONFIG_ENV, _VALID_CRITIC_PROTOCOLS, _VALID_RESOLUTION_MODES, _IMPACT_CLASSES, _LOCKED_IMPACT_CLASSES, _DEFAULT_RESOLUTION_MODES, _VALID_MEMBER_MODES, _VALID_DISPATCH_MODES, DEFAULT_CLI_CALLS_PER_DAY2;
29767
29934
  var init_config = __esm({
29768
29935
  "src/scripts/ai_council/config.ts"() {
29769
29936
  "use strict";
@@ -29773,6 +29940,7 @@ var init_config = __esm({
29773
29940
  init_clients();
29774
29941
  init_quorum();
29775
29942
  init_fallback_config();
29943
+ init_py_format();
29776
29944
  _VALID_PROVIDERS = /* @__PURE__ */ new Set([
29777
29945
  "anthropic",
29778
29946
  "openai",
@@ -29804,12 +29972,6 @@ var init_config = __esm({
29804
29972
  this.name = "CouncilConfigError";
29805
29973
  }
29806
29974
  };
29807
- _Float = class {
29808
- constructor(value) {
29809
- this.value = value;
29810
- }
29811
- value;
29812
- };
29813
29975
  _VALID_NECESSITY_MODES = /* @__PURE__ */ new Set([
29814
29976
  "off",
29815
29977
  "educate",
@@ -30422,6 +30584,25 @@ function autoUnavailableReason(provider, binary, cliAuthed) {
30422
30584
  }
30423
30585
  return `no transport available: \`${expected}\` is on PATH but not authenticated and no key resolves \u2014 log in to the CLI, or add an api_key_ref`;
30424
30586
  }
30587
+ function effectiveApiOnQuota(policy) {
30588
+ if (policy.apiOnQuota === "ask") return policy.billingGrant === true;
30589
+ return policy.apiOnQuota === true;
30590
+ }
30591
+ function parseApiOnQuota(raw) {
30592
+ if (typeof raw === "boolean") return raw;
30593
+ if (raw === void 0 || raw === null) return false;
30594
+ if (typeof raw === "string") {
30595
+ const s = raw.trim().toLowerCase();
30596
+ if (s === "ask") return "ask";
30597
+ if (s === "true" || s === "yes" || s === "on" || s === "1") return true;
30598
+ if (s === "" || s === "false" || s === "no" || s === "off" || s === "0") {
30599
+ return false;
30600
+ }
30601
+ }
30602
+ throw new Error(
30603
+ `ai_council.fallback.api_on_quota: expected false | true | 'ask', got ${JSON.stringify(raw)}`
30604
+ );
30605
+ }
30425
30606
  function classifyCliFailure(raw) {
30426
30607
  const s = raw.trim().toLowerCase();
30427
30608
  if (s === "binary_missing" || s === "file_not_found") return "binary_missing";
@@ -30449,7 +30630,7 @@ function classifyCliFailure(raw) {
30449
30630
  }
30450
30631
  function isFallbackEligibleUnder(failure, policy) {
30451
30632
  if (FALLBACK_ELIGIBLE.has(failure)) return true;
30452
- return policy.apiOnQuota && failure === "quota_exhausted";
30633
+ return effectiveApiOnQuota(policy) && failure === "quota_exhausted";
30453
30634
  }
30454
30635
  function absentReasonFromCliFailure(failure) {
30455
30636
  switch (failure) {
@@ -34280,9 +34461,9 @@ function detectToolPresence(root) {
34280
34461
  agentsMd: existsSync28(join50(root, "AGENTS.md"))
34281
34462
  };
34282
34463
  }
34283
- function isDir3(path81) {
34464
+ function isDir3(path83) {
34284
34465
  try {
34285
- return statSync34(path81).isDirectory();
34466
+ return statSync34(path83).isDirectory();
34286
34467
  } catch {
34287
34468
  return false;
34288
34469
  }
@@ -34933,10 +35114,12 @@ function classifyAuthorization(prompt) {
34933
35114
  }
34934
35115
  for (const line of _commandLines(fence)) {
34935
35116
  for (const { op, re } of PASTED_COMMANDS) {
34936
- if (re.test(line)) {
35117
+ if (!re.test(line)) continue;
35118
+ if (op !== null) {
34937
35119
  authorized.add(op);
34938
35120
  evidence[op] = `pasted command: "${line.slice(0, 80)}"`;
34939
35121
  }
35122
+ break;
34940
35123
  }
34941
35124
  }
34942
35125
  }
@@ -35071,6 +35254,7 @@ var init_git_authorization_hook = __esm({
35071
35254
  "branch",
35072
35255
  "pr-create",
35073
35256
  "pr-merge",
35257
+ "pr-merge-auto",
35074
35258
  "tag",
35075
35259
  "release",
35076
35260
  "publish"
@@ -35084,8 +35268,29 @@ var init_git_authorization_hook = __esm({
35084
35268
  op: "pr-create",
35085
35269
  re: /\b(erstell(e|en)?|mach(e|en)?|leg(e|en)?\s+an|(er)?(ö|oe)ffne|open|create|raise|aufmachen)\b[^.\n]{0,30}\b(pr|pull[- ]request)\b|\b(pr|pull[- ]request)\b[^.\n]{0,20}\b(erstellen|aufmachen|anlegen|(er)?(ö|oe)ffnen)\b/i
35086
35270
  },
35087
- // `merge` as an ACTION, never as the noun in "merge conflict" / "merge commit".
35088
- { op: "pr-merge", re: /\b(merge|merg(e|en|st|t)|zusammenf(ü|ue)hren|reinmergen)\b(?!\s*[- ]?(conflict|konflikt|commit|base|queue|state|status))/i },
35271
+ // `merge` as an ACTION, never as the noun in "merge conflict" / "merge commit",
35272
+ // and never under a NEGATION.
35273
+ //
35274
+ // The negation half closes a measured defect: probed directly against
35275
+ // `classifyAuthorization`, "nicht mergen", "don't merge this" and
35276
+ // "never auto-merge" each returned ["pr-merge"] — a prompt saying DO NOT
35277
+ // MERGE authorized a merge. The noun-sense lookahead was never a negator.
35278
+ //
35279
+ // The lookBEHIND is line-scoped by `[^.!?\n]` on purpose, the same scoping
35280
+ // `turn_end_gate_hook.ts` uses for its own negation exclusion (`:330`) and
35281
+ // its negated-claim window (`:490-493`). A sentence boundary ends a
35282
+ // negation's reach: "Do not push. Merge PR #12." is two instructions, and a
35283
+ // guard that let the first suppress the second would silently stop
35284
+ // authorizing merges the user DID order — the failure mode that is worse
35285
+ // than the defect, because nothing happens and nothing says why.
35286
+ //
35287
+ // Reusing that vocabulary rather than inventing a third is deliberate: two
35288
+ // negation vocabularies in one tree drift, and the drift is invisible until
35289
+ // a prompt lands in the gap between them.
35290
+ {
35291
+ op: "pr-merge",
35292
+ re: /(?<!\b(nicht|nichts|kein(e|en|em|er|es)?|niemals|nie|no|not|dont|don't|never|without|ohne)\b[^.!?\n]{0,30})\b(merge|merg(e|en|st|t)|zusammenf(ü|ue)hren|reinmergen)\b(?!\s*[- ]?(conflict|konflikt|commit|base|queue|state|status))/i
35293
+ },
35089
35294
  // A tag is an ACTION here — bare "Tag" is the German word for day, and
35090
35295
  // "Version" is an ordinary noun. Both authorized a BLOCK op before this.
35091
35296
  { op: "tag", re: /\b(tagge(n|st)?|tag\s+(setzen|anlegen|erstellen)|git\s+tag|--tags|--follow-tags)\b/i },
@@ -35101,6 +35306,16 @@ var init_git_authorization_hook = __esm({
35101
35306
  { op: "publish", re: /\bnpm\s+publish\b/i },
35102
35307
  { op: "tag", re: /\bgit\s+push\s+[^\n]*--tags\b|\bgit\s+tag\s+-a\b/i },
35103
35308
  { op: "release", re: /\bgh\s+release\s+create\b/i },
35309
+ // ORDER IS LOAD-BEARING: the auto variants precede the plain merge, because
35310
+ // the first match wins and `gh pr merge 12 --auto` also matches the plain
35311
+ // pattern. Same rule the block-side table states for `git push --tags`.
35312
+ //
35313
+ // The DE-ESCALATING forms come first of all, and they map to no op at all:
35314
+ // `--disable-auto` and `disablePullRequestAutoMerge` turn the capability OFF.
35315
+ // Requiring merge authorization to switch auto-merge off is a live deadlock,
35316
+ // and it is why this cannot ship after the split rather than with it.
35317
+ { op: null, re: /\bgh\s+pr\s+merge\b[^\n]*--disable-auto\b|\bdisablePullRequestAutoMerge\b/i },
35318
+ { op: "pr-merge-auto", re: /\bgh\s+pr\s+merge\b[^\n]*--auto\b|\benablePullRequestAutoMerge\b/i },
35104
35319
  { op: "pr-merge", re: /\bgh\s+pr\s+merge\b/i },
35105
35320
  { op: "pr-create", re: /\bgh\s+pr\s+create\b/i },
35106
35321
  { op: "push", re: /\bgit\s+push\b/i },
@@ -35444,7 +35659,10 @@ var init_block_unauthorized_git = __esm({
35444
35659
  "publish",
35445
35660
  "tag",
35446
35661
  "release",
35447
- "pr-merge"
35662
+ "pr-merge",
35663
+ // Enabling auto-merge commits the outcome to a condition the agent does not
35664
+ // control, so it is blocked on the same terms as the merge it schedules.
35665
+ "pr-merge-auto"
35448
35666
  ]);
35449
35667
  WARN_OPS = /* @__PURE__ */ new Set([
35450
35668
  "commit",
@@ -35464,10 +35682,25 @@ var init_block_unauthorized_git = __esm({
35464
35682
  op: "tag",
35465
35683
  re: new RegExp(`${P}git\\s+${G}push\\b[^\\n;|&]*(--tags|--follow-tags|refs\\/tags\\/)`, "i")
35466
35684
  },
35685
+ // ORDER IS LOAD-BEARING, per this table's own rule that the most specific
35686
+ // pattern wins: `gh pr merge 12 --auto` matches the plain merge pattern too.
35687
+ //
35688
+ // The GraphQL mutation needs its OWN pattern rather than a widening of
35689
+ // `ghApiWrite()`. That helper requires BOTH a REST-shaped path and an
35690
+ // explicit write method, and `gh api graphql -f query='mutation{...}'` has
35691
+ // neither — widening it to reach this would loosen every other op that uses
35692
+ // it, which is a bigger change than the defect.
35693
+ {
35694
+ op: "pr-merge-auto",
35695
+ re: new RegExp(
35696
+ `${P}gh\\s+pr\\s+merge\\b(?=[^\\n]*--auto\\b)|${P}gh\\s+api\\b(?=[^\\n]*enablePullRequestAutoMerge\\b)`,
35697
+ "i"
35698
+ )
35699
+ },
35467
35700
  {
35468
35701
  op: "pr-merge",
35469
35702
  re: new RegExp(
35470
- `${P}gh\\s+pr\\s+merge\\b|${ghApiWrite("\\/pulls\\/\\d+\\/merge\\b").source}`,
35703
+ `${P}gh\\s+pr\\s+merge\\b(?![^\\n]*--(auto|disable-auto)\\b)|${ghApiWrite("\\/pulls\\/\\d+\\/merge\\b").source}`,
35471
35704
  "i"
35472
35705
  )
35473
35706
  },
@@ -36268,6 +36501,11 @@ var init_subagent_capsule = __esm({
36268
36501
  });
36269
36502
 
36270
36503
  // src/scripts/_lib/subagent_response.ts
36504
+ function countContractFields(input) {
36505
+ if (input === null || typeof input !== "object") return 0;
36506
+ const r = input;
36507
+ return RESPONSE_REQUIRED_FIELDS.filter((k) => Object.hasOwn(r, k)).length;
36508
+ }
36271
36509
  function validateResponse(input) {
36272
36510
  const errors = [];
36273
36511
  if (input === null || typeof input !== "object") {
@@ -36347,7 +36585,7 @@ function validateResponse(input) {
36347
36585
  }
36348
36586
  return { valid: errors.length === 0, errors };
36349
36587
  }
36350
- var MAX_SUMMARY_CHARS, MAX_RESPONSE_LINE_CHARS, MAX_RESPONSE_ENTRIES, MAX_ARTIFACT_REF_CHARS, MAX_ENVELOPE_CHARS, CONFIDENCE;
36588
+ var MAX_SUMMARY_CHARS, MAX_RESPONSE_LINE_CHARS, MAX_RESPONSE_ENTRIES, MAX_ARTIFACT_REF_CHARS, MAX_ENVELOPE_CHARS, CONFIDENCE, RESPONSE_REQUIRED_FIELDS;
36351
36589
  var init_subagent_response = __esm({
36352
36590
  "src/scripts/_lib/subagent_response.ts"() {
36353
36591
  "use strict";
@@ -36358,6 +36596,13 @@ var init_subagent_response = __esm({
36358
36596
  MAX_ARTIFACT_REF_CHARS = 200;
36359
36597
  MAX_ENVELOPE_CHARS = 12e3;
36360
36598
  CONFIDENCE = /* @__PURE__ */ new Set(["low", "medium", "high"]);
36599
+ RESPONSE_REQUIRED_FIELDS = [
36600
+ "summary",
36601
+ "handoff",
36602
+ "confidence",
36603
+ "findings",
36604
+ "risks"
36605
+ ];
36361
36606
  }
36362
36607
  });
36363
36608
 
@@ -36394,16 +36639,25 @@ function extractParentId(payload, ownId) {
36394
36639
  return null;
36395
36640
  }
36396
36641
  function classifyEnvelope(message) {
36397
- if (message === null || !message.trim()) return { verdict: "no_message", error_count: 0 };
36642
+ if (message === null || !message.trim()) {
36643
+ return { verdict: "no_message", error_count: 0, field_hits: 0 };
36644
+ }
36398
36645
  const candidates = _jsonObjectCandidates(message);
36399
- if (candidates.length === 0) return { verdict: "no_envelope", error_count: 0 };
36646
+ if (candidates.length === 0) return { verdict: "no_envelope", error_count: 0, field_hits: 0 };
36400
36647
  let best = null;
36401
36648
  for (const candidate of candidates) {
36402
36649
  const result = validateResponse(candidate);
36403
- if (result.valid) return { verdict: "ok", error_count: 0 };
36404
- if (best === null) best = { verdict: "fail", error_count: result.errors.length };
36650
+ const fieldHits = countContractFields(candidate);
36651
+ if (result.valid) return { verdict: "ok", error_count: 0, field_hits: fieldHits };
36652
+ if (best === null || fieldHits > best.field_hits) {
36653
+ best = {
36654
+ verdict: fieldHits === 0 ? "foreign_object" : "fail",
36655
+ error_count: result.errors.length,
36656
+ field_hits: fieldHits
36657
+ };
36658
+ }
36405
36659
  }
36406
- return best ?? { verdict: "no_envelope", error_count: 0 };
36660
+ return best ?? { verdict: "no_envelope", error_count: 0, field_hits: 0 };
36407
36661
  }
36408
36662
  function _jsonObjectCandidates(message) {
36409
36663
  const texts = [];
@@ -36666,6 +36920,9 @@ function handleStop(root, payload, nowIso, sessionId) {
36666
36920
  start_seen: rec !== null,
36667
36921
  envelope_parse: parse6.verdict,
36668
36922
  envelope_error_count: parse6.error_count,
36923
+ // Beside the count, never instead of it: the count says how wrong the
36924
+ // candidate was, this says whether it was aimed at the envelope.
36925
+ envelope_field_hits: parse6.field_hits,
36669
36926
  concurrent_open: countOpen(root)
36670
36927
  });
36671
36928
  }
@@ -43212,29 +43469,116 @@ function renderPostureLines(postures, apiOnQuota) {
43212
43469
  const lines = live.map(
43213
43470
  ([name, p]) => ` fallback ${name}: ` + (p === "api" ? "would fall back to api" : "no api rung \u2014 a lost cli transport loses the seat")
43214
43471
  );
43215
- lines.push(
43216
- ` fallback quota api_on_quota: ${apiOnQuota ? "on" : "off"} \u2014 an exhausted cli quota ${apiOnQuota ? "MAY" : "may not"} retry on the metered rung`
43217
- );
43472
+ const word = apiOnQuota === "ask" ? "ask" : apiOnQuota ? "on" : "off";
43473
+ const consequence = apiOnQuota === "ask" ? " \u2014 an exhausted cli quota PARKS the seat and the round closes with a question, unless a run-scoped billing grant is already in force" : apiOnQuota ? " \u2014 an exhausted cli quota MAY retry on the metered rung" : " \u2014 an exhausted cli quota may not retry on the metered rung";
43474
+ lines.push(` fallback quota api_on_quota: ${word}${consequence}`);
43218
43475
  return lines;
43219
43476
  }
43477
+ function renderBillingGateLines(parked, opts) {
43478
+ if (parked.length === 0) return [];
43479
+ const seats = [...new Set(parked)].sort();
43480
+ const cost = opts.estimatedUsd === null ? "unknown \u2014 no priced estimate for the retry" : `~$${opts.estimatedUsd.toFixed(2)}`;
43481
+ return [
43482
+ "",
43483
+ "HUMAN GATE \u2014 plan quota exhausted, metered spend not authorised",
43484
+ ` parked seats ${seats.join(", ")}`,
43485
+ ` retry cost ${cost}`,
43486
+ // The command is printed rather than described because the whole
43487
+ // mechanism fails if answering it takes a lookup: an operator who has
43488
+ // to go find the syntax is an operator who says yes tomorrow, on a run
43489
+ // that has already ended.
43490
+ ` to authorise agent-config council:grant-billing ${opts.runId}`,
43491
+ " to decline do nothing \u2014 the grant is never implied by silence"
43492
+ ];
43493
+ }
43220
43494
  var init_council_fallback_posture = __esm({
43221
43495
  "src/scripts/_lib/council_fallback_posture.ts"() {
43222
43496
  "use strict";
43223
43497
  }
43224
43498
  });
43225
43499
 
43500
+ // src/scripts/_lib/billing_grant.ts
43501
+ import * as fs76 from "node:fs";
43502
+ import * as path74 from "node:path";
43503
+ function grantFile(repoRoot, runId) {
43504
+ return path74.join(
43505
+ repoRoot,
43506
+ BILLING_GRANT_DIR_REL,
43507
+ `${runId.replace(/[^A-Za-z0-9_-]/g, "_")}.json`
43508
+ );
43509
+ }
43510
+ function issueBillingGrant(repoRoot, runId, now = () => /* @__PURE__ */ new Date()) {
43511
+ const file = grantFile(repoRoot, runId);
43512
+ const existing = _read(file);
43513
+ if (existing !== null && existing.run_id === runId) return existing;
43514
+ const grant = { run_id: runId, issued_at: now().toISOString() };
43515
+ fs76.mkdirSync(path74.dirname(file), { recursive: true });
43516
+ fs76.writeFileSync(file, `${JSON.stringify(grant, null, 2)}
43517
+ `, "utf8");
43518
+ return grant;
43519
+ }
43520
+ function isBillingGrantActive(repoRoot, runId, env = process.env, now = () => /* @__PURE__ */ new Date()) {
43521
+ if ((env[BILLING_GRANT_ENV] ?? "").trim() !== runId) return false;
43522
+ const grant = _read(grantFile(repoRoot, runId));
43523
+ if (grant === null || grant.run_id !== runId) return false;
43524
+ const age = now().getTime() - Date.parse(grant.issued_at);
43525
+ return Number.isFinite(age) && age >= 0 && age <= BILLING_GRANT_MAX_AGE_MS;
43526
+ }
43527
+ function hasBillingGrant(repoRoot, env = process.env, now = () => /* @__PURE__ */ new Date()) {
43528
+ const runId = (env[BILLING_GRANT_ENV] ?? "").trim();
43529
+ if (runId === "") return false;
43530
+ return isBillingGrantActive(repoRoot, runId, env, now);
43531
+ }
43532
+ function revokeBillingGrant(repoRoot, runId) {
43533
+ try {
43534
+ fs76.unlinkSync(grantFile(repoRoot, runId));
43535
+ } catch {
43536
+ }
43537
+ }
43538
+ function _read(file) {
43539
+ try {
43540
+ const raw = JSON.parse(fs76.readFileSync(file, "utf8"));
43541
+ if (raw === null || typeof raw !== "object") return null;
43542
+ const o = raw;
43543
+ if (typeof o.run_id !== "string" || typeof o.issued_at !== "string") return null;
43544
+ return { run_id: o.run_id, issued_at: o.issued_at };
43545
+ } catch {
43546
+ return null;
43547
+ }
43548
+ }
43549
+ function currentRunId(env = process.env) {
43550
+ for (const key of [BILLING_GRANT_ENV, "AC_RUN_ID", "CLAUDE_CODE_SESSION_ID"]) {
43551
+ const v = (env[key] ?? "").trim();
43552
+ if (v !== "") return v;
43553
+ }
43554
+ return null;
43555
+ }
43556
+ var BILLING_GRANT_ENV, BILLING_GRANT_DIR_REL, BILLING_GRANT_MAX_AGE_MS;
43557
+ var init_billing_grant = __esm({
43558
+ "src/scripts/_lib/billing_grant.ts"() {
43559
+ "use strict";
43560
+ BILLING_GRANT_ENV = "AC_BILLING_GRANT";
43561
+ BILLING_GRANT_DIR_REL = path74.join("agents", "runtime", "billing-grants");
43562
+ BILLING_GRANT_MAX_AGE_MS = 24 * 60 * 60 * 1e3;
43563
+ }
43564
+ });
43565
+
43226
43566
  // src/scripts/_lib/council_fallback_wiring.ts
43227
43567
  function isRefusal(exc) {
43228
43568
  if (exc instanceof CouncilConfigError) return true;
43229
43569
  return exc instanceof Error && REFUSAL_NAMES.has(exc.constructor.name);
43230
43570
  }
43231
43571
  function buildFallbackOptions(deps) {
43572
+ const parked = [];
43232
43573
  return {
43233
43574
  api_on_quota: deps.apiOnQuota,
43575
+ billing_grant: deps.billingGrant === true,
43576
+ parked,
43234
43577
  // The orchestrator is a pure library and holds no sink; this is it.
43235
43578
  // One line per establishing escalation, so attendance analysis can
43236
43579
  // tell a seat SAVED by the fallback from one that was natively api.
43237
43580
  on_event: (e) => {
43581
+ if (e.outcome === "awaiting_grant") parked.push(e.provider);
43238
43582
  try {
43239
43583
  deps.emit({
43240
43584
  action: "transport_fallback",
@@ -43263,10 +43607,25 @@ function buildFallbackOptions(deps) {
43263
43607
  }
43264
43608
  };
43265
43609
  }
43610
+ function wireCouncilFallback(out, ai, d) {
43611
+ if (out === null) return;
43612
+ const cfg = d.isDict(ai["fallback"]) ? ai["fallback"] : {};
43613
+ out.options = buildFallbackOptions({
43614
+ apiOnQuota: parseApiOnQuota(cfg["api_on_quota"]),
43615
+ billingGrant: hasBillingGrant(d.repoRoot),
43616
+ hasApiRung: d.hasApiRung,
43617
+ memberConfig: (p) => d.membersCfg[p] || {},
43618
+ modelOverride: (p) => d.overrides[p] ?? null,
43619
+ constructApi: d.constructApi,
43620
+ emit: d.emit
43621
+ });
43622
+ }
43266
43623
  var REFUSAL_NAMES;
43267
43624
  var init_council_fallback_wiring = __esm({
43268
43625
  "src/scripts/_lib/council_fallback_wiring.ts"() {
43269
43626
  "use strict";
43627
+ init_transport_resolver();
43628
+ init_billing_grant();
43270
43629
  init_config();
43271
43630
  REFUSAL_NAMES = /* @__PURE__ */ new Set([
43272
43631
  "CouncilDisabledError",
@@ -43287,6 +43646,107 @@ var init_council_fallback_wiring = __esm({
43287
43646
  }
43288
43647
  });
43289
43648
 
43649
+ // src/scripts/_lib/quota_parked.ts
43650
+ import * as fs77 from "node:fs";
43651
+ import * as path75 from "node:path";
43652
+ function markerFile(repoRoot, runId) {
43653
+ return path75.join(
43654
+ repoRoot,
43655
+ QUOTA_PARKED_DIR_REL,
43656
+ `${runId.replace(/[^A-Za-z0-9_-]/g, "_")}.json`
43657
+ );
43658
+ }
43659
+ function writeQuotaParked(repoRoot, runId, providers, now = () => /* @__PURE__ */ new Date()) {
43660
+ const file = markerFile(repoRoot, runId);
43661
+ const existing = readMarker(file);
43662
+ const merged = [.../* @__PURE__ */ new Set([...existing?.providers ?? [], ...providers])].sort();
43663
+ const marker = {
43664
+ run_id: runId,
43665
+ providers: merged,
43666
+ parked_at: existing?.parked_at ?? now().toISOString()
43667
+ };
43668
+ fs77.mkdirSync(path75.dirname(file), { recursive: true });
43669
+ fs77.writeFileSync(file, `${JSON.stringify(marker, null, 2)}
43670
+ `, "utf8");
43671
+ return marker;
43672
+ }
43673
+ function readMarker(file) {
43674
+ try {
43675
+ const raw = JSON.parse(fs77.readFileSync(file, "utf8"));
43676
+ if (raw === null || typeof raw !== "object") return null;
43677
+ const o = raw;
43678
+ if (typeof o["run_id"] !== "string" || typeof o["parked_at"] !== "string") return null;
43679
+ if (!Array.isArray(o["providers"])) return null;
43680
+ const providers = o["providers"].filter((p) => typeof p === "string");
43681
+ return { run_id: o["run_id"], providers, parked_at: o["parked_at"] };
43682
+ } catch {
43683
+ return null;
43684
+ }
43685
+ }
43686
+ var QUOTA_PARKED_DIR_REL;
43687
+ var init_quota_parked = __esm({
43688
+ "src/scripts/_lib/quota_parked.ts"() {
43689
+ "use strict";
43690
+ QUOTA_PARKED_DIR_REL = path75.join("agents", "runtime", "state", "quota-parked");
43691
+ }
43692
+ });
43693
+
43694
+ // src/scripts/_lib/billing_grant_cli.ts
43695
+ function billingArgSpec(cmd) {
43696
+ return BILLING_SUBCOMMANDS.includes(cmd) ? { positionals: ["run_id"], opts: [], requiredOpts: [] } : null;
43697
+ }
43698
+ function handleBillingCommand(cmd, runId, d) {
43699
+ if (cmd === "grant-billing") return grantBilling(String(runId ?? ""), d);
43700
+ if (cmd === "revoke-billing") return revokeBilling(String(runId ?? ""), d);
43701
+ return null;
43702
+ }
43703
+ function grantBilling(runId, d) {
43704
+ if (runId.trim() === "") {
43705
+ d.stderr("\u274C council:grant-billing: a run id is required.\n");
43706
+ return 2;
43707
+ }
43708
+ const g = issueBillingGrant(d.repoRoot, runId.trim());
43709
+ d.stdout(`\u2705 billing grant recorded for run ${g.run_id} (issued ${g.issued_at})
43710
+ `);
43711
+ d.stdout(` export ${BILLING_GRANT_ENV}=${g.run_id}
43712
+ `);
43713
+ const live = hasBillingGrant(d.repoRoot) ? "yes" : "not until the export above is set";
43714
+ d.stdout(` in force: ${live}
43715
+ `);
43716
+ return 0;
43717
+ }
43718
+ function revokeBilling(runId, d) {
43719
+ if (runId.trim() === "") {
43720
+ d.stderr("\u274C council:revoke-billing: a run id is required.\n");
43721
+ return 2;
43722
+ }
43723
+ revokeBillingGrant(d.repoRoot, runId.trim());
43724
+ d.stdout(`\u2705 billing grant revoked for run ${runId.trim()}
43725
+ `);
43726
+ return 0;
43727
+ }
43728
+ function printBillingGate(parked, d) {
43729
+ const runId = currentRunId();
43730
+ if (parked.length > 0 && runId !== null) writeQuotaParked(d.repoRoot, runId, parked);
43731
+ for (const line of renderBillingGateLines(parked, {
43732
+ runId: runId ?? "<run-id>",
43733
+ estimatedUsd: null
43734
+ })) {
43735
+ d.stdout(`${line}
43736
+ `);
43737
+ }
43738
+ }
43739
+ var BILLING_SUBCOMMANDS;
43740
+ var init_billing_grant_cli = __esm({
43741
+ "src/scripts/_lib/billing_grant_cli.ts"() {
43742
+ "use strict";
43743
+ init_billing_grant();
43744
+ init_council_fallback_posture();
43745
+ init_quota_parked();
43746
+ BILLING_SUBCOMMANDS = ["grant-billing", "revoke-billing"];
43747
+ }
43748
+ });
43749
+
43290
43750
  // src/scripts/ai_council/low_impact_corpus.ts
43291
43751
  var low_impact_corpus_exports = {};
43292
43752
  __export(low_impact_corpus_exports, {
@@ -43297,7 +43757,7 @@ __export(low_impact_corpus_exports, {
43297
43757
  load_validated_phrases: () => load_validated_phrases,
43298
43758
  parse_corpus_strict: () => parse_corpus_strict
43299
43759
  });
43300
- import * as fs76 from "node:fs";
43760
+ import * as fs78 from "node:fs";
43301
43761
  function _entry(phrase, normalised, section, line_no, trailing_metadata = "") {
43302
43762
  return { phrase, normalised, section, line_no, trailing_metadata };
43303
43763
  }
@@ -43470,10 +43930,10 @@ function _checkHeadingDrift(text, title) {
43470
43930
  }
43471
43931
  function parse_corpus_strict(corpusPath) {
43472
43932
  const p = corpusPath;
43473
- if (!fs76.existsSync(p)) {
43933
+ if (!fs78.existsSync(p)) {
43474
43934
  return new CorpusParseResult();
43475
43935
  }
43476
- const text = fs76.readFileSync(p, { encoding: "utf-8" });
43936
+ const text = fs78.readFileSync(p, { encoding: "utf-8" });
43477
43937
  const allTitles = _SECTION_KEYS.map((k) => _SECTION_TITLES[k]);
43478
43938
  const resultSections = {
43479
43939
  validated: [],
@@ -43536,10 +43996,10 @@ function load_anti_example_phrases(corpusPath) {
43536
43996
  }
43537
43997
  function load_corpus_lock(yamlPath) {
43538
43998
  const p = yamlPath;
43539
- if (!fs76.existsSync(p)) {
43999
+ if (!fs78.existsSync(p)) {
43540
44000
  return new CorpusParseResult();
43541
44001
  }
43542
- const parsed = (0, import_yaml7.parse)(fs76.readFileSync(p, { encoding: "utf-8" }), { version: "1.1" });
44002
+ const parsed = (0, import_yaml7.parse)(fs78.readFileSync(p, { encoding: "utf-8" }), { version: "1.1" });
43543
44003
  const doc = parsed === null || parsed === void 0 ? {} : parsed;
43544
44004
  const schemaVersion = doc["schema_version"];
43545
44005
  if (schemaVersion !== 1) {
@@ -43601,7 +44061,7 @@ function _deriveLockPath(corpusPath) {
43601
44061
  }
43602
44062
  function _loadSectionFromLock(corpusPath, section) {
43603
44063
  const lockPath = _deriveLockPath(corpusPath);
43604
- if (!fs76.existsSync(lockPath)) {
44064
+ if (!fs78.existsSync(lockPath)) {
43605
44065
  return null;
43606
44066
  }
43607
44067
  try {
@@ -43613,10 +44073,10 @@ function _loadSectionFromLock(corpusPath, section) {
43613
44073
  }
43614
44074
  function _loadSectionLenient(corpusPath, section) {
43615
44075
  const p = corpusPath;
43616
- if (!fs76.existsSync(p)) {
44076
+ if (!fs78.existsSync(p)) {
43617
44077
  return [];
43618
44078
  }
43619
- const text = fs76.readFileSync(p, { encoding: "utf-8" });
44079
+ const text = fs78.readFileSync(p, { encoding: "utf-8" });
43620
44080
  const allTitles = _SECTION_KEYS.map((k) => _SECTION_TITLES[k]);
43621
44081
  const bounds = _sectionBounds(text, _SECTION_TITLES[section], allTitles);
43622
44082
  if (bounds === null) {
@@ -44396,8 +44856,8 @@ var init_necessity = __esm({
44396
44856
  });
44397
44857
 
44398
44858
  // src/scripts/ai_council/budget_guard.ts
44399
- import * as fs77 from "node:fs";
44400
- import * as path74 from "node:path";
44859
+ import * as fs79 from "node:fs";
44860
+ import * as path76 from "node:path";
44401
44861
  function _resolveLedgerPath(p) {
44402
44862
  if (p !== null) {
44403
44863
  return p;
@@ -44412,18 +44872,18 @@ function _nowUtcMs() {
44412
44872
  return Date.now();
44413
44873
  }
44414
44874
  function _ensureLedgerDir(p) {
44415
- const parent = path74.dirname(p);
44875
+ const parent = path76.dirname(p);
44416
44876
  try {
44417
- fs77.mkdirSync(parent, { recursive: true });
44877
+ fs79.mkdirSync(parent, { recursive: true });
44418
44878
  let mode;
44419
44879
  try {
44420
- mode = fs77.statSync(parent).mode & 511;
44880
+ mode = fs79.statSync(parent).mode & 511;
44421
44881
  } catch {
44422
44882
  mode = 448;
44423
44883
  }
44424
44884
  if (mode !== 448) {
44425
44885
  try {
44426
- fs77.chmodSync(parent, 448);
44886
+ fs79.chmodSync(parent, 448);
44427
44887
  } catch {
44428
44888
  }
44429
44889
  }
@@ -44435,18 +44895,18 @@ function _ensureLedgerDir(p) {
44435
44895
  }
44436
44896
  }
44437
44897
  function _ensureLedgerFileMode(p) {
44438
- if (!fs77.existsSync(p)) {
44898
+ if (!fs79.existsSync(p)) {
44439
44899
  return;
44440
44900
  }
44441
44901
  let current;
44442
44902
  try {
44443
- current = fs77.statSync(p).mode & 511;
44903
+ current = fs79.statSync(p).mode & 511;
44444
44904
  } catch {
44445
44905
  return;
44446
44906
  }
44447
44907
  if (current !== 384) {
44448
44908
  try {
44449
- fs77.chmodSync(p, 384);
44909
+ fs79.chmodSync(p, 384);
44450
44910
  } catch {
44451
44911
  }
44452
44912
  }
@@ -44598,11 +45058,11 @@ function pyNumToStr(n) {
44598
45058
  }
44599
45059
  function read_entries2(p = null) {
44600
45060
  const resolved = _resolveLedgerPath(p);
44601
- if (!fs77.existsSync(resolved)) {
45061
+ if (!fs79.existsSync(resolved)) {
44602
45062
  return [];
44603
45063
  }
44604
45064
  const out = [];
44605
- const text = fs77.readFileSync(resolved, "utf-8");
45065
+ const text = fs79.readFileSync(resolved, "utf-8");
44606
45066
  for (const rawLine of text.split(/\r\n|\r|\n/u)) {
44607
45067
  const line = rawLine.trim();
44608
45068
  if (line === "") {
@@ -44705,7 +45165,7 @@ function record_spend(usd, provider, model, options = {}) {
44705
45165
  )}
44706
45166
  `;
44707
45167
  try {
44708
- fs77.appendFileSync(p, entry, { encoding: "utf-8" });
45168
+ fs79.appendFileSync(p, entry, { encoding: "utf-8" });
44709
45169
  } catch (exc) {
44710
45170
  process.stderr.write(`[council:budget_guard] write failed: ${_errStr(exc)}
44711
45171
  `);
@@ -44828,8 +45288,8 @@ function aggregate_scores(findings, scores) {
44828
45288
  by_id.get(s.finding_id).push(s);
44829
45289
  }
44830
45290
  const out = /* @__PURE__ */ new Map();
44831
- for (const [fid, fs84] of by_id) {
44832
- if (fs84.length === 0) {
45291
+ for (const [fid, fs86] of by_id) {
45292
+ if (fs86.length === 0) {
44833
45293
  out.set(
44834
45294
  fid,
44835
45295
  new ConsensusMetadata({
@@ -44845,13 +45305,13 @@ function aggregate_scores(findings, scores) {
44845
45305
  );
44846
45306
  continue;
44847
45307
  }
44848
- const mean2 = fs84.reduce((acc, s) => acc + s.score, 0) / fs84.length;
44849
- const agree_rate = fs84.filter((s) => s.agree).length / fs84.length;
45308
+ const mean2 = fs86.reduce((acc, s) => acc + s.score, 0) / fs86.length;
45309
+ const agree_rate = fs86.filter((s) => s.agree).length / fs86.length;
44850
45310
  const strength = mean2 / 10 * agree_rate;
44851
- const dissent = fs84.filter((s) => !s.agree).length;
44852
- const concur = fs84.filter((s) => s.agree).length;
44853
- const scorers = fs84.map((s) => s.scorer);
44854
- const dissent_reasons = fs84.filter((s) => !s.agree).map((s) => [s.scorer, s.reason]);
45311
+ const dissent = fs86.filter((s) => !s.agree).length;
45312
+ const concur = fs86.filter((s) => s.agree).length;
45313
+ const scorers = fs86.map((s) => s.scorer);
45314
+ const dissent_reasons = fs86.filter((s) => !s.agree).map((s) => [s.scorer, s.reason]);
44855
45315
  const mean_rounded = pyRound(mean2, 2);
44856
45316
  out.set(
44857
45317
  fid,
@@ -45326,10 +45786,25 @@ var init_stance_tally = __esm({
45326
45786
  });
45327
45787
 
45328
45788
  // src/scripts/ai_council/mid_flight_fallback.ts
45789
+ function isEstablishedTwin(o) {
45790
+ return o !== null && !("parked" in o);
45791
+ }
45329
45792
  function establishTwin(input) {
45330
45793
  const { member, error, fallback, ledger } = input;
45331
45794
  const failure = classifyCliFailure(error);
45332
- const policy = { apiOnQuota: fallback.api_on_quota };
45795
+ const policy = {
45796
+ apiOnQuota: fallback.api_on_quota,
45797
+ billingGrant: fallback.billing_grant === true
45798
+ };
45799
+ if (fallback.api_on_quota === "ask" && failure === "quota_exhausted" && !effectiveApiOnQuota(policy)) {
45800
+ fallback.on_event?.({
45801
+ provider: member.name,
45802
+ failure,
45803
+ outcome: "awaiting_grant",
45804
+ api_on_quota: fallback.api_on_quota
45805
+ });
45806
+ return { parked: true, provider: member.name, reason: failure, original_error: error };
45807
+ }
45333
45808
  if (!isFallbackEligibleUnder(failure, policy)) return null;
45334
45809
  if (ledger.attempt(member.name, failure, policy) !== "api") return null;
45335
45810
  const twin = fallback.construct(member.name);
@@ -45385,7 +45860,7 @@ function escalateUnmetered(member, response, transport, fallback, ledger) {
45385
45860
  fallback,
45386
45861
  ledger
45387
45862
  });
45388
- if (twin === null) return null;
45863
+ if (!isEstablishedTwin(twin)) return null;
45389
45864
  return twin;
45390
45865
  }
45391
45866
  function refuseUnmeteredEscalation(args) {
@@ -46102,7 +46577,7 @@ ${suffix}` : base;
46102
46577
  fallback,
46103
46578
  ledger
46104
46579
  });
46105
- if (twin !== null) {
46580
+ if (isEstablishedTwin(twin)) {
46106
46581
  const out = runGatedRetry(response, member, twin, fallback, {
46107
46582
  gate: (client) => table === null || _breach(
46108
46583
  estimate(question, [client], table, {
@@ -46999,18 +47474,18 @@ __export(project_context_exports, {
46999
47474
  REPO_PURPOSE_MAX_CHARS: () => REPO_PURPOSE_MAX_CHARS,
47000
47475
  detect_project_context: () => detect_project_context
47001
47476
  });
47002
- import * as fs78 from "node:fs";
47003
- import * as path75 from "node:path";
47477
+ import * as fs80 from "node:fs";
47478
+ import * as path77 from "node:path";
47004
47479
  function _isPlainObject11(v) {
47005
47480
  return typeof v === "object" && v !== null && !Array.isArray(v);
47006
47481
  }
47007
47482
  function _read_json(p) {
47008
- if (!fs78.existsSync(p)) {
47483
+ if (!fs80.existsSync(p)) {
47009
47484
  return null;
47010
47485
  }
47011
47486
  let raw;
47012
47487
  try {
47013
- raw = fs78.readFileSync(p, "utf-8");
47488
+ raw = fs80.readFileSync(p, "utf-8");
47014
47489
  } catch {
47015
47490
  return null;
47016
47491
  }
@@ -47032,7 +47507,7 @@ function _name_from(composer, pkg, root) {
47032
47507
  }
47033
47508
  }
47034
47509
  try {
47035
- const base = path75.basename(root);
47510
+ const base = path77.basename(root);
47036
47511
  return base || null;
47037
47512
  } catch {
47038
47513
  return null;
@@ -47101,12 +47576,12 @@ function _splitlines10(text) {
47101
47576
  return parts;
47102
47577
  }
47103
47578
  function _purpose_from_readme(p) {
47104
- if (!fs78.existsSync(p)) {
47579
+ if (!fs80.existsSync(p)) {
47105
47580
  return null;
47106
47581
  }
47107
47582
  let text;
47108
47583
  try {
47109
- text = fs78.readFileSync(p, "utf-8");
47584
+ text = fs80.readFileSync(p, "utf-8");
47110
47585
  } catch {
47111
47586
  return null;
47112
47587
  }
@@ -47190,13 +47665,13 @@ function _rfind(haystack, needle) {
47190
47665
  return -1;
47191
47666
  }
47192
47667
  function detect_project_context(root) {
47193
- const resolvedRoot = path75.resolve(root ?? process.cwd());
47194
- const composer = _read_json(path75.join(resolvedRoot, "composer.json"));
47195
- const pkg = _read_json(path75.join(resolvedRoot, "package.json"));
47668
+ const resolvedRoot = path77.resolve(root ?? process.cwd());
47669
+ const composer = _read_json(path77.join(resolvedRoot, "composer.json"));
47670
+ const pkg = _read_json(path77.join(resolvedRoot, "package.json"));
47196
47671
  return new ProjectContext(
47197
47672
  _name_from(composer, pkg, resolvedRoot),
47198
47673
  _stack_from(composer, pkg),
47199
- _purpose_from_readme(path75.join(resolvedRoot, "README.md"))
47674
+ _purpose_from_readme(path77.join(resolvedRoot, "README.md"))
47200
47675
  );
47201
47676
  }
47202
47677
  var REPO_PURPOSE_MAX_CHARS, _HEADING_RE, _BADGE_RE, _HTML_RE, ProjectContext;
@@ -47466,7 +47941,7 @@ __export(shadow_dispatch_exports, {
47466
47941
  slo_banner: () => slo_banner,
47467
47942
  slo_status: () => slo_status
47468
47943
  });
47469
- import * as fs79 from "node:fs";
47944
+ import * as fs81 from "node:fs";
47470
47945
  import { createHash as createHash14 } from "node:crypto";
47471
47946
  function should_shadow(sampleRate, opts = {}) {
47472
47947
  const rate = Math.max(0, Math.min(1, sampleRate));
@@ -47504,7 +47979,7 @@ function record_shadow_decision(logPath, opts) {
47504
47979
  escalated,
47505
47980
  escalation_reason: escalationReason
47506
47981
  };
47507
- fs79.mkdirSync(_dirname2(logPath), { recursive: true });
47982
+ fs81.mkdirSync(_dirname2(logPath), { recursive: true });
47508
47983
  const row = _pyJsonDumps2({
47509
47984
  timestamp: decision.timestamp,
47510
47985
  query_hash: decision.query_hash,
@@ -47514,7 +47989,7 @@ function record_shadow_decision(logPath, opts) {
47514
47989
  escalated: decision.escalated,
47515
47990
  escalation_reason: decision.escalation_reason
47516
47991
  }) + "\n";
47517
- fs79.appendFileSync(logPath, row, { encoding: "utf-8" });
47992
+ fs81.appendFileSync(logPath, row, { encoding: "utf-8" });
47518
47993
  return decision;
47519
47994
  }
47520
47995
  function _isoNowSeconds() {
@@ -47523,10 +47998,10 @@ function _isoNowSeconds() {
47523
47998
  return `${pad(d.getUTCFullYear(), 4)}-${pad(d.getUTCMonth() + 1)}-${pad(d.getUTCDate())}T${pad(d.getUTCHours())}:${pad(d.getUTCMinutes())}:${pad(d.getUTCSeconds())}+00:00`;
47524
47999
  }
47525
48000
  function* _iterLog(logPath) {
47526
- if (!fs79.existsSync(logPath)) {
48001
+ if (!fs81.existsSync(logPath)) {
47527
48002
  return;
47528
48003
  }
47529
- const content = fs79.readFileSync(logPath, { encoding: "utf-8" });
48004
+ const content = fs81.readFileSync(logPath, { encoding: "utf-8" });
47530
48005
  for (const rawLine of _splitlines11(content)) {
47531
48006
  const line = _strip7(rawLine);
47532
48007
  if (!line) {
@@ -48453,8 +48928,8 @@ __export(council_cli_exports, {
48453
48928
  load_settings: () => load_settings,
48454
48929
  main: () => main34
48455
48930
  });
48456
- import * as fs80 from "node:fs";
48457
- import * as path76 from "node:path";
48931
+ import * as fs82 from "node:fs";
48932
+ import * as path78 from "node:path";
48458
48933
  import { fileURLToPath as fileURLToPath46, pathToFileURL as pathToFileURL34 } from "node:url";
48459
48934
  function _pyFixed6(x, ndigits) {
48460
48935
  if (!Number.isFinite(x)) {
@@ -48663,7 +49138,7 @@ function _stderr2(s) {
48663
49138
  function load_settings(p = SETTINGS_FILE2, opts = {}) {
48664
49139
  const ai_council_path = opts.ai_council_path ?? AI_COUNCIL_FILE;
48665
49140
  const settings = load_agent_settings({ project_path: p });
48666
- if (fs80.existsSync(ai_council_path)) {
49141
+ if (fs82.existsSync(ai_council_path)) {
48667
49142
  const cfg = load_council_config(ai_council_path);
48668
49143
  settings["ai_council"] = synthesizeAiCouncilBlock(cfg);
48669
49144
  }
@@ -48894,17 +49369,15 @@ function build_members(settings, opts = {}) {
48894
49369
  `no council member has \`enabled: true\` \u2014 enable at least one under members.* in ${COUNCIL_CONFIG_USER_GLOBAL_REL} (user-global root; never the project tree, ADR-104). \`agent-config council:status\` prints the resolved path.`
48895
49370
  );
48896
49371
  }
48897
- if (fallback_out !== null) {
48898
- const fallback_cfg = _isDict3(ai["fallback"]) ? ai["fallback"] : {};
48899
- fallback_out.options = buildFallbackOptions({
48900
- apiOnQuota: _pyBool2(fallback_cfg["api_on_quota"]),
48901
- hasApiRung: (p) => _API_PROVIDERS.has(p),
48902
- memberConfig: (p) => members_cfg[p] || {},
48903
- modelOverride: (p) => overrides[p] ?? null,
48904
- constructApi: _construct_api_member,
48905
- emit: appendEvent
48906
- });
48907
- }
49372
+ wireCouncilFallback(fallback_out, ai, {
49373
+ repoRoot: REPO_ROOT11,
49374
+ isDict: _isDict3,
49375
+ membersCfg: members_cfg,
49376
+ overrides,
49377
+ hasApiRung: (p) => _API_PROVIDERS.has(p),
49378
+ constructApi: _construct_api_member,
49379
+ emit: appendEvent
49380
+ });
48908
49381
  return members;
48909
49382
  }
48910
49383
  function _setDifference(items, known) {
@@ -49031,7 +49504,7 @@ function build_question(opts) {
49031
49504
  let ctx;
49032
49505
  let artefact;
49033
49506
  if (input_mode === "prompt") {
49034
- const text = fs80.readFileSync(input_path, "utf-8");
49507
+ const text = fs82.readFileSync(input_path, "utf-8");
49035
49508
  ctx = bundle_prompt(text);
49036
49509
  artefact = String(input_path);
49037
49510
  } else if (input_mode === "roadmap") {
@@ -49174,9 +49647,9 @@ function _maybe_write_decision_replay(opts) {
49174
49647
  include_member_arguments: include_args
49175
49648
  })
49176
49649
  );
49177
- const target = path76.join(path76.dirname(opts.out_path), "decision-replay.md");
49178
- fs80.mkdirSync(path76.dirname(target), { recursive: true });
49179
- fs80.writeFileSync(target, replay, { encoding: "utf-8" });
49650
+ const target = path78.join(path78.dirname(opts.out_path), "decision-replay.md");
49651
+ fs82.mkdirSync(path78.dirname(target), { recursive: true });
49652
+ fs82.writeFileSync(target, replay, { encoding: "utf-8" });
49180
49653
  return target;
49181
49654
  }
49182
49655
  function _peer_review_active(ai_cfg, args) {
@@ -49881,7 +50354,7 @@ function cmd_status(args, opts = {}) {
49881
50354
  const env = opts.env ?? process.env;
49882
50355
  const override = env[COUNCIL_CONFIG_ENV];
49883
50356
  const path_ = resolve_config_path(REPO_ROOT11, { env });
49884
- const exists3 = fs80.existsSync(String(path_));
50357
+ const exists3 = fs82.existsSync(String(path_));
49885
50358
  const provenance = override ? `${COUNCIL_CONFIG_ENV} override` : "user-global";
49886
50359
  let cfg = null;
49887
50360
  let parse_error = null;
@@ -50224,6 +50697,7 @@ function cmd_run(args, opts = {}) {
50224
50697
  quorum_out.result = post_run.quorum;
50225
50698
  skipped.push(...post_run.absent);
50226
50699
  recordRoundObservations(REPO_ROOT11, members, responses, classifyCliFailure);
50700
+ printBillingGate(fallback_out.options?.parked ?? [], { repoRoot: REPO_ROOT11, stdout: _stdout2, stderr: _stderr2 });
50227
50701
  _emitQuorumEvent("post_run", post_run.quorum, post_run.absent, {
50228
50702
  command: "run",
50229
50703
  // Whether the roster actually shrank — see `dispatch_shape`. Without
@@ -50337,8 +50811,8 @@ function cmd_run(args, opts = {}) {
50337
50811
  kind: "responses",
50338
50812
  subcommand: "run"
50339
50813
  });
50340
- fs80.mkdirSync(path76.dirname(_resolveTarget(out_path)), { recursive: true });
50341
- fs80.writeFileSync(_resolveTarget(out_path), _jsonDumpsIndent2(payload) + "\n", { encoding: "utf-8" });
50814
+ fs82.mkdirSync(path78.dirname(_resolveTarget(out_path)), { recursive: true });
50815
+ fs82.writeFileSync(_resolveTarget(out_path), _jsonDumpsIndent2(payload) + "\n", { encoding: "utf-8" });
50342
50816
  _stdout2(
50343
50817
  `
50344
50818
  council:run \xB7 wrote ${out_path} (estimated $${_pyFixed6(estimated_total, 4)} / actual $${_pyFixed6(actual_total, 4)})
@@ -50363,7 +50837,7 @@ function _debate_round_filename(round_number) {
50363
50837
  return `debate-round-${round_number}.json`;
50364
50838
  }
50365
50839
  function _write_debate_round(out_dir, round_number, responses, opts) {
50366
- fs80.mkdirSync(_resolveTarget(out_dir), { recursive: true });
50840
+ fs82.mkdirSync(_resolveTarget(out_dir), { recursive: true });
50367
50841
  let actual_total = 0;
50368
50842
  for (const r of responses) {
50369
50843
  if (r.error) {
@@ -50387,15 +50861,15 @@ function _write_debate_round(out_dir, round_number, responses, opts) {
50387
50861
  prompt_cache_round_gap_ms: opts.cache_gap_ms_since_previous_round ?? null,
50388
50862
  responses: _serialise_responses(responses)
50389
50863
  };
50390
- const out_path = path76.join(_resolveTarget(out_dir), _debate_round_filename(round_number));
50391
- fs80.writeFileSync(out_path, _jsonDumpsIndent2(payload) + "\n", { encoding: "utf-8" });
50864
+ const out_path = path78.join(_resolveTarget(out_dir), _debate_round_filename(round_number));
50865
+ fs82.writeFileSync(out_path, _jsonDumpsIndent2(payload) + "\n", { encoding: "utf-8" });
50392
50866
  return out_path;
50393
50867
  }
50394
50868
  function _load_debate_seed(p, expected_members) {
50395
- if (!fs80.existsSync(p)) {
50869
+ if (!fs82.existsSync(p)) {
50396
50870
  throw new FileNotFoundError3(`--continue-as-debate path not found: ${p}`);
50397
50871
  }
50398
- const payload = JSON.parse(fs80.readFileSync(p, "utf-8"));
50872
+ const payload = JSON.parse(fs82.readFileSync(p, "utf-8"));
50399
50873
  const source_members = (payload["members"] || []).slice();
50400
50874
  const expected_labels = expected_members.map((m) => `${m.name}/${m.model}`);
50401
50875
  if (!_listEq(source_members, expected_labels)) {
@@ -50441,7 +50915,7 @@ function _readStdinLine() {
50441
50915
  try {
50442
50916
  const buf = Buffer.alloc(4096);
50443
50917
  const fd = 0;
50444
- const n = fs80.readSync(fd, buf, 0, buf.length, null);
50918
+ const n = fs82.readSync(fd, buf, 0, buf.length, null);
50445
50919
  return buf.toString("utf-8", 0, n).split("\n")[0]?.trim().toLowerCase() ?? "";
50446
50920
  } catch {
50447
50921
  return "";
@@ -50675,7 +51149,7 @@ council:debate \xB7 ${all_rounds.length} round(s) complete \xB7 actual $${_pyFix
50675
51149
  return errors_last.length > 0 && errors_last.length === last.length ? 1 : 0;
50676
51150
  }
50677
51151
  function cmd_render(args) {
50678
- const payload = JSON.parse(fs80.readFileSync(args.responses, "utf-8"));
51152
+ const payload = JSON.parse(fs82.readFileSync(args.responses, "utf-8"));
50679
51153
  const items = payload["responses"] || [];
50680
51154
  const explicit = _getattr3(args, "prompt_mode", null);
50681
51155
  const mode = explicit || payload["prompt_mode"] || payload["mode"];
@@ -50704,8 +51178,8 @@ function cmd_render(args) {
50704
51178
  kind: "sessions",
50705
51179
  subcommand: "render"
50706
51180
  });
50707
- fs80.mkdirSync(path76.dirname(_resolveTarget(out_path)), { recursive: true });
50708
- fs80.writeFileSync(_resolveTarget(out_path), body + "\n", { encoding: "utf-8" });
51181
+ fs82.mkdirSync(path78.dirname(_resolveTarget(out_path)), { recursive: true });
51182
+ fs82.writeFileSync(_resolveTarget(out_path), body + "\n", { encoding: "utf-8" });
50709
51183
  _stdout2(`council:render \xB7 wrote ${out_path}
50710
51184
  `);
50711
51185
  return 0;
@@ -50716,15 +51190,15 @@ function cmd_render(args) {
50716
51190
  function _cmd_replay_low_impact_stats(args) {
50717
51191
  const li = low_impact_exports;
50718
51192
  const responses_path = args.responses;
50719
- const log_path = path76.join(path76.dirname(responses_path), "low-impact-resolutions.md");
50720
- if (!fs80.existsSync(log_path)) {
51193
+ const log_path = path78.join(path78.dirname(responses_path), "low-impact-resolutions.md");
51194
+ if (!fs82.existsSync(log_path)) {
50721
51195
  _stdout2(
50722
51196
  `council:replay \xB7 no low-impact-resolutions.md alongside ${responses_path} \u2014 session had no fast-path entries.
50723
51197
  `
50724
51198
  );
50725
51199
  return 0;
50726
51200
  }
50727
- const body = fs80.readFileSync(log_path, "utf-8");
51201
+ const body = fs82.readFileSync(log_path, "utf-8");
50728
51202
  const stats = li.parse_low_impact_log(body);
50729
51203
  const out = li.render_low_impact_stats(stats);
50730
51204
  if (_getattr3(args, "output", null)) {
@@ -50732,8 +51206,8 @@ function _cmd_replay_low_impact_stats(args) {
50732
51206
  kind: "sessions",
50733
51207
  subcommand: "replay"
50734
51208
  });
50735
- fs80.mkdirSync(path76.dirname(_resolveTarget(target)), { recursive: true });
50736
- fs80.writeFileSync(_resolveTarget(target), out, { encoding: "utf-8" });
51209
+ fs82.mkdirSync(path78.dirname(_resolveTarget(target)), { recursive: true });
51210
+ fs82.writeFileSync(_resolveTarget(target), out, { encoding: "utf-8" });
50737
51211
  _stdout2(`council:replay \xB7 wrote ${target}
50738
51212
  `);
50739
51213
  return 0;
@@ -50745,7 +51219,7 @@ function cmd_replay(args) {
50745
51219
  if (_getattr3(args, "low_impact_stats", false)) {
50746
51220
  return _cmd_replay_low_impact_stats(args);
50747
51221
  }
50748
- const payload = JSON.parse(fs80.readFileSync(args.responses, "utf-8"));
51222
+ const payload = JSON.parse(fs82.readFileSync(args.responses, "utf-8"));
50749
51223
  const consensus = _deserialise_consensus(payload["consensus"]);
50750
51224
  if (consensus === null) {
50751
51225
  _stderr2(
@@ -50770,8 +51244,8 @@ function cmd_replay(args) {
50770
51244
  kind: "sessions",
50771
51245
  subcommand: "replay"
50772
51246
  });
50773
- fs80.mkdirSync(path76.dirname(_resolveTarget(out_path)), { recursive: true });
50774
- fs80.writeFileSync(_resolveTarget(out_path), body, { encoding: "utf-8" });
51247
+ fs82.mkdirSync(path78.dirname(_resolveTarget(out_path)), { recursive: true });
51248
+ fs82.writeFileSync(_resolveTarget(out_path), body, { encoding: "utf-8" });
50775
51249
  _stdout2(`council:replay \xB7 wrote ${out_path}
50776
51250
  `);
50777
51251
  } else {
@@ -50828,8 +51302,8 @@ function cmd_quota(args, opts = {}) {
50828
51302
  }
50829
51303
  function _validate_council_output_path(path_str, opts) {
50830
51304
  const expected_rel = COUNCIL_CANONICAL_DIRS[opts.kind];
50831
- const expected_abs = _resolveReal(path76.join(REPO_ROOT11, expected_rel));
50832
- const target = path76.isAbsolute(path_str) ? path_str : path76.join(REPO_ROOT11, path_str);
51305
+ const expected_abs = _resolveReal(path78.join(REPO_ROOT11, expected_rel));
51306
+ const target = path78.isAbsolute(path_str) ? path_str : path78.join(REPO_ROOT11, path_str);
50833
51307
  const target_resolved = _resolveReal(target);
50834
51308
  if (!_isRelativeTo(target_resolved, expected_abs)) {
50835
51309
  throw new ArgumentTypeError(
@@ -50839,12 +51313,12 @@ function _validate_council_output_path(path_str, opts) {
50839
51313
  return path_str;
50840
51314
  }
50841
51315
  function _resolveTarget(path_str) {
50842
- return path76.isAbsolute(path_str) ? path_str : path76.join(REPO_ROOT11, path_str);
51316
+ return path78.isAbsolute(path_str) ? path_str : path78.join(REPO_ROOT11, path_str);
50843
51317
  }
50844
51318
  function _resolveReal(p) {
50845
- const abs = path76.resolve(p);
51319
+ const abs = path78.resolve(p);
50846
51320
  try {
50847
- return fs80.realpathSync(abs);
51321
+ return fs82.realpathSync(abs);
50848
51322
  } catch {
50849
51323
  return abs;
50850
51324
  }
@@ -50853,8 +51327,8 @@ function _isRelativeTo(target, base) {
50853
51327
  if (target === base) {
50854
51328
  return true;
50855
51329
  }
50856
- const rel = path76.relative(base, target);
50857
- return rel !== "" && !rel.startsWith("..") && !path76.isAbsolute(rel);
51330
+ const rel = path78.relative(base, target);
51331
+ return rel !== "" && !rel.startsWith("..") && !path78.isAbsolute(rel);
50858
51332
  }
50859
51333
  function _topError(message) {
50860
51334
  _stderr2(_TOP_USAGE2);
@@ -51031,7 +51505,7 @@ function _specsFor(cmd) {
51031
51505
  requiredOpts: []
51032
51506
  };
51033
51507
  default:
51034
- return { positionals: [], opts: [], requiredOpts: [] };
51508
+ return billingArgSpec(cmd) ?? { positionals: [], opts: [], requiredOpts: [] };
51035
51509
  }
51036
51510
  }
51037
51511
  function _parseArgs7(argv) {
@@ -51206,6 +51680,8 @@ function main34(argv = null) {
51206
51680
  if (args.cmd === "status") {
51207
51681
  return cmd_status(args);
51208
51682
  }
51683
+ const billing = handleBillingCommand(String(args.cmd), _getattr3(args, "run_id", null), { repoRoot: REPO_ROOT11, stdout: _stdout2, stderr: _stderr2 });
51684
+ if (billing !== null) return billing;
51209
51685
  } catch (exc) {
51210
51686
  if (exc instanceof CouncilDisabledError) {
51211
51687
  _stderr2(`\u274C council:${args.cmd}: ${exc.message}
@@ -51225,13 +51701,13 @@ function _isCliEntry31() {
51225
51701
  if (process.argv[1] === void 0) {
51226
51702
  return false;
51227
51703
  }
51228
- const argvUrl = pathToFileURL34(path76.resolve(process.argv[1])).href;
51704
+ const argvUrl = pathToFileURL34(path78.resolve(process.argv[1])).href;
51229
51705
  if (import.meta.url === argvUrl) {
51230
51706
  return true;
51231
51707
  }
51232
51708
  try {
51233
- const here = fs80.realpathSync(fileURLToPath46(import.meta.url));
51234
- const argv = fs80.realpathSync(path76.resolve(process.argv[1]));
51709
+ const here = fs82.realpathSync(fileURLToPath46(import.meta.url));
51710
+ const argv = fs82.realpathSync(path78.resolve(process.argv[1]));
51235
51711
  return here === argv;
51236
51712
  } catch {
51237
51713
  return false;
@@ -51267,6 +51743,7 @@ var init_council_cli = __esm({
51267
51743
  init_council_settings_block();
51268
51744
  init_council_fallback_posture();
51269
51745
  init_council_fallback_wiring();
51746
+ init_billing_grant_cli();
51270
51747
  init_necessity();
51271
51748
  init_orchestrator();
51272
51749
  init_pricing();
@@ -51298,7 +51775,7 @@ var init_council_cli = __esm({
51298
51775
  "xai",
51299
51776
  "perplexity"
51300
51777
  ]);
51301
- _HERE23 = path76.dirname(fileURLToPath46(import.meta.url));
51778
+ _HERE23 = path78.dirname(fileURLToPath46(import.meta.url));
51302
51779
  [REPO_ROOT11] = resolve_project_root(null);
51303
51780
  SETTINGS_FILE2 = project_settings_path(REPO_ROOT11);
51304
51781
  AI_COUNCIL_FILE = resolve_config_path(REPO_ROOT11);
@@ -51326,7 +51803,7 @@ var init_council_cli = __esm({
51326
51803
  ]);
51327
51804
  FileNotFoundError3 = class extends Error {
51328
51805
  };
51329
- _SUBCOMMANDS = ["estimate", "run", "debate", "render", "replay", "quota", "shadow-report", "status"];
51806
+ _SUBCOMMANDS = ["estimate", "run", "debate", "render", "replay", "quota", "shadow-report", "status", ...BILLING_SUBCOMMANDS];
51330
51807
  _TOP_USAGE2 = `usage: ${_PROG9} [-h]
51331
51808
  {estimate,run,debate,render,replay,quota,shadow-report,status}
51332
51809
  ...
@@ -51431,13 +51908,13 @@ __export(skill_catalogue_exports, {
51431
51908
  resolveSkillsRoot: () => resolveSkillsRoot,
51432
51909
  truncationModeOf: () => truncationModeOf
51433
51910
  });
51434
- import * as fs81 from "node:fs";
51435
- import * as path77 from "node:path";
51911
+ import * as fs83 from "node:fs";
51912
+ import * as path79 from "node:path";
51436
51913
  function resolveSkillsRoot(workspaceRoot) {
51437
51914
  for (const candidate of DEFAULT_CATALOGUE_ROOTS) {
51438
- const abs = path77.join(workspaceRoot, candidate);
51915
+ const abs = path79.join(workspaceRoot, candidate);
51439
51916
  try {
51440
- if (fs81.existsSync(abs) && fs81.statSync(abs).isDirectory()) return abs;
51917
+ if (fs83.existsSync(abs) && fs83.statSync(abs).isDirectory()) return abs;
51441
51918
  } catch {
51442
51919
  }
51443
51920
  }
@@ -51481,9 +51958,9 @@ function descriptionOf(frontmatter) {
51481
51958
  return "";
51482
51959
  }
51483
51960
  function readProjectedCatalogue(root) {
51484
- const names = fs81.readdirSync(root).filter((n) => fs81.existsSync(path77.join(root, n, "SKILL.md"))).sort();
51961
+ const names = fs83.readdirSync(root).filter((n) => fs83.existsSync(path79.join(root, n, "SKILL.md"))).sort();
51485
51962
  return names.map((name, index) => {
51486
- const content = fs81.readFileSync(path77.join(root, name, "SKILL.md"), "utf-8");
51963
+ const content = fs83.readFileSync(path79.join(root, name, "SKILL.md"), "utf-8");
51487
51964
  const frontmatter = frontmatterOf(content);
51488
51965
  const description = descriptionOf(frontmatter);
51489
51966
  return {
@@ -51685,12 +52162,12 @@ function buildNoTruncationRecord(host, observedAt, entriesOffered, projectedSkil
51685
52162
  };
51686
52163
  }
51687
52164
  function markdownFilesUnder(root) {
51688
- if (!fs81.existsSync(root)) return [];
52165
+ if (!fs83.existsSync(root)) return [];
51689
52166
  const out = [];
51690
52167
  const walk = (dir) => {
51691
- for (const entry of fs81.readdirSync(dir, { withFileTypes: true })) {
51692
- const full = path77.join(dir, entry.name);
51693
- if (fs81.statSync(full).isDirectory()) walk(full);
52168
+ for (const entry of fs83.readdirSync(dir, { withFileTypes: true })) {
52169
+ const full = path79.join(dir, entry.name);
52170
+ if (fs83.statSync(full).isDirectory()) walk(full);
51694
52171
  else if (entry.name.endsWith(".md")) out.push(full);
51695
52172
  }
51696
52173
  };
@@ -51698,9 +52175,9 @@ function markdownFilesUnder(root) {
51698
52175
  return out;
51699
52176
  }
51700
52177
  function measureCatalogueVolume(host, root) {
51701
- const skillsRoot = path77.join(root, "skills");
51702
- const skills = fs81.existsSync(skillsRoot) ? readProjectedCatalogue(skillsRoot) : [];
51703
- const commandEntries = markdownFilesUnder(path77.join(root, "commands")).length;
52178
+ const skillsRoot = path79.join(root, "skills");
52179
+ const skills = fs83.existsSync(skillsRoot) ? readProjectedCatalogue(skillsRoot) : [];
52180
+ const commandEntries = markdownFilesUnder(path79.join(root, "commands")).length;
51704
52181
  return {
51705
52182
  host,
51706
52183
  root,
@@ -51831,9 +52308,9 @@ function migrationPromptLines(host, eligibility, settingsPath) {
51831
52308
  ];
51832
52309
  }
51833
52310
  function readObservationLog(logPath) {
51834
- if (!fs81.existsSync(logPath)) return [];
52311
+ if (!fs83.existsSync(logPath)) return [];
51835
52312
  const out = [];
51836
- for (const line of fs81.readFileSync(logPath, "utf-8").split("\n")) {
52313
+ for (const line of fs83.readFileSync(logPath, "utf-8").split("\n")) {
51837
52314
  const trimmed = line.trim();
51838
52315
  if (trimmed.length === 0) continue;
51839
52316
  try {
@@ -51908,7 +52385,7 @@ var init_skill_catalogue = __esm({
51908
52385
  "src/scripts/_lib/skill_catalogue.ts"() {
51909
52386
  "use strict";
51910
52387
  DEFAULT_CATALOGUE_ROOTS = [".claude/skills", "src/skills"];
51911
- OBSERVATION_LOG = path77.join(
52388
+ OBSERVATION_LOG = path79.join(
51912
52389
  "agents",
51913
52390
  "evidence",
51914
52391
  "metrics",
@@ -51929,8 +52406,8 @@ __export(score_skill_relevance_exports, {
51929
52406
  parse_args: () => parse_args7,
51930
52407
  rank: () => rank
51931
52408
  });
51932
- import * as fs82 from "node:fs";
51933
- import * as path78 from "node:path";
52409
+ import * as fs84 from "node:fs";
52410
+ import * as path80 from "node:path";
51934
52411
  import { fileURLToPath as fileURLToPath47, pathToFileURL as pathToFileURL35 } from "node:url";
51935
52412
  function pyLen(s) {
51936
52413
  let n = 0;
@@ -51950,7 +52427,7 @@ function _tokenize(text) {
51950
52427
  return out;
51951
52428
  }
51952
52429
  function _parse_frontmatter2(filePath) {
51953
- const text = fs82.readFileSync(filePath, "utf-8");
52430
+ const text = fs84.readFileSync(filePath, "utf-8");
51954
52431
  if (!text.startsWith("---")) {
51955
52432
  return {};
51956
52433
  }
@@ -52007,7 +52484,7 @@ function _load_skills(skillsDir) {
52007
52484
  for (const skillMd of _globSkillMd(skillsDir)) {
52008
52485
  const fm = _parse_frontmatter2(skillMd);
52009
52486
  const rawName = fm["name"];
52010
- const name = _truthyStr(rawName) ? String(rawName) : path78.basename(path78.dirname(skillMd));
52487
+ const name = _truthyStr(rawName) ? String(rawName) : path80.basename(path80.dirname(skillMd));
52011
52488
  const rawDesc = fm["description"];
52012
52489
  const desc = _truthyStr(rawDesc) ? String(rawDesc) : "";
52013
52490
  let personas = fm["personas"] ?? [];
@@ -52033,23 +52510,23 @@ function _truthyStr(v) {
52033
52510
  function _globSkillMd(root) {
52034
52511
  let names;
52035
52512
  try {
52036
- names = fs82.readdirSync(root);
52513
+ names = fs84.readdirSync(root);
52037
52514
  } catch {
52038
52515
  return [];
52039
52516
  }
52040
52517
  const dirs = [];
52041
52518
  for (const name of names) {
52042
- const dir = path78.join(root, name);
52043
- const skillMd = path78.join(dir, "SKILL.md");
52519
+ const dir = path80.join(root, name);
52520
+ const skillMd = path80.join(dir, "SKILL.md");
52044
52521
  try {
52045
- if (fs82.statSync(dir).isDirectory() && fs82.statSync(skillMd).isFile()) {
52522
+ if (fs84.statSync(dir).isDirectory() && fs84.statSync(skillMd).isFile()) {
52046
52523
  dirs.push(name);
52047
52524
  }
52048
52525
  } catch {
52049
52526
  }
52050
52527
  }
52051
52528
  dirs.sort();
52052
- return dirs.map((name) => path78.join(root, name, "SKILL.md"));
52529
+ return dirs.map((name) => path80.join(root, name, "SKILL.md"));
52053
52530
  }
52054
52531
  function _score3(taskTerms, skill) {
52055
52532
  if (taskTerms.size === 0) {
@@ -52272,13 +52749,13 @@ function _isCliEntry32() {
52272
52749
  if (process.argv[1] === void 0) {
52273
52750
  return false;
52274
52751
  }
52275
- const argvUrl = pathToFileURL35(path78.resolve(process.argv[1])).href;
52752
+ const argvUrl = pathToFileURL35(path80.resolve(process.argv[1])).href;
52276
52753
  if (import.meta.url === argvUrl) {
52277
52754
  return true;
52278
52755
  }
52279
52756
  try {
52280
- const here = fs82.realpathSync(fileURLToPath47(import.meta.url));
52281
- const argv = fs82.realpathSync(path78.resolve(process.argv[1]));
52757
+ const here = fs84.realpathSync(fileURLToPath47(import.meta.url));
52758
+ const argv = fs84.realpathSync(path80.resolve(process.argv[1]));
52282
52759
  return here === argv;
52283
52760
  } catch {
52284
52761
  return false;
@@ -52290,8 +52767,8 @@ var init_score_skill_relevance = __esm({
52290
52767
  "use strict";
52291
52768
  init_value_ladder();
52292
52769
  _HERE24 = fileURLToPath47(import.meta.url);
52293
- ROOT3 = path78.resolve(path78.dirname(_HERE24), "..", "..", "..");
52294
- DEFAULT_SKILLS_DIR = path78.join(ROOT3, ".agent-src.uncondensed", "skills");
52770
+ ROOT3 = path80.resolve(path80.dirname(_HERE24), "..", "..", "..");
52771
+ DEFAULT_SKILLS_DIR = path80.join(ROOT3, ".agent-src.uncondensed", "skills");
52295
52772
  TOKEN_RE3 = /[a-z][a-z0-9]+/g;
52296
52773
  STOPWORDS = /* @__PURE__ */ new Set([
52297
52774
  "the",
@@ -52376,7 +52853,7 @@ var init_score_skill_relevance = __esm({
52376
52853
  });
52377
52854
 
52378
52855
  // src/scripts/mcp_server/__main__.ts
52379
- import * as path80 from "node:path";
52856
+ import * as path82 from "node:path";
52380
52857
  import { fileURLToPath as fileURLToPath49 } from "node:url";
52381
52858
 
52382
52859
  // src/scripts/mcp_server/index.ts
@@ -52424,8 +52901,8 @@ init_prompts();
52424
52901
  init_resources();
52425
52902
 
52426
52903
  // src/scripts/mcp_server/tools.ts
52427
- import * as fs83 from "node:fs";
52428
- import * as path79 from "node:path";
52904
+ import * as fs85 from "node:fs";
52905
+ import * as path81 from "node:path";
52429
52906
  import { fileURLToPath as fileURLToPath48 } from "node:url";
52430
52907
 
52431
52908
  // src/scripts/chat_history.ts
@@ -54659,9 +55136,9 @@ function _strip8(s) {
54659
55136
  }
54660
55137
  function _resolvePath2(p) {
54661
55138
  try {
54662
- return fs83.realpathSync(p);
55139
+ return fs85.realpathSync(p);
54663
55140
  } catch {
54664
- return path79.resolve(p);
55141
+ return path81.resolve(p);
54665
55142
  }
54666
55143
  }
54667
55144
  function _resolveConsumerRoot(override) {
@@ -54671,14 +55148,14 @@ function _resolveConsumerRoot(override) {
54671
55148
  return _resolvePath2(process.cwd());
54672
55149
  }
54673
55150
  function _relativeUnder(target, root) {
54674
- const rel = path79.relative(root, target);
55151
+ const rel = path81.relative(root, target);
54675
55152
  if (rel === "") {
54676
55153
  return "";
54677
55154
  }
54678
- if (rel.startsWith("..") || path79.isAbsolute(rel)) {
55155
+ if (rel.startsWith("..") || path81.isAbsolute(rel)) {
54679
55156
  return null;
54680
55157
  }
54681
- return rel.split(path79.sep).join("/");
55158
+ return rel.split(path81.sep).join("/");
54682
55159
  }
54683
55160
  function _reprStrList(values) {
54684
55161
  return `[${values.map((v) => `'${v}'`).join(", ")}]`;
@@ -54687,11 +55164,11 @@ function _validateInTreePath(raw, consumerRoot) {
54687
55164
  const root = _resolvePath2(consumerRoot);
54688
55165
  let target;
54689
55166
  if (raw === null || raw === void 0 || raw === "") {
54690
- target = path79.join(root, "agents", "runtime", ".agent-chat-history");
54691
- } else if (path79.isAbsolute(raw)) {
55167
+ target = path81.join(root, "agents", "runtime", ".agent-chat-history");
55168
+ } else if (path81.isAbsolute(raw)) {
54692
55169
  target = _resolvePath2(raw);
54693
55170
  } else {
54694
- target = _resolvePath2(path79.join(root, raw));
55171
+ target = _resolvePath2(path81.join(root, raw));
54695
55172
  }
54696
55173
  const rel = _relativeUnder(target, root);
54697
55174
  if (rel === null) {
@@ -54729,11 +55206,11 @@ async function _lintSkillsHandler(args, consumerRoot) {
54729
55206
  if (typeof raw !== "string") {
54730
55207
  throw new Error("'paths' entries must be strings");
54731
55208
  }
54732
- const resolved = path79.isAbsolute(raw) ? _resolvePath2(raw) : _resolvePath2(path79.join(root, raw));
55209
+ const resolved = path81.isAbsolute(raw) ? _resolvePath2(raw) : _resolvePath2(path81.join(root, raw));
54733
55210
  if (_relativeUnder(resolved, root) === null) {
54734
55211
  throw new Error(`path escapes consumer_root: ${resolved}`);
54735
55212
  }
54736
- if (fs83.existsSync(resolved)) {
55213
+ if (fs85.existsSync(resolved)) {
54737
55214
  paths.push(resolved);
54738
55215
  }
54739
55216
  }
@@ -54770,7 +55247,7 @@ async function _chatHistoryAppendHandler(args, consumerRoot) {
54770
55247
  if (typeof minSchema !== "number" || !Number.isInteger(minSchema) || typeof minSchema === "boolean") {
54771
55248
  throw new Error("'min_schema_version' must be an integer");
54772
55249
  }
54773
- const existingHeader = fs83.existsSync(target) ? _chReadHeader(target) : null;
55250
+ const existingHeader = fs85.existsSync(target) ? _chReadHeader(target) : null;
54774
55251
  const observed = existingHeader !== null && typeof existingHeader === "object" ? _pyInt7(existingHeader.v ?? 0) : SCHEMA_VERSION3;
54775
55252
  if (observed < minSchema) {
54776
55253
  throw new Error(`chat-history schema ${observed} below required ${minSchema}`);
@@ -54785,8 +55262,8 @@ async function _chatHistoryAppendHandler(args, consumerRoot) {
54785
55262
  session: session === void 0 ? null : session
54786
55263
  };
54787
55264
  }
54788
- if (!fs83.existsSync(target) || _chReadHeader(target) === null) {
54789
- fs83.mkdirSync(path79.dirname(target), { recursive: true });
55265
+ if (!fs85.existsSync(target) || _chReadHeader(target) === null) {
55266
+ fs85.mkdirSync(path81.dirname(target), { recursive: true });
54790
55267
  _chInit(target);
54791
55268
  }
54792
55269
  _chAppend(entry, target, session ?? null);
@@ -54830,7 +55307,7 @@ async function _chatHistoryReadHandler(args, consumerRoot) {
54830
55307
  if (detail !== "full" && detail !== "index") {
54831
55308
  throw new Error("'detail' must be 'index' or 'full'");
54832
55309
  }
54833
- if (!fs83.existsSync(target)) {
55310
+ if (!fs85.existsSync(target)) {
54834
55311
  return { path: target, entries: [], count: 0 };
54835
55312
  }
54836
55313
  if (around !== void 0 && around !== null) {
@@ -54932,8 +55409,8 @@ async function _memoryStatusHandler(_args, consumerRoot) {
54932
55409
  }
54933
55410
  return result;
54934
55411
  }
54935
- var _PACKAGE_ROOT3 = path79.resolve(
54936
- path79.dirname(fileURLToPath48(import.meta.url)),
55412
+ var _PACKAGE_ROOT3 = path81.resolve(
55413
+ path81.dirname(fileURLToPath48(import.meta.url)),
54937
55414
  "..",
54938
55415
  "..",
54939
55416
  ".."
@@ -54977,10 +55454,10 @@ async function _memorySignalHandler(args, consumerRoot) {
54977
55454
  async function _roadmapProgressHandler(args, consumerRoot) {
54978
55455
  const dryRun = _pyTruthy6(args.dry_run ?? false);
54979
55456
  const root = _resolvePath2(consumerRoot);
54980
- const roadmapRoot = path79.join(root, "agents", "roadmaps");
54981
- const target = path79.join(root, "agents", "roadmaps-progress.md");
55457
+ const roadmapRoot = path81.join(root, "agents", "roadmaps");
55458
+ const target = path81.join(root, "agents", "roadmaps-progress.md");
54982
55459
  const urp = await Promise.resolve().then(() => (init_update_roadmap_progress(), update_roadmap_progress_exports));
54983
- if (!fs83.existsSync(roadmapRoot)) {
55460
+ if (!fs85.existsSync(roadmapRoot)) {
54984
55461
  return {
54985
55462
  written: false,
54986
55463
  path: target,
@@ -54995,7 +55472,7 @@ async function _roadmapProgressHandler(args, consumerRoot) {
54995
55472
  const stepsDone = roadmaps.reduce((s, r) => s + r.done, 0);
54996
55473
  const stepsTotal = roadmaps.reduce((s, r) => s + r.total_active, 0);
54997
55474
  if (!dryRun) {
54998
- fs83.writeFileSync(target, content, "utf-8");
55475
+ fs85.writeFileSync(target, content, "utf-8");
54999
55476
  }
55000
55477
  return {
55001
55478
  written: !dryRun,
@@ -55016,11 +55493,11 @@ async function _roadmapArchiveHandler(_args, consumerRoot) {
55016
55493
  let dashboardRegenerated = false;
55017
55494
  if (archived.length > 0) {
55018
55495
  const urp = await Promise.resolve().then(() => (init_update_roadmap_progress(), update_roadmap_progress_exports));
55019
- const roadmapRoot = path79.join(root, "agents", "roadmaps");
55020
- if (fs83.existsSync(roadmapRoot)) {
55496
+ const roadmapRoot = path81.join(root, "agents", "roadmaps");
55497
+ if (fs85.existsSync(roadmapRoot)) {
55021
55498
  const roadmaps = urp.collect(roadmapRoot);
55022
- fs83.writeFileSync(
55023
- path79.join(root, "agents", "roadmaps-progress.md"),
55499
+ fs85.writeFileSync(
55500
+ path81.join(root, "agents", "roadmaps-progress.md"),
55024
55501
  urp.render(roadmaps, urp.collect_bundles(root), roadmapRoot),
55025
55502
  "utf-8"
55026
55503
  );
@@ -55036,9 +55513,9 @@ async function _roadmapArchiveHandler(_args, consumerRoot) {
55036
55513
  async function _capabilitiesIndexHandler(args, consumerRoot) {
55037
55514
  const check = _pyTruthy6(args.check ?? false);
55038
55515
  const cap = await Promise.resolve().then(() => (init_generate_capabilities_index(), generate_capabilities_index_exports));
55039
- const out = path79.join(_PACKAGE_ROOT3, "CAPABILITIES.yaml");
55516
+ const out = path81.join(_PACKAGE_ROOT3, "CAPABILITIES.yaml");
55040
55517
  const content = cap.build();
55041
- const onDisk = fs83.existsSync(out) ? fs83.readFileSync(out, "utf-8") : "";
55518
+ const onDisk = fs85.existsSync(out) ? fs85.readFileSync(out, "utf-8") : "";
55042
55519
  const drift = onDisk !== content;
55043
55520
  if (check) {
55044
55521
  return { check: true, written: false, drift, path: out };
@@ -55049,7 +55526,7 @@ async function _capabilitiesIndexHandler(args, consumerRoot) {
55049
55526
  `CAPABILITIES.yaml path escapes consumer_root: ${out} not under ${root}`
55050
55527
  );
55051
55528
  }
55052
- fs83.writeFileSync(out, content, "utf-8");
55529
+ fs85.writeFileSync(out, content, "utf-8");
55053
55530
  return { check: false, written: true, drift, path: out };
55054
55531
  }
55055
55532
  async function _runDoctorLeg(consumerRoot) {
@@ -55149,11 +55626,11 @@ async function _councilEstimateHandler(args, consumerRoot) {
55149
55626
  throw new Error("'depth' must be 'shallow' or 'deep' when provided");
55150
55627
  }
55151
55628
  const root = _resolvePath2(consumerRoot);
55152
- const target = path79.isAbsolute(inputRaw) ? _resolvePath2(inputRaw) : _resolvePath2(path79.join(root, inputRaw));
55629
+ const target = path81.isAbsolute(inputRaw) ? _resolvePath2(inputRaw) : _resolvePath2(path81.join(root, inputRaw));
55153
55630
  if (_relativeUnder(target, root) === null) {
55154
55631
  throw new Error(`path escapes consumer_root: ${target}`);
55155
55632
  }
55156
- if (!fs83.existsSync(target)) {
55633
+ if (!fs85.existsSync(target)) {
55157
55634
  throw new Error(`input_path not found: ${target}`);
55158
55635
  }
55159
55636
  const cli = await Promise.resolve().then(() => (init_council_cli(), council_cli_exports));
@@ -55215,18 +55692,18 @@ async function _runTestsHandler(args, consumerRoot) {
55215
55692
  if (typeof relPathRaw !== "string" || !_strip8(relPathRaw)) {
55216
55693
  throw new Error("'path' must be a non-empty string when provided");
55217
55694
  }
55218
- const resolved = path79.isAbsolute(relPathRaw) ? _resolvePath2(relPathRaw) : _resolvePath2(path79.join(root, relPathRaw));
55695
+ const resolved = path81.isAbsolute(relPathRaw) ? _resolvePath2(relPathRaw) : _resolvePath2(path81.join(root, relPathRaw));
55219
55696
  const rel = _relativeUnder(resolved, root);
55220
55697
  if (rel === null) {
55221
55698
  throw new Error(`path escapes consumer_root: ${resolved}`);
55222
55699
  }
55223
- if (!fs83.existsSync(resolved)) {
55700
+ if (!fs85.existsSync(resolved)) {
55224
55701
  throw new Error(`path not found: ${resolved}`);
55225
55702
  }
55226
55703
  relArg = rel;
55227
55704
  }
55228
- const vitestEntry = path79.join(root, "node_modules", "vitest", "vitest.mjs");
55229
- if (!fs83.existsSync(vitestEntry)) {
55705
+ const vitestEntry = path81.join(root, "node_modules", "vitest", "vitest.mjs");
55706
+ if (!fs85.existsSync(vitestEntry)) {
55230
55707
  throw new Error(
55231
55708
  "run_tests pilot supports vitest projects only \u2014 node_modules/vitest/vitest.mjs not found under consumer_root"
55232
55709
  );
@@ -55880,8 +56357,8 @@ function _strCmp3(a, b) {
55880
56357
  return a < b ? -1 : a > b ? 1 : 0;
55881
56358
  }
55882
56359
  function _pathlibCompare3(a, b) {
55883
- const pa = a.split(path79.sep);
55884
- const pb = b.split(path79.sep);
56360
+ const pa = a.split(path81.sep);
56361
+ const pb = b.split(path81.sep);
55885
56362
  const n = Math.min(pa.length, pb.length);
55886
56363
  for (let i = 0; i < n; i++) {
55887
56364
  const c = _strCmp3(pa[i], pb[i]);
@@ -56106,7 +56583,7 @@ function main36() {
56106
56583
 
56107
56584
  // src/scripts/mcp_server/__main__.ts
56108
56585
  var _selfPath = fileURLToPath49(import.meta.url);
56109
- var _invokedDirectly2 = globalThis.__AC_MCP_BUNDLE_DIRECT === true || process.argv[1] !== void 0 && path80.resolve(process.argv[1]) === path80.resolve(_selfPath);
56586
+ var _invokedDirectly2 = globalThis.__AC_MCP_BUNDLE_DIRECT === true || process.argv[1] !== void 0 && path82.resolve(process.argv[1]) === path82.resolve(_selfPath);
56110
56587
  if (_invokedDirectly2) {
56111
56588
  main36();
56112
56589
  }
@@ -56116,5 +56593,5 @@ export {
56116
56593
  /*! Bundled license information:
56117
56594
 
56118
56595
  js-yaml/dist/js-yaml.mjs:
56119
- (*! js-yaml 5.2.3 https://github.com/nodeca/js-yaml @license MIT *)
56596
+ (*! js-yaml 5.3.0 https://github.com/nodeca/js-yaml @license MIT *)
56120
56597
  */