@event4u/agent-config 14.6.0 → 14.7.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 (188) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/CHANGELOG.md +260 -7
  3. package/README.md +1 -1
  4. package/dist/agent-src/commands/analyze/inbox.md +264 -10
  5. package/dist/agent-src/commands/analyze.md +1 -1
  6. package/dist/agent-src/commands/roadmap/process-full.md +116 -30
  7. package/dist/agent-src/contexts/execution/roadmap-execution-contract.md +31 -0
  8. package/dist/agent-src/contexts/execution/roadmap-process-loop.md +135 -104
  9. package/dist/agent-src/rules/context-hygiene.md +2 -0
  10. package/dist/agent-src/rules/decision-revisit-gate.md +3 -0
  11. package/dist/agent-src/rules/fix-what-you-see.md +108 -0
  12. package/dist/agent-src/rules/no-roadmap-references.md +0 -5
  13. package/dist/agent-src/rules/recurring-criticism.md +110 -0
  14. package/dist/agent-src/rules/roadmap-progress-sync.md +1 -1
  15. package/dist/agent-src/rules/rule-type-governance.md +0 -2
  16. package/dist/agent-src/rules/self-repair-loop.md +17 -0
  17. package/dist/agent-src/rules/skill-quality.md +0 -2
  18. package/dist/agent-src/rules/source-confidentiality.md +37 -7
  19. package/dist/agent-src/scripts/archival_sweep.ts +117 -0
  20. package/dist/agent-src/scripts/archive_completed_roadmaps.ts +19 -3
  21. package/dist/agent-src/scripts/gate_budget.ts +282 -0
  22. package/dist/agent-src/scripts/gate_execute.ts +72 -31
  23. package/dist/agent-src/scripts/roadmap_gates.ts +74 -3
  24. package/dist/agent-src/scripts/update_roadmap_progress.ts +251 -7
  25. package/dist/agent-src/skills/ai-council/SKILL.md +48 -807
  26. package/dist/agent-src/skills/ai-council/references/advanced-modes.md +320 -0
  27. package/dist/agent-src/skills/ai-council/references/cost-and-redaction.md +99 -0
  28. package/dist/agent-src/skills/ai-council/references/execution-modes.md +162 -0
  29. package/dist/agent-src/skills/ai-council/references/output-and-synthesis.md +125 -0
  30. package/dist/agent-src/skills/ai-council/references/procedure.md +143 -0
  31. package/dist/agent-src/skills/quality-tools/SKILL.md +34 -326
  32. package/dist/agent-src/skills/quality-tools/references/js-ts-tools.md +113 -0
  33. package/dist/agent-src/skills/quality-tools/references/php-tools.md +222 -0
  34. package/dist/agent-src/skills/roadmap-management/SKILL.md +15 -409
  35. package/dist/agent-src/skills/roadmap-management/references/archival.md +226 -0
  36. package/dist/agent-src/skills/roadmap-management/references/authoring.md +107 -0
  37. package/dist/agent-src/skills/roadmap-management/references/dashboard.md +47 -0
  38. package/dist/agent-src/skills/roadmap-management/references/lifecycle.md +58 -0
  39. package/dist/agent-src/skills/skill-writing/SKILL.md +34 -570
  40. package/dist/agent-src/skills/skill-writing/references/procedure.md +275 -0
  41. package/dist/agent-src/skills/skill-writing/references/read-only-scripts.md +18 -0
  42. package/dist/agent-src/skills/skill-writing/references/section-patterns.md +298 -0
  43. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  44. package/dist/agent-src/templates/roadmaps.md +45 -2
  45. package/dist/agent-src/templates/scripts/telemetry/flush_sender.mjs +163 -0
  46. package/dist/agent-src/templates/scripts/telemetry/remote.ts +160 -7
  47. package/dist/agent-src/templates/scripts/telemetry/transport.ts +169 -0
  48. package/dist/cli/registry.js +1 -1
  49. package/dist/cli/registry.js.map +1 -1
  50. package/dist/cli-delegate/chunk-2GNWGMAL.js +172 -0
  51. package/dist/cli-delegate/{chunk-RLN73PR5.js → chunk-4VR4ORQ6.js} +10 -7
  52. package/dist/cli-delegate/chunk-6EOCNQAM.js +402 -0
  53. package/dist/cli-delegate/{chunk-XURJ4AQC.js → chunk-74E3TKWV.js} +381 -280
  54. package/dist/cli-delegate/{chunk-3UCJWMMP.js → chunk-7F3VYSM2.js} +4 -4
  55. package/dist/cli-delegate/{chunk-BKO2AZ7Z.js → chunk-B2ERU2VA.js} +1 -1
  56. package/dist/cli-delegate/{chunk-NXFWFAYV.js → chunk-G23AT6GD.js} +1 -0
  57. package/dist/cli-delegate/{chunk-63WSP6YZ.js → chunk-GJ5BVHXM.js} +72 -165
  58. package/dist/cli-delegate/{chunk-P6LQDIWK.js → chunk-JZ4NR2TW.js} +338 -0
  59. package/dist/cli-delegate/chunk-MWRD5YOH.js +100 -0
  60. package/dist/cli-delegate/{chunk-GRRPEPRN.js → chunk-T7L2QK3K.js} +24 -5
  61. package/dist/cli-delegate/{chunk-EVTY7ISR.js → chunk-YM4GZDJG.js} +9 -1
  62. package/dist/cli-delegate/cmd_conformance.js +459 -709
  63. package/dist/cli-delegate/cmd_doctor.js +6 -6
  64. package/dist/cli-delegate/cmd_explain.js +1 -1
  65. package/dist/cli-delegate/cmd_export.js +7 -6
  66. package/dist/cli-delegate/cmd_handoff.js +6 -6
  67. package/dist/cli-delegate/cmd_packs_active.js +1 -1
  68. package/dist/cli-delegate/cmd_preflight.js +2 -2
  69. package/dist/cli-delegate/cmd_prune.js +7 -6
  70. package/dist/cli-delegate/cmd_session_recycle.js +840 -30
  71. package/dist/cli-delegate/cmd_settings_migrate.js +7 -6
  72. package/dist/cli-delegate/cmd_settings_set.js +1 -1
  73. package/dist/cli-delegate/cmd_sync.js +7 -6
  74. package/dist/cli-delegate/cmd_uninstall.js +9 -7
  75. package/dist/cli-delegate/cmd_update.js +1 -1
  76. package/dist/cli-delegate/cmd_upgrade.js +1 -1
  77. package/dist/cli-delegate/cmd_validate.js +7 -6
  78. package/dist/discovery/deprecation-report.md +1 -1
  79. package/dist/discovery/discovery-manifest.json +68 -25
  80. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  81. package/dist/discovery/discovery-manifest.summary.md +4 -4
  82. package/dist/discovery/dormancy-report.md +1 -1
  83. package/dist/discovery/orphan-report.md +1 -1
  84. package/dist/discovery/packs.json +10 -8
  85. package/dist/discovery/trust-report.md +3 -3
  86. package/dist/discovery/workspaces.json +8 -6
  87. package/dist/hooks/dispatch.js +2901 -2053
  88. package/dist/install/claudePathsPlan.js +187 -0
  89. package/dist/install/claudePathsPlan.js.map +1 -0
  90. package/dist/install/hostLayerFingerprint.js +136 -0
  91. package/dist/install/hostLayerFingerprint.js.map +1 -0
  92. package/dist/install/install.mjs +553 -425
  93. package/dist/install/partitionEligibility.js +276 -0
  94. package/dist/install/partitionEligibility.js.map +1 -0
  95. package/dist/mcp/registry-manifest.json +3 -3
  96. package/dist/mcp/server.json +2 -2
  97. package/dist/mcp/server.mjs +1744 -1191
  98. package/dist/router.json +1 -1
  99. package/dist/scripts/_lib/agent_src.js +41 -0
  100. package/dist/scripts/_lib/agent_src.js.map +1 -1
  101. package/dist/scripts/_lib/install_layout.js +83 -0
  102. package/dist/scripts/_lib/install_layout.js.map +1 -0
  103. package/dist/scripts/_lib/installed_lock.js +444 -0
  104. package/dist/scripts/_lib/installed_lock.js.map +1 -0
  105. package/dist/scripts/condense.js +13 -164
  106. package/dist/scripts/condense.js.map +1 -1
  107. package/dist/server/schemas/settings.js +4 -0
  108. package/dist/server/schemas/settings.js.map +1 -1
  109. package/docs/contracts/settings-classes.md +12 -6
  110. package/docs/guidelines/agent-infra/agent-interaction-and-decision-quality.md +8 -3
  111. package/docs/guidelines/agent-infra/context-hygiene-mechanics.md +26 -0
  112. package/docs/guidelines/agent-infra/memory-access.md +17 -0
  113. package/docs/guidelines/agent-infra/recurring-criticism-mechanics.md +96 -0
  114. package/package.json +1 -1
  115. package/src/agent-src/scripts/archival_sweep.ts +117 -0
  116. package/src/agent-src/scripts/archive_completed_roadmaps.ts +19 -3
  117. package/src/agent-src/scripts/gate_budget.ts +282 -0
  118. package/src/agent-src/scripts/gate_execute.ts +72 -31
  119. package/src/agent-src/scripts/roadmap_gates.ts +74 -3
  120. package/src/agent-src/scripts/update_roadmap_progress.ts +251 -7
  121. package/src/agent-src/templates/scripts/telemetry/flush_sender.mjs +163 -0
  122. package/src/agent-src/templates/scripts/telemetry/remote.ts +160 -7
  123. package/src/agent-src/templates/scripts/telemetry/transport.ts +169 -0
  124. package/src/config/agent-settings.template.yml +27 -2
  125. package/src/config/ci-local-parity.yml +18 -0
  126. package/src/config/estate-count-budget.json +339 -3
  127. package/src/config/gate-violation-baselines.json +41 -41
  128. package/src/config/rule-activation-census.json +14 -6
  129. package/src/config/rule-stub-ceilings.json +19 -6
  130. package/src/install/claudePathsPlan.ts +196 -0
  131. package/src/install/hostLayerFingerprint.ts +145 -0
  132. package/src/install/partitionEligibility.ts +325 -0
  133. package/src/scripts/_cli/cmd_session_recycle.ts +9 -1
  134. package/src/scripts/_dispatch.bash +6 -1
  135. package/src/scripts/_lib/ac_heading.ts +30 -0
  136. package/src/scripts/_lib/agent_src.ts +42 -0
  137. package/src/scripts/_lib/bench_ab_pinned_repo.ts +162 -0
  138. package/src/scripts/_lib/bench_ab_workspace.ts +10 -1
  139. package/src/scripts/_lib/envelope_grounding.ts +38 -8
  140. package/src/scripts/_lib/installed_lock.ts +50 -5
  141. package/src/scripts/_lib/md_section.ts +129 -0
  142. package/src/scripts/_lib/scope_guard.sh +26 -3
  143. package/src/scripts/_lib/self_repair.ts +19 -0
  144. package/src/scripts/_lib/self_repair_class_b.ts +171 -0
  145. package/src/scripts/ai_council/cli_help.ts +55 -0
  146. package/src/scripts/before_complete_hook.ts +153 -28
  147. package/src/scripts/bench_ab_v2_complexity.ts +27 -7
  148. package/src/scripts/check_references.ts +60 -0
  149. package/src/scripts/check_release_published.ts +32 -11
  150. package/src/scripts/check_single_delivery.ts +59 -15
  151. package/src/scripts/ci_settle.ts +170 -0
  152. package/src/scripts/condense.ts +20 -170
  153. package/src/scripts/council_cli.ts +3 -3
  154. package/src/scripts/dispatch_r2_reviewer.ts +6 -14
  155. package/src/scripts/hook_manifest.json +1 -1
  156. package/src/scripts/hook_manifest.yaml +77 -14
  157. package/src/scripts/hooks/block_no_verify.ts +61 -10
  158. package/src/scripts/hooks/block_unauthorized_git.ts +1 -1
  159. package/src/scripts/hooks/concern_registry.ts +4 -0
  160. package/src/scripts/hooks/rtk_wrap_hook.ts +8 -3
  161. package/src/scripts/hooks/run_continuation_hook.ts +8 -5
  162. package/src/scripts/hooks/ship_diff_volume_hook.ts +81 -15
  163. package/src/scripts/hooks/source_first_gate_hook.ts +464 -0
  164. package/src/scripts/hooks/state_io.ts +782 -20
  165. package/src/scripts/hooks/subagent_ledger_hook.ts +44 -15
  166. package/src/scripts/hooks/telemetry_flush_hook.ts +139 -0
  167. package/src/scripts/hooks/telemetry_self_repair.ts +128 -0
  168. package/src/scripts/hooks/telemetry_usage_hook.ts +22 -4
  169. package/src/scripts/hooks/turn_end_gate_hook.ts +81 -15
  170. package/src/scripts/install.ts +16 -11
  171. package/src/scripts/language_mirror_hook.ts +561 -25
  172. package/src/scripts/lint_framework_leakage_allowlist.json +2 -2
  173. package/src/scripts/lint_plan_risk_register.ts +4 -3
  174. package/src/scripts/lint_skill_router_head.ts +4 -4
  175. package/src/scripts/mcp_server/tools.ts +2 -2
  176. package/src/scripts/new_roadmap.ts +136 -0
  177. package/src/scripts/pack_mcp_content.ts +20 -5
  178. package/src/scripts/release.ts +37 -38
  179. package/src/scripts/report_layer_overlap.ts +6 -0
  180. package/src/scripts/self_repair_hook.ts +37 -5
  181. package/src/scripts/session_register_hook.ts +11 -0
  182. package/src/scripts/skill_usage_collect.ts +11 -1
  183. package/src/scripts/skill_usage_report.ts +278 -8
  184. package/src/scripts/sync_pr_branch.ts +7 -0
  185. package/src/server/schemas/settings.ts +8 -0
  186. package/dist/cli-delegate/chunk-EJITJBJX.js +0 -172
  187. package/dist/cli-delegate/chunk-PZWRPRWP.js +0 -38
  188. /package/dist/cli-delegate/{chunk-RYNADUFG.js → chunk-LWTYTX6F.js} +0 -0
