@event4u/agent-config 9.10.0 → 9.11.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 +59 -0
- package/README.md +12 -15
- package/agents/templates/.ai-council.yml.example +481 -0
- package/agents/templates/.ai-video.xml.example +247 -0
- package/dist/agent-src/rules/design-fidelity.md +1 -1
- 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/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +30 -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 +20 -0
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/review.ts +20 -1
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/stack_bundles.ts +179 -0
- package/dist/agent-src/templates/scripts/work_engine/stack/detect.ts +155 -4
- 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-4SV3XGFA.js +6910 -0
- package/dist/cli-delegate/chunk-736JCWLM.js +1104 -0
- package/dist/cli-delegate/chunk-7DSAMZFU.js +356 -0
- package/dist/cli-delegate/chunk-7HQ52DHU.js +74 -0
- package/dist/cli-delegate/chunk-BJGXZNPM.js +266 -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-IR7P7JWA.js +872 -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-RDGRHAAB.js +259 -0
- package/dist/cli-delegate/chunk-TFG57JJM.js +1969 -0
- package/dist/cli-delegate/chunk-XX6TOPD7.js +715 -0
- package/dist/cli-delegate/chunk-YMFO6FDN.js +10603 -0
- package/dist/cli-delegate/cmd_analyze_session.js +294 -0
- package/dist/cli-delegate/cmd_conformance.js +646 -0
- package/dist/cli-delegate/cmd_converge.js +326 -0
- package/dist/cli-delegate/cmd_doctor.js +144 -0
- package/dist/cli-delegate/cmd_explain.js +2508 -0
- package/dist/cli-delegate/cmd_export.js +296 -0
- package/dist/cli-delegate/cmd_fleet.js +332 -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 +270 -0
- package/dist/cli-delegate/cmd_prune.js +444 -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 +223 -0
- package/dist/cli-delegate/cmd_sync.js +264 -0
- package/dist/cli-delegate/cmd_uninstall.js +656 -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 +305 -0
- package/dist/cli-delegate/cmd_versions.js +370 -0
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +14 -7
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +2 -2
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +12 -7
- package/dist/discovery/trust-report.md +1 -1
- package/dist/discovery/workspaces.json +4 -3
- 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 +410 -378
- package/dist/install/rule_scope.js +5 -1
- 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 +2 -2
- package/dist/install/wizard-plan.js.map +1 -1
- package/dist/mcp/registry-manifest.json +1 -1
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +1614 -765
- package/dist/router.json +1 -1
- package/package.json +4 -2
- package/src/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +30 -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 +20 -0
- package/src/agent-src/templates/scripts/work_engine/directives/ui/review.ts +20 -1
- package/src/agent-src/templates/scripts/work_engine/directives/ui/stack_bundles.ts +179 -0
- package/src/agent-src/templates/scripts/work_engine/stack/detect.ts +155 -4
- 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/rule_scope.ts +5 -1
- package/src/install/toolDetection.ts +39 -8
- package/src/install/wizard-plan.ts +2 -2
- 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/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_pack_size.ts +188 -0
- package/src/scripts/council_cli.ts +6 -2
- package/src/scripts/evaluator_umbrella.sh +34 -1
- package/src/scripts/lint_eval_fixture_citations.ts +113 -0
- package/src/scripts/lint_ui_stack_bundles.ts +170 -0
|
@@ -0,0 +1,574 @@
|
|
|
1
|
+
import { createRequire as __acCreateRequire } from 'node:module'; const require = globalThis.require ?? __acCreateRequire(import.meta.url);
|
|
2
|
+
import "./chunk-J55WI3RR.js";
|
|
3
|
+
|
|
4
|
+
// src/scripts/_cli/cmd_settings_check.ts
|
|
5
|
+
import process from "node:process";
|
|
6
|
+
import * as fs from "node:fs";
|
|
7
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
8
|
+
import * as path from "node:path";
|
|
9
|
+
|
|
10
|
+
// src/scripts/sync_yaml_rt.ts
|
|
11
|
+
function makeNode(partial = {}) {
|
|
12
|
+
return {
|
|
13
|
+
key: null,
|
|
14
|
+
indent: 0,
|
|
15
|
+
raw_value: null,
|
|
16
|
+
inline_comment: null,
|
|
17
|
+
is_list_item: false,
|
|
18
|
+
leading: [],
|
|
19
|
+
header_line: null,
|
|
20
|
+
trailing: [],
|
|
21
|
+
children: [],
|
|
22
|
+
origin_line: null,
|
|
23
|
+
line_ending: "\n",
|
|
24
|
+
...partial
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function splitKeepEnds(text) {
|
|
28
|
+
const out = [];
|
|
29
|
+
let start = 0;
|
|
30
|
+
for (let i = 0; i < text.length; i++) {
|
|
31
|
+
const ch = text[i];
|
|
32
|
+
if (ch === "\n") {
|
|
33
|
+
out.push(text.slice(start, i + 1));
|
|
34
|
+
start = i + 1;
|
|
35
|
+
} else if (ch === "\r") {
|
|
36
|
+
if (text[i + 1] === "\n") {
|
|
37
|
+
out.push(text.slice(start, i + 2));
|
|
38
|
+
start = i + 2;
|
|
39
|
+
i++;
|
|
40
|
+
} else {
|
|
41
|
+
out.push(text.slice(start, i + 1));
|
|
42
|
+
start = i + 1;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if (start < text.length) {
|
|
47
|
+
out.push(text.slice(start));
|
|
48
|
+
}
|
|
49
|
+
return out;
|
|
50
|
+
}
|
|
51
|
+
function tokenise(text) {
|
|
52
|
+
const out = [];
|
|
53
|
+
if (text === "") {
|
|
54
|
+
return out;
|
|
55
|
+
}
|
|
56
|
+
const rawLines = splitKeepEnds(text);
|
|
57
|
+
for (let idx = 0; idx < rawLines.length; idx++) {
|
|
58
|
+
const i = idx + 1;
|
|
59
|
+
const raw = rawLines[idx];
|
|
60
|
+
if (raw === void 0) {
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
let le;
|
|
64
|
+
let body;
|
|
65
|
+
if (raw.endsWith("\r\n")) {
|
|
66
|
+
le = "\r\n";
|
|
67
|
+
body = raw.slice(0, -2);
|
|
68
|
+
} else if (raw.endsWith("\n")) {
|
|
69
|
+
le = "\n";
|
|
70
|
+
body = raw.slice(0, -1);
|
|
71
|
+
} else if (raw.endsWith("\r")) {
|
|
72
|
+
le = "\r";
|
|
73
|
+
body = raw.slice(0, -1);
|
|
74
|
+
} else {
|
|
75
|
+
le = "";
|
|
76
|
+
body = raw;
|
|
77
|
+
}
|
|
78
|
+
const stripped0 = body.replace(/^[ \t]+/, "");
|
|
79
|
+
const ws = body.slice(0, body.length - stripped0.length);
|
|
80
|
+
if (ws.includes(" ")) {
|
|
81
|
+
throw new Error(`tab character in indent at line ${i} (only spaces allowed)`);
|
|
82
|
+
}
|
|
83
|
+
const indent = ws.length;
|
|
84
|
+
const stripped = body.trim();
|
|
85
|
+
let kind;
|
|
86
|
+
if (stripped === "") {
|
|
87
|
+
kind = "blank";
|
|
88
|
+
} else if (stripped.startsWith("#")) {
|
|
89
|
+
kind = "comment";
|
|
90
|
+
} else if (stripped.startsWith("- ") || stripped === "-") {
|
|
91
|
+
kind = "list";
|
|
92
|
+
} else {
|
|
93
|
+
kind = "mapping";
|
|
94
|
+
}
|
|
95
|
+
out.push({ number: i, raw, line_ending: le, body, indent, kind });
|
|
96
|
+
}
|
|
97
|
+
return out;
|
|
98
|
+
}
|
|
99
|
+
function rstripSpacesTabs(s) {
|
|
100
|
+
return s.replace(/[ \t]+$/, "");
|
|
101
|
+
}
|
|
102
|
+
function splitInlineComment(valuePart) {
|
|
103
|
+
let inSingle = false;
|
|
104
|
+
let inDouble = false;
|
|
105
|
+
for (let i = 0; i < valuePart.length; i++) {
|
|
106
|
+
const ch = valuePart[i];
|
|
107
|
+
if (ch === "'" && !inDouble) {
|
|
108
|
+
inSingle = !inSingle;
|
|
109
|
+
} else if (ch === '"' && !inSingle) {
|
|
110
|
+
inDouble = !inDouble;
|
|
111
|
+
} else if (ch === "#" && !inSingle && !inDouble) {
|
|
112
|
+
if (i === 0 || valuePart[i - 1] === " " || valuePart[i - 1] === " ") {
|
|
113
|
+
const valueText = rstripSpacesTabs(valuePart.slice(0, i));
|
|
114
|
+
const commentText = valuePart.slice(i);
|
|
115
|
+
return [valueText, commentText];
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return [rstripSpacesTabs(valuePart) || "", null];
|
|
120
|
+
}
|
|
121
|
+
function parseMappingLine(body) {
|
|
122
|
+
const stripped = body.replace(/^ +/, "");
|
|
123
|
+
let rawKey;
|
|
124
|
+
let rest;
|
|
125
|
+
let key;
|
|
126
|
+
if (stripped.startsWith('"')) {
|
|
127
|
+
const end = stripped.indexOf('"', 1);
|
|
128
|
+
if (end === -1) {
|
|
129
|
+
throw new Error("unterminated double-quoted key");
|
|
130
|
+
}
|
|
131
|
+
rawKey = stripped.slice(0, end + 1);
|
|
132
|
+
rest = stripped.slice(end + 1);
|
|
133
|
+
key = stripped.slice(1, end);
|
|
134
|
+
} else if (stripped.startsWith("'")) {
|
|
135
|
+
const end = stripped.indexOf("'", 1);
|
|
136
|
+
if (end === -1) {
|
|
137
|
+
throw new Error("unterminated single-quoted key");
|
|
138
|
+
}
|
|
139
|
+
rawKey = stripped.slice(0, end + 1);
|
|
140
|
+
rest = stripped.slice(end + 1);
|
|
141
|
+
key = stripped.slice(1, end);
|
|
142
|
+
} else {
|
|
143
|
+
let colon = -1;
|
|
144
|
+
for (let i = 0; i < stripped.length; i++) {
|
|
145
|
+
if (stripped[i] === ":") {
|
|
146
|
+
const following = stripped.slice(i + 1, i + 2);
|
|
147
|
+
if (following === "" || following === " " || following === " " || following === "#") {
|
|
148
|
+
colon = i;
|
|
149
|
+
break;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
if (colon === -1) {
|
|
154
|
+
throw new Error(`missing ':' in mapping line: ${pyRepr(stripped)}`);
|
|
155
|
+
}
|
|
156
|
+
rawKey = stripped.slice(0, colon);
|
|
157
|
+
rest = stripped.slice(colon);
|
|
158
|
+
key = rawKey;
|
|
159
|
+
}
|
|
160
|
+
if (rest.startsWith(":")) {
|
|
161
|
+
rest = rest.slice(1);
|
|
162
|
+
} else if (rest.startsWith(" :") || rest.startsWith(" :")) {
|
|
163
|
+
rest = rest.replace(/^[ \t]+/, "").slice(1);
|
|
164
|
+
} else if (rest.replace(/^\s+/, "").startsWith(":")) {
|
|
165
|
+
rest = rest.replace(/^\s+/, "").slice(1);
|
|
166
|
+
} else {
|
|
167
|
+
throw new Error(`missing ':' after key ${pyRepr(rawKey)}: rest=${pyRepr(rest)}`);
|
|
168
|
+
}
|
|
169
|
+
const restText = rest.replace(/^[ \t]+/, "");
|
|
170
|
+
if (restText === "") {
|
|
171
|
+
return [key, null, null];
|
|
172
|
+
}
|
|
173
|
+
if (restText.startsWith("#")) {
|
|
174
|
+
return [key, null, restText];
|
|
175
|
+
}
|
|
176
|
+
const [rawValue, comment] = splitInlineComment(restText);
|
|
177
|
+
return [key, rawValue, comment];
|
|
178
|
+
}
|
|
179
|
+
function parseListLine(body) {
|
|
180
|
+
const stripped = body.replace(/^ +/, "");
|
|
181
|
+
if (stripped !== "-" && !stripped.startsWith("- ")) {
|
|
182
|
+
throw new Error(`not a list line: ${pyRepr(body)}`);
|
|
183
|
+
}
|
|
184
|
+
if (stripped === "-") {
|
|
185
|
+
return [null, null];
|
|
186
|
+
}
|
|
187
|
+
const rest = stripped.slice(2);
|
|
188
|
+
if (rest === "") {
|
|
189
|
+
return [null, null];
|
|
190
|
+
}
|
|
191
|
+
if (rest.startsWith("#")) {
|
|
192
|
+
return [null, rest];
|
|
193
|
+
}
|
|
194
|
+
return splitInlineComment(rest);
|
|
195
|
+
}
|
|
196
|
+
function pyRepr(s) {
|
|
197
|
+
const hasSingle = s.includes("'");
|
|
198
|
+
const hasDouble = s.includes('"');
|
|
199
|
+
const quote = hasSingle && !hasDouble ? '"' : "'";
|
|
200
|
+
let out = quote;
|
|
201
|
+
for (const ch of s) {
|
|
202
|
+
if (ch === "\\") {
|
|
203
|
+
out += "\\\\";
|
|
204
|
+
} else if (ch === quote) {
|
|
205
|
+
out += "\\" + quote;
|
|
206
|
+
} else if (ch === "\n") {
|
|
207
|
+
out += "\\n";
|
|
208
|
+
} else if (ch === "\r") {
|
|
209
|
+
out += "\\r";
|
|
210
|
+
} else if (ch === " ") {
|
|
211
|
+
out += "\\t";
|
|
212
|
+
} else {
|
|
213
|
+
out += ch;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
out += quote;
|
|
217
|
+
return out;
|
|
218
|
+
}
|
|
219
|
+
function buildTree(lines) {
|
|
220
|
+
const root = makeNode({ indent: -1 });
|
|
221
|
+
const stack = [[root, null]];
|
|
222
|
+
let pending = [];
|
|
223
|
+
for (const line of lines) {
|
|
224
|
+
if (line.kind === "blank" || line.kind === "comment") {
|
|
225
|
+
pending.push(line.raw);
|
|
226
|
+
continue;
|
|
227
|
+
}
|
|
228
|
+
let parent;
|
|
229
|
+
for (; ; ) {
|
|
230
|
+
const top = stack[stack.length - 1];
|
|
231
|
+
if (top === void 0) {
|
|
232
|
+
throw new Error(`indent underflow at line ${line.number}`);
|
|
233
|
+
}
|
|
234
|
+
parent = top[0];
|
|
235
|
+
const fixedIndent = top[1];
|
|
236
|
+
const parentIndent = parent.indent;
|
|
237
|
+
if (line.indent > parentIndent) {
|
|
238
|
+
if (fixedIndent === null) {
|
|
239
|
+
stack[stack.length - 1] = [parent, line.indent];
|
|
240
|
+
break;
|
|
241
|
+
}
|
|
242
|
+
if (line.indent === fixedIndent) {
|
|
243
|
+
break;
|
|
244
|
+
}
|
|
245
|
+
if (line.indent > fixedIndent) {
|
|
246
|
+
throw new Error(
|
|
247
|
+
`unexpected over-indent at line ${line.number} (parent expects ${fixedIndent}, got ${line.indent})`
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
stack.pop();
|
|
252
|
+
if (stack.length === 0) {
|
|
253
|
+
throw new Error(`indent underflow at line ${line.number}`);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
const node = lineToNode(line);
|
|
257
|
+
if (node.key !== null) {
|
|
258
|
+
for (let i = 0; i < parent.children.length; i++) {
|
|
259
|
+
const sib = parent.children[i];
|
|
260
|
+
if (sib !== void 0 && sib.key === node.key && !sib.is_list_item) {
|
|
261
|
+
parent.children.splice(i, 1);
|
|
262
|
+
break;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
parent.children.push(node);
|
|
267
|
+
stack.push([node, null]);
|
|
268
|
+
if (pending.length > 0) {
|
|
269
|
+
node.leading = pending;
|
|
270
|
+
pending = [];
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
if (pending.length > 0) {
|
|
274
|
+
root.trailing = pending;
|
|
275
|
+
}
|
|
276
|
+
return root;
|
|
277
|
+
}
|
|
278
|
+
function lineToNode(line) {
|
|
279
|
+
if (line.kind === "list") {
|
|
280
|
+
const [rawValue2, inline2] = parseListLine(line.body);
|
|
281
|
+
return makeNode({
|
|
282
|
+
key: null,
|
|
283
|
+
indent: line.indent,
|
|
284
|
+
raw_value: rawValue2,
|
|
285
|
+
inline_comment: inline2,
|
|
286
|
+
is_list_item: true,
|
|
287
|
+
header_line: line.raw,
|
|
288
|
+
origin_line: line.number,
|
|
289
|
+
line_ending: line.line_ending
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
const [key, rawValue, inline] = parseMappingLine(line.body);
|
|
293
|
+
return makeNode({
|
|
294
|
+
key,
|
|
295
|
+
indent: line.indent,
|
|
296
|
+
raw_value: rawValue,
|
|
297
|
+
inline_comment: inline,
|
|
298
|
+
is_list_item: false,
|
|
299
|
+
header_line: line.raw,
|
|
300
|
+
origin_line: line.number,
|
|
301
|
+
line_ending: line.line_ending
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
function parse(text) {
|
|
305
|
+
if (text === "") {
|
|
306
|
+
return makeNode({ indent: -1 });
|
|
307
|
+
}
|
|
308
|
+
return buildTree(tokenise(text));
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// src/scripts/_cli/cmd_settings_check.ts
|
|
312
|
+
var DEFAULT_PATH = ".agent-settings.yml";
|
|
313
|
+
var ArgparseExit = class extends Error {
|
|
314
|
+
code;
|
|
315
|
+
constructor(code) {
|
|
316
|
+
super(`ArgparseExit(${code})`);
|
|
317
|
+
this.name = "ArgparseExit";
|
|
318
|
+
this.code = code;
|
|
319
|
+
}
|
|
320
|
+
};
|
|
321
|
+
function _stdoutSink() {
|
|
322
|
+
return { write: (t) => process.stdout.write(t) };
|
|
323
|
+
}
|
|
324
|
+
function _stderrSink() {
|
|
325
|
+
return { write: (t) => process.stderr.write(t) };
|
|
326
|
+
}
|
|
327
|
+
function _print(out, line = "") {
|
|
328
|
+
out.write(line + "\n");
|
|
329
|
+
}
|
|
330
|
+
function _ljust(s, width) {
|
|
331
|
+
const len = [...s].length;
|
|
332
|
+
if (len >= width) return s;
|
|
333
|
+
return s + " ".repeat(width - len);
|
|
334
|
+
}
|
|
335
|
+
function _isPyWs(code) {
|
|
336
|
+
return code === 9 || // \t
|
|
337
|
+
code === 10 || // \n
|
|
338
|
+
code === 11 || // \v
|
|
339
|
+
code === 12 || // \f
|
|
340
|
+
code === 13 || // \r
|
|
341
|
+
code === 28 || code === 29 || code === 30 || code === 31 || code === 32 || // space
|
|
342
|
+
code === 133 || code === 160 || code === 5760 || code >= 8192 && code <= 8202 || code === 8232 || code === 8233 || code === 8239 || code === 8287 || code === 12288;
|
|
343
|
+
}
|
|
344
|
+
function _pyStrip(s) {
|
|
345
|
+
let start = 0;
|
|
346
|
+
let end = s.length;
|
|
347
|
+
while (start < end && _isPyWs(s.charCodeAt(start))) start += 1;
|
|
348
|
+
while (end > start && _isPyWs(s.charCodeAt(end - 1))) end -= 1;
|
|
349
|
+
return s.slice(start, end);
|
|
350
|
+
}
|
|
351
|
+
function _leadWsLen(s) {
|
|
352
|
+
let i = 0;
|
|
353
|
+
while (i < s.length && (s[i] === " " || s[i] === " ")) i += 1;
|
|
354
|
+
return i;
|
|
355
|
+
}
|
|
356
|
+
function _splitlines(text) {
|
|
357
|
+
if (text === "") return [];
|
|
358
|
+
const out = [];
|
|
359
|
+
let cur = "";
|
|
360
|
+
for (let i = 0; i < text.length; i++) {
|
|
361
|
+
const ch = text[i];
|
|
362
|
+
const code = text.charCodeAt(i);
|
|
363
|
+
if (ch === "\r") {
|
|
364
|
+
if (text[i + 1] === "\n") i += 1;
|
|
365
|
+
out.push(cur);
|
|
366
|
+
cur = "";
|
|
367
|
+
} else if (ch === "\n" || code === 11 || code === 12 || code === 28 || code === 29 || code === 30 || code === 133 || code === 8232 || code === 8233) {
|
|
368
|
+
out.push(cur);
|
|
369
|
+
cur = "";
|
|
370
|
+
} else {
|
|
371
|
+
cur += ch;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
if (cur !== "") out.push(cur);
|
|
375
|
+
return out;
|
|
376
|
+
}
|
|
377
|
+
var _PRESCAN_RULES = [
|
|
378
|
+
[
|
|
379
|
+
"multi-doc separator",
|
|
380
|
+
/^(---|\.\.\.)\s*(#.*)?$/,
|
|
381
|
+
"remove the separator \u2014 one YAML document per file only."
|
|
382
|
+
],
|
|
383
|
+
["complex key", /^\?\s/, "rewrite as a plain ``key: value`` mapping line."],
|
|
384
|
+
[
|
|
385
|
+
"block-scalar indicator",
|
|
386
|
+
/:\s*[|>][+-]?\s*(#.*)?$/,
|
|
387
|
+
"inline the value as a single-line quoted scalar."
|
|
388
|
+
],
|
|
389
|
+
["tagged scalar", /:\s*!!?[A-Za-z_]/, "remove the ``!tag``; the parser does not honour it."],
|
|
390
|
+
[
|
|
391
|
+
"anchor / alias",
|
|
392
|
+
/:\s*[&*][A-Za-z_]/,
|
|
393
|
+
"expand the anchor inline \u2014 anchors / aliases are not supported."
|
|
394
|
+
],
|
|
395
|
+
[
|
|
396
|
+
"nested flow-mapping",
|
|
397
|
+
/:\s*\{[^}]*:[^}]*\}/,
|
|
398
|
+
"rewrite as a block-style nested mapping (indented child keys)."
|
|
399
|
+
]
|
|
400
|
+
];
|
|
401
|
+
function _scan_line(stripped) {
|
|
402
|
+
if (!stripped || stripped.startsWith("#")) {
|
|
403
|
+
return null;
|
|
404
|
+
}
|
|
405
|
+
for (const [label, pattern, hint] of _PRESCAN_RULES) {
|
|
406
|
+
if (pattern.test(stripped)) {
|
|
407
|
+
return [label, hint];
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
return null;
|
|
411
|
+
}
|
|
412
|
+
function _scan_text(text) {
|
|
413
|
+
const findings = [];
|
|
414
|
+
const lines = _splitlines(text);
|
|
415
|
+
for (let idx = 0; idx < lines.length; idx++) {
|
|
416
|
+
const raw = lines[idx];
|
|
417
|
+
const lineno = idx + 1;
|
|
418
|
+
const stripped = _pyStrip(raw);
|
|
419
|
+
const lead = raw.slice(0, _leadWsLen(raw));
|
|
420
|
+
if (lead.includes(" ")) {
|
|
421
|
+
findings.push({
|
|
422
|
+
line: lineno,
|
|
423
|
+
kind: "tab in indent",
|
|
424
|
+
verdict: "not supported",
|
|
425
|
+
hint: "replace leading tabs with 2 or 4 spaces."
|
|
426
|
+
});
|
|
427
|
+
continue;
|
|
428
|
+
}
|
|
429
|
+
const hit = _scan_line(stripped);
|
|
430
|
+
if (hit !== null) {
|
|
431
|
+
const [label, hint] = hit;
|
|
432
|
+
findings.push({
|
|
433
|
+
line: lineno,
|
|
434
|
+
kind: label,
|
|
435
|
+
verdict: "not supported",
|
|
436
|
+
hint
|
|
437
|
+
});
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
return findings;
|
|
441
|
+
}
|
|
442
|
+
function _format(finding) {
|
|
443
|
+
return ` \u274C line:${_ljust(String(finding.line), 4)} ${_ljust(finding.kind, 22)} ${_ljust(finding.verdict, 14)} ${finding.hint}`;
|
|
444
|
+
}
|
|
445
|
+
function _parse(argv, out, err) {
|
|
446
|
+
const prog = "agent-config settings:check";
|
|
447
|
+
const usage = `usage: ${prog} [-h] [--path PATH] [--allow-missing]
|
|
448
|
+
${" ".repeat(35)}[--quiet]
|
|
449
|
+
`;
|
|
450
|
+
const emitError = (msg) => {
|
|
451
|
+
err.write(usage);
|
|
452
|
+
err.write(`${prog}: error: ${msg}
|
|
453
|
+
`);
|
|
454
|
+
throw new ArgparseExit(2);
|
|
455
|
+
};
|
|
456
|
+
const opts = { path: DEFAULT_PATH, allow_missing: false, quiet: false };
|
|
457
|
+
let i = 0;
|
|
458
|
+
while (i < argv.length) {
|
|
459
|
+
const tok = argv[i];
|
|
460
|
+
if (tok === "-h" || tok === "--help") {
|
|
461
|
+
out.write(usage);
|
|
462
|
+
throw new ArgparseExit(0);
|
|
463
|
+
} else if (tok === "--path") {
|
|
464
|
+
const val = argv[i + 1];
|
|
465
|
+
if (val === void 0) {
|
|
466
|
+
emitError("argument --path: expected one argument");
|
|
467
|
+
}
|
|
468
|
+
opts.path = val;
|
|
469
|
+
i += 2;
|
|
470
|
+
} else if (tok.startsWith("--path=")) {
|
|
471
|
+
opts.path = tok.slice("--path=".length);
|
|
472
|
+
i += 1;
|
|
473
|
+
} else if (tok === "--allow-missing") {
|
|
474
|
+
opts.allow_missing = true;
|
|
475
|
+
i += 1;
|
|
476
|
+
} else if (tok === "--quiet") {
|
|
477
|
+
opts.quiet = true;
|
|
478
|
+
i += 1;
|
|
479
|
+
} else {
|
|
480
|
+
emitError(`unrecognized arguments: ${tok}`);
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
return opts;
|
|
484
|
+
}
|
|
485
|
+
function main(argv = null, options = {}) {
|
|
486
|
+
const out = options.out ?? _stdoutSink();
|
|
487
|
+
const err = options.err ?? _stderrSink();
|
|
488
|
+
const opts = _parse(argv ?? process.argv.slice(2), out, err);
|
|
489
|
+
const target = opts.path;
|
|
490
|
+
let isFile;
|
|
491
|
+
try {
|
|
492
|
+
isFile = fs.statSync(target).isFile();
|
|
493
|
+
} catch {
|
|
494
|
+
isFile = false;
|
|
495
|
+
}
|
|
496
|
+
if (!isFile) {
|
|
497
|
+
if (opts.allow_missing) {
|
|
498
|
+
if (!opts.quiet) {
|
|
499
|
+
_print(out, `\u2705 ${target}: file absent (allow-missing).`);
|
|
500
|
+
}
|
|
501
|
+
return 0;
|
|
502
|
+
}
|
|
503
|
+
_print(err, `\u274C ${target}: file not found.`);
|
|
504
|
+
_print(err, " Run `./agent-config sync-agent-settings` to create it.");
|
|
505
|
+
return 2;
|
|
506
|
+
}
|
|
507
|
+
let text;
|
|
508
|
+
try {
|
|
509
|
+
text = fs.readFileSync(target, { encoding: "utf-8" });
|
|
510
|
+
} catch (exc) {
|
|
511
|
+
_print(err, `\u274C ${target}: cannot read: ${exc.message}`);
|
|
512
|
+
return 2;
|
|
513
|
+
}
|
|
514
|
+
const findings = _scan_text(text);
|
|
515
|
+
if (findings.length === 0) {
|
|
516
|
+
try {
|
|
517
|
+
parse(text);
|
|
518
|
+
} catch (exc) {
|
|
519
|
+
findings.push({
|
|
520
|
+
line: 0,
|
|
521
|
+
kind: "parser",
|
|
522
|
+
verdict: "not supported",
|
|
523
|
+
hint: String(exc.message)
|
|
524
|
+
});
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
if (findings.length === 0) {
|
|
528
|
+
if (!opts.quiet) {
|
|
529
|
+
_print(
|
|
530
|
+
out,
|
|
531
|
+
`\u2705 ${target}: inside the supported subset (docs/contracts/settings-sync-yaml-subset.md).`
|
|
532
|
+
);
|
|
533
|
+
}
|
|
534
|
+
return 0;
|
|
535
|
+
}
|
|
536
|
+
_print(err, `\u274C ${target}: ${findings.length} finding(s) outside the supported subset.`);
|
|
537
|
+
for (const finding of findings) {
|
|
538
|
+
_print(err, _format(finding));
|
|
539
|
+
}
|
|
540
|
+
_print(err, "");
|
|
541
|
+
_print(err, " Contract: docs/contracts/settings-sync-yaml-subset.md");
|
|
542
|
+
return 1;
|
|
543
|
+
}
|
|
544
|
+
var _HERE = fileURLToPath(import.meta.url);
|
|
545
|
+
function _isCliEntry() {
|
|
546
|
+
if (process.argv[1] === void 0) {
|
|
547
|
+
return false;
|
|
548
|
+
}
|
|
549
|
+
const argvUrl = pathToFileURL(path.resolve(process.argv[1])).href;
|
|
550
|
+
if (import.meta.url === argvUrl) {
|
|
551
|
+
return true;
|
|
552
|
+
}
|
|
553
|
+
try {
|
|
554
|
+
const here = fs.realpathSync(fileURLToPath(import.meta.url));
|
|
555
|
+
const argv = fs.realpathSync(path.resolve(process.argv[1]));
|
|
556
|
+
return here === argv;
|
|
557
|
+
} catch {
|
|
558
|
+
return false;
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
if (_isCliEntry() || process.argv[1] === _HERE) {
|
|
562
|
+
try {
|
|
563
|
+
process.exitCode = main(process.argv.slice(2));
|
|
564
|
+
} catch (exc) {
|
|
565
|
+
if (exc instanceof ArgparseExit) {
|
|
566
|
+
process.exitCode = exc.code;
|
|
567
|
+
} else {
|
|
568
|
+
throw exc;
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
export {
|
|
573
|
+
main
|
|
574
|
+
};
|