ai-ops-cli 1.4.1 → 1.5.1
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/README.ko.md +9 -9
- package/README.md +9 -9
- package/data/context-layer/AGENTS.md +3 -2
- package/data/context-layer/docs/agent/rules/doc-update-rules.md +1 -0
- package/data/context-layer/docs/agent/workflow.md +8 -0
- package/dist/bin/index.js +254 -114
- package/dist/bin/index.js.map +1 -1
- package/package.json +1 -1
package/dist/bin/index.js
CHANGED
|
@@ -1246,6 +1246,25 @@ var replaceOrAppendBlock = (content, start, end, block) => {
|
|
|
1246
1246
|
const separator = content.trim().length > 0 && !content.endsWith("\n") ? "\n\n" : content.length > 0 ? "\n" : "";
|
|
1247
1247
|
return `${content}${separator}${cleanBlock}`;
|
|
1248
1248
|
};
|
|
1249
|
+
var insertBlockBeforeFirstTable = (content, block) => {
|
|
1250
|
+
const cleanBlock = block.endsWith("\n") ? block : `${block}
|
|
1251
|
+
`;
|
|
1252
|
+
if (content.trim().length === 0) {
|
|
1253
|
+
return cleanBlock;
|
|
1254
|
+
}
|
|
1255
|
+
const lines = content.split("\n");
|
|
1256
|
+
const firstTableIndex = lines.findIndex(
|
|
1257
|
+
(line) => !line.trimStart().startsWith("#") && /^\s*\[[^\]]+\]\s*(?:#.*)?$/.test(line)
|
|
1258
|
+
);
|
|
1259
|
+
if (firstTableIndex < 0) {
|
|
1260
|
+
const separator = content.endsWith("\n") ? "\n" : "\n\n";
|
|
1261
|
+
return `${content}${separator}${cleanBlock}`;
|
|
1262
|
+
}
|
|
1263
|
+
const before = lines.slice(0, firstTableIndex).join("\n").trimEnd();
|
|
1264
|
+
const after = lines.slice(firstTableIndex).join("\n").trimStart();
|
|
1265
|
+
return `${[before, cleanBlock.trimEnd(), after].filter((section) => section.length > 0).join("\n\n")}
|
|
1266
|
+
`;
|
|
1267
|
+
};
|
|
1249
1268
|
var quoteTomlString = (value) => JSON.stringify(value);
|
|
1250
1269
|
var readActiveStringAssignment = (content, key) => {
|
|
1251
1270
|
for (const line of content.split("\n")) {
|
|
@@ -1259,6 +1278,22 @@ var readActiveStringAssignment = (content, key) => {
|
|
|
1259
1278
|
}
|
|
1260
1279
|
return null;
|
|
1261
1280
|
};
|
|
1281
|
+
var readTopLevelStringAssignment = (content, key) => {
|
|
1282
|
+
for (const line of content.split("\n")) {
|
|
1283
|
+
const trimmed = line.trim();
|
|
1284
|
+
if (trimmed.length === 0 || trimmed.startsWith("#")) {
|
|
1285
|
+
continue;
|
|
1286
|
+
}
|
|
1287
|
+
if (/^\[[^\]]+\]\s*(?:#.*)?$/.test(trimmed)) {
|
|
1288
|
+
return null;
|
|
1289
|
+
}
|
|
1290
|
+
const match = new RegExp(`^\\s*${key}\\s*=\\s*["']([^"']+)["']`).exec(line);
|
|
1291
|
+
if (match) {
|
|
1292
|
+
return match[1];
|
|
1293
|
+
}
|
|
1294
|
+
}
|
|
1295
|
+
return null;
|
|
1296
|
+
};
|
|
1262
1297
|
var hasActiveTable = (content, tableName) => {
|
|
1263
1298
|
const tablePattern = new RegExp(`^\\s*\\[${escapeRegExp(tableName)}\\]\\s*(?:#.*)?$`);
|
|
1264
1299
|
return content.split("\n").some((line) => !line.trimStart().startsWith("#") && tablePattern.test(line));
|
|
@@ -1409,12 +1444,12 @@ var buildPermissionProfileBlock = (paths, includeDefaultPermissions) => [
|
|
|
1409
1444
|
`${quoteTomlString(paths.personalContextRoot)} = "write"`,
|
|
1410
1445
|
`${quoteTomlString(join10(paths.userBasePath, ".ai-ops", "context-promotion"))} = "write"`,
|
|
1411
1446
|
"",
|
|
1412
|
-
`[permissions.${SAFE_LOCAL_CODEX_PERMISSION_NAME}.filesystem.":
|
|
1447
|
+
`[permissions.${SAFE_LOCAL_CODEX_PERMISSION_NAME}.filesystem.":project_roots"]`,
|
|
1413
1448
|
'"." = "write"',
|
|
1414
1449
|
'".git" = "read"',
|
|
1415
1450
|
'".codex" = "read"',
|
|
1416
1451
|
'".codex/plans" = "write"',
|
|
1417
|
-
'"**/*.env" = "
|
|
1452
|
+
'"**/*.env" = "none"',
|
|
1418
1453
|
"",
|
|
1419
1454
|
`[permissions.${SAFE_LOCAL_CODEX_PERMISSION_NAME}.network]`,
|
|
1420
1455
|
"enabled = false",
|
|
@@ -1450,7 +1485,7 @@ var cleanupLegacySandboxConfig = (content) => removeLegacyManagedSandboxWorkspac
|
|
|
1450
1485
|
var editConfigForInstall = (content, paths) => {
|
|
1451
1486
|
const withoutCurrentProfileBlock = stripBlock(content, PROFILE_BLOCK_START, PROFILE_BLOCK_END);
|
|
1452
1487
|
const withoutLegacy = cleanupLegacySandboxConfig(withoutCurrentProfileBlock);
|
|
1453
|
-
const activeDefaultPermissions =
|
|
1488
|
+
const activeDefaultPermissions = readTopLevelStringAssignment(withoutLegacy, "default_permissions");
|
|
1454
1489
|
if (readActiveStringAssignment(withoutLegacy, "sandbox_mode") || hasActiveTable(withoutLegacy, "sandbox_workspace_write")) {
|
|
1455
1490
|
return {
|
|
1456
1491
|
content,
|
|
@@ -1475,12 +1510,9 @@ var editConfigForInstall = (content, paths) => {
|
|
|
1475
1510
|
conflict: CONFIG_CONFLICT_EXISTING_PROFILE
|
|
1476
1511
|
};
|
|
1477
1512
|
}
|
|
1478
|
-
const
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
PROFILE_BLOCK_END,
|
|
1482
|
-
buildPermissionProfileBlock(paths, activeDefaultPermissions !== SAFE_LOCAL_CODEX_PERMISSION_NAME)
|
|
1483
|
-
);
|
|
1513
|
+
const shouldWriteDefaultPermissions = activeDefaultPermissions !== SAFE_LOCAL_CODEX_PERMISSION_NAME;
|
|
1514
|
+
const profileBlock = buildPermissionProfileBlock(paths, shouldWriteDefaultPermissions);
|
|
1515
|
+
const nextContent = shouldWriteDefaultPermissions ? insertBlockBeforeFirstTable(withoutLegacy, profileBlock) : replaceOrAppendBlock(withoutLegacy, PROFILE_BLOCK_START, PROFILE_BLOCK_END, profileBlock);
|
|
1484
1516
|
return {
|
|
1485
1517
|
content: nextContent,
|
|
1486
1518
|
installed: true,
|
|
@@ -2082,13 +2114,14 @@ var pruneContextPromotionReceipts = (params) => {
|
|
|
2082
2114
|
};
|
|
2083
2115
|
|
|
2084
2116
|
// src/features/context-promotion/status.ts
|
|
2085
|
-
import { existsSync as
|
|
2117
|
+
import { existsSync as existsSync10 } from "fs";
|
|
2086
2118
|
import { join as join16, resolve as resolve8 } from "path";
|
|
2087
2119
|
|
|
2088
2120
|
// src/features/project-layer/constants.ts
|
|
2089
2121
|
import { join as join13 } from "path";
|
|
2090
2122
|
var PROJECT_LAYER_MANIFEST_RELATIVE_PATH = ".ai-ops/manifest.json";
|
|
2091
2123
|
var PROJECT_LAYER_CONTEXT_INDEX_RELATIVE_PATH = ".ai-ops/context-layer.json";
|
|
2124
|
+
var CUSTOM_PROJECT_RULES_DIR = "docs/agent/project-rules";
|
|
2092
2125
|
var CONTEXT_LAYER_DATA_DIR = join13(COMPILER_DATA_DIR, "context-layer");
|
|
2093
2126
|
var TOOL_ORDER2 = ["codex", "gemini", "claude-code"];
|
|
2094
2127
|
var DEFAULT_TOOLS = TOOL_ORDER2;
|
|
@@ -2125,7 +2158,7 @@ var resolveProjectLayerManifestPath = (basePath) => join14(basePath, PROJECT_LAY
|
|
|
2125
2158
|
var resolveProjectLayerContextIndexPath = (basePath) => join14(basePath, PROJECT_LAYER_CONTEXT_INDEX_RELATIVE_PATH);
|
|
2126
2159
|
var resolveTemplatePath = (relativePath) => join14(CONTEXT_LAYER_DATA_DIR, relativePath);
|
|
2127
2160
|
var toRelativeDir = (relativePath) => dirname8(relativePath);
|
|
2128
|
-
var
|
|
2161
|
+
var resolveProjectLayerFilePath = (basePath, relativePath) => {
|
|
2129
2162
|
if (!isSafeProjectLayerPath(relativePath)) {
|
|
2130
2163
|
throw new Error(`Unsafe project layer path: ${relativePath}`);
|
|
2131
2164
|
}
|
|
@@ -2258,18 +2291,86 @@ var loadProjectLayerTemplateSpecs = (tools) => {
|
|
|
2258
2291
|
};
|
|
2259
2292
|
var computeProjectLayerSourceHash = (specs) => computeHash(specs.map((spec) => `${spec.path}:${spec.content}`));
|
|
2260
2293
|
|
|
2294
|
+
// src/features/project-layer/custom-project-rules.ts
|
|
2295
|
+
import { existsSync as existsSync5, readdirSync as readdirSync3, readFileSync as readFileSync9 } from "fs";
|
|
2296
|
+
var isMarkdownPath = (path) => path.endsWith(".md");
|
|
2297
|
+
var hasMarkdownFrontmatter = (content) => content.startsWith("---\n");
|
|
2298
|
+
var assertCustomProjectRuleContract = (params) => {
|
|
2299
|
+
if (params.owner !== "project") {
|
|
2300
|
+
throw new Error(`${params.path} owner\uB294 project\uC5EC\uC57C \uD569\uB2C8\uB2E4. \uD604\uC7AC \uAC12: ${params.owner}`);
|
|
2301
|
+
}
|
|
2302
|
+
if (params.layer !== "agent") {
|
|
2303
|
+
throw new Error(`${params.path} layer\uB294 agent\uC5EC\uC57C \uD569\uB2C8\uB2E4. \uD604\uC7AC \uAC12: ${params.layer}`);
|
|
2304
|
+
}
|
|
2305
|
+
};
|
|
2306
|
+
var isCustomProjectRulePath = (path) => path.startsWith(`${CUSTOM_PROJECT_RULES_DIR}/`) && isMarkdownPath(path);
|
|
2307
|
+
var collectMarkdownPaths = (params) => {
|
|
2308
|
+
const absoluteDir = resolveProjectLayerFilePath(params.basePath, params.relativeDir);
|
|
2309
|
+
if (!existsSync5(absoluteDir)) {
|
|
2310
|
+
return [];
|
|
2311
|
+
}
|
|
2312
|
+
return readdirSync3(absoluteDir, { withFileTypes: true }).flatMap((entry) => {
|
|
2313
|
+
const relativePath = `${params.relativeDir}/${entry.name}`;
|
|
2314
|
+
if (entry.isDirectory()) {
|
|
2315
|
+
return collectMarkdownPaths({ basePath: params.basePath, relativeDir: relativePath });
|
|
2316
|
+
}
|
|
2317
|
+
return entry.isFile() && isMarkdownPath(relativePath) ? [relativePath] : [];
|
|
2318
|
+
});
|
|
2319
|
+
};
|
|
2320
|
+
var discoverCustomProjectRuleFiles = (basePath) => collectMarkdownPaths({ basePath, relativeDir: CUSTOM_PROJECT_RULES_DIR }).sort((left, right) => left.localeCompare(right)).flatMap((path) => {
|
|
2321
|
+
const content = readFileSync9(resolveProjectLayerFilePath(basePath, path), "utf-8");
|
|
2322
|
+
if (!hasMarkdownFrontmatter(content)) {
|
|
2323
|
+
return [];
|
|
2324
|
+
}
|
|
2325
|
+
try {
|
|
2326
|
+
const document = parseProjectLayerDocument(path, content);
|
|
2327
|
+
assertCustomProjectRuleContract({
|
|
2328
|
+
path,
|
|
2329
|
+
owner: document.owner,
|
|
2330
|
+
layer: document.layer
|
|
2331
|
+
});
|
|
2332
|
+
return [
|
|
2333
|
+
{
|
|
2334
|
+
path,
|
|
2335
|
+
templateHash: document.contentHash,
|
|
2336
|
+
created: false
|
|
2337
|
+
}
|
|
2338
|
+
];
|
|
2339
|
+
} catch (error) {
|
|
2340
|
+
const reason = error instanceof Error ? error.message : "unknown error";
|
|
2341
|
+
throw new Error(`${path} frontmatter \uD30C\uC2F1 \uC2E4\uD328: ${reason}`);
|
|
2342
|
+
}
|
|
2343
|
+
});
|
|
2344
|
+
var syncCustomProjectRuleFiles = (params) => {
|
|
2345
|
+
const customFiles = discoverCustomProjectRuleFiles(params.basePath);
|
|
2346
|
+
const customPathSet = new Set(customFiles.map((file) => file.path));
|
|
2347
|
+
const projectFilesByPath = /* @__PURE__ */ new Map();
|
|
2348
|
+
for (const file of params.manifest.project_files) {
|
|
2349
|
+
if (!isCustomProjectRulePath(file.path) || customPathSet.has(file.path)) {
|
|
2350
|
+
projectFilesByPath.set(file.path, file);
|
|
2351
|
+
}
|
|
2352
|
+
}
|
|
2353
|
+
for (const file of customFiles) {
|
|
2354
|
+
projectFilesByPath.set(file.path, file);
|
|
2355
|
+
}
|
|
2356
|
+
return ProjectLayerManifestSchema.parse({
|
|
2357
|
+
...params.manifest,
|
|
2358
|
+
project_files: [...projectFilesByPath.values()].sort((left, right) => left.path.localeCompare(right.path))
|
|
2359
|
+
});
|
|
2360
|
+
};
|
|
2361
|
+
|
|
2261
2362
|
// src/features/project-layer/state-io.ts
|
|
2262
|
-
import { mkdirSync as mkdirSync6, readFileSync as
|
|
2363
|
+
import { mkdirSync as mkdirSync6, readFileSync as readFileSync11, writeFileSync as writeFileSync7 } from "fs";
|
|
2263
2364
|
import { dirname as dirname9 } from "path";
|
|
2264
2365
|
|
|
2265
2366
|
// src/features/project-layer/docs-status.logic.ts
|
|
2266
|
-
import { readFileSync as
|
|
2367
|
+
import { readFileSync as readFileSync10, writeFileSync as writeFileSync6 } from "fs";
|
|
2267
2368
|
var docsStatusIssue = (code, message) => ({
|
|
2268
2369
|
level: "error",
|
|
2269
2370
|
code,
|
|
2270
2371
|
message
|
|
2271
2372
|
});
|
|
2272
|
-
var computeDocsStatusFileHash = (basePath, relativePath) => computeHash([
|
|
2373
|
+
var computeDocsStatusFileHash = (basePath, relativePath) => computeHash([readFileSync10(resolveProjectLayerFilePath(basePath, relativePath), "utf-8").trimEnd()]);
|
|
2273
2374
|
var parseMarkdownTableCells = (line) => {
|
|
2274
2375
|
const trimmed = line.trim();
|
|
2275
2376
|
if (!trimmed.startsWith("|") || !trimmed.endsWith("|")) {
|
|
@@ -2319,7 +2420,7 @@ var parseDocsStatusEntries = (content) => {
|
|
|
2319
2420
|
});
|
|
2320
2421
|
};
|
|
2321
2422
|
var buildDocsStatusRowsFromDisk = (params) => params.documentPaths.map((path) => {
|
|
2322
|
-
const document = parseProjectLayerDocument(path,
|
|
2423
|
+
const document = parseProjectLayerDocument(path, readFileSync10(resolveProjectLayerFilePath(params.basePath, path), "utf-8"));
|
|
2323
2424
|
return `| ${document.path} | ${document.status} | ${document.owner} |`;
|
|
2324
2425
|
});
|
|
2325
2426
|
var replaceDocsStatusRows = (content, rows) => {
|
|
@@ -2332,10 +2433,10 @@ var replaceDocsStatusRows = (content, rows) => {
|
|
|
2332
2433
|
};
|
|
2333
2434
|
var updateDocsStatusTable = (basePath, documentPaths) => {
|
|
2334
2435
|
const docsStatusPath = "docs/docs-status.md";
|
|
2335
|
-
const absolutePath =
|
|
2436
|
+
const absolutePath = resolveProjectLayerFilePath(basePath, docsStatusPath);
|
|
2336
2437
|
const beforeHash = computeDocsStatusFileHash(basePath, docsStatusPath);
|
|
2337
2438
|
const rows = buildDocsStatusRowsFromDisk({ basePath, documentPaths });
|
|
2338
|
-
const nextContent = replaceDocsStatusRows(
|
|
2439
|
+
const nextContent = replaceDocsStatusRows(readFileSync10(absolutePath, "utf-8"), rows);
|
|
2339
2440
|
writeFileSync6(absolutePath, nextContent, "utf-8");
|
|
2340
2441
|
return {
|
|
2341
2442
|
beforeHash,
|
|
@@ -2372,7 +2473,7 @@ var compareDocsStatusEntry = (params) => {
|
|
|
2372
2473
|
// src/features/project-layer/state-io.ts
|
|
2373
2474
|
var readProjectLayerManifest = (basePath) => {
|
|
2374
2475
|
try {
|
|
2375
|
-
return parseProjectLayerManifest(
|
|
2476
|
+
return parseProjectLayerManifest(readFileSync11(resolveProjectLayerManifestPath(basePath), "utf-8"));
|
|
2376
2477
|
} catch (error) {
|
|
2377
2478
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
2378
2479
|
return null;
|
|
@@ -2387,7 +2488,7 @@ var writeProjectLayerManifest = (basePath, manifest) => {
|
|
|
2387
2488
|
};
|
|
2388
2489
|
var readProjectLayerContextIndex = (basePath) => {
|
|
2389
2490
|
try {
|
|
2390
|
-
return parseProjectLayerContextIndex(
|
|
2491
|
+
return parseProjectLayerContextIndex(readFileSync11(resolveProjectLayerContextIndexPath(basePath), "utf-8"));
|
|
2391
2492
|
} catch (error) {
|
|
2392
2493
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
2393
2494
|
return null;
|
|
@@ -2402,7 +2503,7 @@ var writeProjectLayerContextIndex = (basePath, contextIndex) => {
|
|
|
2402
2503
|
};
|
|
2403
2504
|
var buildContextIndexFromDisk = (params) => {
|
|
2404
2505
|
const documents = params.documentPaths.map(
|
|
2405
|
-
(path) => parseProjectLayerDocument(path,
|
|
2506
|
+
(path) => parseProjectLayerDocument(path, readFileSync11(resolveProjectLayerFilePath(params.basePath, path), "utf-8"))
|
|
2406
2507
|
);
|
|
2407
2508
|
return ProjectLayerContextIndexSchema.parse({
|
|
2408
2509
|
schemaVersion: 1,
|
|
@@ -2417,10 +2518,14 @@ var collectDocumentPathsFromManifest = (manifest) => [
|
|
|
2417
2518
|
...manifest.packs.flatMap((pack) => pack.documents.map((file) => file.path))
|
|
2418
2519
|
].sort();
|
|
2419
2520
|
var refreshProjectLayerDerivedState = (params) => {
|
|
2420
|
-
const
|
|
2521
|
+
const manifestWithCustomRules = syncCustomProjectRuleFiles({
|
|
2522
|
+
basePath: params.basePath,
|
|
2523
|
+
manifest: params.manifest
|
|
2524
|
+
});
|
|
2525
|
+
const documentPaths = collectDocumentPathsFromManifest(manifestWithCustomRules);
|
|
2421
2526
|
const docsStatusHashes = updateDocsStatusTable(params.basePath, documentPaths);
|
|
2422
2527
|
const manifest = updateDocsStatusProjectFileRecord({
|
|
2423
|
-
manifest:
|
|
2528
|
+
manifest: manifestWithCustomRules,
|
|
2424
2529
|
beforeHash: docsStatusHashes.beforeHash,
|
|
2425
2530
|
afterHash: docsStatusHashes.afterHash
|
|
2426
2531
|
});
|
|
@@ -2437,17 +2542,17 @@ var refreshProjectLayerDerivedState = (params) => {
|
|
|
2437
2542
|
};
|
|
2438
2543
|
|
|
2439
2544
|
// src/features/project-layer/lifecycle.logic.ts
|
|
2440
|
-
import { existsSync as
|
|
2545
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync7, readFileSync as readFileSync13, writeFileSync as writeFileSync9 } from "fs";
|
|
2441
2546
|
import { dirname as dirname10 } from "path";
|
|
2442
2547
|
|
|
2443
2548
|
// src/features/project-layer/uninstall.logic.ts
|
|
2444
|
-
import { existsSync as
|
|
2549
|
+
import { existsSync as existsSync6, readFileSync as readFileSync12, readdirSync as readdirSync4, rmSync as rmSync2, writeFileSync as writeFileSync8 } from "fs";
|
|
2445
2550
|
function removeManagedProjectFile(basePath, relativePath) {
|
|
2446
|
-
const absolutePath =
|
|
2447
|
-
if (!
|
|
2551
|
+
const absolutePath = resolveProjectLayerFilePath(basePath, relativePath);
|
|
2552
|
+
if (!existsSync6(absolutePath)) {
|
|
2448
2553
|
return { deleted: [], cleaned: [], preserved: [], notFound: [relativePath] };
|
|
2449
2554
|
}
|
|
2450
|
-
const content =
|
|
2555
|
+
const content = readFileSync12(absolutePath, "utf-8");
|
|
2451
2556
|
if (!hasAiOpsSection(content)) {
|
|
2452
2557
|
return { deleted: [], cleaned: [], preserved: [relativePath], notFound: [] };
|
|
2453
2558
|
}
|
|
@@ -2460,11 +2565,11 @@ function removeManagedProjectFile(basePath, relativePath) {
|
|
|
2460
2565
|
return { deleted: [], cleaned: [relativePath], preserved: [], notFound: [] };
|
|
2461
2566
|
}
|
|
2462
2567
|
var removeCreateOnlyProjectFile = (basePath, file) => {
|
|
2463
|
-
const absolutePath =
|
|
2464
|
-
if (!
|
|
2568
|
+
const absolutePath = resolveProjectLayerFilePath(basePath, file.path);
|
|
2569
|
+
if (!existsSync6(absolutePath)) {
|
|
2465
2570
|
return { deleted: [], cleaned: [], preserved: [], notFound: [file.path] };
|
|
2466
2571
|
}
|
|
2467
|
-
const content =
|
|
2572
|
+
const content = readFileSync12(absolutePath, "utf-8").trimEnd();
|
|
2468
2573
|
const currentHash = computeHash([content]);
|
|
2469
2574
|
if (file.created && currentHash === file.templateHash) {
|
|
2470
2575
|
rmSync2(absolutePath);
|
|
@@ -2473,11 +2578,11 @@ var removeCreateOnlyProjectFile = (basePath, file) => {
|
|
|
2473
2578
|
return { deleted: [], cleaned: [], preserved: [file.path], notFound: [] };
|
|
2474
2579
|
};
|
|
2475
2580
|
var removePackOwnedFile = (basePath, file) => {
|
|
2476
|
-
const absolutePath =
|
|
2477
|
-
if (!
|
|
2581
|
+
const absolutePath = resolveProjectLayerFilePath(basePath, file.path);
|
|
2582
|
+
if (!existsSync6(absolutePath)) {
|
|
2478
2583
|
return { deleted: [], cleaned: [], preserved: [], notFound: [file.path] };
|
|
2479
2584
|
}
|
|
2480
|
-
const currentHash = computeHash([
|
|
2585
|
+
const currentHash = computeHash([readFileSync12(absolutePath, "utf-8").trimEnd()]);
|
|
2481
2586
|
if (currentHash === file.sourceHash) {
|
|
2482
2587
|
rmSync2(absolutePath);
|
|
2483
2588
|
return { deleted: [file.path], cleaned: [], preserved: [], notFound: [] };
|
|
@@ -2495,10 +2600,10 @@ var removeEmptyDirs = (basePath, relativePaths) => {
|
|
|
2495
2600
|
(a, b) => b.length - a.length
|
|
2496
2601
|
);
|
|
2497
2602
|
for (const dir of [...dirs, ".ai-ops"]) {
|
|
2498
|
-
const absoluteDir =
|
|
2499
|
-
if (!
|
|
2603
|
+
const absoluteDir = resolveProjectLayerFilePath(basePath, dir);
|
|
2604
|
+
if (!existsSync6(absoluteDir)) continue;
|
|
2500
2605
|
try {
|
|
2501
|
-
if (
|
|
2606
|
+
if (readdirSync4(absoluteDir).length === 0) {
|
|
2502
2607
|
rmSync2(absoluteDir, { recursive: true });
|
|
2503
2608
|
}
|
|
2504
2609
|
} catch {
|
|
@@ -2513,7 +2618,7 @@ var uninstallProjectLayer = (basePath, manifest) => {
|
|
|
2513
2618
|
);
|
|
2514
2619
|
const stateFiles = [PROJECT_LAYER_CONTEXT_INDEX_RELATIVE_PATH, PROJECT_LAYER_MANIFEST_RELATIVE_PATH];
|
|
2515
2620
|
for (const stateFile of stateFiles) {
|
|
2516
|
-
rmSync2(
|
|
2621
|
+
rmSync2(resolveProjectLayerFilePath(basePath, stateFile), { force: true });
|
|
2517
2622
|
}
|
|
2518
2623
|
const result = mergeRemoveResults([...managedResults, ...projectResults, ...packResults]);
|
|
2519
2624
|
removeEmptyDirs(basePath, [...result.deleted, ...stateFiles]);
|
|
@@ -2525,15 +2630,15 @@ var installManagedFiles = (basePath, specs, meta) => {
|
|
|
2525
2630
|
const written = [];
|
|
2526
2631
|
const appended = [];
|
|
2527
2632
|
for (const spec of specs) {
|
|
2528
|
-
const absolutePath =
|
|
2633
|
+
const absolutePath = resolveProjectLayerFilePath(basePath, spec.path);
|
|
2529
2634
|
const wrappedContent = wrapWithSection(spec.content, meta);
|
|
2530
|
-
if (!
|
|
2635
|
+
if (!existsSync7(absolutePath)) {
|
|
2531
2636
|
mkdirSync7(dirname10(absolutePath), { recursive: true });
|
|
2532
2637
|
writeFileSync9(absolutePath, wrappedContent + "\n", "utf-8");
|
|
2533
2638
|
written.push(spec.path);
|
|
2534
2639
|
continue;
|
|
2535
2640
|
}
|
|
2536
|
-
const existing =
|
|
2641
|
+
const existing = readFileSync13(absolutePath, "utf-8");
|
|
2537
2642
|
if (hasAiOpsSection(existing)) {
|
|
2538
2643
|
writeFileSync9(absolutePath, replaceAiOpsSection(existing, wrappedContent), "utf-8");
|
|
2539
2644
|
const stripped = stripAiOpsSection(existing);
|
|
@@ -2557,9 +2662,9 @@ var installProjectFiles = (params) => {
|
|
|
2557
2662
|
const preserved = [];
|
|
2558
2663
|
const previousByPath = new Map((params.previousProjectFiles ?? []).map((file) => [file.path, file]));
|
|
2559
2664
|
for (const spec of params.specs) {
|
|
2560
|
-
const absolutePath =
|
|
2665
|
+
const absolutePath = resolveProjectLayerFilePath(params.basePath, spec.path);
|
|
2561
2666
|
const previous = previousByPath.get(spec.path);
|
|
2562
|
-
if (!
|
|
2667
|
+
if (!existsSync7(absolutePath)) {
|
|
2563
2668
|
mkdirSync7(dirname10(absolutePath), { recursive: true });
|
|
2564
2669
|
writeFileSync9(absolutePath, spec.content + "\n", "utf-8");
|
|
2565
2670
|
created.push(spec.path);
|
|
@@ -2570,7 +2675,7 @@ var installProjectFiles = (params) => {
|
|
|
2570
2675
|
});
|
|
2571
2676
|
continue;
|
|
2572
2677
|
}
|
|
2573
|
-
const existingContent =
|
|
2678
|
+
const existingContent = readFileSync13(absolutePath, "utf-8").trimEnd();
|
|
2574
2679
|
const existingHash = computeHash([existingContent]);
|
|
2575
2680
|
if (previous?.created === true && existingHash === previous.templateHash) {
|
|
2576
2681
|
if (existingHash !== spec.contentHash) {
|
|
@@ -2704,7 +2809,7 @@ var updateProjectLayer = (params) => {
|
|
|
2704
2809
|
};
|
|
2705
2810
|
|
|
2706
2811
|
// src/features/project-layer/audit.logic.ts
|
|
2707
|
-
import { existsSync as
|
|
2812
|
+
import { existsSync as existsSync8, readFileSync as readFileSync14 } from "fs";
|
|
2708
2813
|
var issue = (level, code, message) => ({
|
|
2709
2814
|
level,
|
|
2710
2815
|
code,
|
|
@@ -2712,11 +2817,11 @@ var issue = (level, code, message) => ({
|
|
|
2712
2817
|
});
|
|
2713
2818
|
var readDocumentSafely = (basePath, path) => {
|
|
2714
2819
|
try {
|
|
2715
|
-
const absolutePath =
|
|
2716
|
-
if (!
|
|
2820
|
+
const absolutePath = resolveProjectLayerFilePath(basePath, path);
|
|
2821
|
+
if (!existsSync8(absolutePath)) {
|
|
2717
2822
|
return issue("error", "missing-file", `\uD30C\uC77C \uC5C6\uC74C: ${path}`);
|
|
2718
2823
|
}
|
|
2719
|
-
return parseProjectLayerDocument(path,
|
|
2824
|
+
return parseProjectLayerDocument(path, readFileSync14(absolutePath, "utf-8"));
|
|
2720
2825
|
} catch (error) {
|
|
2721
2826
|
const reason = error instanceof Error ? error.message : "unknown error";
|
|
2722
2827
|
return issue("error", "invalid-frontmatter", `${path} frontmatter \uD30C\uC2F1 \uC2E4\uD328: ${reason}`);
|
|
@@ -2724,6 +2829,10 @@ var readDocumentSafely = (basePath, path) => {
|
|
|
2724
2829
|
};
|
|
2725
2830
|
var buildContextIndexMap = (contextIndex) => new Map((contextIndex?.documents ?? []).map((document) => [document.path, document]));
|
|
2726
2831
|
var compareArray = (left, right) => left.length === right.length && left.every((value, index) => value === right[index]);
|
|
2832
|
+
var compareProjectFileRecords = (left, right) => left.length === right.length && left.every((file, index) => {
|
|
2833
|
+
const other = right[index];
|
|
2834
|
+
return other !== void 0 && file.path === other.path && file.templateHash === other.templateHash && file.created === other.created;
|
|
2835
|
+
});
|
|
2727
2836
|
var compareContextDocument = (params) => {
|
|
2728
2837
|
const indexed = params.indexed;
|
|
2729
2838
|
if (indexed === void 0) {
|
|
@@ -2767,6 +2876,13 @@ var diffProjectLayer = (basePath) => {
|
|
|
2767
2876
|
const currentSourceHash = computeProjectLayerSourceHash(specs);
|
|
2768
2877
|
let contextIndex = null;
|
|
2769
2878
|
const issues = [];
|
|
2879
|
+
let syncedManifest = manifest;
|
|
2880
|
+
try {
|
|
2881
|
+
syncedManifest = syncCustomProjectRuleFiles({ basePath, manifest });
|
|
2882
|
+
} catch (error) {
|
|
2883
|
+
const reason = error instanceof Error ? error.message : "unknown error";
|
|
2884
|
+
issues.push(issue("error", "invalid-custom-project-rule", reason));
|
|
2885
|
+
}
|
|
2770
2886
|
try {
|
|
2771
2887
|
contextIndex = readProjectLayerContextIndex(basePath);
|
|
2772
2888
|
} catch (error) {
|
|
@@ -2786,18 +2902,27 @@ var diffProjectLayer = (basePath) => {
|
|
|
2786
2902
|
if (contextIndex === null) {
|
|
2787
2903
|
issues.push(issue("error", "missing-context-index", `${PROJECT_LAYER_CONTEXT_INDEX_RELATIVE_PATH}\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.`));
|
|
2788
2904
|
}
|
|
2905
|
+
if (!compareProjectFileRecords(manifest.project_files, syncedManifest.project_files)) {
|
|
2906
|
+
issues.push(
|
|
2907
|
+
issue(
|
|
2908
|
+
"warning",
|
|
2909
|
+
"custom-project-rules-drift",
|
|
2910
|
+
"`docs/agent/project-rules/**/*.md` discovery \uACB0\uACFC\uAC00 manifest\uC640 \uB2E4\uB985\uB2C8\uB2E4. `ai-ops update`\uB85C \uB3D9\uAE30\uD654\uD558\uC138\uC694."
|
|
2911
|
+
)
|
|
2912
|
+
);
|
|
2913
|
+
}
|
|
2789
2914
|
for (const expectedPath of expectedManagedPaths) {
|
|
2790
2915
|
if (!manifestManagedPaths.has(expectedPath)) {
|
|
2791
2916
|
issues.push(issue("error", "manifest-missing-managed-file", `manifest managed_files \uB204\uB77D: ${expectedPath}`));
|
|
2792
2917
|
}
|
|
2793
2918
|
}
|
|
2794
2919
|
for (const file of manifest.managed_files) {
|
|
2795
|
-
const absolutePath =
|
|
2796
|
-
if (!
|
|
2920
|
+
const absolutePath = resolveProjectLayerFilePath(basePath, file.path);
|
|
2921
|
+
if (!existsSync8(absolutePath)) {
|
|
2797
2922
|
issues.push(issue("error", "missing-file", `\uD30C\uC77C \uC5C6\uC74C: ${file.path}`));
|
|
2798
2923
|
continue;
|
|
2799
2924
|
}
|
|
2800
|
-
const content =
|
|
2925
|
+
const content = readFileSync14(absolutePath, "utf-8");
|
|
2801
2926
|
const meta = parseAiOpsMeta(content);
|
|
2802
2927
|
if (!meta) {
|
|
2803
2928
|
issues.push(issue("error", "missing-managed-section", `managed section \uBA54\uD0C0 \uC5C6\uC74C: ${file.path}`));
|
|
@@ -2809,19 +2934,19 @@ var diffProjectLayer = (basePath) => {
|
|
|
2809
2934
|
);
|
|
2810
2935
|
}
|
|
2811
2936
|
}
|
|
2812
|
-
for (const file of
|
|
2813
|
-
if (!
|
|
2937
|
+
for (const file of syncedManifest.project_files) {
|
|
2938
|
+
if (!existsSync8(resolveProjectLayerFilePath(basePath, file.path))) {
|
|
2814
2939
|
issues.push(issue("error", "missing-file", `\uD30C\uC77C \uC5C6\uC74C: ${file.path}`));
|
|
2815
2940
|
}
|
|
2816
2941
|
}
|
|
2817
|
-
for (const pack of
|
|
2942
|
+
for (const pack of syncedManifest.packs) {
|
|
2818
2943
|
for (const file of [...pack.documents, ...pack.files]) {
|
|
2819
|
-
if (!
|
|
2944
|
+
if (!existsSync8(resolveProjectLayerFilePath(basePath, file.path))) {
|
|
2820
2945
|
issues.push(issue("error", "missing-file", `\uD30C\uC77C \uC5C6\uC74C: ${file.path}`));
|
|
2821
2946
|
}
|
|
2822
2947
|
}
|
|
2823
2948
|
}
|
|
2824
|
-
for (const path of collectDocumentPathsFromManifest(
|
|
2949
|
+
for (const path of collectDocumentPathsFromManifest(syncedManifest)) {
|
|
2825
2950
|
const document = readDocumentSafely(basePath, path);
|
|
2826
2951
|
if ("code" in document) {
|
|
2827
2952
|
issues.push(document);
|
|
@@ -2848,18 +2973,24 @@ var auditProjectLayer = (basePath) => {
|
|
|
2848
2973
|
} catch {
|
|
2849
2974
|
contextIndex = null;
|
|
2850
2975
|
}
|
|
2851
|
-
|
|
2976
|
+
let syncedManifest = manifest;
|
|
2977
|
+
try {
|
|
2978
|
+
syncedManifest = syncCustomProjectRuleFiles({ basePath, manifest });
|
|
2979
|
+
} catch {
|
|
2980
|
+
return diffReport;
|
|
2981
|
+
}
|
|
2982
|
+
const documentPaths = collectDocumentPathsFromManifest(syncedManifest);
|
|
2852
2983
|
const documentPathSet = new Set(documentPaths);
|
|
2853
2984
|
const contextPathSet = new Set(contextIndex?.documents.map((document) => document.path) ?? []);
|
|
2854
2985
|
const issues = [...diffReport.issues];
|
|
2855
|
-
const docsStatusPath =
|
|
2856
|
-
if (!
|
|
2986
|
+
const docsStatusPath = resolveProjectLayerFilePath(basePath, "docs/docs-status.md");
|
|
2987
|
+
if (!existsSync8(docsStatusPath)) {
|
|
2857
2988
|
issues.push(issue("error", "missing-docs-status", "docs/docs-status.md\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4."));
|
|
2858
2989
|
return { currentSourceHash: diffReport.currentSourceHash, issues };
|
|
2859
2990
|
}
|
|
2860
2991
|
let docsStatusEntries = [];
|
|
2861
2992
|
try {
|
|
2862
|
-
docsStatusEntries = parseDocsStatusEntries(
|
|
2993
|
+
docsStatusEntries = parseDocsStatusEntries(readFileSync14(docsStatusPath, "utf-8"));
|
|
2863
2994
|
} catch (error) {
|
|
2864
2995
|
const reason = error instanceof Error ? error.message : "unknown error";
|
|
2865
2996
|
issues.push(issue("error", "invalid-docs-status", `docs/docs-status.md \uD30C\uC2F1 \uC2E4\uD328: ${reason}`));
|
|
@@ -2886,11 +3017,11 @@ var auditProjectLayer = (basePath) => {
|
|
|
2886
3017
|
};
|
|
2887
3018
|
|
|
2888
3019
|
// src/features/project-layer/pack.logic.ts
|
|
2889
|
-
import { existsSync as
|
|
3020
|
+
import { existsSync as existsSync9, mkdirSync as mkdirSync8, readFileSync as readFileSync16, readdirSync as readdirSync6, rmSync as rmSync3, writeFileSync as writeFileSync10 } from "fs";
|
|
2890
3021
|
import { dirname as dirname11 } from "path";
|
|
2891
3022
|
|
|
2892
3023
|
// src/features/project-layer/pack-source.logic.ts
|
|
2893
|
-
import { readFileSync as
|
|
3024
|
+
import { readFileSync as readFileSync15, readdirSync as readdirSync5 } from "fs";
|
|
2894
3025
|
import { isAbsolute as isAbsolute2, join as join15, relative as relative2, resolve as resolve7 } from "path";
|
|
2895
3026
|
var PACK_REGISTRY_FILENAME = "pack-registry.json";
|
|
2896
3027
|
var SPEC_LIFECYCLE_PACK_ID = "spec-lifecycle";
|
|
@@ -2901,7 +3032,7 @@ var RESERVED_DOCUMENT_WARNINGS2 = [
|
|
|
2901
3032
|
];
|
|
2902
3033
|
var DEFAULT_PACKS_DIR = join15(COMPILER_DATA_DIR, "packs");
|
|
2903
3034
|
var includesReservedDocumentWarning2 = (content) => RESERVED_DOCUMENT_WARNINGS2.some((warning) => content.includes(warning));
|
|
2904
|
-
var readPackCatalog = (packsDir) => PackCatalogSchema.parse(JSON.parse(
|
|
3035
|
+
var readPackCatalog = (packsDir) => PackCatalogSchema.parse(JSON.parse(readFileSync15(join15(packsDir, PACK_REGISTRY_FILENAME), "utf-8")));
|
|
2905
3036
|
var assertPackInstallPath = (path) => {
|
|
2906
3037
|
if (!isSafeProjectLayerPath(path) || !path.startsWith(PACK_INSTALL_ROOT)) {
|
|
2907
3038
|
throw new Error(`Unsafe pack path: ${path}`);
|
|
@@ -2911,7 +3042,7 @@ var readPackSourceFiles = (packDir) => {
|
|
|
2911
3042
|
const files = [];
|
|
2912
3043
|
const walk = (relativeDir = "") => {
|
|
2913
3044
|
const absoluteDir = relativeDir.length > 0 ? join15(packDir, relativeDir) : packDir;
|
|
2914
|
-
const entries =
|
|
3045
|
+
const entries = readdirSync5(absoluteDir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
|
|
2915
3046
|
for (const entry of entries) {
|
|
2916
3047
|
const nextRelativePath = relativeDir.length > 0 ? join15(relativeDir, entry.name) : entry.name;
|
|
2917
3048
|
if (entry.isDirectory()) {
|
|
@@ -2919,7 +3050,7 @@ var readPackSourceFiles = (packDir) => {
|
|
|
2919
3050
|
continue;
|
|
2920
3051
|
}
|
|
2921
3052
|
assertPackInstallPath(nextRelativePath);
|
|
2922
|
-
const content =
|
|
3053
|
+
const content = readFileSync15(join15(packDir, nextRelativePath), "utf-8");
|
|
2923
3054
|
files.push({
|
|
2924
3055
|
path: nextRelativePath,
|
|
2925
3056
|
content,
|
|
@@ -2979,9 +3110,9 @@ var resolvePackById = (packsDir, packId) => {
|
|
|
2979
3110
|
|
|
2980
3111
|
// src/features/project-layer/pack.logic.ts
|
|
2981
3112
|
var serializePackFileContent = (content) => content.length === 0 ? "" : content.trimEnd() + "\n";
|
|
2982
|
-
var readProjectFileHash = (basePath, relativePath) => computeHash([
|
|
3113
|
+
var readProjectFileHash = (basePath, relativePath) => computeHash([readFileSync16(resolveProjectLayerFilePath(basePath, relativePath), "utf-8").trimEnd()]);
|
|
2983
3114
|
var writePackFile = (basePath, file) => {
|
|
2984
|
-
const absolutePath =
|
|
3115
|
+
const absolutePath = resolveProjectLayerFilePath(basePath, file.path);
|
|
2985
3116
|
mkdirSync8(dirname11(absolutePath), { recursive: true });
|
|
2986
3117
|
writeFileSync10(absolutePath, serializePackFileContent(file.content), "utf-8");
|
|
2987
3118
|
};
|
|
@@ -3011,9 +3142,9 @@ var applyPackSourceFiles = (params) => {
|
|
|
3011
3142
|
])
|
|
3012
3143
|
);
|
|
3013
3144
|
for (const file of sourceFiles) {
|
|
3014
|
-
const absolutePath =
|
|
3145
|
+
const absolutePath = resolveProjectLayerFilePath(params.basePath, file.path);
|
|
3015
3146
|
const previous = previousByPath.get(file.path);
|
|
3016
|
-
if (!
|
|
3147
|
+
if (!existsSync9(absolutePath)) {
|
|
3017
3148
|
writePackFile(params.basePath, file);
|
|
3018
3149
|
written.push(file.path);
|
|
3019
3150
|
continue;
|
|
@@ -3036,8 +3167,8 @@ var applyPackSourceFiles = (params) => {
|
|
|
3036
3167
|
if (sourceByPath.has(previous.path)) {
|
|
3037
3168
|
continue;
|
|
3038
3169
|
}
|
|
3039
|
-
const absolutePath =
|
|
3040
|
-
if (!
|
|
3170
|
+
const absolutePath = resolveProjectLayerFilePath(params.basePath, previous.path);
|
|
3171
|
+
if (!existsSync9(absolutePath)) {
|
|
3041
3172
|
notFound.push(previous.path);
|
|
3042
3173
|
continue;
|
|
3043
3174
|
}
|
|
@@ -3055,8 +3186,8 @@ var removePackFiles = (basePath, record) => {
|
|
|
3055
3186
|
const preserved = [];
|
|
3056
3187
|
const notFound = [];
|
|
3057
3188
|
for (const file of [...record.documents, ...record.files]) {
|
|
3058
|
-
const absolutePath =
|
|
3059
|
-
if (!
|
|
3189
|
+
const absolutePath = resolveProjectLayerFilePath(basePath, file.path);
|
|
3190
|
+
if (!existsSync9(absolutePath)) {
|
|
3060
3191
|
notFound.push(file.path);
|
|
3061
3192
|
continue;
|
|
3062
3193
|
}
|
|
@@ -3074,12 +3205,12 @@ var removeEmptyDirs2 = (basePath, relativePaths) => {
|
|
|
3074
3205
|
(a, b) => b.length - a.length
|
|
3075
3206
|
);
|
|
3076
3207
|
for (const dir of dirs) {
|
|
3077
|
-
const absoluteDir =
|
|
3078
|
-
if (!
|
|
3208
|
+
const absoluteDir = resolveProjectLayerFilePath(basePath, dir);
|
|
3209
|
+
if (!existsSync9(absoluteDir)) {
|
|
3079
3210
|
continue;
|
|
3080
3211
|
}
|
|
3081
3212
|
try {
|
|
3082
|
-
if (
|
|
3213
|
+
if (readdirSync6(absoluteDir).length === 0) {
|
|
3083
3214
|
rmSync3(absoluteDir, { recursive: true });
|
|
3084
3215
|
}
|
|
3085
3216
|
} catch {
|
|
@@ -3190,8 +3321,8 @@ var diffProjectLayerPack = (params) => {
|
|
|
3190
3321
|
);
|
|
3191
3322
|
}
|
|
3192
3323
|
for (const file of [...record.documents, ...record.files]) {
|
|
3193
|
-
const absolutePath =
|
|
3194
|
-
if (!
|
|
3324
|
+
const absolutePath = resolveProjectLayerFilePath(params.basePath, file.path);
|
|
3325
|
+
if (!existsSync9(absolutePath)) {
|
|
3195
3326
|
issues.push(packIssue("error", "missing-file", `\uD30C\uC77C \uC5C6\uC74C: ${file.path}`));
|
|
3196
3327
|
}
|
|
3197
3328
|
}
|
|
@@ -3200,7 +3331,7 @@ var diffProjectLayerPack = (params) => {
|
|
|
3200
3331
|
};
|
|
3201
3332
|
|
|
3202
3333
|
// src/features/context-promotion/status.ts
|
|
3203
|
-
var hasContextPromotionLayer = (gitRoot) =>
|
|
3334
|
+
var hasContextPromotionLayer = (gitRoot) => existsSync10(join16(gitRoot, PROJECT_LAYER_CONTEXT_INDEX_RELATIVE_PATH));
|
|
3204
3335
|
var getContextPromotionStatus = (params) => {
|
|
3205
3336
|
const cwd = resolve8(params.cwd);
|
|
3206
3337
|
const gitRoot = resolveContextPromotionGitRoot(cwd);
|
|
@@ -3528,11 +3659,11 @@ import * as p5 from "@clack/prompts";
|
|
|
3528
3659
|
|
|
3529
3660
|
// src/features/pc/status.ts
|
|
3530
3661
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
3531
|
-
import { existsSync as
|
|
3662
|
+
import { existsSync as existsSync11, readdirSync as readdirSync7 } from "fs";
|
|
3532
3663
|
import { join as join17, resolve as resolve10, sep as sep2 } from "path";
|
|
3533
3664
|
|
|
3534
3665
|
// src/features/pc/markdown.ts
|
|
3535
|
-
import { readFileSync as
|
|
3666
|
+
import { readFileSync as readFileSync17 } from "fs";
|
|
3536
3667
|
import { resolve as resolve9, sep } from "path";
|
|
3537
3668
|
var normalizePath = (path) => resolve9(path.replace(/^~(?=$|\/)/, process.env.HOME ?? "~"));
|
|
3538
3669
|
var pathContains = (parentPath, childPath) => {
|
|
@@ -3571,7 +3702,7 @@ var parseListField = (content, labels) => {
|
|
|
3571
3702
|
};
|
|
3572
3703
|
var readTextFileOrNull = (filePath) => {
|
|
3573
3704
|
try {
|
|
3574
|
-
return
|
|
3705
|
+
return readFileSync17(filePath, "utf-8");
|
|
3575
3706
|
} catch {
|
|
3576
3707
|
return null;
|
|
3577
3708
|
}
|
|
@@ -3599,10 +3730,10 @@ var readGitHead2 = (cwd) => {
|
|
|
3599
3730
|
};
|
|
3600
3731
|
var listWorkspaceStatePaths = (contextRoot) => {
|
|
3601
3732
|
const workspacesDir = join17(contextRoot, "workspaces");
|
|
3602
|
-
if (!
|
|
3733
|
+
if (!existsSync11(workspacesDir)) {
|
|
3603
3734
|
return [];
|
|
3604
3735
|
}
|
|
3605
|
-
return
|
|
3736
|
+
return readdirSync7(workspacesDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => join17(workspacesDir, entry.name, "workspace-state.md")).filter((statePath) => existsSync11(statePath)).sort((a, b) => a.localeCompare(b));
|
|
3606
3737
|
};
|
|
3607
3738
|
var parseWorkspaceCandidate = (statePath) => {
|
|
3608
3739
|
const content = readTextFileOrNull(statePath);
|
|
@@ -3646,10 +3777,10 @@ var parseRepoEntry = (entryPath) => {
|
|
|
3646
3777
|
};
|
|
3647
3778
|
var findCurrentEntry = (params) => {
|
|
3648
3779
|
const reposDir = join17(params.workspaceDir, "repos");
|
|
3649
|
-
if (!
|
|
3780
|
+
if (!existsSync11(reposDir)) {
|
|
3650
3781
|
return null;
|
|
3651
3782
|
}
|
|
3652
|
-
const entries =
|
|
3783
|
+
const entries = readdirSync7(reposDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".md")).map((entry) => parseRepoEntry(join17(reposDir, entry.name))).filter((entry) => entry !== null).filter((entry) => {
|
|
3653
3784
|
const paths = [entry.path, entry.gitRoot].filter((path) => path !== null);
|
|
3654
3785
|
return paths.some((path) => pathContains(path, params.cwd));
|
|
3655
3786
|
}).sort((a, b) => {
|
|
@@ -3701,7 +3832,7 @@ var parseLastConfirmedCommitHash = (params) => {
|
|
|
3701
3832
|
var getPcHandoffStatus = (params) => {
|
|
3702
3833
|
const cwd = normalizePath(params.cwd);
|
|
3703
3834
|
const contextRoot = normalizePath(params.contextRoot);
|
|
3704
|
-
if (!
|
|
3835
|
+
if (!existsSync11(contextRoot)) {
|
|
3705
3836
|
return {
|
|
3706
3837
|
cwd,
|
|
3707
3838
|
contextRoot,
|
|
@@ -3864,7 +3995,7 @@ var evaluatePcPostToolUseHook = (params) => {
|
|
|
3864
3995
|
};
|
|
3865
3996
|
|
|
3866
3997
|
// src/features/integrations/manifest-io.ts
|
|
3867
|
-
import { mkdirSync as mkdirSync9, readFileSync as
|
|
3998
|
+
import { mkdirSync as mkdirSync9, readFileSync as readFileSync18, rmSync as rmSync4, writeFileSync as writeFileSync11 } from "fs";
|
|
3868
3999
|
import { dirname as dirname12, join as join18 } from "path";
|
|
3869
4000
|
var INTEGRATION_MANIFEST_FILENAME = "integrations-manifest.json";
|
|
3870
4001
|
var parseIntegrationManifest = (json) => IntegrationManifestSchema.parse(JSON.parse(json));
|
|
@@ -3873,7 +4004,7 @@ var resolveIntegrationManifestPath = (userBasePath) => join18(userBasePath, ".ai
|
|
|
3873
4004
|
var readIntegrationManifest = (manifestPath) => {
|
|
3874
4005
|
let raw;
|
|
3875
4006
|
try {
|
|
3876
|
-
raw =
|
|
4007
|
+
raw = readFileSync18(manifestPath, "utf-8");
|
|
3877
4008
|
} catch {
|
|
3878
4009
|
return null;
|
|
3879
4010
|
}
|
|
@@ -3906,7 +4037,7 @@ var writeUserIntegrationState = (params) => {
|
|
|
3906
4037
|
};
|
|
3907
4038
|
|
|
3908
4039
|
// src/features/integrations/components.ts
|
|
3909
|
-
import { existsSync as
|
|
4040
|
+
import { existsSync as existsSync12, rmSync as rmSync5 } from "fs";
|
|
3910
4041
|
import { join as join19 } from "path";
|
|
3911
4042
|
var readInstalledSkills2 = (basePath) => (readSkillRegistry(resolveSkillRegistryPath(basePath))?.skills ?? []).map((installedSkill) => ({
|
|
3912
4043
|
...installedSkill,
|
|
@@ -3921,7 +4052,7 @@ var resolveSkillById = (skillId) => {
|
|
|
3921
4052
|
};
|
|
3922
4053
|
var hasInstalledCodexSkill = (params) => {
|
|
3923
4054
|
const installedSkill = findInstalledSkill(readInstalledSkills2(params.basePath), params.skillId);
|
|
3924
|
-
return installedSkill?.tools.includes(SKILL_TOOL.CODEX) === true &&
|
|
4055
|
+
return installedSkill?.tools.includes(SKILL_TOOL.CODEX) === true && existsSync12(join19(params.basePath, ".agents/skills", params.skillId, "SKILL.md"));
|
|
3925
4056
|
};
|
|
3926
4057
|
var writeUserSkillState = (params) => {
|
|
3927
4058
|
const registryPath = resolveSkillRegistryPath(params.basePath);
|
|
@@ -3949,7 +4080,7 @@ var ensureSkillComponent = (params) => {
|
|
|
3949
4080
|
skill,
|
|
3950
4081
|
requestedTools
|
|
3951
4082
|
});
|
|
3952
|
-
const alreadyCurrent = existingInstalledSkill?.sourceHash === installedSkill.sourceHash && existingInstalledSkill.tools.includes(SKILL_TOOL.CODEX) &&
|
|
4083
|
+
const alreadyCurrent = existingInstalledSkill?.sourceHash === installedSkill.sourceHash && existingInstalledSkill.tools.includes(SKILL_TOOL.CODEX) && existsSync12(join19(params.basePath, ".agents/skills", params.skillId, "SKILL.md"));
|
|
3953
4084
|
if (alreadyCurrent) {
|
|
3954
4085
|
return {
|
|
3955
4086
|
type: INTEGRATION_COMPONENT_TYPE.SKILL,
|
|
@@ -4884,7 +5015,7 @@ var registerSkillCommands = (program) => {
|
|
|
4884
5015
|
import { join as join23 } from "path";
|
|
4885
5016
|
|
|
4886
5017
|
// src/features/studio/project-snapshot.ts
|
|
4887
|
-
import { existsSync as
|
|
5018
|
+
import { existsSync as existsSync13, readFileSync as readFileSync19 } from "fs";
|
|
4888
5019
|
import { resolve as resolve11 } from "path";
|
|
4889
5020
|
import { z as z14 } from "zod";
|
|
4890
5021
|
|
|
@@ -4951,7 +5082,9 @@ var AUDIT_ISSUE_SOURCES_BY_CODE = {
|
|
|
4951
5082
|
"invalid-frontmatter": "frontmatter",
|
|
4952
5083
|
"missing-managed-section": "managed-section",
|
|
4953
5084
|
"source-hash-drift": "source-hash",
|
|
4954
|
-
"managed-source-hash-drift": "source-hash"
|
|
5085
|
+
"managed-source-hash-drift": "source-hash",
|
|
5086
|
+
"invalid-custom-project-rule": "frontmatter",
|
|
5087
|
+
"custom-project-rules-drift": "manifest"
|
|
4955
5088
|
};
|
|
4956
5089
|
var AUDIT_ISSUE_ACTION_LABELS_BY_SOURCE = {
|
|
4957
5090
|
manifest: "Review manifest record",
|
|
@@ -4998,6 +5131,10 @@ var extractTrailingIssuePath = (message) => {
|
|
|
4998
5131
|
const [firstToken] = trailingSegment.trim().split(/\s+/);
|
|
4999
5132
|
return firstToken === void 0 ? null : parsePathLikeToken(firstToken);
|
|
5000
5133
|
};
|
|
5134
|
+
var extractLeadingIssuePath = (message) => {
|
|
5135
|
+
const [firstToken] = message.trim().split(/\s+/);
|
|
5136
|
+
return firstToken === void 0 ? null : parsePathLikeToken(firstToken);
|
|
5137
|
+
};
|
|
5001
5138
|
var resolveIssueSource = (issue2) => AUDIT_ISSUE_SOURCES_BY_CODE[issue2.code] ?? "unknown";
|
|
5002
5139
|
var resolveIssueAffectedPath = (params) => {
|
|
5003
5140
|
if (params.issue.code === "missing-manifest" || params.issue.code === "invalid-manifest") {
|
|
@@ -5012,6 +5149,9 @@ var resolveIssueAffectedPath = (params) => {
|
|
|
5012
5149
|
if (params.issue.code === "source-hash-drift") {
|
|
5013
5150
|
return null;
|
|
5014
5151
|
}
|
|
5152
|
+
if (params.issue.code === "invalid-custom-project-rule") {
|
|
5153
|
+
return extractLeadingIssuePath(params.issue.message);
|
|
5154
|
+
}
|
|
5015
5155
|
const knownPath = findKnownPathInMessage(params.issue.message, params.knownPaths);
|
|
5016
5156
|
if (knownPath !== null) {
|
|
5017
5157
|
return knownPath;
|
|
@@ -5051,7 +5191,7 @@ var RecoverableContextIndexSchema = z14.object({
|
|
|
5051
5191
|
});
|
|
5052
5192
|
var readProjectManifestSnapshot = (basePath) => {
|
|
5053
5193
|
const manifestPath = resolveProjectLayerManifestPath(basePath);
|
|
5054
|
-
if (!
|
|
5194
|
+
if (!existsSync13(manifestPath)) {
|
|
5055
5195
|
return {
|
|
5056
5196
|
source: createMissingSourceState(PROJECT_LAYER_MANIFEST_RELATIVE_PATH),
|
|
5057
5197
|
manifest: null
|
|
@@ -5082,14 +5222,14 @@ var readProjectManifestSnapshot = (basePath) => {
|
|
|
5082
5222
|
};
|
|
5083
5223
|
var readProjectContextIndexSnapshot = (basePath) => {
|
|
5084
5224
|
const contextIndexPath = resolveProjectLayerContextIndexPath(basePath);
|
|
5085
|
-
if (!
|
|
5225
|
+
if (!existsSync13(contextIndexPath)) {
|
|
5086
5226
|
return {
|
|
5087
5227
|
source: createMissingSourceState(PROJECT_LAYER_CONTEXT_INDEX_RELATIVE_PATH),
|
|
5088
5228
|
contextIndex: null
|
|
5089
5229
|
};
|
|
5090
5230
|
}
|
|
5091
5231
|
try {
|
|
5092
|
-
const parsedJson = JSON.parse(
|
|
5232
|
+
const parsedJson = JSON.parse(readFileSync19(contextIndexPath, "utf-8"));
|
|
5093
5233
|
const strictContextIndex = ProjectLayerContextIndexSchema.safeParse(parsedJson);
|
|
5094
5234
|
if (strictContextIndex.success) {
|
|
5095
5235
|
return {
|
|
@@ -5146,12 +5286,12 @@ var readProjectContextIndexSnapshot = (basePath) => {
|
|
|
5146
5286
|
}
|
|
5147
5287
|
};
|
|
5148
5288
|
var readDocsStatusSourceState = (basePath) => {
|
|
5149
|
-
const docsStatusPath =
|
|
5150
|
-
if (!
|
|
5289
|
+
const docsStatusPath = resolveProjectLayerFilePath(basePath, DOCS_STATUS_RELATIVE_PATH);
|
|
5290
|
+
if (!existsSync13(docsStatusPath)) {
|
|
5151
5291
|
return createMissingSourceState(DOCS_STATUS_RELATIVE_PATH);
|
|
5152
5292
|
}
|
|
5153
5293
|
try {
|
|
5154
|
-
parseProjectLayerDocument(DOCS_STATUS_RELATIVE_PATH,
|
|
5294
|
+
parseProjectLayerDocument(DOCS_STATUS_RELATIVE_PATH, readFileSync19(docsStatusPath, "utf-8"));
|
|
5155
5295
|
return buildSourceState({
|
|
5156
5296
|
path: DOCS_STATUS_RELATIVE_PATH,
|
|
5157
5297
|
exists: true,
|
|
@@ -5182,7 +5322,7 @@ var buildDocumentReadError = (code, message) => `${code}: ${message}`;
|
|
|
5182
5322
|
var buildProjectDocumentSnapshot = (params) => {
|
|
5183
5323
|
let absolutePath;
|
|
5184
5324
|
try {
|
|
5185
|
-
absolutePath =
|
|
5325
|
+
absolutePath = resolveProjectLayerFilePath(params.basePath, params.indexed.path);
|
|
5186
5326
|
} catch (error) {
|
|
5187
5327
|
return {
|
|
5188
5328
|
path: params.indexed.path,
|
|
@@ -5200,7 +5340,7 @@ var buildProjectDocumentSnapshot = (params) => {
|
|
|
5200
5340
|
readError: buildDocumentReadError("unsafe-path", getErrorMessage(error))
|
|
5201
5341
|
};
|
|
5202
5342
|
}
|
|
5203
|
-
if (!
|
|
5343
|
+
if (!existsSync13(absolutePath)) {
|
|
5204
5344
|
return {
|
|
5205
5345
|
path: params.indexed.path,
|
|
5206
5346
|
status: params.indexed.status,
|
|
@@ -5218,7 +5358,7 @@ var buildProjectDocumentSnapshot = (params) => {
|
|
|
5218
5358
|
};
|
|
5219
5359
|
}
|
|
5220
5360
|
try {
|
|
5221
|
-
const document = parseProjectLayerDocument(params.indexed.path,
|
|
5361
|
+
const document = parseProjectLayerDocument(params.indexed.path, readFileSync19(absolutePath, "utf-8"));
|
|
5222
5362
|
return {
|
|
5223
5363
|
path: params.indexed.path,
|
|
5224
5364
|
status: params.indexed.status,
|
|
@@ -5309,11 +5449,11 @@ var buildProjectSnapshot = (basePath) => {
|
|
|
5309
5449
|
};
|
|
5310
5450
|
|
|
5311
5451
|
// src/features/studio/runtime-snapshot.ts
|
|
5312
|
-
import { existsSync as
|
|
5452
|
+
import { existsSync as existsSync14, readFileSync as readFileSync21 } from "fs";
|
|
5313
5453
|
import { join as join22 } from "path";
|
|
5314
5454
|
|
|
5315
5455
|
// src/features/subagents/manifest-io.ts
|
|
5316
|
-
import { mkdirSync as mkdirSync10, readFileSync as
|
|
5456
|
+
import { mkdirSync as mkdirSync10, readFileSync as readFileSync20, writeFileSync as writeFileSync12 } from "fs";
|
|
5317
5457
|
import { dirname as dirname13, join as join21 } from "path";
|
|
5318
5458
|
var SUBAGENT_MANIFEST_FILENAME = "subagents-manifest.json";
|
|
5319
5459
|
var parseSubagentManifest = (json) => SubagentManifestSchema.parse(JSON.parse(json));
|
|
@@ -5322,7 +5462,7 @@ var resolveSubagentManifestPath = (userBasePath) => join21(userBasePath, ".ai-op
|
|
|
5322
5462
|
var readSubagentManifest = (manifestPath) => {
|
|
5323
5463
|
let raw;
|
|
5324
5464
|
try {
|
|
5325
|
-
raw =
|
|
5465
|
+
raw = readFileSync20(manifestPath, "utf-8");
|
|
5326
5466
|
} catch {
|
|
5327
5467
|
return null;
|
|
5328
5468
|
}
|
|
@@ -5352,7 +5492,7 @@ var readRuntimeManifest = (params) => {
|
|
|
5352
5492
|
value: null
|
|
5353
5493
|
};
|
|
5354
5494
|
}
|
|
5355
|
-
if (!
|
|
5495
|
+
if (!existsSync14(params.manifestPath)) {
|
|
5356
5496
|
return {
|
|
5357
5497
|
source: createMissingSourceState(params.manifestPath),
|
|
5358
5498
|
value: null
|
|
@@ -5390,11 +5530,11 @@ var readHooksSourceState = (codexHomePath, unavailableReason) => {
|
|
|
5390
5530
|
});
|
|
5391
5531
|
}
|
|
5392
5532
|
const hooksPath = resolveCodexHooksPath(codexHomePath);
|
|
5393
|
-
if (!
|
|
5533
|
+
if (!existsSync14(hooksPath)) {
|
|
5394
5534
|
return createMissingSourceState(hooksPath);
|
|
5395
5535
|
}
|
|
5396
5536
|
try {
|
|
5397
|
-
const parsed = JSON.parse(
|
|
5537
|
+
const parsed = JSON.parse(readFileSync21(hooksPath, "utf-8"));
|
|
5398
5538
|
if (!isJsonRecord4(parsed)) {
|
|
5399
5539
|
return buildSourceState({
|
|
5400
5540
|
path: hooksPath,
|
|
@@ -5455,7 +5595,7 @@ var buildInstalledPathStates = (params) => {
|
|
|
5455
5595
|
}
|
|
5456
5596
|
return params.installedPaths.map((path) => ({
|
|
5457
5597
|
path,
|
|
5458
|
-
exists:
|
|
5598
|
+
exists: existsSync14(join22(params.userBasePath ?? "", path))
|
|
5459
5599
|
}));
|
|
5460
5600
|
};
|
|
5461
5601
|
var buildInstalledSkillMap = (installedSkills) => new Map(
|
|
@@ -5659,7 +5799,7 @@ var registerStudioCommands = (program) => {
|
|
|
5659
5799
|
|
|
5660
5800
|
// src/features/subagents/commands.ts
|
|
5661
5801
|
import * as p14 from "@clack/prompts";
|
|
5662
|
-
import { existsSync as
|
|
5802
|
+
import { existsSync as existsSync16, rmSync as rmSync8 } from "fs";
|
|
5663
5803
|
|
|
5664
5804
|
// src/features/subagents/renderer.ts
|
|
5665
5805
|
import { resolve as resolve12 } from "path";
|
|
@@ -5782,7 +5922,7 @@ var buildSubagentInstallPlan = (params) => {
|
|
|
5782
5922
|
};
|
|
5783
5923
|
|
|
5784
5924
|
// src/features/subagents/install-files.ts
|
|
5785
|
-
import { existsSync as
|
|
5925
|
+
import { existsSync as existsSync15, mkdirSync as mkdirSync11, rmSync as rmSync7, writeFileSync as writeFileSync13 } from "fs";
|
|
5786
5926
|
import { dirname as dirname14, isAbsolute as isAbsolute3, relative as relative3, resolve as resolve13 } from "path";
|
|
5787
5927
|
var resolveInsideBasePath = (basePath, relativePath) => {
|
|
5788
5928
|
const absBasePath = resolve13(basePath);
|
|
@@ -5798,7 +5938,7 @@ var installSubagentPackages = (basePath, packages) => {
|
|
|
5798
5938
|
for (const subagentPackage of packages) {
|
|
5799
5939
|
for (const file of subagentPackage.files) {
|
|
5800
5940
|
const absPath = resolveInsideBasePath(basePath, file.relativePath);
|
|
5801
|
-
if (
|
|
5941
|
+
if (existsSync15(absPath)) {
|
|
5802
5942
|
rmSync7(absPath, { recursive: true, force: true });
|
|
5803
5943
|
}
|
|
5804
5944
|
mkdirSync11(dirname14(absPath), { recursive: true });
|
|
@@ -5812,7 +5952,7 @@ var removeSubagentFiles = (basePath, relativePaths) => {
|
|
|
5812
5952
|
const removed = [];
|
|
5813
5953
|
for (const relativePath of relativePaths) {
|
|
5814
5954
|
const absPath = resolveInsideBasePath(basePath, relativePath);
|
|
5815
|
-
if (!
|
|
5955
|
+
if (!existsSync15(absPath)) continue;
|
|
5816
5956
|
rmSync7(absPath, { recursive: true, force: true });
|
|
5817
5957
|
removed.push(relativePath);
|
|
5818
5958
|
}
|
|
@@ -5874,7 +6014,7 @@ var writeUserSubagentState = (params) => {
|
|
|
5874
6014
|
};
|
|
5875
6015
|
var readInstalledSubagents = (basePath) => readSubagentManifest(resolveSubagentManifestPath(basePath))?.subagents ?? [];
|
|
5876
6016
|
var warnMissingSkills = (requiredSkills) => {
|
|
5877
|
-
const missing = requiredSkills.filter((skill) => !
|
|
6017
|
+
const missing = requiredSkills.filter((skill) => !existsSync16(skill.path));
|
|
5878
6018
|
if (missing.length === 0) {
|
|
5879
6019
|
return;
|
|
5880
6020
|
}
|