@@ -0,0 +1,172 @@
1
+ import { createRequire as __acCreateRequire } from 'node:module'; const require = globalThis.require ?? __acCreateRequire(import.meta.url);
2
+ import {
3
+ read_lockfile
4
+ } from "./chunk-T7L2QK3K.js";
5
+
6
+ // src/scripts/_lib/turn_end_refusals.ts
7
+ import * as crypto from "node:crypto";
8
+ import * as fs from "node:fs";
9
+ import * as path from "node:path";
10
+ var DETECTOR_IDS = [
11
+ "promissory",
12
+ "language",
13
+ "verification",
14
+ "completion"
15
+ ];
16
+ var REFUSAL_STATE_REL = path.join("agents", "runtime", "state", "turn-end-gate");
17
+ function refusalStateDir(workspaceRoot) {
18
+ return path.join(workspaceRoot, REFUSAL_STATE_REL);
19
+ }
20
+ function deriveSessionKey(sessionId) {
21
+ return crypto.createHash("sha256").update(sessionId).digest("hex").slice(0, 32);
22
+ }
23
+ function sessionRefusalFile(workspaceRoot, sessionKey) {
24
+ return path.join(refusalStateDir(workspaceRoot), `${sessionKey}.json`);
25
+ }
26
+ function readSessionCounts(workspaceRoot, sessionId) {
27
+ try {
28
+ const raw = fs.readFileSync(
29
+ sessionRefusalFile(workspaceRoot, deriveSessionKey(sessionId)),
30
+ "utf-8"
31
+ );
32
+ const rec = parseRecord(raw);
33
+ return rec === null ? null : countsOf(rec);
34
+ } catch {
35
+ return null;
36
+ }
37
+ }
38
+ function emptyCounts() {
39
+ return { promissory: 0, language: 0, verification: 0, completion: 0 };
40
+ }
41
+ function isDetector(v) {
42
+ return typeof v === "string" && DETECTOR_IDS.includes(v);
43
+ }
44
+ function parseRecord(raw) {
45
+ let decoded;
46
+ try {
47
+ decoded = JSON.parse(raw);
48
+ } catch {
49
+ return null;
50
+ }
51
+ if (typeof decoded !== "object" || decoded === null || Array.isArray(decoded)) return null;
52
+ const o = decoded;
53
+ if (typeof o["refused_at"] !== "string") return null;
54
+ if (typeof o["refused_turn"] !== "number") return null;
55
+ if (!isDetector(o["detector"])) return null;
56
+ const rec = {
57
+ refused_at: o["refused_at"],
58
+ refused_turn: o["refused_turn"],
59
+ detector: o["detector"]
60
+ };
61
+ if (typeof o["first_refused_at"] === "string") rec.first_refused_at = o["first_refused_at"];
62
+ if (typeof o["agent_config_version"] === "string") {
63
+ rec.agent_config_version = o["agent_config_version"];
64
+ }
65
+ const counts = o["counts"];
66
+ if (typeof counts === "object" && counts !== null && !Array.isArray(counts)) {
67
+ const parsed = {};
68
+ for (const id of DETECTOR_IDS) {
69
+ const n = counts[id];
70
+ if (typeof n === "number" && Number.isFinite(n) && n >= 0) parsed[id] = n;
71
+ }
72
+ rec.counts = parsed;
73
+ }
74
+ return rec;
75
+ }
76
+ function countsOf(rec) {
77
+ const out = emptyCounts();
78
+ if (rec.counts === void 0) {
79
+ out[rec.detector] = 1;
80
+ return out;
81
+ }
82
+ let any = false;
83
+ for (const id of DETECTOR_IDS) {
84
+ const n = rec.counts[id];
85
+ if (typeof n === "number" && n > 0) {
86
+ out[id] = n;
87
+ any = true;
88
+ }
89
+ }
90
+ if (!any) out[rec.detector] = 1;
91
+ return out;
92
+ }
93
+ function foldRefusal(prev, input) {
94
+ const counts = prev === null ? emptyCounts() : countsOf(prev);
95
+ for (const d of input.detectors) counts[d] += 1;
96
+ const primary = input.detectors[0] ?? prev?.detector ?? "verification";
97
+ const rec = {
98
+ refused_at: input.at,
99
+ refused_turn: input.turnOrdinal,
100
+ detector: primary,
101
+ first_refused_at: prev?.first_refused_at ?? prev?.refused_at ?? input.at,
102
+ counts
103
+ };
104
+ if (input.version !== void 0) rec.agent_config_version = input.version;
105
+ else if (prev?.agent_config_version !== void 0) {
106
+ rec.agent_config_version = prev.agent_config_version;
107
+ }
108
+ return rec;
109
+ }
110
+ function readInstallBoundary() {
111
+ try {
112
+ const lock = read_lockfile();
113
+ if (lock === null) return { version: null, installed_at: null };
114
+ return {
115
+ version: lock.agent_config_version ?? null,
116
+ installed_at: lock.installed_at ?? null
117
+ };
118
+ } catch {
119
+ return { version: null, installed_at: null };
120
+ }
121
+ }
122
+ var REFUSAL_STATE_MAX_AGE_DAYS = 90;
123
+ function pruneAgedRefusalState(workspaceRoot, opts = {}) {
124
+ const maxAgeDays = opts.maxAgeDays ?? REFUSAL_STATE_MAX_AGE_DAYS;
125
+ const now = opts.now ?? /* @__PURE__ */ new Date();
126
+ const dir = refusalStateDir(workspaceRoot);
127
+ const result = { scanned: 0, pruned: 0, kept: 0 };
128
+ let entries;
129
+ try {
130
+ entries = fs.readdirSync(dir);
131
+ } catch {
132
+ return result;
133
+ }
134
+ const cutoffMs = now.getTime() - maxAgeDays * 24 * 60 * 60 * 1e3;
135
+ for (const name of entries) {
136
+ if (!name.endsWith(".json")) continue;
137
+ result.scanned += 1;
138
+ const file = path.join(dir, name);
139
+ let rec = null;
140
+ try {
141
+ rec = parseRecord(fs.readFileSync(file, "utf-8"));
142
+ } catch {
143
+ rec = null;
144
+ }
145
+ if (rec === null) {
146
+ result.kept += 1;
147
+ continue;
148
+ }
149
+ const at = Date.parse(rec.refused_at);
150
+ if (!Number.isFinite(at) || at >= cutoffMs) {
151
+ result.kept += 1;
152
+ continue;
153
+ }
154
+ try {
155
+ fs.unlinkSync(file);
156
+ result.pruned += 1;
157
+ } catch {
158
+ result.kept += 1;
159
+ }
160
+ }
161
+ return result;
162
+ }
163
+
164
+ export {
165
+ deriveSessionKey,
166
+ sessionRefusalFile,
167
+ readSessionCounts,
168
+ parseRecord,
169
+ foldRefusal,
170
+ readInstallBoundary,
171
+ pruneAgedRefusalState
172
+ };
@@ -1,7 +1,10 @@
1
1
  import { createRequire as __acCreateRequire } from 'node:module'; const require = globalThis.require ?? __acCreateRequire(import.meta.url);
