@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,502 @@
|
|
|
1
|
+
import { createRequire as __acCreateRequire } from 'node:module'; const require = globalThis.require ?? __acCreateRequire(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
resolve_with_fallback,
|
|
4
|
+
write_target
|
|
5
|
+
} from "./chunk-NDJLNC6Q.js";
|
|
6
|
+
|
|
7
|
+
// src/scripts/_lib/agent_settings.ts
|
|
8
|
+
import { createRequire } from "node:module";
|
|
9
|
+
import * as fs from "node:fs";
|
|
10
|
+
import * as os from "node:os";
|
|
11
|
+
import * as path from "node:path";
|
|
12
|
+
var _require = createRequire(import.meta.url);
|
|
13
|
+
var Logger = class {
|
|
14
|
+
name = "scripts._lib.agent_settings";
|
|
15
|
+
records = [];
|
|
16
|
+
info(message, ...args) {
|
|
17
|
+
this.records.push({ level: "INFO", message: _format(message, args) });
|
|
18
|
+
}
|
|
19
|
+
warning(message, ...args) {
|
|
20
|
+
this.records.push({ level: "WARNING", message: _format(message, args) });
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
function _format(template, args) {
|
|
24
|
+
let i = 0;
|
|
25
|
+
return template.replace(/%s/g, () => {
|
|
26
|
+
if (i < args.length) {
|
|
27
|
+
const value = args[i];
|
|
28
|
+
i += 1;
|
|
29
|
+
return _pystr(value);
|
|
30
|
+
}
|
|
31
|
+
return "%s";
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
function _pystr(value) {
|
|
35
|
+
if (Array.isArray(value)) {
|
|
36
|
+
return `[${value.map((v) => _pyrepr(v)).join(", ")}]`;
|
|
37
|
+
}
|
|
38
|
+
return String(value);
|
|
39
|
+
}
|
|
40
|
+
function _pyrepr(value) {
|
|
41
|
+
if (typeof value === "string") {
|
|
42
|
+
return `'${value}'`;
|
|
43
|
+
}
|
|
44
|
+
return String(value);
|
|
45
|
+
}
|
|
46
|
+
var logger = new Logger();
|
|
47
|
+
var DEFAULT_PROJECT_FILE = ".agent-settings.yml";
|
|
48
|
+
var LOCAL_PROJECT_FILE = ".agent-settings.local.yml";
|
|
49
|
+
var LOCAL_PROJECT_SUBDIR = ["agents", "settings"];
|
|
50
|
+
function _local_settings_path(project_root) {
|
|
51
|
+
return path.join(project_root, ...LOCAL_PROJECT_SUBDIR, LOCAL_PROJECT_FILE);
|
|
52
|
+
}
|
|
53
|
+
function _canonical_settings_path(project_root) {
|
|
54
|
+
return path.join(project_root, ...LOCAL_PROJECT_SUBDIR, DEFAULT_PROJECT_FILE);
|
|
55
|
+
}
|
|
56
|
+
function project_settings_path(project_root) {
|
|
57
|
+
const canonical = _canonical_settings_path(project_root);
|
|
58
|
+
if (_exists(canonical)) {
|
|
59
|
+
return canonical;
|
|
60
|
+
}
|
|
61
|
+
const legacy = path.join(project_root, DEFAULT_PROJECT_FILE);
|
|
62
|
+
if (_exists(legacy)) {
|
|
63
|
+
return legacy;
|
|
64
|
+
}
|
|
65
|
+
return canonical;
|
|
66
|
+
}
|
|
67
|
+
var USER_GLOBAL_FILENAME = "agent-settings.yml";
|
|
68
|
+
function DEFAULT_USER_GLOBAL_FILE() {
|
|
69
|
+
return write_target(USER_GLOBAL_FILENAME);
|
|
70
|
+
}
|
|
71
|
+
function _resolve_user_global_file() {
|
|
72
|
+
const found = resolve_with_fallback(USER_GLOBAL_FILENAME);
|
|
73
|
+
if (found !== null) {
|
|
74
|
+
return found;
|
|
75
|
+
}
|
|
76
|
+
return DEFAULT_USER_GLOBAL_FILE();
|
|
77
|
+
}
|
|
78
|
+
var MERGEABLE_KEYS = [
|
|
79
|
+
"name",
|
|
80
|
+
"ide",
|
|
81
|
+
"rule_loading_tier",
|
|
82
|
+
"memory.cadence",
|
|
83
|
+
"personal.bot_icon",
|
|
84
|
+
"personal.autonomy",
|
|
85
|
+
"telegraph.speak_scope",
|
|
86
|
+
// Knowledge-card global cross-project sharing is a USER-GLOBAL setting
|
|
87
|
+
// (ADR-100 / road-to-structure-grounding-v2). Whitelisted so the
|
|
88
|
+
// ~/.event4u/agent-config/agent-settings.yml values are honoured.
|
|
89
|
+
"knowledge.global_sharing.enabled",
|
|
90
|
+
"knowledge.global_sharing.allowed_tiers",
|
|
91
|
+
"knowledge.global_sharing.redaction.enabled",
|
|
92
|
+
"knowledge.global_sharing.redaction.halt_on_trigger",
|
|
93
|
+
"knowledge.global_sharing.auto_promote_threshold",
|
|
94
|
+
"knowledge.global_sharing.freshness.hypothesis_after_days",
|
|
95
|
+
"knowledge.global_sharing.freshness.stale_after_days"
|
|
96
|
+
];
|
|
97
|
+
var _DEFAULTS = {};
|
|
98
|
+
var ANCHOR_AGENT_SETTINGS = "agent-settings";
|
|
99
|
+
var ANCHOR_AGENTS_DIR = "agents-dir";
|
|
100
|
+
var ANCHOR_GIT = "git";
|
|
101
|
+
var _AGENTS_DIR_MARKERS = [
|
|
102
|
+
"roadmaps",
|
|
103
|
+
"settings/.ai-council.yml",
|
|
104
|
+
"roadmaps-progress.md",
|
|
105
|
+
// `overrides/` is the guaranteed minimal-consumer surface (ADR-020).
|
|
106
|
+
// Replaced the retired `.event4u-bridge.yml` marker (ADR-020 amendment
|
|
107
|
+
// 2026-07-13) so a bare consumer `agents/` dir stays anchorable.
|
|
108
|
+
"overrides"
|
|
109
|
+
];
|
|
110
|
+
var _LEGACY_ANCHOR_ENV = "AGENT_CONFIG_LEGACY_ANCHOR";
|
|
111
|
+
function _exists(p) {
|
|
112
|
+
try {
|
|
113
|
+
fs.lstatSync(p);
|
|
114
|
+
fs.statSync(p);
|
|
115
|
+
return true;
|
|
116
|
+
} catch {
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
function _is_dir(p) {
|
|
121
|
+
try {
|
|
122
|
+
return fs.statSync(p).isDirectory();
|
|
123
|
+
} catch {
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
function _is_file(p) {
|
|
128
|
+
try {
|
|
129
|
+
return fs.statSync(p).isFile();
|
|
130
|
+
} catch {
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
function _resolve(p) {
|
|
135
|
+
const absolute = path.resolve(p);
|
|
136
|
+
try {
|
|
137
|
+
return fs.realpathSync(absolute);
|
|
138
|
+
} catch {
|
|
139
|
+
return absolute;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
function _ancestor_chain(start) {
|
|
143
|
+
const chain = [];
|
|
144
|
+
let cursor = start;
|
|
145
|
+
for (; ; ) {
|
|
146
|
+
chain.push(cursor);
|
|
147
|
+
const parent = path.dirname(cursor);
|
|
148
|
+
if (parent === cursor) {
|
|
149
|
+
break;
|
|
150
|
+
}
|
|
151
|
+
cursor = parent;
|
|
152
|
+
}
|
|
153
|
+
return chain;
|
|
154
|
+
}
|
|
155
|
+
function _boundary_anchor_at(dir) {
|
|
156
|
+
const agents_dir = path.join(dir, "agents");
|
|
157
|
+
if (_is_dir(agents_dir)) {
|
|
158
|
+
for (const marker of _AGENTS_DIR_MARKERS) {
|
|
159
|
+
if (_exists(path.join(agents_dir, marker))) {
|
|
160
|
+
return ANCHOR_AGENTS_DIR;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
if (_exists(path.join(dir, ".git"))) {
|
|
165
|
+
return ANCHOR_GIT;
|
|
166
|
+
}
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
function find_project_root_with_anchor(start) {
|
|
170
|
+
const current = _exists(start) ? _resolve(start) : start;
|
|
171
|
+
const legacy = process.env[_LEGACY_ANCHOR_ENV] === "1";
|
|
172
|
+
const chain = _ancestor_chain(current);
|
|
173
|
+
if (legacy) {
|
|
174
|
+
for (const candidate of chain) {
|
|
175
|
+
if (_exists(path.join(candidate, ".git"))) {
|
|
176
|
+
return [candidate, ANCHOR_GIT];
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
for (const candidate of chain) {
|
|
182
|
+
const anchor = _boundary_anchor_at(candidate);
|
|
183
|
+
if (anchor !== null) {
|
|
184
|
+
return [candidate, anchor];
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
let outermost = null;
|
|
188
|
+
for (const candidate of chain) {
|
|
189
|
+
if (_exists(path.join(candidate, DEFAULT_PROJECT_FILE))) {
|
|
190
|
+
outermost = candidate;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
if (outermost !== null) {
|
|
194
|
+
return [outermost, ANCHOR_AGENT_SETTINGS];
|
|
195
|
+
}
|
|
196
|
+
return null;
|
|
197
|
+
}
|
|
198
|
+
function find_project_root(start) {
|
|
199
|
+
const result = find_project_root_with_anchor(start);
|
|
200
|
+
return result !== null ? result[0] : null;
|
|
201
|
+
}
|
|
202
|
+
function find_project_root_with_trace(start) {
|
|
203
|
+
const trace = [];
|
|
204
|
+
const current = _exists(start) ? _resolve(start) : start;
|
|
205
|
+
const legacy = process.env[_LEGACY_ANCHOR_ENV] === "1";
|
|
206
|
+
const chain = _ancestor_chain(current);
|
|
207
|
+
if (legacy) {
|
|
208
|
+
for (const candidate of chain) {
|
|
209
|
+
const hit = _exists(path.join(candidate, ".git"));
|
|
210
|
+
trace.push({
|
|
211
|
+
ancestor: candidate,
|
|
212
|
+
pass: "boundary",
|
|
213
|
+
hit: hit ? ANCHOR_GIT : null,
|
|
214
|
+
reason: hit ? "legacy: .git found" : "legacy: no .git"
|
|
215
|
+
});
|
|
216
|
+
if (hit) {
|
|
217
|
+
return [candidate, ANCHOR_GIT, trace];
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
return [null, null, trace];
|
|
221
|
+
}
|
|
222
|
+
for (const candidate of chain) {
|
|
223
|
+
const agents_dir = path.join(candidate, "agents");
|
|
224
|
+
if (_is_dir(agents_dir)) {
|
|
225
|
+
for (const marker of _AGENTS_DIR_MARKERS) {
|
|
226
|
+
if (_exists(path.join(agents_dir, marker))) {
|
|
227
|
+
trace.push({
|
|
228
|
+
ancestor: candidate,
|
|
229
|
+
pass: "boundary",
|
|
230
|
+
hit: ANCHOR_AGENTS_DIR,
|
|
231
|
+
reason: `agents/ has ${marker}`
|
|
232
|
+
});
|
|
233
|
+
return [candidate, ANCHOR_AGENTS_DIR, trace];
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
if (_exists(path.join(candidate, ".git"))) {
|
|
238
|
+
trace.push({
|
|
239
|
+
ancestor: candidate,
|
|
240
|
+
pass: "boundary",
|
|
241
|
+
hit: ANCHOR_GIT,
|
|
242
|
+
reason: ".git present"
|
|
243
|
+
});
|
|
244
|
+
return [candidate, ANCHOR_GIT, trace];
|
|
245
|
+
}
|
|
246
|
+
trace.push({
|
|
247
|
+
ancestor: candidate,
|
|
248
|
+
pass: "boundary",
|
|
249
|
+
hit: null,
|
|
250
|
+
reason: "no agents/ marker, no .git"
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
let outermost = null;
|
|
254
|
+
for (const candidate of chain) {
|
|
255
|
+
const present = _exists(path.join(candidate, DEFAULT_PROJECT_FILE));
|
|
256
|
+
trace.push({
|
|
257
|
+
ancestor: candidate,
|
|
258
|
+
pass: "layer",
|
|
259
|
+
hit: present ? ANCHOR_AGENT_SETTINGS : null,
|
|
260
|
+
reason: present ? `${DEFAULT_PROJECT_FILE} present` : `no ${DEFAULT_PROJECT_FILE}`
|
|
261
|
+
});
|
|
262
|
+
if (present) {
|
|
263
|
+
outermost = candidate;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
if (outermost !== null) {
|
|
267
|
+
return [outermost, ANCHOR_AGENT_SETTINGS, trace];
|
|
268
|
+
}
|
|
269
|
+
return [null, null, trace];
|
|
270
|
+
}
|
|
271
|
+
var ORIGIN_ROOT_FLAG = "root-flag";
|
|
272
|
+
var ORIGIN_EXPLICIT = "explicit";
|
|
273
|
+
var ORIGIN_ENV = "env";
|
|
274
|
+
var ORIGIN_CWD_FALLBACK = "cwd-fallback";
|
|
275
|
+
var PROJECT_ROOT_ENV = "AGENT_CONFIG_PROJECT_ROOT";
|
|
276
|
+
var ROOT_OVERRIDE_ENV = "AGENT_CONFIG_ROOT_OVERRIDE";
|
|
277
|
+
var ProjectRootError = class extends Error {
|
|
278
|
+
constructor(message) {
|
|
279
|
+
super(message);
|
|
280
|
+
this.name = "ProjectRootError";
|
|
281
|
+
}
|
|
282
|
+
};
|
|
283
|
+
function _validate_root_path(p, origin_label) {
|
|
284
|
+
const resolved = _expanduser(p);
|
|
285
|
+
if (!_exists(resolved)) {
|
|
286
|
+
throw new ProjectRootError(
|
|
287
|
+
`${origin_label} points to a path that does not exist: ${resolved}`
|
|
288
|
+
);
|
|
289
|
+
}
|
|
290
|
+
if (!_is_dir(resolved)) {
|
|
291
|
+
throw new ProjectRootError(
|
|
292
|
+
`${origin_label} points to a non-directory: ${resolved}`
|
|
293
|
+
);
|
|
294
|
+
}
|
|
295
|
+
return _resolve(resolved);
|
|
296
|
+
}
|
|
297
|
+
function _expanduser(p) {
|
|
298
|
+
if (p === "~") {
|
|
299
|
+
return os.homedir();
|
|
300
|
+
}
|
|
301
|
+
if (p.startsWith("~/") || process.platform === "win32" && p.startsWith("~\\")) {
|
|
302
|
+
return path.join(os.homedir(), p.slice(2));
|
|
303
|
+
}
|
|
304
|
+
return p;
|
|
305
|
+
}
|
|
306
|
+
function resolve_project_root(arg, options = {}) {
|
|
307
|
+
const cwd = options.cwd ?? null;
|
|
308
|
+
if (process.env[ROOT_OVERRIDE_ENV] === "1") {
|
|
309
|
+
const env_value2 = process.env[PROJECT_ROOT_ENV];
|
|
310
|
+
if (env_value2) {
|
|
311
|
+
return [_validate_root_path(env_value2, "--root"), ORIGIN_ROOT_FLAG];
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
if (arg !== null && String(arg) !== "") {
|
|
315
|
+
return [_validate_root_path(arg, "--project"), ORIGIN_EXPLICIT];
|
|
316
|
+
}
|
|
317
|
+
const env_value = process.env[PROJECT_ROOT_ENV];
|
|
318
|
+
if (env_value) {
|
|
319
|
+
return [_validate_root_path(env_value, PROJECT_ROOT_ENV), ORIGIN_ENV];
|
|
320
|
+
}
|
|
321
|
+
const start = _resolve(cwd ?? process.cwd());
|
|
322
|
+
const walked = find_project_root_with_anchor(start);
|
|
323
|
+
if (walked !== null) {
|
|
324
|
+
return walked;
|
|
325
|
+
}
|
|
326
|
+
return [start, ORIGIN_CWD_FALLBACK];
|
|
327
|
+
}
|
|
328
|
+
function _resolve_cascade_paths(cwd, project_path) {
|
|
329
|
+
if (cwd === null) {
|
|
330
|
+
const legacy = project_path ? project_path : DEFAULT_PROJECT_FILE;
|
|
331
|
+
const parent = path.dirname(legacy);
|
|
332
|
+
return [legacy, _canonical_settings_path(parent), _local_settings_path(parent)];
|
|
333
|
+
}
|
|
334
|
+
const root = find_project_root(cwd);
|
|
335
|
+
if (root === null) {
|
|
336
|
+
const legacy = project_path ? project_path : DEFAULT_PROJECT_FILE;
|
|
337
|
+
const parent = path.dirname(legacy);
|
|
338
|
+
return [legacy, _canonical_settings_path(parent), _local_settings_path(parent)];
|
|
339
|
+
}
|
|
340
|
+
const cwd_resolved = _resolve(cwd);
|
|
341
|
+
const chain = [];
|
|
342
|
+
let cursor = cwd_resolved;
|
|
343
|
+
for (; ; ) {
|
|
344
|
+
chain.push(cursor);
|
|
345
|
+
if (cursor === root) {
|
|
346
|
+
break;
|
|
347
|
+
}
|
|
348
|
+
const parent = path.dirname(cursor);
|
|
349
|
+
if (parent === cursor) {
|
|
350
|
+
break;
|
|
351
|
+
}
|
|
352
|
+
cursor = parent;
|
|
353
|
+
}
|
|
354
|
+
chain.reverse();
|
|
355
|
+
return [
|
|
356
|
+
...chain.map((d) => path.join(d, DEFAULT_PROJECT_FILE)),
|
|
357
|
+
_canonical_settings_path(root),
|
|
358
|
+
_local_settings_path(root)
|
|
359
|
+
];
|
|
360
|
+
}
|
|
361
|
+
function load_agent_settings(options = {}) {
|
|
362
|
+
const project_path = options.project_path ?? null;
|
|
363
|
+
const user_global_path = options.user_global_path ?? null;
|
|
364
|
+
const verbose = options.verbose ?? false;
|
|
365
|
+
const cwd = options.cwd ?? null;
|
|
366
|
+
const user_global_raw = _read_yaml(user_global_path ? user_global_path : _resolve_user_global_file()) ?? {};
|
|
367
|
+
const [user_global_filtered, ignored] = _filter_whitelist(user_global_raw, MERGEABLE_KEYS);
|
|
368
|
+
if (verbose && ignored.length > 0) {
|
|
369
|
+
logger.info(
|
|
370
|
+
"agent_settings: ignored non-whitelisted user-global keys: %s",
|
|
371
|
+
[...ignored].sort()
|
|
372
|
+
);
|
|
373
|
+
}
|
|
374
|
+
const cascade = _resolve_cascade_paths(cwd, project_path);
|
|
375
|
+
const merged = _deep_copy_defaults(_DEFAULTS);
|
|
376
|
+
_deep_merge(merged, user_global_filtered);
|
|
377
|
+
for (const p of cascade) {
|
|
378
|
+
const layer = _read_yaml(p) ?? {};
|
|
379
|
+
if (Object.keys(layer).length > 0) {
|
|
380
|
+
_deep_merge(merged, layer);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
return merged;
|
|
384
|
+
}
|
|
385
|
+
function _read_yaml(p) {
|
|
386
|
+
if (!_is_file(p)) {
|
|
387
|
+
return null;
|
|
388
|
+
}
|
|
389
|
+
let YAML;
|
|
390
|
+
try {
|
|
391
|
+
YAML = _require("yaml");
|
|
392
|
+
} catch {
|
|
393
|
+
return null;
|
|
394
|
+
}
|
|
395
|
+
let data;
|
|
396
|
+
try {
|
|
397
|
+
const text = fs.readFileSync(p, "utf-8");
|
|
398
|
+
data = YAML.parse(text, { version: "1.1" });
|
|
399
|
+
if (data === null || data === void 0) {
|
|
400
|
+
data = {};
|
|
401
|
+
}
|
|
402
|
+
} catch (err) {
|
|
403
|
+
if (_is_yaml_error(err) || _is_os_error(err)) {
|
|
404
|
+
logger.warning("agent_settings: unreadable or malformed YAML at %s", p);
|
|
405
|
+
return null;
|
|
406
|
+
}
|
|
407
|
+
throw err;
|
|
408
|
+
}
|
|
409
|
+
return _is_plain_dict(data) ? data : null;
|
|
410
|
+
}
|
|
411
|
+
function _is_yaml_error(err) {
|
|
412
|
+
if (err instanceof Error) {
|
|
413
|
+
return err.name.startsWith("YAML") || err.name === "Error" || err.name === "TypeError";
|
|
414
|
+
}
|
|
415
|
+
return false;
|
|
416
|
+
}
|
|
417
|
+
function _is_os_error(err) {
|
|
418
|
+
return typeof err === "object" && err !== null && "code" in err && typeof err.code === "string";
|
|
419
|
+
}
|
|
420
|
+
function _filter_whitelist(raw, allowed) {
|
|
421
|
+
const filtered = {};
|
|
422
|
+
for (const dotted of allowed) {
|
|
423
|
+
const value = _get_dotted(raw, dotted);
|
|
424
|
+
if (value !== null && value !== void 0) {
|
|
425
|
+
_set_dotted(filtered, dotted, value);
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
const ignored = _leaf_paths(raw).filter((p) => !allowed.includes(p));
|
|
429
|
+
return [filtered, ignored];
|
|
430
|
+
}
|
|
431
|
+
function _get_dotted(data, dotted) {
|
|
432
|
+
let cursor = data;
|
|
433
|
+
for (const part of dotted.split(".")) {
|
|
434
|
+
if (!_is_plain_dict(cursor) || !(part in cursor)) {
|
|
435
|
+
return null;
|
|
436
|
+
}
|
|
437
|
+
cursor = cursor[part];
|
|
438
|
+
}
|
|
439
|
+
return cursor;
|
|
440
|
+
}
|
|
441
|
+
function _set_dotted(target, dotted, value) {
|
|
442
|
+
const parts = dotted.split(".");
|
|
443
|
+
let cursor = target;
|
|
444
|
+
for (const part of parts.slice(0, -1)) {
|
|
445
|
+
let nxt = cursor[part];
|
|
446
|
+
if (nxt === void 0) {
|
|
447
|
+
nxt = {};
|
|
448
|
+
cursor[part] = nxt;
|
|
449
|
+
}
|
|
450
|
+
if (!_is_plain_dict(nxt)) {
|
|
451
|
+
nxt = {};
|
|
452
|
+
cursor[part] = nxt;
|
|
453
|
+
}
|
|
454
|
+
cursor = nxt;
|
|
455
|
+
}
|
|
456
|
+
cursor[parts[parts.length - 1]] = value;
|
|
457
|
+
}
|
|
458
|
+
function _leaf_paths(data, prefix = "") {
|
|
459
|
+
const paths = [];
|
|
460
|
+
for (const [key, value] of Object.entries(data)) {
|
|
461
|
+
const p = prefix ? `${prefix}.${key}` : key;
|
|
462
|
+
if (_is_plain_dict(value) && Object.keys(value).length > 0) {
|
|
463
|
+
paths.push(..._leaf_paths(value, p));
|
|
464
|
+
} else {
|
|
465
|
+
paths.push(p);
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
return paths;
|
|
469
|
+
}
|
|
470
|
+
function _deep_merge(dst, src) {
|
|
471
|
+
for (const [key, value] of Object.entries(src)) {
|
|
472
|
+
if (_is_plain_dict(value) && _is_plain_dict(dst[key])) {
|
|
473
|
+
_deep_merge(dst[key], value);
|
|
474
|
+
} else {
|
|
475
|
+
dst[key] = value;
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
function _deep_copy_defaults(src) {
|
|
480
|
+
const out = {};
|
|
481
|
+
_deep_merge(out, src);
|
|
482
|
+
return out;
|
|
483
|
+
}
|
|
484
|
+
function _is_plain_dict(value) {
|
|
485
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
export {
|
|
489
|
+
logger,
|
|
490
|
+
DEFAULT_PROJECT_FILE,
|
|
491
|
+
LOCAL_PROJECT_FILE,
|
|
492
|
+
LOCAL_PROJECT_SUBDIR,
|
|
493
|
+
project_settings_path,
|
|
494
|
+
find_project_root_with_anchor,
|
|
495
|
+
find_project_root,
|
|
496
|
+
find_project_root_with_trace,
|
|
497
|
+
PROJECT_ROOT_ENV,
|
|
498
|
+
ROOT_OVERRIDE_ENV,
|
|
499
|
+
ProjectRootError,
|
|
500
|
+
resolve_project_root,
|
|
501
|
+
load_agent_settings
|
|
502
|
+
};
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { createRequire as __acCreateRequire } from 'node:module'; const require = globalThis.require ?? __acCreateRequire(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
detectToolPresence
|
|
4
|
+
} from "./chunk-OMIVVCG2.js";
|
|
5
|
+
import {
|
|
6
|
+
buildInstallPlan,
|
|
7
|
+
sha256File
|
|
8
|
+
} from "./chunk-523HCFYO.js";
|
|
9
|
+
|
|
10
|
+
// src/install/preflight.ts
|
|
11
|
+
import { accessSync, constants, existsSync as existsSync2, statSync } from "node:fs";
|
|
12
|
+
import * as fs from "node:fs";
|
|
13
|
+
import { dirname } from "node:path";
|
|
14
|
+
|
|
15
|
+
// src/install/conflict.ts
|
|
16
|
+
import { existsSync } from "node:fs";
|
|
17
|
+
function isJsonTarget(entry) {
|
|
18
|
+
return entry.kind === "deployed" && entry.path.endsWith(".json");
|
|
19
|
+
}
|
|
20
|
+
function computeConflicts(plan) {
|
|
21
|
+
if (plan.policy.force) return [];
|
|
22
|
+
const out = [];
|
|
23
|
+
for (const entries of Object.values(plan.filesByTool)) {
|
|
24
|
+
for (const entry of entries) {
|
|
25
|
+
if (entry.kind === "bridge") continue;
|
|
26
|
+
if (entry.sha256 === null) continue;
|
|
27
|
+
if (!existsSync(entry.path)) continue;
|
|
28
|
+
if (plan.policy.knownPaths.has(entry.path)) continue;
|
|
29
|
+
const onDisk = sha256File(entry.path);
|
|
30
|
+
if (onDisk === entry.sha256) continue;
|
|
31
|
+
out.push({
|
|
32
|
+
path: entry.path,
|
|
33
|
+
kind: entry.kind,
|
|
34
|
+
plannedSha256: entry.sha256,
|
|
35
|
+
existingSha256: onDisk,
|
|
36
|
+
mergeable: isJsonTarget(entry)
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return out;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// src/install/preflight.ts
|
|
44
|
+
var DEFAULT_DISK_FLOOR_BYTES = 50 * 1024 * 1024;
|
|
45
|
+
function nearestExistingAncestor(p) {
|
|
46
|
+
let cur = p;
|
|
47
|
+
while (!existsSync2(cur)) {
|
|
48
|
+
const parent = dirname(cur);
|
|
49
|
+
if (parent === cur) return cur;
|
|
50
|
+
cur = parent;
|
|
51
|
+
}
|
|
52
|
+
return cur;
|
|
53
|
+
}
|
|
54
|
+
function checkPermissions(inputs) {
|
|
55
|
+
const out = [];
|
|
56
|
+
const roots = /* @__PURE__ */ new Set([inputs.root, ...inputs.sources.map((s) => s.destDir)]);
|
|
57
|
+
for (const root of roots) {
|
|
58
|
+
const probe = nearestExistingAncestor(root);
|
|
59
|
+
try {
|
|
60
|
+
accessSync(probe, constants.W_OK);
|
|
61
|
+
} catch {
|
|
62
|
+
out.push({
|
|
63
|
+
id: "permissions",
|
|
64
|
+
severity: "blocking",
|
|
65
|
+
path: root,
|
|
66
|
+
message: `target root is not writable (nearest existing ancestor: ${probe})`,
|
|
67
|
+
remedy: `fix permissions on ${probe} or choose a different target`
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
if (existsSync2(root)) {
|
|
71
|
+
try {
|
|
72
|
+
if (!statSync(root).isDirectory()) {
|
|
73
|
+
out.push({
|
|
74
|
+
id: "permissions",
|
|
75
|
+
severity: "blocking",
|
|
76
|
+
path: root,
|
|
77
|
+
message: "target root exists but is not a directory",
|
|
78
|
+
remedy: `move or remove the file at ${root}`
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
} catch {
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return out;
|
|
86
|
+
}
|
|
87
|
+
function checkDiskSpace(inputs, opts = {}) {
|
|
88
|
+
const floor = opts.diskFloorBytes ?? DEFAULT_DISK_FLOOR_BYTES;
|
|
89
|
+
const probe = nearestExistingAncestor(inputs.root);
|
|
90
|
+
const statfsSync2 = fs.statfsSync;
|
|
91
|
+
if (typeof statfsSync2 !== "function") {
|
|
92
|
+
return [
|
|
93
|
+
{
|
|
94
|
+
id: "disk-space",
|
|
95
|
+
severity: "info",
|
|
96
|
+
path: probe,
|
|
97
|
+
message: "free-disk check unavailable on this Node runtime",
|
|
98
|
+
remedy: ""
|
|
99
|
+
}
|
|
100
|
+
];
|
|
101
|
+
}
|
|
102
|
+
try {
|
|
103
|
+
const st = statfsSync2(probe);
|
|
104
|
+
const free = st.bavail * st.bsize;
|
|
105
|
+
if (free < floor) {
|
|
106
|
+
return [
|
|
107
|
+
{
|
|
108
|
+
id: "disk-space",
|
|
109
|
+
severity: "blocking",
|
|
110
|
+
path: probe,
|
|
111
|
+
message: `free disk ${free} B is below the ${floor} B floor`,
|
|
112
|
+
remedy: "free disk space on the target volume, then re-run"
|
|
113
|
+
}
|
|
114
|
+
];
|
|
115
|
+
}
|
|
116
|
+
} catch {
|
|
117
|
+
return [
|
|
118
|
+
{
|
|
119
|
+
id: "disk-space",
|
|
120
|
+
severity: "info",
|
|
121
|
+
path: probe,
|
|
122
|
+
message: "free-disk probe failed (statfs error) \u2014 check skipped",
|
|
123
|
+
remedy: ""
|
|
124
|
+
}
|
|
125
|
+
];
|
|
126
|
+
}
|
|
127
|
+
return [];
|
|
128
|
+
}
|
|
129
|
+
function checkConflicts(inputs) {
|
|
130
|
+
const plan = buildInstallPlan(inputs);
|
|
131
|
+
const conflicts = computeConflicts(plan);
|
|
132
|
+
return conflicts.map((c) => ({
|
|
133
|
+
id: "conflicts",
|
|
134
|
+
severity: "warning",
|
|
135
|
+
path: c.path,
|
|
136
|
+
message: `existing file conflicts with planned ${c.kind} content`,
|
|
137
|
+
remedy: "resolve interactively, or pass --force to overwrite"
|
|
138
|
+
}));
|
|
139
|
+
}
|
|
140
|
+
function checkHostDetection(inputs) {
|
|
141
|
+
const presence = detectToolPresence(inputs.root);
|
|
142
|
+
const detected = Object.entries(presence).filter(([, v]) => v === true).map(([k]) => k);
|
|
143
|
+
if (detected.length === 0) {
|
|
144
|
+
return [
|
|
145
|
+
{
|
|
146
|
+
id: "host-detection",
|
|
147
|
+
severity: "info",
|
|
148
|
+
path: inputs.root,
|
|
149
|
+
message: "no AI-tool directories detected at the target root",
|
|
150
|
+
remedy: "expected for a first global install; verify the target path is right"
|
|
151
|
+
}
|
|
152
|
+
];
|
|
153
|
+
}
|
|
154
|
+
return [
|
|
155
|
+
{
|
|
156
|
+
id: "host-detection",
|
|
157
|
+
severity: "info",
|
|
158
|
+
path: inputs.root,
|
|
159
|
+
message: `detected AI-tool surfaces: ${detected.join(", ")}`,
|
|
160
|
+
remedy: ""
|
|
161
|
+
}
|
|
162
|
+
];
|
|
163
|
+
}
|
|
164
|
+
function runPreflight(inputs, opts = {}) {
|
|
165
|
+
return [
|
|
166
|
+
...checkPermissions(inputs),
|
|
167
|
+
...checkDiskSpace(inputs, opts),
|
|
168
|
+
...checkConflicts(inputs),
|
|
169
|
+
...checkHostDetection(inputs)
|
|
170
|
+
];
|
|
171
|
+
}
|
|
172
|
+
function hasBlockingFinding(findings) {
|
|
173
|
+
return findings.some((f) => f.severity === "blocking");
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
export {
|
|
177
|
+
runPreflight,
|
|
178
|
+
hasBlockingFinding
|
|
179
|
+
};
|