@event4u/agent-config 9.10.0 → 9.12.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/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +111 -0
- package/README.md +20 -16
- package/agents/templates/.ai-council.yml.example +481 -0
- package/agents/templates/.ai-video.xml.example +247 -0
- package/dist/agent-src/commands/fix/ci.md +29 -0
- package/dist/agent-src/commands/pr/create.md +60 -0
- package/dist/agent-src/contexts/authority/kernel-rule-edits.md +18 -2
- package/dist/agent-src/rules/design-fidelity.md +2 -2
- package/dist/agent-src/skills/ai-code-blindspots/SKILL.md +1 -0
- package/dist/agent-src/skills/design-intelligence/SKILL.md +27 -1
- package/dist/agent-src/skills/design-intelligence/data/font-pairings-reference.csv +74 -74
- package/dist/agent-src/skills/design-intelligence/data/manifest.json +2 -0
- package/dist/agent-src/skills/design-tokens/scripts/tokens.ts +0 -7
- package/dist/agent-src/skills/existing-ui-audit/SKILL.md +15 -2
- package/dist/agent-src/skills/fe-design/SKILL.md +10 -0
- package/dist/agent-src/skills/typography-system/SKILL.md +55 -11
- package/dist/agent-src/skills/ui-apply-generic/SKILL.md +180 -0
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +34 -30
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/design.ts +88 -33
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/polish.ts +23 -0
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/review.ts +24 -1
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/stack_bundles.ts +332 -0
- package/dist/agent-src/templates/scripts/work_engine/stack/detect.ts +449 -11
- package/dist/agent-src/templates/scripts/work_engine/state.ts +21 -4
- package/dist/cli/initRouting.js +74 -11
- package/dist/cli/initRouting.js.map +1 -1
- package/dist/cli/main.js +14 -3
- package/dist/cli/main.js.map +1 -1
- package/dist/cli-delegate/chunk-523HCFYO.js +90 -0
- package/dist/cli-delegate/chunk-736JCWLM.js +1104 -0
- package/dist/cli-delegate/chunk-7HQ52DHU.js +74 -0
- package/dist/cli-delegate/chunk-A3HJ6NTI.js +1084 -0
- package/dist/cli-delegate/chunk-EJYIGZ3T.js +125 -0
- package/dist/cli-delegate/chunk-FTAISGDQ.js +117 -0
- package/dist/cli-delegate/chunk-GME3Q44L.js +82 -0
- package/dist/cli-delegate/chunk-GRRPEPRN.js +336 -0
- package/dist/cli-delegate/chunk-HJ6DAJHR.js +502 -0
- package/dist/cli-delegate/chunk-HYWSRNUX.js +179 -0
- package/dist/cli-delegate/chunk-J55WI3RR.js +47 -0
- package/dist/cli-delegate/chunk-MCJYCQPF.js +35 -0
- package/dist/cli-delegate/chunk-NDJLNC6Q.js +169 -0
- package/dist/cli-delegate/chunk-OMIVVCG2.js +26 -0
- package/dist/cli-delegate/chunk-OY53J6II.js +7336 -0
- package/dist/cli-delegate/chunk-QFKQLQ7X.js +10835 -0
- package/dist/cli-delegate/chunk-TEGJU2JX.js +6908 -0
- package/dist/cli-delegate/chunk-TJIAM5FW.js +133 -0
- package/dist/cli-delegate/chunk-XX6TOPD7.js +715 -0
- package/dist/cli-delegate/cmd_analyze_session.js +294 -0
- package/dist/cli-delegate/cmd_conformance.js +643 -0
- package/dist/cli-delegate/cmd_converge.js +326 -0
- package/dist/cli-delegate/cmd_doctor.js +142 -0
- package/dist/cli-delegate/cmd_explain.js +2576 -0
- package/dist/cli-delegate/cmd_export.js +298 -0
- package/dist/cli-delegate/cmd_fleet.js +333 -0
- package/dist/cli-delegate/cmd_memory_get.js +3878 -0
- package/dist/cli-delegate/cmd_migrate.js +11 -0
- package/dist/cli-delegate/cmd_preflight.js +153 -0
- package/dist/cli-delegate/cmd_prune.js +446 -0
- package/dist/cli-delegate/cmd_refresh.js +28 -0
- package/dist/cli-delegate/cmd_settings_check.js +574 -0
- package/dist/cli-delegate/cmd_settings_migrate.js +225 -0
- package/dist/cli-delegate/cmd_sync.js +266 -0
- package/dist/cli-delegate/cmd_uninstall.js +657 -0
- package/dist/cli-delegate/cmd_update.js +425 -0
- package/dist/cli-delegate/cmd_upgrade.js +444 -0
- package/dist/cli-delegate/cmd_validate.js +307 -0
- package/dist/cli-delegate/cmd_versions.js +370 -0
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +45 -16
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +3 -3
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +13 -7
- package/dist/discovery/trust-report.md +2 -2
- package/dist/discovery/workspaces.json +6 -4
- package/dist/install/emit_host_rules_cli.js +2 -1
- package/dist/install/emit_host_rules_cli.js.map +1 -1
- package/dist/install/install.mjs +634 -409
- package/dist/install/ruleInScope.js +123 -0
- package/dist/install/ruleInScope.js.map +1 -0
- package/dist/install/rule_scope.js +7 -3
- package/dist/install/rule_scope.js.map +1 -1
- package/dist/install/toolDetection.js +40 -12
- package/dist/install/toolDetection.js.map +1 -1
- package/dist/install/wizard-plan.js +12 -3
- package/dist/install/wizard-plan.js.map +1 -1
- package/dist/mcp/registry-manifest.json +3 -3
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +1553 -2728
- package/dist/router.json +1 -1
- package/dist/scripts/condense.js +6 -22
- package/dist/scripts/condense.js.map +1 -1
- package/docs/guidelines/design-fidelity-mechanics.md +14 -0
- package/package.json +4 -2
- package/src/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +34 -30
- package/src/agent-src/templates/scripts/work_engine/directives/ui/design.ts +88 -33
- package/src/agent-src/templates/scripts/work_engine/directives/ui/polish.ts +23 -0
- package/src/agent-src/templates/scripts/work_engine/directives/ui/review.ts +24 -1
- package/src/agent-src/templates/scripts/work_engine/directives/ui/stack_bundles.ts +332 -0
- package/src/agent-src/templates/scripts/work_engine/stack/detect.ts +449 -11
- package/src/agent-src/templates/scripts/work_engine/state.ts +21 -4
- package/src/config/discovery/packs.yml +7 -0
- package/src/config/evaluator-budgets.json +1 -1
- package/src/config/pack-size-budget.json +27 -0
- package/src/install/emit_host_rules_cli.ts +2 -1
- package/src/install/ruleInScope.ts +133 -0
- package/src/install/rule_scope.ts +7 -3
- package/src/install/toolDetection.ts +39 -8
- package/src/install/wizard-plan.ts +13 -3
- package/src/scripts/_cli/cmd_conformance.ts +2 -1
- package/src/scripts/_cli/cmd_converge.ts +2 -1
- package/src/scripts/_cli/cmd_doctor.ts +214 -13
- package/src/scripts/_cli/cmd_export.ts +2 -1
- package/src/scripts/_cli/cmd_fleet.ts +2 -1
- package/src/scripts/_cli/cmd_migrate.ts +2 -1
- package/src/scripts/_cli/cmd_preflight.ts +2 -1
- package/src/scripts/_cli/cmd_refresh.ts +2 -1
- package/src/scripts/_cli/cmd_update.ts +2 -1
- package/src/scripts/_cli/cmd_upgrade.ts +2 -1
- package/src/scripts/_cli/cmd_versions.ts +2 -1
- package/src/scripts/_cli/detection_report.ts +480 -0
- package/src/scripts/_dispatch.bash +52 -14
- package/src/scripts/_lib/changelog_eras.ts +103 -9
- package/src/scripts/_lib/environment_detector.ts +441 -0
- package/src/scripts/_lib/global_deploy_inventory.ts +38 -2
- package/src/scripts/_lib/package_root.ts +72 -0
- package/src/scripts/ai_council/config.ts +15 -7
- package/src/scripts/ai_council/modes.ts +68 -2
- package/src/scripts/ai_council/transport_resolver.ts +331 -0
- package/src/scripts/check_bundle_path_leakage.ts +10 -4
- package/src/scripts/check_dependency_floors.ts +153 -0
- package/src/scripts/check_installer_import_purity.ts +295 -0
- package/src/scripts/check_pack_size.ts +188 -0
- package/src/scripts/condense.ts +7 -28
- package/src/scripts/council_cli.ts +6 -2
- package/src/scripts/evaluator_umbrella.sh +34 -1
- package/src/scripts/install-hooks.sh +36 -4
- package/src/scripts/install.ts +210 -5
- package/src/scripts/lint_eval_fixture_citations.ts +113 -0
- package/src/scripts/lint_ui_stack_bundles.ts +201 -0
|
@@ -0,0 +1,643 @@
|
|
|
1
|
+
import { createRequire as __acCreateRequire } from 'node:module'; const require = globalThis.require ?? __acCreateRequire(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
ArgparseExit,
|
|
4
|
+
STATUS_SYMBOLS,
|
|
5
|
+
_classify,
|
|
6
|
+
_collect_manifest_entries,
|
|
7
|
+
_foreign_records,
|
|
8
|
+
_is_global_only_consumer,
|
|
9
|
+
_jsonDumpsIndentAscii,
|
|
10
|
+
_resolve_project_root,
|
|
11
|
+
_run_checks,
|
|
12
|
+
_run_checks_no_manifest,
|
|
13
|
+
_scan_foreign
|
|
14
|
+
} from "./chunk-TEGJU2JX.js";
|
|
15
|
+
import "./chunk-FTAISGDQ.js";
|
|
16
|
+
import "./chunk-736JCWLM.js";
|
|
17
|
+
import {
|
|
18
|
+
atomicAppendLine,
|
|
19
|
+
manifest_path,
|
|
20
|
+
read_manifest
|
|
21
|
+
} from "./chunk-A3HJ6NTI.js";
|
|
22
|
+
import "./chunk-GRRPEPRN.js";
|
|
23
|
+
import "./chunk-TJIAM5FW.js";
|
|
24
|
+
import "./chunk-HJ6DAJHR.js";
|
|
25
|
+
import "./chunk-NDJLNC6Q.js";
|
|
26
|
+
import {
|
|
27
|
+
detectToolPresence
|
|
28
|
+
} from "./chunk-OMIVVCG2.js";
|
|
29
|
+
import {
|
|
30
|
+
resolvePackageRoot
|
|
31
|
+
} from "./chunk-MCJYCQPF.js";
|
|
32
|
+
import {
|
|
33
|
+
require_dist
|
|
34
|
+
} from "./chunk-OY53J6II.js";
|
|
35
|
+
import {
|
|
36
|
+
__toESM
|
|
37
|
+
} from "./chunk-J55WI3RR.js";
|
|
38
|
+
|
|
39
|
+
// src/scripts/_cli/cmd_conformance.ts
|
|
40
|
+
var YAML = __toESM(require_dist(), 1);
|
|
41
|
+
import * as fs from "node:fs";
|
|
42
|
+
import * as os from "node:os";
|
|
43
|
+
import * as path from "node:path";
|
|
44
|
+
import process from "node:process";
|
|
45
|
+
import { spawnSync } from "node:child_process";
|
|
46
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
47
|
+
|
|
48
|
+
// src/install/txlog.ts
|
|
49
|
+
import { createReadStream, createWriteStream, existsSync, readFileSync, renameSync, statSync, unlinkSync } from "node:fs";
|
|
50
|
+
var ROTATION_MAX_BYTES = 10 * 1024 * 1024;
|
|
51
|
+
var ROTATION_MAX_AGE_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
52
|
+
var RECOVERY_DEPTH_CAP = 500;
|
|
53
|
+
function readRecentEntries(logPath) {
|
|
54
|
+
if (!existsSync(logPath)) {
|
|
55
|
+
return [];
|
|
56
|
+
}
|
|
57
|
+
const raw = readFileSync(logPath, "utf8");
|
|
58
|
+
const lines = raw.split("\n").filter((l) => l.length > 0);
|
|
59
|
+
const tail = lines.slice(-RECOVERY_DEPTH_CAP);
|
|
60
|
+
const out = [];
|
|
61
|
+
for (const line of tail) {
|
|
62
|
+
const parsed = tryParseEntry(line);
|
|
63
|
+
if (parsed !== null) {
|
|
64
|
+
out.push(parsed);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return out;
|
|
68
|
+
}
|
|
69
|
+
function tryParseEntry(line) {
|
|
70
|
+
try {
|
|
71
|
+
const obj = JSON.parse(line);
|
|
72
|
+
if (typeof obj.ts !== "string" || typeof obj.kind !== "string" || typeof obj.path !== "string") {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
return obj;
|
|
76
|
+
} catch {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// src/scripts/_cli/cmd_conformance.ts
|
|
82
|
+
var _HERE = fileURLToPath(import.meta.url);
|
|
83
|
+
var PACKAGE_ROOT = resolvePackageRoot(import.meta.url);
|
|
84
|
+
var CONFORMANCE_CHECK_IDS = [
|
|
85
|
+
"txlog-clean",
|
|
86
|
+
"router-pointers",
|
|
87
|
+
"hook-dispatcher",
|
|
88
|
+
"lean-projection",
|
|
89
|
+
"host-manifest"
|
|
90
|
+
];
|
|
91
|
+
var THIN_STUB_MARKER = "Routed rule \u2014 load the body on trigger-match";
|
|
92
|
+
function print(s = "") {
|
|
93
|
+
process.stdout.write(`${s}
|
|
94
|
+
`);
|
|
95
|
+
}
|
|
96
|
+
function eprint(s = "") {
|
|
97
|
+
process.stderr.write(`${s}
|
|
98
|
+
`);
|
|
99
|
+
}
|
|
100
|
+
function conformanceLogPath() {
|
|
101
|
+
const override = process.env["AGENT_CONFIG_CONFORMANCE_LOG"];
|
|
102
|
+
if (override && override.trim().length > 0) {
|
|
103
|
+
return override;
|
|
104
|
+
}
|
|
105
|
+
return path.join(os.homedir(), ".event4u", "agent-config", "conformance-log.jsonl");
|
|
106
|
+
}
|
|
107
|
+
function installLogPath() {
|
|
108
|
+
const override = process.env["AGENT_CONFIG_INSTALL_LOG"];
|
|
109
|
+
if (override && override.trim().length > 0) {
|
|
110
|
+
return override;
|
|
111
|
+
}
|
|
112
|
+
return path.join(os.homedir(), ".event4u", "agent-config", "install-log.jsonl");
|
|
113
|
+
}
|
|
114
|
+
function _check_txlog_clean(logPath = installLogPath()) {
|
|
115
|
+
if (!fs.existsSync(logPath)) {
|
|
116
|
+
return {
|
|
117
|
+
id: "txlog-clean",
|
|
118
|
+
status: "ok",
|
|
119
|
+
message: "no install transaction log \u2014 nothing to recover",
|
|
120
|
+
remedy: ""
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
const entries = readRecentEntries(logPath);
|
|
124
|
+
if (entries.length === 0) {
|
|
125
|
+
return {
|
|
126
|
+
id: "txlog-clean",
|
|
127
|
+
status: "ok",
|
|
128
|
+
message: "install transaction log is empty",
|
|
129
|
+
remedy: ""
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
const last = entries[entries.length - 1];
|
|
133
|
+
if (last.kind === "abort") {
|
|
134
|
+
return {
|
|
135
|
+
id: "txlog-clean",
|
|
136
|
+
status: "fail",
|
|
137
|
+
message: `install log tail is an abandoned run (abort at ${last.ts}${last.note ? `: ${last.note}` : ""})`,
|
|
138
|
+
remedy: "re-run `agent-config init` (recovery reverse-applies the aborted tail)"
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
return {
|
|
142
|
+
id: "txlog-clean",
|
|
143
|
+
status: "ok",
|
|
144
|
+
message: `install log tail clean (${entries.length} recent entries, last: ${last.kind})`,
|
|
145
|
+
remedy: ""
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
function routeTargetPaths(target) {
|
|
149
|
+
const sep = target.indexOf(":");
|
|
150
|
+
if (sep <= 0) return [];
|
|
151
|
+
const kind = target.slice(0, sep);
|
|
152
|
+
const id = target.slice(sep + 1);
|
|
153
|
+
if (!id) return [];
|
|
154
|
+
switch (kind) {
|
|
155
|
+
case "skill":
|
|
156
|
+
return [path.join("dist", "agent-src", "skills", id, "SKILL.md")];
|
|
157
|
+
case "command":
|
|
158
|
+
return [path.join("dist", "agent-src", "commands", `${id}.md`)];
|
|
159
|
+
case "guideline":
|
|
160
|
+
return [path.join("docs", "guidelines", `${id}.md`)];
|
|
161
|
+
case "contract":
|
|
162
|
+
return [
|
|
163
|
+
path.join("docs", "contracts", `${id}.md`),
|
|
164
|
+
path.join("dist", "agent-src", "contexts", "contracts", `${id}.md`)
|
|
165
|
+
];
|
|
166
|
+
default:
|
|
167
|
+
return [];
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
function _check_router_pointers(packageRoot = PACKAGE_ROOT) {
|
|
171
|
+
const routerPath = path.join(packageRoot, "dist", "router.json");
|
|
172
|
+
if (!fs.existsSync(routerPath)) {
|
|
173
|
+
return {
|
|
174
|
+
id: "router-pointers",
|
|
175
|
+
status: "fail",
|
|
176
|
+
message: `router index missing: ${routerPath}`,
|
|
177
|
+
remedy: "reinstall the package (dist/router.json ships with every release)"
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
let router;
|
|
181
|
+
try {
|
|
182
|
+
router = JSON.parse(fs.readFileSync(routerPath, "utf8"));
|
|
183
|
+
} catch (exc) {
|
|
184
|
+
return {
|
|
185
|
+
id: "router-pointers",
|
|
186
|
+
status: "fail",
|
|
187
|
+
message: `router index does not parse: ${exc.message}`,
|
|
188
|
+
remedy: "reinstall the package \u2014 dist/router.json is corrupt"
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
const rulesDir = path.join(packageRoot, "dist", "agent-src", "rules");
|
|
192
|
+
const broken = [];
|
|
193
|
+
let ids = 0;
|
|
194
|
+
let targets = 0;
|
|
195
|
+
for (const kernelId of router["kernel"] ?? []) {
|
|
196
|
+
ids += 1;
|
|
197
|
+
if (!fs.existsSync(path.join(rulesDir, `${kernelId}.md`))) {
|
|
198
|
+
broken.push(`kernel:${kernelId} \u2192 rules/${kernelId}.md missing`);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
for (const tier of ["tier_1", "tier_2"]) {
|
|
202
|
+
for (const entry of router[tier] ?? []) {
|
|
203
|
+
const ruleId = String(entry["id"] ?? "");
|
|
204
|
+
ids += 1;
|
|
205
|
+
if (!fs.existsSync(path.join(rulesDir, `${ruleId}.md`))) {
|
|
206
|
+
broken.push(`${tier}:${ruleId} \u2192 rules/${ruleId}.md missing`);
|
|
207
|
+
}
|
|
208
|
+
for (const target of entry["routes_to"] ?? []) {
|
|
209
|
+
targets += 1;
|
|
210
|
+
const candidates = routeTargetPaths(String(target));
|
|
211
|
+
if (candidates.length === 0) {
|
|
212
|
+
broken.push(`${ruleId} \u2192 unparseable routes_to ${JSON.stringify(target)}`);
|
|
213
|
+
continue;
|
|
214
|
+
}
|
|
215
|
+
if (!candidates.some((rel) => fs.existsSync(path.join(packageRoot, rel)))) {
|
|
216
|
+
broken.push(`${ruleId} \u2192 ${target} (${candidates[0]} missing)`);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
if (broken.length > 0) {
|
|
222
|
+
const sample = broken.slice(0, 5).join("; ");
|
|
223
|
+
return {
|
|
224
|
+
id: "router-pointers",
|
|
225
|
+
status: "fail",
|
|
226
|
+
message: `${broken.length} unresolved router pointer(s): ${sample}`,
|
|
227
|
+
remedy: "reinstall the package; if this is a dev tree, run the compile/condense pipeline"
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
return {
|
|
231
|
+
id: "router-pointers",
|
|
232
|
+
status: "ok",
|
|
233
|
+
message: `router index parses; ${ids} rule ids + ${targets} routes_to targets resolve`,
|
|
234
|
+
remedy: ""
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
function detectSmokePlatform(projectRoot) {
|
|
238
|
+
const presence = detectToolPresence(projectRoot);
|
|
239
|
+
if (presence.claude) return "claude";
|
|
240
|
+
if (presence.cursor) return "cursor";
|
|
241
|
+
if (presence.augment) return "augment";
|
|
242
|
+
if (presence.windsurf) return "windsurf";
|
|
243
|
+
if (presence.cline) return "cline";
|
|
244
|
+
return "claude";
|
|
245
|
+
}
|
|
246
|
+
function dispatcherRunner(packageRoot) {
|
|
247
|
+
const localTsx = path.join(packageRoot, "node_modules", ".bin", "tsx");
|
|
248
|
+
const script = path.join(packageRoot, "src", "scripts", "hooks", "dispatch_hook.ts");
|
|
249
|
+
if (fs.existsSync(localTsx)) {
|
|
250
|
+
return [localTsx, script];
|
|
251
|
+
}
|
|
252
|
+
return ["npx", "tsx", script];
|
|
253
|
+
}
|
|
254
|
+
function _check_hook_dispatcher(projectRoot, packageRoot = PACKAGE_ROOT, opts = {}) {
|
|
255
|
+
const platform = opts.platform ?? detectSmokePlatform(projectRoot);
|
|
256
|
+
const runner = opts.runner ?? dispatcherRunner(packageRoot);
|
|
257
|
+
const results = [];
|
|
258
|
+
for (const event of ["session_start", "stop"]) {
|
|
259
|
+
const payload = JSON.stringify({
|
|
260
|
+
session_id: "conformance-smoke",
|
|
261
|
+
cwd: projectRoot,
|
|
262
|
+
platform_hint: platform,
|
|
263
|
+
...event === "stop" ? { stop_reason: "conformance-smoke" } : { source: "startup" }
|
|
264
|
+
});
|
|
265
|
+
const argv = [...runner, "--platform", platform, "--event", event];
|
|
266
|
+
const proc = spawnSync(argv[0], argv.slice(1), {
|
|
267
|
+
input: payload,
|
|
268
|
+
cwd: projectRoot,
|
|
269
|
+
encoding: "utf8",
|
|
270
|
+
timeout: opts.timeoutMs ?? 3e4
|
|
271
|
+
});
|
|
272
|
+
if (proc.error) {
|
|
273
|
+
return {
|
|
274
|
+
id: "hook-dispatcher",
|
|
275
|
+
status: "fail",
|
|
276
|
+
message: `dispatcher spawn failed for ${event}: ${proc.error.message}`,
|
|
277
|
+
remedy: "verify the package install (node_modules present) and re-run"
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
if (proc.status !== 0 && proc.status !== 2) {
|
|
281
|
+
const tail = (proc.stderr ?? "").trim().split("\n").slice(-2).join(" | ");
|
|
282
|
+
return {
|
|
283
|
+
id: "hook-dispatcher",
|
|
284
|
+
status: "fail",
|
|
285
|
+
message: `dispatcher returned exit ${proc.status} for synthetic ${event} (${tail || "no stderr"})`,
|
|
286
|
+
remedy: "run `agent-config doctor --check offline-readiness` and check hook_manifest.yaml"
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
results.push(`${event}=${proc.status}`);
|
|
290
|
+
}
|
|
291
|
+
return {
|
|
292
|
+
id: "hook-dispatcher",
|
|
293
|
+
status: "ok",
|
|
294
|
+
message: `dispatcher (platform: ${platform}) answered ${results.join(", ")}`,
|
|
295
|
+
remedy: ""
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
function readSettingsMode(projectRoot) {
|
|
299
|
+
const settingsPath = path.join(projectRoot, ".agent-settings.yml");
|
|
300
|
+
if (!fs.existsSync(settingsPath)) {
|
|
301
|
+
return "eager-all";
|
|
302
|
+
}
|
|
303
|
+
try {
|
|
304
|
+
const parsed = YAML.parse(fs.readFileSync(settingsPath, "utf8"));
|
|
305
|
+
const lean = parsed?.["lean_projection"] ?? null;
|
|
306
|
+
const mode = lean?.["mode"];
|
|
307
|
+
return typeof mode === "string" && mode.length > 0 ? mode : "eager-all";
|
|
308
|
+
} catch {
|
|
309
|
+
return "eager-all";
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
function kernelIdsFromRouter(packageRoot) {
|
|
313
|
+
try {
|
|
314
|
+
const router = JSON.parse(
|
|
315
|
+
fs.readFileSync(path.join(packageRoot, "dist", "router.json"), "utf8")
|
|
316
|
+
);
|
|
317
|
+
return new Set((router["kernel"] ?? []).map(String));
|
|
318
|
+
} catch {
|
|
319
|
+
return /* @__PURE__ */ new Set();
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
function _check_lean_projection(projectRoot, packageRoot = PACKAGE_ROOT, projectedRulesDir) {
|
|
323
|
+
const mode = readSettingsMode(projectRoot);
|
|
324
|
+
if (mode !== "eager-all" && mode !== "thin") {
|
|
325
|
+
return {
|
|
326
|
+
id: "lean-projection",
|
|
327
|
+
status: "fail",
|
|
328
|
+
message: `lean_projection.mode has unknown value ${JSON.stringify(mode)}`,
|
|
329
|
+
remedy: "set lean_projection.mode to 'eager-all' or 'thin' in .agent-settings.yml"
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
const rulesDir = projectedRulesDir ?? path.join(projectRoot, ".augment", "rules");
|
|
333
|
+
if (!fs.existsSync(rulesDir)) {
|
|
334
|
+
return {
|
|
335
|
+
id: "lean-projection",
|
|
336
|
+
status: "skipped",
|
|
337
|
+
message: `no projected rules dir at ${rulesDir} \u2014 projection consistency not applicable`,
|
|
338
|
+
remedy: ""
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
const kernel = kernelIdsFromRouter(packageRoot);
|
|
342
|
+
const files = fs.readdirSync(rulesDir).filter((f) => f.endsWith(".md") && f !== "INDEX.md").sort();
|
|
343
|
+
const nonKernel = files.filter((f) => !kernel.has(f.replace(/\.md$/, "")));
|
|
344
|
+
if (nonKernel.length === 0) {
|
|
345
|
+
return {
|
|
346
|
+
id: "lean-projection",
|
|
347
|
+
status: "skipped",
|
|
348
|
+
message: "no non-kernel projected rules found \u2014 nothing to compare",
|
|
349
|
+
remedy: ""
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
const inconsistent = [];
|
|
353
|
+
for (const f of nonKernel) {
|
|
354
|
+
let text = "";
|
|
355
|
+
try {
|
|
356
|
+
text = fs.readFileSync(path.join(rulesDir, f), "utf8");
|
|
357
|
+
} catch {
|
|
358
|
+
continue;
|
|
359
|
+
}
|
|
360
|
+
const isStub = text.includes(THIN_STUB_MARKER);
|
|
361
|
+
if (mode === "thin" && !isStub) {
|
|
362
|
+
inconsistent.push(`${f} (full body under thin mode)`);
|
|
363
|
+
}
|
|
364
|
+
if (mode === "eager-all" && isStub) {
|
|
365
|
+
inconsistent.push(`${f} (thin stub under eager-all mode)`);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
if (inconsistent.length > 0) {
|
|
369
|
+
const sample = inconsistent.slice(0, 3).join("; ");
|
|
370
|
+
return {
|
|
371
|
+
id: "lean-projection",
|
|
372
|
+
status: "fail",
|
|
373
|
+
message: `${inconsistent.length}/${nonKernel.length} projected rules contradict lean_projection.mode=${mode}: ${sample}`,
|
|
374
|
+
remedy: "re-run the install/sync so the projection matches the configured mode"
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
return {
|
|
378
|
+
id: "lean-projection",
|
|
379
|
+
status: "ok",
|
|
380
|
+
message: `mode=${mode} consistent across ${nonKernel.length} non-kernel projected rules`,
|
|
381
|
+
remedy: ""
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
var HOST_MANIFEST_KEYS = /* @__PURE__ */ new Set([
|
|
385
|
+
"schema_version",
|
|
386
|
+
"subagent_spawn",
|
|
387
|
+
"parallel_spawn",
|
|
388
|
+
"status_polling",
|
|
389
|
+
"separate_quota_pool"
|
|
390
|
+
]);
|
|
391
|
+
function _check_host_manifest(projectRoot) {
|
|
392
|
+
const detected = Object.entries(detectToolPresence(projectRoot)).filter(([, v]) => v === true).map(([k]) => k);
|
|
393
|
+
const detectedNote = detected.length > 0 ? `detected surfaces: ${detected.join(", ")}` : "no surfaces detected";
|
|
394
|
+
const settingsPath = path.join(projectRoot, ".agent-settings.yml");
|
|
395
|
+
if (!fs.existsSync(settingsPath)) {
|
|
396
|
+
return {
|
|
397
|
+
id: "host-manifest",
|
|
398
|
+
status: "ok",
|
|
399
|
+
message: `no .agent-settings.yml \u2014 safe-default manifest applies (${detectedNote})`,
|
|
400
|
+
remedy: ""
|
|
401
|
+
};
|
|
402
|
+
}
|
|
403
|
+
let parsed = null;
|
|
404
|
+
try {
|
|
405
|
+
parsed = YAML.parse(fs.readFileSync(settingsPath, "utf8"));
|
|
406
|
+
} catch (exc) {
|
|
407
|
+
return {
|
|
408
|
+
id: "host-manifest",
|
|
409
|
+
status: "fail",
|
|
410
|
+
message: `.agent-settings.yml does not parse: ${exc.message}`,
|
|
411
|
+
remedy: "fix the YAML syntax, or run `agent-config settings:check`"
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
const subagents = parsed?.["subagents"] ?? null;
|
|
415
|
+
const manifest = subagents?.["host_capabilities"];
|
|
416
|
+
if (manifest === void 0 || manifest === null) {
|
|
417
|
+
return {
|
|
418
|
+
id: "host-manifest",
|
|
419
|
+
status: "ok",
|
|
420
|
+
message: `no host_capabilities override \u2014 safe-default manifest applies (${detectedNote})`,
|
|
421
|
+
remedy: ""
|
|
422
|
+
};
|
|
423
|
+
}
|
|
424
|
+
if (typeof manifest !== "object" || Array.isArray(manifest)) {
|
|
425
|
+
return {
|
|
426
|
+
id: "host-manifest",
|
|
427
|
+
status: "fail",
|
|
428
|
+
message: "subagents.host_capabilities is not a mapping",
|
|
429
|
+
remedy: "use the four boolean fields from the host-capability manifest contract"
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
const problems = [];
|
|
433
|
+
for (const [key, value] of Object.entries(manifest)) {
|
|
434
|
+
if (!HOST_MANIFEST_KEYS.has(key)) {
|
|
435
|
+
problems.push(`unknown key '${key}'`);
|
|
436
|
+
continue;
|
|
437
|
+
}
|
|
438
|
+
if (key === "schema_version") {
|
|
439
|
+
if (value !== 1) problems.push(`schema_version must be 1 (got ${JSON.stringify(value)})`);
|
|
440
|
+
continue;
|
|
441
|
+
}
|
|
442
|
+
if (typeof value !== "boolean") {
|
|
443
|
+
problems.push(`'${key}' must be boolean (got ${JSON.stringify(value)})`);
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
if (problems.length > 0) {
|
|
447
|
+
return {
|
|
448
|
+
id: "host-manifest",
|
|
449
|
+
status: "fail",
|
|
450
|
+
message: `host_capabilities malformed: ${problems.slice(0, 4).join("; ")}`,
|
|
451
|
+
remedy: "only schema_version:1 + four boolean capability fields are valid"
|
|
452
|
+
};
|
|
453
|
+
}
|
|
454
|
+
return {
|
|
455
|
+
id: "host-manifest",
|
|
456
|
+
status: "ok",
|
|
457
|
+
message: `host_capabilities override parses strictly (${detectedNote})`,
|
|
458
|
+
remedy: ""
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
function runConformanceChecks(opts = {}) {
|
|
462
|
+
const projectRoot = opts.projectRoot ?? process.cwd();
|
|
463
|
+
const packageRoot = opts.packageRoot ?? PACKAGE_ROOT;
|
|
464
|
+
const checks = [];
|
|
465
|
+
checks.push(_check_txlog_clean());
|
|
466
|
+
checks.push(_check_router_pointers(packageRoot));
|
|
467
|
+
if (opts.skipDispatcher === true) {
|
|
468
|
+
checks.push({
|
|
469
|
+
id: "hook-dispatcher",
|
|
470
|
+
status: "skipped",
|
|
471
|
+
message: "dispatcher smoke skipped by flag",
|
|
472
|
+
remedy: ""
|
|
473
|
+
});
|
|
474
|
+
} else {
|
|
475
|
+
checks.push(_check_hook_dispatcher(projectRoot, packageRoot));
|
|
476
|
+
}
|
|
477
|
+
checks.push(_check_lean_projection(projectRoot, packageRoot));
|
|
478
|
+
checks.push(_check_host_manifest(projectRoot));
|
|
479
|
+
return checks;
|
|
480
|
+
}
|
|
481
|
+
function appendConformanceReport(checks, projectRoot, logPath = conformanceLogPath()) {
|
|
482
|
+
const fails = checks.filter((c) => c["status"] === "fail").map((c) => String(c["id"]));
|
|
483
|
+
const ok = checks.filter((c) => c["status"] === "ok").length;
|
|
484
|
+
const entry = {
|
|
485
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
486
|
+
kind: "conformance",
|
|
487
|
+
path: projectRoot,
|
|
488
|
+
sha256: null,
|
|
489
|
+
note: `${ok}/${checks.length} ok; fails: ${fails.length > 0 ? fails.join(",") : "none"}`
|
|
490
|
+
};
|
|
491
|
+
try {
|
|
492
|
+
atomicAppendLine(logPath, JSON.stringify(entry));
|
|
493
|
+
} catch {
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
var USAGE = "usage: agent-config conformance [-h] [--project PROJECT] [--json]\n [--skip-dispatcher]\n";
|
|
497
|
+
function _parse(argv) {
|
|
498
|
+
const opts = { project: null, json: false, skip_dispatcher: false };
|
|
499
|
+
let i = 0;
|
|
500
|
+
while (i < argv.length) {
|
|
501
|
+
const a = argv[i];
|
|
502
|
+
if (a === "-h" || a === "--help") {
|
|
503
|
+
process.stdout.write(USAGE);
|
|
504
|
+
throw new ArgparseExit(0);
|
|
505
|
+
}
|
|
506
|
+
if (a === "--json") {
|
|
507
|
+
opts.json = true;
|
|
508
|
+
} else if (a === "--skip-dispatcher") {
|
|
509
|
+
opts.skip_dispatcher = true;
|
|
510
|
+
} else if (a === "--project" || a.startsWith("--project=")) {
|
|
511
|
+
if (a.includes("=")) {
|
|
512
|
+
opts.project = a.slice(a.indexOf("=") + 1);
|
|
513
|
+
} else {
|
|
514
|
+
if (i + 1 >= argv.length) {
|
|
515
|
+
process.stderr.write(USAGE);
|
|
516
|
+
process.stderr.write("agent-config conformance: error: --project expects a value\n");
|
|
517
|
+
throw new ArgparseExit(2);
|
|
518
|
+
}
|
|
519
|
+
opts.project = argv[i + 1];
|
|
520
|
+
i += 1;
|
|
521
|
+
}
|
|
522
|
+
} else {
|
|
523
|
+
process.stderr.write(USAGE);
|
|
524
|
+
process.stderr.write(`agent-config conformance: error: unrecognized argument ${a}
|
|
525
|
+
`);
|
|
526
|
+
throw new ArgparseExit(2);
|
|
527
|
+
}
|
|
528
|
+
i += 1;
|
|
529
|
+
}
|
|
530
|
+
return opts;
|
|
531
|
+
}
|
|
532
|
+
function main(argv = null) {
|
|
533
|
+
const opts = _parse(argv !== null ? Array.from(argv) : process.argv.slice(2));
|
|
534
|
+
let project_root;
|
|
535
|
+
try {
|
|
536
|
+
[project_root] = _resolve_project_root(opts.project);
|
|
537
|
+
} catch (exc) {
|
|
538
|
+
eprint(`\u274C conformance: ${exc.message}`);
|
|
539
|
+
return 2;
|
|
540
|
+
}
|
|
541
|
+
const manifest_pth = manifest_path(project_root);
|
|
542
|
+
const manifest = read_manifest(manifest_pth);
|
|
543
|
+
let doctorChecks;
|
|
544
|
+
let drift = { missing: [], modified: [], foreign: [], tag_drift: [] };
|
|
545
|
+
if (manifest === null) {
|
|
546
|
+
const bridge_present = _is_global_only_consumer(project_root);
|
|
547
|
+
doctorChecks = _run_checks_no_manifest(project_root, bridge_present, null);
|
|
548
|
+
} else {
|
|
549
|
+
const [records, known] = _collect_manifest_entries(project_root, manifest);
|
|
550
|
+
const [missing, modified, tag_drift] = _classify(records);
|
|
551
|
+
const foreign = _foreign_records(
|
|
552
|
+
project_root,
|
|
553
|
+
_scan_foreign(project_root, manifest, known)
|
|
554
|
+
);
|
|
555
|
+
drift = { missing, modified, foreign, tag_drift };
|
|
556
|
+
doctorChecks = _run_checks(project_root, manifest, drift, null);
|
|
557
|
+
}
|
|
558
|
+
const conformanceChecks = runConformanceChecks({
|
|
559
|
+
projectRoot: project_root,
|
|
560
|
+
skipDispatcher: opts.skip_dispatcher
|
|
561
|
+
});
|
|
562
|
+
const allChecks = [...doctorChecks, ...conformanceChecks];
|
|
563
|
+
const driftCount = drift["missing"].length + drift["modified"].length + drift["foreign"].length + drift["tag_drift"].length;
|
|
564
|
+
const failed = allChecks.some((c) => c["status"] === "fail") || driftCount > 0;
|
|
565
|
+
appendConformanceReport(conformanceChecks, project_root);
|
|
566
|
+
if (opts.json) {
|
|
567
|
+
print(
|
|
568
|
+
_jsonDumpsIndentAscii(
|
|
569
|
+
{
|
|
570
|
+
project_root,
|
|
571
|
+
drift,
|
|
572
|
+
doctor_checks: doctorChecks,
|
|
573
|
+
conformance_checks: conformanceChecks,
|
|
574
|
+
status: failed ? "fail" : "ok"
|
|
575
|
+
},
|
|
576
|
+
2
|
|
577
|
+
)
|
|
578
|
+
);
|
|
579
|
+
} else {
|
|
580
|
+
print(` \u{1F4CD} project_root: ${project_root}`);
|
|
581
|
+
print("conformance:");
|
|
582
|
+
for (const c of allChecks) {
|
|
583
|
+
const sym = STATUS_SYMBOLS[c["status"]] ?? "?";
|
|
584
|
+
print(` ${sym} ${c["id"]}: ${c["message"]}`);
|
|
585
|
+
if (c["status"] !== "ok" && c["remedy"]) {
|
|
586
|
+
print(` fix: ${c["remedy"]}`);
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
if (driftCount > 0) {
|
|
590
|
+
print(` \u274C drift: ${driftCount} drifted file(s) \u2014 run \`agent-config doctor\` for detail`);
|
|
591
|
+
}
|
|
592
|
+
print("");
|
|
593
|
+
print(
|
|
594
|
+
failed ? "\u274C conformance: red \u2014 the OS is not fully installed/firing here" : "\u2705 conformance: green \u2014 installed and firing"
|
|
595
|
+
);
|
|
596
|
+
}
|
|
597
|
+
return failed ? 1 : 0;
|
|
598
|
+
}
|
|
599
|
+
function _isCliEntry() {
|
|
600
|
+
if (process.argv[1] === void 0) {
|
|
601
|
+
return false;
|
|
602
|
+
}
|
|
603
|
+
const argvUrl = pathToFileURL(path.resolve(process.argv[1])).href;
|
|
604
|
+
if (import.meta.url === argvUrl) {
|
|
605
|
+
return true;
|
|
606
|
+
}
|
|
607
|
+
try {
|
|
608
|
+
const here = fs.realpathSync(fileURLToPath(import.meta.url));
|
|
609
|
+
const argv = fs.realpathSync(path.resolve(process.argv[1]));
|
|
610
|
+
return here === argv;
|
|
611
|
+
} catch {
|
|
612
|
+
return false;
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
if (_isCliEntry() || process.argv[1] === _HERE) {
|
|
616
|
+
try {
|
|
617
|
+
process.exitCode = main(process.argv.slice(2));
|
|
618
|
+
} catch (e) {
|
|
619
|
+
if (e instanceof ArgparseExit) {
|
|
620
|
+
process.exitCode = e.code;
|
|
621
|
+
} else {
|
|
622
|
+
throw e;
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
export {
|
|
627
|
+
CONFORMANCE_CHECK_IDS,
|
|
628
|
+
PACKAGE_ROOT,
|
|
629
|
+
THIN_STUB_MARKER,
|
|
630
|
+
_check_hook_dispatcher,
|
|
631
|
+
_check_host_manifest,
|
|
632
|
+
_check_lean_projection,
|
|
633
|
+
_check_router_pointers,
|
|
634
|
+
_check_txlog_clean,
|
|
635
|
+
_parse,
|
|
636
|
+
appendConformanceReport,
|
|
637
|
+
conformanceLogPath,
|
|
638
|
+
detectSmokePlatform,
|
|
639
|
+
installLogPath,
|
|
640
|
+
main,
|
|
641
|
+
routeTargetPaths,
|
|
642
|
+
runConformanceChecks
|
|
643
|
+
};
|