2
+ import {
3
+ statePathFor
4
+ } from "./chunk-JZ4NR2TW.js";
2
5
  import {
3
6
  git_common_dir
4
- } from "./chunk-PZWRPRWP.js";
7
+ } from "./chunk-6EOCNQAM.js";
5
8
 
6
9
  // src/scripts/_lib/envelope_grounding.ts
7
10
  import { execFileSync } from "node:child_process";
@@ -78,10 +81,10 @@ function collectRepoAnchor(root) {
78
81
  head: git(root, ["rev-parse", "HEAD"])
79
82
  };
80
83
  }
81
- var VERIFY_STATE_REL = path.join("agents", "runtime", "state", "verify-before-complete.json");
82
- function readLastVerify(root) {
84
+ function readLastVerify(root, session_id) {
85
+ if (typeof session_id !== "string" || session_id.trim() === "") return null;
83
86
  try {
84
- const raw = fs.readFileSync(path.join(root, VERIFY_STATE_REL), "utf-8");
87
+ const raw = fs.readFileSync(path.join(root, statePathFor(session_id)), "utf-8");
85
88
  const state = JSON.parse(raw);
86
89
  const lv = state["last_verification"];
87
90
  if (typeof lv !== "object" || lv === null || Array.isArray(lv)) return null;
@@ -94,11 +97,11 @@ function readLastVerify(root) {
94
97
  return null;
95
98
  }
96
99
  }
97
- function collectGrounding(root) {
100
+ function collectGrounding(root, session_id) {
98
101
  const anchor = collectRepoAnchor(root);
99
102
  const porcelain = git(root, ["status", "--porcelain"]);
100
103
  if (porcelain === null) {
101
- return { ...anchor, uncommitted_paths: [], status_summary: null, last_verify: readLastVerify(root) };
104
+ return { ...anchor, uncommitted_paths: [], status_summary: null, last_verify: readLastVerify(root, session_id) };
102
105
  }
103
106
  const lines = porcelain.split("\n").filter((l) => l.trim().length > 0);
104
107
  const paths = lines.map((l) => l.slice(3).trim()).filter((p) => p.length > 0 && p.length <= MAX_FIELD_CHARS).slice(0, MAX_PATHS);
@@ -106,7 +109,7 @@ function collectGrounding(root) {
106
109
  ...anchor,
107
110
  uncommitted_paths: paths,
108
111
  status_summary: lines.length === 0 ? "clean working tree" : `${lines.length} uncommitted path(s)${lines.length > MAX_PATHS ? `, first ${MAX_PATHS} listed` : ""}`,
109
- last_verify: readLastVerify(root)
112
+ last_verify: readLastVerify(root, session_id)
110
113
  };
111
114
  }
112
115
  function describeDrift(envelope, actual) {
@@ -0,0 +1,402 @@
1
+ import { createRequire as __acCreateRequire } from 'node:module'; const require = globalThis.require ?? __acCreateRequire(import.meta.url);
2
+
3
+ // src/scripts/hooks/state_io.ts
4
+ import { createHash } from "node:crypto";
5
+ import fs from "node:fs";
6
+ import path from "node:path";
7
+ var LOCK_BASENAME = ".dispatcher.lock";
8
+ var REPLAY_ENV_VAR = "AGENT_CONFIG_REPLAY";
9
+ function is_replay_mode() {
10
+ return (process.env[REPLAY_ENV_VAR] ?? "").trim() === "1";
11
+ }
12
+ function _lock_path(state_dir) {
13
+ return path.join(state_dir, LOCK_BASENAME);
14
+ }
15
+ function _target_lock_path(target_path) {
16
+ return `${target_path}.lock`;
17
+ }
18
+ function _py_json_dumps(value, indent) {
19
+ const pad = " ".repeat(indent);
20
+ const escapeString = (s) => {
21
+ let out = '"';
22
+ for (const ch of s) {
23
+ const code = ch.codePointAt(0);
24
+ switch (ch) {
25
+ case '"':
26
+ out += '\\"';
27
+ break;
28
+ case "\\":
29
+ out += "\\\\";
30
+ break;
31
+ case "\n":
32
+ out += "\\n";
33
+ break;
34
+ case "\r":
35
+ out += "\\r";
36
+ break;
37
+ case " ":
38
+ out += "\\t";
39
+ break;
40
+ case "\b":
41
+ out += "\\b";
42
+ break;
43
+ case "\f":
44
+ out += "\\f";
45
+ break;
46
+ default:
47
+ if (code < 32 || code > 126) {
48
+ if (code > 65535) {
49
+ const c = code - 65536;
50
+ const hi = 55296 + (c >> 10);
51
+ const lo = 56320 + (c & 1023);
52
+ out += "\\u" + hi.toString(16).padStart(4, "0") + "\\u" + lo.toString(16).padStart(4, "0");
53
+ } else {
54
+ out += "\\u" + code.toString(16).padStart(4, "0");
55
+ }
56
+ } else {
57
+ out += ch;
58
+ }
59
+ }
60
+ }
61
+ return out + '"';
62
+ };
63
+ const render = (v, depth) => {
64
+ if (v === null || v === void 0) {
65
+ return "null";
66
+ }
67
+ if (typeof v === "boolean") {
68
+ return v ? "true" : "false";
69
+ }
70
+ if (typeof v === "number") {
71
+ if (!Number.isFinite(v)) {
72
+ if (Number.isNaN(v)) return "NaN";
73
+ return v > 0 ? "Infinity" : "-Infinity";
74
+ }
75
+ return String(v);
76
+ }
77
+ if (typeof v === "string") {
78
+ return escapeString(v);
79
+ }
80
+ const curPad = pad.repeat(depth + 1);
81
+ const closePad = pad.repeat(depth);
82
+ if (Array.isArray(v)) {
83
+ if (v.length === 0) {
84
+ return "[]";
85
+ }
86
+ const items = v.map((item) => curPad + render(item, depth + 1));
87
+ return "[\n" + items.join(",\n") + "\n" + closePad + "]";
88
+ }
89
+ if (typeof v === "object") {
90
+ const obj = v;
91
+ const keys = Object.keys(obj);
92
+ if (keys.length === 0) {
93
+ return "{}";
94
+ }
95
+ const items = keys.map(
96
+ (k) => curPad + escapeString(k) + ": " + render(obj[k], depth + 1)
97
+ );
98
+ return "{\n" + items.join(",\n") + "\n" + closePad + "}";
99
+ }
100
+ throw new TypeError(`Object of type ${typeof v} is not JSON serializable`);
101
+ };
102
+ return render(value, 0);
103
+ }
104
+ function atomic_write_json(target, payload, options = {}) {
105
+ if (is_replay_mode()) {
106
+ return;
107
+ }
108
+ const indent = options.indent ?? 2;
109
+ const targetPath = path.resolve(target);
110
+ const state_dir = path.dirname(targetPath);
111
+ fs.mkdirSync(state_dir, { recursive: true });
112
+ const body = _py_json_dumps(payload, indent) + "\n";
113
+ _atomic_write_text(targetPath, body);
114
+ }
115
+ function atomic_write_text(target, text) {
116
+ if (is_replay_mode()) {
117
+ return;
118
+ }
119
+ const targetPath = path.resolve(target);
120
+ const state_dir = path.dirname(targetPath);
121
+ fs.mkdirSync(state_dir, { recursive: true });
122
+ _atomic_write_text(targetPath, text);
123
+ }
124
+ var LOCK_STALE_MS = 3e4;
125
+ var LOCK_ACQUIRE_DEADLINE_MS = 5e3;
126
+ var LOCK_SPIN_SLEEP_MS = 2;
127
+ function _sleep(ms) {
128
+ const sab = new Int32Array(new SharedArrayBuffer(4));
129
+ Atomics.wait(sab, 0, 0, ms);
130
+ }
131
+ function _acquire_lock(lock_path, options = {}) {
132
+ const blocking = options.blocking ?? true;
133
+ const fd = fs.openSync(lock_path, "a", 420);
134
+ const held = lock_path + ".held";
135
+ const give_up = () => {
136
+ try {
137
+ fs.closeSync(fd);
138
+ } catch {
139
+ }
140
+ return null;
141
+ };
142
+ const start = Date.now();
143
+ for (; ; ) {
144
+ try {
145
+ const heldFd = fs.openSync(held, "wx", 420);
146
+ fs.closeSync(heldFd);
147
+ return fd;
148
+ } catch (err) {
149
+ if (err.code !== "EEXIST") {
150
+ return fd;
151
+ }
152
+ let age_ms;
153
+ try {
154
+ age_ms = Date.now() - fs.statSync(held).mtimeMs;
155
+ } catch {
156
+ continue;
157
+ }
158
+ if (age_ms >= LOCK_STALE_MS) {
159
+ try {
160
+ fs.rmSync(held, { force: true });
161
+ } catch {
162
+ }
163
+ continue;
164
+ }
165
+ if (!blocking) {
166
+ return give_up();
167
+ }
168
+ if (Date.now() - start > LOCK_ACQUIRE_DEADLINE_MS) {
169
+ return give_up();
170
+ }
171
+ _sleep(LOCK_SPIN_SLEEP_MS);
172
+ }
173
+ }
174
+ }
175
+ function _release_lock(fd, lock_path) {
176
+ try {
177
+ fs.closeSync(fd);
178
+ } catch {
179
+ }
180
+ try {
181
+ fs.rmSync(lock_path + ".held", { force: true });
182
+ } catch {
183
+ }
184
+ }
185
+ function _publish_text_locked(target, text) {
186
+ const tmp = target + `.tmp.${process.pid}`;
187
+ fs.writeFileSync(tmp, text, { encoding: "utf-8" });
188
+ fs.renameSync(tmp, target);
189
+ }
190
+ function _atomic_write_text(target, text) {
191
+ const lock_path = _lock_path(path.dirname(target));
192
+ const fd = _acquire_lock(lock_path);
193
+ if (fd === null) {
194
+ _publish_text_locked(target, text);
195
+ return;
196
+ }
197
+ try {
198
+ _publish_text_locked(target, text);
199
+ } finally {
200
+ _release_lock(fd, lock_path);
201
+ }
202
+ }
203
+ function has_stable_session_id(session_id) {
204
+ return typeof session_id === "string" && session_id.trim() !== "";
205
+ }
206
+ function session_state_file(dir, session_id) {
207
+ const digest = createHash("sha256").update(session_id, "utf8").digest("hex").slice(0, 32);
208
+ return path.join(dir, `${digest}.json`);
209
+ }
210
+ function restore_claimed_state(tomb, live, link = fs.linkSync) {
211
+ try {
212
+ link(tomb, live);
213
+ } catch (err) {
214
+ const code = err.code;
215
+ if (code !== "EEXIST" && code !== "ENOENT") {
216
+ if (!NO_HARD_LINK_CODES.has(code ?? "")) throw err;
217
+ if (!fs.existsSync(live)) {
218
+ fs.renameSync(tomb, live);
219
+ return;
220
+ }
221
+ }
222
+ }
223
+ fs.rmSync(tomb, { force: true });
224
+ }
225
+ var NO_HARD_LINK_CODES = /* @__PURE__ */ new Set(["EPERM", "ENOSYS", "EXDEV", "EOPNOTSUPP", "EMLINK"]);
226
+ function prune_stale_session_states(dir, now_ms, retention_days, mtime_of = (target) => fs.statSync(target).mtimeMs) {
227
+ if (is_replay_mode()) return 0;
228
+ const cutoff = now_ms - retention_days * 24 * 60 * 60 * 1e3;
229
+ let entries;
230
+ try {
231
+ entries = fs.readdirSync(dir);
232
+ } catch {
233
+ return 0;
234
+ }
235
+ let removed = 0;
236
+ let claim = 0;
237
+ for (const name of entries) {
238
+ const orphan = /^(.+\.json)\.\d+\.\d+\.tomb$/.exec(name);
239
+ const live_name = orphan?.[1];
240
+ if (live_name === void 0) continue;
241
+ const tomb = path.join(dir, name);
242
+ const live = path.join(dir, live_name);
243
+ try {
244
+ if (mtime_of(tomb) >= cutoff) {
245
+ restore_claimed_state(tomb, live);
246
+ continue;
247
+ }
248
+ fs.rmSync(tomb, { force: true });
249
+ removed += 1;
250
+ } catch {
251
+ }
252
+ }
253
+ for (const name of entries) {
254
+ if (!name.endsWith(".json")) continue;
255
+ const full = path.join(dir, name);
256
+ try {
257
+ if (mtime_of(full) >= cutoff) continue;
258
+ claim += 1;
259
+ const tomb = `${full}.${process.pid}.${claim}.tomb`;
260
+ fs.renameSync(full, tomb);
261
+ if (mtime_of(tomb) >= cutoff) {
262
+ restore_claimed_state(tomb, full);
263
+ continue;
264
+ }
265
+ fs.rmSync(tomb, { force: true });
266
+ for (const suffix of [".lock", ".lock.held"]) {
267
+ try {
268
+ fs.rmSync(`${full}${suffix}`, { force: true });
269
+ } catch {
270
+ }
271
+ }
272
+ removed += 1;
273
+ } catch {
274
+ }
275
+ }
276
+ return removed;
277
+ }
278
+ function prune_legacy_state_file(target) {
279
+ if (is_replay_mode()) return;
280
+ try {
281
+ if (fs.statSync(target).isFile()) {
282
+ fs.rmSync(target, { force: true });
283
+ }
284
+ } catch {
285
+ }
286
+ }
287
+ function owns_session_state(state, session_id) {
288
+ if (typeof state !== "object" || state === null || Array.isArray(state)) return false;
289
+ return state["session_id"] === session_id;
290
+ }
291
+ function update_json_under_lock(target, mutate, options = {}) {
292
+ if (is_replay_mode()) return "failed";
293
+ const targetPath = path.resolve(target);
294
+ const state_dir = path.dirname(targetPath);
295
+ try {
296
+ fs.mkdirSync(state_dir, { recursive: true });
297
+ } catch {
298
+ return "failed";
299
+ }
300
+ const lock_path = _target_lock_path(targetPath);
301
+ let fd;
302
+ try {
303
+ fd = _acquire_lock(lock_path, { blocking: options.blocking ?? true });
304
+ } catch {
305
+ return "failed";
306
+ }
307
+ if (fd === null) return "failed";
308
+ try {
309
+ let loaded = {};
310
+ try {
311
+ const raw = fs.readFileSync(targetPath, "utf-8");
312
+ const decoded = JSON.parse(raw);
313
+ if (typeof decoded === "object" && decoded !== null && !Array.isArray(decoded)) {
314
+ loaded = decoded;
315
+ }
316
+ } catch {
317
+ }
318
+ const next = mutate(loaded);
319
+ if (next === null) return "skipped";
320
+ _publish_text_locked(targetPath, _py_json_dumps(next, options.indent ?? 2) + "\n");
321
+ return "written";
322
+ } catch {
323
+ return "failed";
324
+ } finally {
325
+ _release_lock(fd, lock_path);
326
+ }
327
+ }
328
+
329
+ // src/scripts/_lib/git_common_dir.ts
330
+ import fs2 from "node:fs";
331
+ import path2 from "node:path";
332
+ function realpath_or_self(p) {
333
+ try {
334
+ return fs2.realpathSync(p);
335
+ } catch {
336
+ return p;
337
+ }
338
+ }
339
+ function git_dir(project_root) {
340
+ const dot_git = path2.join(project_root, ".git");
341
+ try {
342
+ const st = fs2.statSync(dot_git);
343
+ if (st.isDirectory()) {
344
+ return realpath_or_self(dot_git);
345
+ }
346
+ const m = fs2.readFileSync(dot_git, "utf-8").match(/^gitdir:\s*(.+)\s*$/m);
347
+ if (m === null) {
348
+ return null;
349
+ }
350
+ return realpath_or_self(path2.resolve(project_root, m[1].trim()));
351
+ } catch {
352
+ return null;
353
+ }
354
+ }
355
+ function current_branch(project_root) {
356
+ const gd = git_dir(project_root);
357
+ if (gd === null) return null;
358
+ try {
359
+ const head = fs2.readFileSync(path2.join(gd, "HEAD"), "utf-8").trim();
360
+ const m = head.match(/^ref:\s*refs\/heads\/(.+)$/);
361
+ return m === null ? null : m[1].trim();
362
+ } catch {
363
+ return null;
364
+ }
365
+ }
366
+ function git_common_dir(project_root) {
367
+ const dot_git = path2.join(project_root, ".git");
368
+ try {
369
+ const st = fs2.statSync(dot_git);
370
+ if (st.isDirectory()) {
371
+ return realpath_or_self(dot_git);
372
+ }
373
+ const m = fs2.readFileSync(dot_git, "utf-8").match(/^gitdir:\s*(.+)\s*$/m);
374
+ if (m === null) {
375
+ return null;
376
+ }
377
+ const gitdir = path2.resolve(project_root, m[1].trim());
378
+ const commondir_file = path2.join(gitdir, "commondir");
379
+ if (fs2.existsSync(commondir_file)) {
380
+ const common = path2.resolve(gitdir, fs2.readFileSync(commondir_file, "utf-8").trim());
381
+ return realpath_or_self(common);
382
+ }
383
+ return realpath_or_self(gitdir);
384
+ } catch {
385
+ return null;
386
+ }
387
+ }
388
+
389
+ export {
390
+ is_replay_mode,
391
+ atomic_write_json,
392
+ atomic_write_text,
393
+ has_stable_session_id,
394
+ session_state_file,
395
+ prune_stale_session_states,
396
+ prune_legacy_state_file,
397
+ owns_session_state,
398
+ update_json_under_lock,
399
+ git_dir,
400
+ current_branch,
401
+ git_common_dir
402
+ };