@event4u/agent-config 14.21.0 → 14.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.augment-plugin/marketplace.json +3 -3
- package/.augment-plugin/plugin.json +1 -1
- package/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +164 -187
- package/CREDITS.md +37 -0
- package/README.md +1 -1
- package/dist/agent-src/commands/analyze/inbox.md +380 -5
- package/dist/agent-src/commands/analyze/repo.md +4 -2
- package/dist/agent-src/commands/pr/merge.md +47 -38
- package/dist/agent-src/commands/roadmap/next.md +8 -0
- package/dist/agent-src/contexts/communication/rules-auto/token-efficiency-mechanics.md +69 -0
- package/dist/agent-src/contexts/execution/auto-dispatch-classification.md +5 -5
- package/dist/agent-src/contexts/execution/autonomy-mechanics.md +12 -0
- package/dist/agent-src/rules/external-code-graph-interop.md +19 -14
- package/dist/agent-src/rules/notes-first-reasoning.md +36 -25
- package/dist/agent-src/rules/token-efficiency.md +26 -3
- package/dist/agent-src/scripts/_cli_entry.ts +51 -0
- package/dist/agent-src/scripts/archive_completed_roadmaps.ts +120 -27
- package/dist/agent-src/scripts/roadmap_gates.ts +4 -20
- package/dist/agent-src/scripts/roadmap_set_step.ts +5 -2
- package/dist/agent-src/scripts/stubs_due.ts +4 -18
- package/dist/agent-src/scripts/update_roadmap_progress.ts +7 -24
- package/dist/agent-src/skills/code-intelligence/SKILL.md +82 -1
- package/dist/agent-src/skills/git-workflow/references/push-closes-its-loop.md +9 -0
- package/dist/agent-src/skills/roadmap-writing/SKILL.md +17 -0
- package/dist/agent-src/skills/tailwind-engineer/SKILL.md +52 -2
- package/dist/agent-src/templates/agent-settings.md +0 -1
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/cli/registry.js +1 -1
- package/dist/cli-delegate/_cli_entry.js +8 -0
- package/dist/cli-delegate/_lib/pin_resolver.js +170 -0
- package/dist/cli-delegate/archival_sweep.js +8 -0
- package/dist/cli-delegate/archive_completed_roadmaps.js +542 -0
- package/dist/cli-delegate/check_update_banner.js +923 -0
- package/dist/cli-delegate/{chunk-ZVBOHSVF.js → chunk-2KKXJW25.js} +23 -9
- package/dist/cli-delegate/chunk-5EK5WQN6.js +28 -0
- package/dist/cli-delegate/chunk-7XGD2OEU.js +96 -0
- package/dist/cli-delegate/chunk-DBH4AHDK.js +155 -0
- package/dist/cli-delegate/{chunk-4FS4WRXP.js → chunk-IAI3XL43.js} +15 -3
- package/dist/cli-delegate/chunk-JO25G5H7.js +20 -0
- package/dist/cli-delegate/{chunk-643Z7FIC.js → chunk-KCNTUSPI.js} +7 -1
- package/dist/cli-delegate/chunk-LTYVIY76.js +7961 -0
- package/dist/cli-delegate/chunk-QAJS5YWY.js +999 -0
- package/dist/cli-delegate/{chunk-YS6XTLEK.js → chunk-TYSY33MD.js} +56 -6
- package/dist/cli-delegate/chunk-ULET4BYS.js +328 -0
- package/dist/cli-delegate/chunk-YDQSHTD7.js +187 -0
- package/dist/cli-delegate/chunk-YWVXLR44.js +48 -0
- package/dist/cli-delegate/chunk-ZZQBUHFK.js +273 -0
- package/dist/cli-delegate/cmd_conformance.js +2 -2
- package/dist/cli-delegate/cmd_export.js +2 -2
- package/dist/cli-delegate/cmd_handoff.js +45 -13
- package/dist/cli-delegate/cmd_prune.js +2 -2
- package/dist/cli-delegate/cmd_session_recycle.js +4 -14
- package/dist/cli-delegate/cmd_settings_migrate.js +2 -2
- package/dist/cli-delegate/cmd_settings_set.js +1 -1
- package/dist/cli-delegate/cmd_sync.js +2 -2
- package/dist/cli-delegate/cmd_uninstall.js +2 -2
- package/dist/cli-delegate/cmd_validate.js +2 -2
- package/dist/cli-delegate/dashboard_mode.js +16 -0
- package/dist/cli-delegate/gate_budget.js +24 -0
- package/dist/cli-delegate/gate_execute.js +25 -0
- package/dist/cli-delegate/guarded_baseline.js +18 -0
- package/dist/cli-delegate/resume_probe.js +22 -0
- package/dist/cli-delegate/roadmap_gates.js +638 -0
- package/dist/cli-delegate/roadmap_set_step.js +173 -0
- package/dist/cli-delegate/stub_queue.js +47 -0
- package/dist/cli-delegate/stubs_due.js +38 -0
- package/dist/cli-delegate/ticket_bundles.js +59 -0
- package/dist/cli-delegate/update_roadmap_progress.js +60 -0
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +13 -13
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +1 -1
- package/dist/discovery/dormancy-report.md +1 -1
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +2 -2
- package/dist/discovery/trust-report.md +1 -1
- package/dist/discovery/workspaces.json +2 -2
- package/dist/hooks/dispatch.js +1813 -946
- package/dist/install/claudeLayerCarriage.js +237 -0
- package/dist/install/claudePathsPlan.js +79 -0
- package/dist/install/hostLayerFingerprint.js +1 -1
- package/dist/install/install.mjs +21 -3
- package/dist/install/partitionEligibility.js +231 -117
- package/dist/install/ruleLayerPartition.js +10 -7
- package/dist/mcp/registry-manifest.json +2 -2
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +10870 -7641
- package/dist/scripts/_lib/lean_projection_mode.js +108 -0
- package/dist/scripts/_lib/router_match.js +243 -0
- package/dist/scripts/_lib/rule_injection.js +216 -0
- package/dist/scripts/condense.js +52 -45
- package/dist/scripts/project_thin_rules.js +139 -19
- package/dist/server/schemas/settings.js +16 -3
- package/docs/MIGRATION.md +105 -1
- package/docs/contracts/settings-classes.md +40 -8
- package/docs/guidelines/agent-infra/minimal-safe-diff-mechanics.md +73 -0
- package/docs/guidelines/agent-infra/notes-horizon-mechanics.md +90 -0
- package/llms.txt +1 -1
- package/package.json +7 -4
- package/src/agent-src/scripts/_cli_entry.ts +51 -0
- package/src/agent-src/scripts/archive_completed_roadmaps.ts +120 -27
- package/src/agent-src/scripts/roadmap_gates.ts +4 -20
- package/src/agent-src/scripts/roadmap_set_step.ts +5 -2
- package/src/agent-src/scripts/stubs_due.ts +4 -18
- package/src/agent-src/scripts/update_roadmap_progress.ts +7 -24
- package/src/config/agent-settings.template.yml +47 -1
- package/src/config/continuity-surface.json +516 -0
- package/src/config/estate-count-budget.json +1 -1
- package/src/config/evaluator-budgets.json +4 -4
- package/src/config/gate-coverage.yml +29 -8
- package/src/config/gate-violation-baselines.json +8 -8
- package/src/config/gitignore-block.txt +19 -0
- package/src/config/hook-token-budget.json +7 -6
- package/src/config/host-injection-effect.json +73 -0
- package/src/config/packed-binary-manifest.json +33 -0
- package/src/config/preamble-payload-budget.json +112 -105
- package/src/config/publish-surface.json +4 -2
- package/src/config/routing-coverage-seed.json +9 -2
- package/src/install/claudeLayerCarriage.ts +273 -0
- package/src/install/claudePathsPlan.ts +76 -0
- package/src/install/hostLayerFingerprint.ts +1 -1
- package/src/install/partitionEligibility.ts +261 -127
- package/src/install/ruleLayerPartition.ts +19 -23
- package/src/scripts/_cli/cmd_session_recycle.ts +2 -25
- package/src/scripts/_cli/handoff_sessions.ts +14 -44
- package/src/scripts/_dispatch.bash +77 -27
- package/src/scripts/_lib/auto_dispatch.ts +2 -2
- package/src/scripts/_lib/catalogue_layer_parity.ts +146 -0
- package/src/scripts/_lib/continuity_slot.ts +295 -0
- package/src/scripts/_lib/continuity_surface.ts +296 -0
- package/src/scripts/_lib/continuity_writer.ts +253 -0
- package/src/scripts/_lib/corpus_manifest.ts +26 -9
- package/src/scripts/_lib/hook_settings.ts +86 -1
- package/src/scripts/_lib/injection_effect.ts +151 -0
- package/src/scripts/_lib/layer_overlap_notice.ts +50 -6
- package/src/scripts/_lib/lean_projection_mode.ts +127 -0
- package/src/scripts/_lib/packed_binary_predicate.ts +262 -0
- package/src/scripts/_lib/pin_resolver.ts +13 -0
- package/src/scripts/_lib/recycle_envelope_paths.ts +109 -21
- package/src/scripts/_lib/regression_neighbourhood.ts +159 -22
- package/src/scripts/_lib/retired_status.ts +74 -0
- package/src/scripts/_lib/session_eol.ts +44 -0
- package/src/scripts/_lib/session_index_trust.ts +346 -0
- package/src/scripts/_lib/skill_catalogue.ts +156 -21
- package/src/scripts/_lib/standing_bound_ratchet.ts +154 -0
- package/src/scripts/_lib/subagent_capsule.ts +117 -8
- package/src/scripts/_lib/vendored_grammar_upstream.ts +280 -0
- package/src/scripts/ai_council/api_transport.ts +5 -0
- package/src/scripts/ai_council/deliberation_metrics.ts +353 -0
- package/src/scripts/ai_council/prompts.ts +9 -0
- package/src/scripts/ai_council/synthesis_disagreement.ts +206 -0
- package/src/scripts/audit_mcp_tools.ts +69 -25
- package/src/scripts/build_mcp_catalog.ts +24 -1
- package/src/scripts/capture_skill_catalogue.ts +24 -11
- package/src/scripts/check_candidate_lines.ts +499 -0
- package/src/scripts/check_continuity_surface.ts +475 -0
- package/src/scripts/check_dependency_floors.ts +13 -6
- package/src/scripts/check_estate_count.ts +40 -79
- package/src/scripts/check_host_tree_parity.ts +291 -0
- package/src/scripts/check_pack_size.ts +262 -23
- package/src/scripts/check_preamble_payload_budget.ts +136 -7
- package/src/scripts/check_roadmap_trackable.ts +19 -16
- package/src/scripts/check_rule_layer_partition.ts +54 -34
- package/src/scripts/check_rule_projection_integrity.ts +102 -2
- package/src/scripts/check_single_delivery.ts +97 -31
- package/src/scripts/check_update_banner.ts +13 -0
- package/src/scripts/ci_settle.ts +205 -5
- package/src/scripts/code_graph/build.ts +217 -15
- package/src/scripts/code_graph/cli.ts +334 -15
- package/src/scripts/code_graph/detect.ts +38 -0
- package/src/scripts/code_graph/extract.ts +11 -0
- package/src/scripts/code_graph/grammar_probe.ts +43 -0
- package/src/scripts/code_graph/loader.ts +88 -14
- package/src/scripts/code_graph/query.ts +144 -11
- package/src/scripts/code_graph/resolution_tiers.ts +238 -0
- package/src/scripts/code_graph/sqlite_store.ts +262 -6
- package/src/scripts/code_graph/types.ts +117 -3
- package/src/scripts/code_graph/validate.ts +26 -1
- package/src/scripts/code_graph/verbs.ts +590 -0
- package/src/scripts/condense.ts +54 -42
- package/src/scripts/corpus_manifest.ts +5 -5
- package/src/scripts/council_cli.ts +11 -12
- package/src/scripts/count_intent_disagreement.ts +426 -0
- package/src/scripts/handoff_context_hook.ts +118 -1
- package/src/scripts/hook_effect_doctor.ts +82 -1
- package/src/scripts/hook_manifest.json +1 -1
- package/src/scripts/hook_manifest.yaml +87 -12
- package/src/scripts/hooks/block_speaking_inbox_dir.ts +182 -16
- package/src/scripts/hooks/chain_nudge_hook.ts +282 -0
- package/src/scripts/hooks/code_graph_context_hook.ts +201 -0
- package/src/scripts/hooks/concern_registry.ts +4 -2
- package/src/scripts/hooks/host_semantics.ts +1 -1
- package/src/scripts/hooks/orchestration_record_hook.ts +2 -2
- package/src/scripts/hooks/push_settle_hook.ts +3 -2
- package/src/scripts/hooks/rule_inject_hook.ts +108 -21
- package/src/scripts/hooks/session_eol_hook.ts +120 -2
- package/src/scripts/hooks/skill_route_hook.ts +11 -4
- package/src/scripts/hot_context_hook.ts +62 -7
- package/src/scripts/inbox_source_census.ts +322 -0
- package/src/scripts/install-hooks.sh +82 -0
- package/src/scripts/{lint_carrier_integrity.ts → lint_deferral_integrity.ts} +60 -214
- package/src/scripts/lint_plan_risk_register.ts +13 -17
- package/src/scripts/lint_roadmap_blockers.ts +164 -1
- package/src/scripts/mcp_server/consumer_tool_catalog.json +152 -2
- package/src/scripts/mcp_server/graph_tools.ts +294 -0
- package/src/scripts/mcp_server/path_util.ts +31 -0
- package/src/scripts/mcp_server/suggest_skill.ts +72 -0
- package/src/scripts/mcp_server/tool_catalog_source.ts +7 -1
- package/src/scripts/mcp_server/tools.ts +5 -69
- package/src/scripts/media/lib/adapter-contract.md +7 -2
- package/src/scripts/media/lib/fixtures/flux/asset-0001.png +0 -0
- package/src/scripts/media/lib/fixtures/gemini-image/asset-0001.png +0 -0
- package/src/scripts/media/lib/fixtures/ideogram/asset-0001.png +0 -0
- package/src/scripts/model_rule_injection.ts +61 -4
- package/src/scripts/project_thin_rules.ts +149 -16
- package/src/scripts/rdp_candidates_delta.ts +276 -0
- package/src/scripts/rdp_quality_eval.ts +217 -19
- package/src/scripts/release_mix_taxonomy.json +3 -2
- package/src/scripts/report_host_injection_effect.ts +189 -0
- package/src/scripts/report_layer_overlap.ts +41 -0
- package/src/scripts/report_skill_menu_census.ts +341 -0
- package/src/scripts/report_standing_payload_by_host.ts +650 -0
- package/src/scripts/schemas/agent-settings.schema.json +7 -1
- package/src/scripts/session_memory_index.ts +81 -8
- package/src/scripts/skill_tools/score_skill_relevance.ts +70 -6
- package/src/scripts/skill_tools/suggest_skill_for_task.ts +37 -3
- package/src/server/schemas/settings.ts +23 -4
- package/src/vendor/grammars/README.md +86 -0
- package/src/vendor/grammars/tree-sitter-javascript.wasm +0 -0
- package/src/vendor/grammars/tree-sitter-php.wasm +0 -0
- package/src/vendor/grammars/tree-sitter-typescript.wasm +0 -0
- package/src/scripts/_lib/carrier_status.ts +0 -118
- package/src/scripts/_lib/estate_carrier_cases.ts +0 -72
- package/src/scripts/hooks/code_graph_nudge_hook.ts +0 -191
|
@@ -0,0 +1,542 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
import { createRequire as __acCreateRequire } from 'node:module'; const require = globalThis.require ?? __acCreateRequire(import.meta.url);
|
|
3
|
+
import {
|
|
4
|
+
blocker_is_resolved,
|
|
5
|
+
collect,
|
|
6
|
+
parse_blockers
|
|
7
|
+
} from "./chunk-QAJS5YWY.js";
|
|
8
|
+
import "./chunk-ULET4BYS.js";
|
|
9
|
+
import {
|
|
10
|
+
isCliEntry
|
|
11
|
+
} from "./chunk-5EK5WQN6.js";
|
|
12
|
+
import "./chunk-YWVXLR44.js";
|
|
13
|
+
import "./chunk-7XGD2OEU.js";
|
|
14
|
+
import {
|
|
15
|
+
guardedBaselineProblems,
|
|
16
|
+
parseGuardedBaselines
|
|
17
|
+
} from "./chunk-YDQSHTD7.js";
|
|
18
|
+
import "./chunk-JO25G5H7.js";
|
|
19
|
+
|
|
20
|
+
// src/agent-src/scripts/archive_completed_roadmaps.ts
|
|
21
|
+
import { spawnSync } from "node:child_process";
|
|
22
|
+
import * as fs from "node:fs";
|
|
23
|
+
import * as path from "node:path";
|
|
24
|
+
import process from "node:process";
|
|
25
|
+
import { fileURLToPath } from "node:url";
|
|
26
|
+
var _HERE = fileURLToPath(import.meta.url);
|
|
27
|
+
var ArgparseExit = class extends Error {
|
|
28
|
+
code;
|
|
29
|
+
constructor(code) {
|
|
30
|
+
super(`ArgparseExit(${code})`);
|
|
31
|
+
this.name = "ArgparseExit";
|
|
32
|
+
this.code = code;
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
function _run(cmd, cwd) {
|
|
36
|
+
const res = spawnSync(cmd[0], cmd.slice(1), { cwd, encoding: "utf-8" });
|
|
37
|
+
if (res.error) {
|
|
38
|
+
return { returncode: -1, stdout: res.stdout ?? "", stderr: String(res.error.message ?? "") };
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
returncode: res.status === null ? -1 : res.status,
|
|
42
|
+
stdout: res.stdout ?? "",
|
|
43
|
+
stderr: res.stderr ?? ""
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
function _repo_root() {
|
|
47
|
+
const cp = _run(["git", "rev-parse", "--show-toplevel"], process.cwd());
|
|
48
|
+
return cp.returncode === 0 ? cp.stdout.trim() : process.cwd();
|
|
49
|
+
}
|
|
50
|
+
function _splitlines(s) {
|
|
51
|
+
if (s === "") return [];
|
|
52
|
+
const parts = s.split(/\r\n|\r|\n/);
|
|
53
|
+
if (parts.length && parts[parts.length - 1] === "") {
|
|
54
|
+
parts.pop();
|
|
55
|
+
}
|
|
56
|
+
return parts;
|
|
57
|
+
}
|
|
58
|
+
function _branch_touched_paths(root, base) {
|
|
59
|
+
const cp = _run(
|
|
60
|
+
["git", "log", `${base}..HEAD`, "--name-only", "--pretty=format:"],
|
|
61
|
+
root
|
|
62
|
+
);
|
|
63
|
+
if (cp.returncode !== 0) {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
const out = /* @__PURE__ */ new Set();
|
|
67
|
+
for (const line of _splitlines(cp.stdout)) {
|
|
68
|
+
const t = line.trim();
|
|
69
|
+
if (t) {
|
|
70
|
+
out.add(t);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return out;
|
|
74
|
+
}
|
|
75
|
+
var _FROZEN_RECORD_PREFIXES = ["agents/evidence/"];
|
|
76
|
+
function _is_frozen_record(rel) {
|
|
77
|
+
const norm = rel.split(path.sep).join("/");
|
|
78
|
+
return _FROZEN_RECORD_PREFIXES.some((p) => norm.startsWith(p)) || norm.endsWith(".patch");
|
|
79
|
+
}
|
|
80
|
+
function _inbound_ref_rewrite(root, old_rel, new_rel, dry_run, tracked = true) {
|
|
81
|
+
const changed = [];
|
|
82
|
+
let candidates;
|
|
83
|
+
if (tracked) {
|
|
84
|
+
const grep = _run(["git", "grep", "-l", "--", old_rel], root);
|
|
85
|
+
if (grep.returncode === 1) {
|
|
86
|
+
return changed;
|
|
87
|
+
}
|
|
88
|
+
candidates = grep.returncode === 0 ? _splitlines(grep.stdout).map((l) => l.trim()) : _fs_grep_files(root, old_rel);
|
|
89
|
+
} else {
|
|
90
|
+
candidates = _fs_grep_files(root, old_rel);
|
|
91
|
+
}
|
|
92
|
+
for (const line of candidates) {
|
|
93
|
+
const rel = line.trim();
|
|
94
|
+
if (!rel || rel === old_rel) {
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
if (_is_frozen_record(rel)) {
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
const fp = path.join(root, rel);
|
|
101
|
+
let text;
|
|
102
|
+
try {
|
|
103
|
+
text = fs.readFileSync(fp, { encoding: "utf-8" });
|
|
104
|
+
} catch {
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
if (!text.includes(old_rel)) {
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
if (!dry_run) {
|
|
111
|
+
fs.writeFileSync(fp, _replaceAll(text, old_rel, new_rel), { encoding: "utf-8" });
|
|
112
|
+
}
|
|
113
|
+
changed.push(rel);
|
|
114
|
+
}
|
|
115
|
+
return changed;
|
|
116
|
+
}
|
|
117
|
+
function _replaceAll(text, oldStr, newStr) {
|
|
118
|
+
return text.split(oldStr).join(newStr);
|
|
119
|
+
}
|
|
120
|
+
function _git_mv(root, src_rel, dst_rel, dry_run) {
|
|
121
|
+
const dst = path.join(root, dst_rel);
|
|
122
|
+
if (dry_run) {
|
|
123
|
+
return { ok: true, tracked: true };
|
|
124
|
+
}
|
|
125
|
+
fs.mkdirSync(path.dirname(dst), { recursive: true });
|
|
126
|
+
const cp = _run(["git", "mv", src_rel, dst_rel], root);
|
|
127
|
+
if (cp.returncode === 0) {
|
|
128
|
+
return { ok: true, tracked: true };
|
|
129
|
+
}
|
|
130
|
+
try {
|
|
131
|
+
fs.renameSync(path.join(root, src_rel), dst);
|
|
132
|
+
return { ok: true, tracked: false };
|
|
133
|
+
} catch {
|
|
134
|
+
return { ok: false, tracked: false };
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
function _blockerStatuses(text) {
|
|
138
|
+
const out = /* @__PURE__ */ new Map();
|
|
139
|
+
for (const b of parse_blockers(text)) {
|
|
140
|
+
out.set(b.id, blocker_is_resolved(b) ? "resolved" : "open");
|
|
141
|
+
}
|
|
142
|
+
return out;
|
|
143
|
+
}
|
|
144
|
+
function _indexContent(root, rel) {
|
|
145
|
+
const cp = _run(["git", "show", `:${rel}`], root);
|
|
146
|
+
return cp.returncode === 0 ? cp.stdout : null;
|
|
147
|
+
}
|
|
148
|
+
function _blockerDivergence(root, rel, workTreeText) {
|
|
149
|
+
const staged = _indexContent(root, rel);
|
|
150
|
+
if (staged === null) {
|
|
151
|
+
return [];
|
|
152
|
+
}
|
|
153
|
+
const wt = _blockerStatuses(workTreeText);
|
|
154
|
+
const idx = _blockerStatuses(staged);
|
|
155
|
+
const ids = [.../* @__PURE__ */ new Set([...wt.keys(), ...idx.keys()])].sort();
|
|
156
|
+
const out = [];
|
|
157
|
+
for (const id of ids) {
|
|
158
|
+
const a = idx.get(id);
|
|
159
|
+
const b = wt.get(id);
|
|
160
|
+
if (a === b) {
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
out.push(
|
|
164
|
+
`blocker '${id}': staged=${a ?? "absent"} vs working tree=${b ?? "absent"}`
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
return out;
|
|
168
|
+
}
|
|
169
|
+
function _fs_grep_files(root, needle) {
|
|
170
|
+
const SKIP = /* @__PURE__ */ new Set([".git", "node_modules", ".augment", "dist"]);
|
|
171
|
+
const hits = [];
|
|
172
|
+
const walk = (dirAbs) => {
|
|
173
|
+
let entries;
|
|
174
|
+
try {
|
|
175
|
+
entries = fs.readdirSync(dirAbs, { withFileTypes: true });
|
|
176
|
+
} catch {
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
for (const e of entries) {
|
|
180
|
+
if (e.name.startsWith(".git") || SKIP.has(e.name)) {
|
|
181
|
+
continue;
|
|
182
|
+
}
|
|
183
|
+
const abs = path.join(dirAbs, e.name);
|
|
184
|
+
if (e.isDirectory()) {
|
|
185
|
+
walk(abs);
|
|
186
|
+
} else if (e.isFile() && /\.(md|json|ya?ml|ts|js|txt)$/.test(e.name)) {
|
|
187
|
+
let text;
|
|
188
|
+
try {
|
|
189
|
+
text = fs.readFileSync(abs, { encoding: "utf-8" });
|
|
190
|
+
} catch {
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
193
|
+
if (text.includes(needle)) {
|
|
194
|
+
hits.push(path.relative(root, abs).split(path.sep).join("/"));
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
walk(root);
|
|
200
|
+
return hits;
|
|
201
|
+
}
|
|
202
|
+
var DEFERRED_RESOLUTION_RE = /<!--\s*deferred-resolution:\s*(carried-to|merged-into)\s*=\s*([A-Za-z0-9._-]+)\s*-->/;
|
|
203
|
+
var DEFERRED_STEP_RE = /^[ \t]*[-*][ \t]+\[~\][ \t]*(.*)$/;
|
|
204
|
+
var BLOCK_END_RE = /^[ \t]*[-*][ \t]+\[[ xX~-]\]|^#{1,6}[ \t]/;
|
|
205
|
+
function _escapeRe(v) {
|
|
206
|
+
return v.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
207
|
+
}
|
|
208
|
+
function _relatesTo(text, slug) {
|
|
209
|
+
const lines = text.split("\n");
|
|
210
|
+
const start = lines.findIndex((l) => /^relates:/.test(l));
|
|
211
|
+
if (start === -1) return false;
|
|
212
|
+
const re = new RegExp(`^\\s*-\\s*(slug:\\s*)?${_escapeRe(slug)}\\s*$`);
|
|
213
|
+
for (let i = start + 1; i < lines.length; i++) {
|
|
214
|
+
const line = lines[i];
|
|
215
|
+
if (/^\S/.test(line)) break;
|
|
216
|
+
if (re.test(line)) return true;
|
|
217
|
+
}
|
|
218
|
+
return false;
|
|
219
|
+
}
|
|
220
|
+
function parseDeferredItems(text) {
|
|
221
|
+
const lines = text.split("\n");
|
|
222
|
+
const out = [];
|
|
223
|
+
for (let i = 0; i < lines.length; i++) {
|
|
224
|
+
const m = DEFERRED_STEP_RE.exec(lines[i]);
|
|
225
|
+
if (m === null) continue;
|
|
226
|
+
let block = lines[i];
|
|
227
|
+
for (let j = i + 1; j < lines.length; j++) {
|
|
228
|
+
if (BLOCK_END_RE.test(lines[j])) break;
|
|
229
|
+
block += "\n" + lines[j];
|
|
230
|
+
}
|
|
231
|
+
const a = DEFERRED_RESOLUTION_RE.exec(block);
|
|
232
|
+
out.push({
|
|
233
|
+
text: (m[1] ?? "").trim().slice(0, 120),
|
|
234
|
+
kind: a === null ? null : a[1],
|
|
235
|
+
destination: a === null ? null : a[2]
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
return out;
|
|
239
|
+
}
|
|
240
|
+
function deferralProblems(root, rel, text, alsoArchiving = /* @__PURE__ */ new Set()) {
|
|
241
|
+
const sourceSlug = rel.replace(/\.md$/, "");
|
|
242
|
+
const problems = [];
|
|
243
|
+
for (const item of parseDeferredItems(text)) {
|
|
244
|
+
const label = item.text === "" ? "(unnamed step)" : item.text;
|
|
245
|
+
if (item.kind === null || item.destination === null) {
|
|
246
|
+
problems.push(
|
|
247
|
+
`deferred step ${JSON.stringify(label)} carries no \`<!-- deferred-resolution: carried-to=<slug> -->\` annotation`
|
|
248
|
+
);
|
|
249
|
+
continue;
|
|
250
|
+
}
|
|
251
|
+
const candidates = [
|
|
252
|
+
path.join(root, "agents", "roadmaps", `${item.destination}.md`),
|
|
253
|
+
path.join(root, "agents", "roadmaps", "later", `${item.destination}.md`)
|
|
254
|
+
];
|
|
255
|
+
if (item.destination === sourceSlug) {
|
|
256
|
+
problems.push(
|
|
257
|
+
`deferred step ${JSON.stringify(label)} names its OWN roadmap as the destination \u2014 a carry needs a different receiver, or the item is not carried at all`
|
|
258
|
+
);
|
|
259
|
+
continue;
|
|
260
|
+
}
|
|
261
|
+
if (alsoArchiving.has(item.destination)) {
|
|
262
|
+
problems.push(
|
|
263
|
+
`destination \`${item.destination}\` is being archived by this same sweep, so it would be dead the moment the carry lands \u2014 archive it first and re-run, or carry to a roadmap that stays active`
|
|
264
|
+
);
|
|
265
|
+
continue;
|
|
266
|
+
}
|
|
267
|
+
const found = candidates.find((c) => fs.existsSync(c));
|
|
268
|
+
if (found === void 0) {
|
|
269
|
+
const dead = ["archive", "skipped"].find(
|
|
270
|
+
(d) => fs.existsSync(path.join(root, "agents", "roadmaps", d, `${item.destination ?? ""}.md`))
|
|
271
|
+
);
|
|
272
|
+
problems.push(
|
|
273
|
+
dead === void 0 ? `deferred step ${JSON.stringify(label)} names destination \`${item.destination}\`, which does not exist` : `deferred step ${JSON.stringify(label)} names destination \`${item.destination}\`, which is in \`${dead}/\` \u2014 a dead roadmap cannot receive a carried item`
|
|
274
|
+
);
|
|
275
|
+
continue;
|
|
276
|
+
}
|
|
277
|
+
const destText = fs.readFileSync(found, "utf-8");
|
|
278
|
+
const backlink = new RegExp(`^parent_roadmap:[ ]*${_escapeRe(sourceSlug)}[ ]*$`, "m");
|
|
279
|
+
if (item.kind === "carried-to" && !backlink.test(destText)) {
|
|
280
|
+
problems.push(
|
|
281
|
+
`destination \`${item.destination}\` carries no \`parent_roadmap: ${sourceSlug}\` back-link \u2014 the link must be verifiable from both ends`
|
|
282
|
+
);
|
|
283
|
+
continue;
|
|
284
|
+
}
|
|
285
|
+
if (item.kind === "merged-into" && !backlink.test(destText) && !_relatesTo(destText, sourceSlug)) {
|
|
286
|
+
problems.push(
|
|
287
|
+
`destination \`${item.destination}\` carries no structured link back to \`${sourceSlug}\` \u2014 add a \`relates:\` row naming it (with a \`relation:\`) or a \`parent_roadmap:\` line. A mention in prose is not a link: it is satisfied by a filename or an example.`
|
|
288
|
+
);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
return problems;
|
|
292
|
+
}
|
|
293
|
+
function archive_completed(root, opts) {
|
|
294
|
+
const { changed_only, base, dry_run } = opts;
|
|
295
|
+
const roadmap_root = path.join(root, "agents", "roadmaps");
|
|
296
|
+
if (!_isDir(roadmap_root)) {
|
|
297
|
+
return [];
|
|
298
|
+
}
|
|
299
|
+
const touched = changed_only ? _branch_touched_paths(root, base) : null;
|
|
300
|
+
if (changed_only && touched === null) {
|
|
301
|
+
process.stderr.write(
|
|
302
|
+
` \u26A0\uFE0F cannot resolve \`${base}\` \u2014 skipping the changed-only archival sweep (run with --all to force).
|
|
303
|
+
`
|
|
304
|
+
);
|
|
305
|
+
return [];
|
|
306
|
+
}
|
|
307
|
+
const sweepSet = new Set(
|
|
308
|
+
collect(roadmap_root).filter((s2) => s2.open_ === 0).map((s2) => s2.rel.replace(/\.md$/, ""))
|
|
309
|
+
);
|
|
310
|
+
const archived = [];
|
|
311
|
+
for (const stats of collect(roadmap_root)) {
|
|
312
|
+
const roadmapText = fs.readFileSync(path.join(roadmap_root, stats.rel), "utf-8");
|
|
313
|
+
const guarded = parseGuardedBaselines(roadmapText);
|
|
314
|
+
if (guarded.length > 0) {
|
|
315
|
+
process.stderr.write(
|
|
316
|
+
` \u26A0\uFE0F ${stats.rel}: ${guarded.length} guarded-baseline step(s) \u2014 not archived. Verify against the real mechanism, then flip to \`[x]\`.
|
|
317
|
+
`
|
|
318
|
+
);
|
|
319
|
+
for (const p of guardedBaselineProblems(guarded)) {
|
|
320
|
+
process.stderr.write(` \xB7 ${p}
|
|
321
|
+
`);
|
|
322
|
+
}
|
|
323
|
+
continue;
|
|
324
|
+
}
|
|
325
|
+
if (stats.open_ !== 0) {
|
|
326
|
+
continue;
|
|
327
|
+
}
|
|
328
|
+
if (stats.deferred !== 0) {
|
|
329
|
+
const abs = path.join(roadmap_root, stats.rel);
|
|
330
|
+
const others = new Set(sweepSet);
|
|
331
|
+
others.delete(stats.rel.replace(/\.md$/, ""));
|
|
332
|
+
const problems = deferralProblems(root, stats.rel, fs.readFileSync(abs, "utf-8"), others);
|
|
333
|
+
if (problems.length > 0) {
|
|
334
|
+
process.stderr.write(
|
|
335
|
+
` \u26A0\uFE0F ${stats.rel}: ${problems.length} unresolved deferral(s) \u2014 not archived.
|
|
336
|
+
`
|
|
337
|
+
);
|
|
338
|
+
for (const p of problems) process.stderr.write(` \xB7 ${p}
|
|
339
|
+
`);
|
|
340
|
+
continue;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
const open_blockers = stats.open_blockers;
|
|
344
|
+
if (open_blockers.length > 0) {
|
|
345
|
+
const ids = open_blockers.map((b) => b.id).join(", ");
|
|
346
|
+
process.stderr.write(
|
|
347
|
+
` \u26A0\uFE0F ${stats.rel}: all steps closed but ${open_blockers.length} blocker(s) still open (${ids}) \u2014 not archived. Resolve them, or record the decision, then re-run the sweep.
|
|
348
|
+
`
|
|
349
|
+
);
|
|
350
|
+
continue;
|
|
351
|
+
}
|
|
352
|
+
const old_rel = `agents/roadmaps/${stats.rel}`;
|
|
353
|
+
if (changed_only && !touched.has(old_rel)) {
|
|
354
|
+
continue;
|
|
355
|
+
}
|
|
356
|
+
const divergence = _blockerDivergence(root, old_rel, roadmapText);
|
|
357
|
+
if (divergence.length > 0) {
|
|
358
|
+
process.stderr.write(
|
|
359
|
+
` \u26A0\uFE0F ${stats.rel}: staged and working-tree blockers disagree (${divergence.length}) \u2014 not archived. \`git mv\` would commit the staged content, which this sweep never validated. Stage or discard the change, then re-run.
|
|
360
|
+
`
|
|
361
|
+
);
|
|
362
|
+
for (const d of divergence) {
|
|
363
|
+
process.stderr.write(` \xB7 ${d}
|
|
364
|
+
`);
|
|
365
|
+
}
|
|
366
|
+
continue;
|
|
367
|
+
}
|
|
368
|
+
const new_rel = `agents/roadmaps/archive/${stats.rel}`;
|
|
369
|
+
const mv = _git_mv(root, old_rel, new_rel, dry_run);
|
|
370
|
+
if (!mv.ok) {
|
|
371
|
+
process.stderr.write(` \u26A0\uFE0F could not archive ${old_rel} (mv failed)
|
|
372
|
+
`);
|
|
373
|
+
continue;
|
|
374
|
+
}
|
|
375
|
+
if (!dry_run && mv.tracked) {
|
|
376
|
+
_run(["git", "add", "--", new_rel], root);
|
|
377
|
+
}
|
|
378
|
+
const refs = _inbound_ref_rewrite(root, old_rel, new_rel, dry_run, mv.tracked);
|
|
379
|
+
if (!dry_run && refs.length && mv.tracked) {
|
|
380
|
+
_run(["git", "add", "--", ...refs], root);
|
|
381
|
+
}
|
|
382
|
+
archived.push({ roadmap: old_rel, archived_to: new_rel, refs_migrated: refs });
|
|
383
|
+
}
|
|
384
|
+
return archived;
|
|
385
|
+
}
|
|
386
|
+
function _isDir(p) {
|
|
387
|
+
try {
|
|
388
|
+
return fs.statSync(p).isDirectory();
|
|
389
|
+
} catch {
|
|
390
|
+
return false;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
function _isFile(p) {
|
|
394
|
+
try {
|
|
395
|
+
return fs.statSync(p).isFile();
|
|
396
|
+
} catch {
|
|
397
|
+
return false;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
function _regen_dashboard(root, dry_run) {
|
|
401
|
+
if (dry_run) {
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
404
|
+
const bundledTwin = path.join(path.dirname(_HERE), "update_roadmap_progress.js");
|
|
405
|
+
if (_isFile(bundledTwin)) {
|
|
406
|
+
spawnSync(process.execPath, [bundledTwin], { cwd: root, encoding: "utf-8" });
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
409
|
+
const script = path.join(path.dirname(_HERE), "update_roadmap_progress.ts");
|
|
410
|
+
_runTwin(root, script);
|
|
411
|
+
}
|
|
412
|
+
function _regen_archive_index(root, dry_run) {
|
|
413
|
+
if (dry_run) {
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
const script = path.join(root, "src", "scripts", "build_archive_index.ts");
|
|
417
|
+
if (!_isFile(script)) {
|
|
418
|
+
return;
|
|
419
|
+
}
|
|
420
|
+
_runTwin(root, script);
|
|
421
|
+
for (const rel of ["agents/roadmaps/archive/INDEX.md", "agents/roadmaps/archive/index.json"]) {
|
|
422
|
+
if (_isFile(path.join(root, rel))) {
|
|
423
|
+
_run(["git", "add", "--", rel], root);
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
function _runTwin(root, script) {
|
|
428
|
+
const binName = process.platform === "win32" ? "tsx.cmd" : "tsx";
|
|
429
|
+
let dir = path.dirname(_HERE);
|
|
430
|
+
for (; ; ) {
|
|
431
|
+
const candidate = path.join(dir, "node_modules", ".bin", binName);
|
|
432
|
+
if (fs.existsSync(candidate)) {
|
|
433
|
+
spawnSync(candidate, [script], { cwd: root, encoding: "utf-8" });
|
|
434
|
+
return;
|
|
435
|
+
}
|
|
436
|
+
const parent = path.dirname(dir);
|
|
437
|
+
if (parent === dir) {
|
|
438
|
+
break;
|
|
439
|
+
}
|
|
440
|
+
dir = parent;
|
|
441
|
+
}
|
|
442
|
+
spawnSync("npx", ["tsx", script], { cwd: root, encoding: "utf-8" });
|
|
443
|
+
}
|
|
444
|
+
var _PROG = "archive_completed_roadmaps.py";
|
|
445
|
+
function _usage() {
|
|
446
|
+
return `usage: ${_PROG} [-h] [--all] [--base BASE] [--dry-run] [--repo-root REPO_ROOT]
|
|
447
|
+
`;
|
|
448
|
+
}
|
|
449
|
+
function _parseArgs(argv) {
|
|
450
|
+
let all = false;
|
|
451
|
+
let base = "origin/main";
|
|
452
|
+
let dry_run = false;
|
|
453
|
+
let repo_root = null;
|
|
454
|
+
const emitError = (msg) => {
|
|
455
|
+
process.stderr.write(_usage());
|
|
456
|
+
process.stderr.write(`${_PROG}: error: ${msg}
|
|
457
|
+
`);
|
|
458
|
+
throw new ArgparseExit(2);
|
|
459
|
+
};
|
|
460
|
+
let i = 0;
|
|
461
|
+
while (i < argv.length) {
|
|
462
|
+
const tok = argv[i];
|
|
463
|
+
if (tok === "-h" || tok === "--help") {
|
|
464
|
+
process.stdout.write(_usage());
|
|
465
|
+
throw new ArgparseExit(0);
|
|
466
|
+
} else if (tok === "--all") {
|
|
467
|
+
all = true;
|
|
468
|
+
i += 1;
|
|
469
|
+
} else if (tok === "--dry-run") {
|
|
470
|
+
dry_run = true;
|
|
471
|
+
i += 1;
|
|
472
|
+
} else if (tok === "--base") {
|
|
473
|
+
const val = argv[i + 1];
|
|
474
|
+
if (val === void 0) {
|
|
475
|
+
emitError("argument --base: expected one argument");
|
|
476
|
+
}
|
|
477
|
+
base = val;
|
|
478
|
+
i += 2;
|
|
479
|
+
} else if (tok.startsWith("--base=")) {
|
|
480
|
+
base = tok.slice("--base=".length);
|
|
481
|
+
i += 1;
|
|
482
|
+
} else if (tok === "--repo-root") {
|
|
483
|
+
const val = argv[i + 1];
|
|
484
|
+
if (val === void 0) {
|
|
485
|
+
emitError("argument --repo-root: expected one argument");
|
|
486
|
+
}
|
|
487
|
+
repo_root = val;
|
|
488
|
+
i += 2;
|
|
489
|
+
} else if (tok.startsWith("--repo-root=")) {
|
|
490
|
+
repo_root = tok.slice("--repo-root=".length);
|
|
491
|
+
i += 1;
|
|
492
|
+
} else {
|
|
493
|
+
emitError(`unrecognized arguments: ${tok}`);
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
return { all, base, dry_run, repo_root };
|
|
497
|
+
}
|
|
498
|
+
function main(argv) {
|
|
499
|
+
const ns = _parseArgs(argv ?? process.argv.slice(2));
|
|
500
|
+
const root = ns.repo_root ?? _repo_root();
|
|
501
|
+
const archived = archive_completed(root, {
|
|
502
|
+
changed_only: !ns.all,
|
|
503
|
+
base: ns.base,
|
|
504
|
+
dry_run: ns.dry_run
|
|
505
|
+
});
|
|
506
|
+
if (archived.length === 0) {
|
|
507
|
+
process.stdout.write(" \u2139\uFE0F No completed roadmaps to archive.\n");
|
|
508
|
+
return 0;
|
|
509
|
+
}
|
|
510
|
+
_regen_dashboard(root, ns.dry_run);
|
|
511
|
+
_regen_archive_index(root, ns.dry_run);
|
|
512
|
+
const verb = ns.dry_run ? "Would archive" : "Archived";
|
|
513
|
+
for (const rec of archived) {
|
|
514
|
+
process.stdout.write(
|
|
515
|
+
` \u2705 ${verb}: ${rec.roadmap} \u2192 ${rec.archived_to}` + (rec.refs_migrated.length ? ` (${rec.refs_migrated.length} ref(s) migrated)` : "") + "\n"
|
|
516
|
+
);
|
|
517
|
+
}
|
|
518
|
+
return 0;
|
|
519
|
+
}
|
|
520
|
+
if (isCliEntry(import.meta.url, "archive_completed_roadmaps")) {
|
|
521
|
+
try {
|
|
522
|
+
process.exitCode = main();
|
|
523
|
+
} catch (exc) {
|
|
524
|
+
if (exc instanceof ArgparseExit) {
|
|
525
|
+
process.exitCode = exc.code;
|
|
526
|
+
} else {
|
|
527
|
+
throw exc;
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
export {
|
|
532
|
+
_branch_touched_paths,
|
|
533
|
+
_git_mv,
|
|
534
|
+
_inbound_ref_rewrite,
|
|
535
|
+
_is_frozen_record,
|
|
536
|
+
_relatesTo,
|
|
537
|
+
_repo_root,
|
|
538
|
+
archive_completed,
|
|
539
|
+
deferralProblems,
|
|
540
|
+
main,
|
|
541
|
+
parseDeferredItems
|
|
542
|
+
};
|