ai-ops-cli 1.4.1 → 1.5.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/dist/bin/index.js
CHANGED
|
@@ -1409,12 +1409,12 @@ var buildPermissionProfileBlock = (paths, includeDefaultPermissions) => [
|
|
|
1409
1409
|
`${quoteTomlString(paths.personalContextRoot)} = "write"`,
|
|
1410
1410
|
`${quoteTomlString(join10(paths.userBasePath, ".ai-ops", "context-promotion"))} = "write"`,
|
|
1411
1411
|
"",
|
|
1412
|
-
`[permissions.${SAFE_LOCAL_CODEX_PERMISSION_NAME}.filesystem.":
|
|
1412
|
+
`[permissions.${SAFE_LOCAL_CODEX_PERMISSION_NAME}.filesystem.":project_roots"]`,
|
|
1413
1413
|
'"." = "write"',
|
|
1414
1414
|
'".git" = "read"',
|
|
1415
1415
|
'".codex" = "read"',
|
|
1416
1416
|
'".codex/plans" = "write"',
|
|
1417
|
-
'"**/*.env" = "
|
|
1417
|
+
'"**/*.env" = "none"',
|
|
1418
1418
|
"",
|
|
1419
1419
|
`[permissions.${SAFE_LOCAL_CODEX_PERMISSION_NAME}.network]`,
|
|
1420
1420
|
"enabled = false",
|
|
@@ -2082,13 +2082,14 @@ var pruneContextPromotionReceipts = (params) => {
|
|
|
2082
2082
|
};
|
|
2083
2083
|
|
|
2084
2084
|
// src/features/context-promotion/status.ts
|
|
2085
|
-
import { existsSync as
|
|
2085
|
+
import { existsSync as existsSync10 } from "fs";
|
|
2086
2086
|
import { join as join16, resolve as resolve8 } from "path";
|
|
2087
2087
|
|
|
2088
2088
|
// src/features/project-layer/constants.ts
|
|
2089
2089
|
import { join as join13 } from "path";
|
|
2090
2090
|
var PROJECT_LAYER_MANIFEST_RELATIVE_PATH = ".ai-ops/manifest.json";
|
|
2091
2091
|
var PROJECT_LAYER_CONTEXT_INDEX_RELATIVE_PATH = ".ai-ops/context-layer.json";
|
|
2092
|
+
var CUSTOM_PROJECT_RULES_DIR = "docs/agent/project-rules";
|
|
2092
2093
|
var CONTEXT_LAYER_DATA_DIR = join13(COMPILER_DATA_DIR, "context-layer");
|
|
2093
2094
|
var TOOL_ORDER2 = ["codex", "gemini", "claude-code"];
|
|
2094
2095
|
var DEFAULT_TOOLS = TOOL_ORDER2;
|
|
@@ -2125,7 +2126,7 @@ var resolveProjectLayerManifestPath = (basePath) => join14(basePath, PROJECT_LAY
|
|
|
2125
2126
|
var resolveProjectLayerContextIndexPath = (basePath) => join14(basePath, PROJECT_LAYER_CONTEXT_INDEX_RELATIVE_PATH);
|
|
2126
2127
|
var resolveTemplatePath = (relativePath) => join14(CONTEXT_LAYER_DATA_DIR, relativePath);
|
|
2127
2128
|
var toRelativeDir = (relativePath) => dirname8(relativePath);
|
|
2128
|
-
var
|
|
2129
|
+
var resolveProjectLayerFilePath = (basePath, relativePath) => {
|
|
2129
2130
|
if (!isSafeProjectLayerPath(relativePath)) {
|
|
2130
2131
|
throw new Error(`Unsafe project layer path: ${relativePath}`);
|
|
2131
2132
|
}
|
|
@@ -2258,18 +2259,86 @@ var loadProjectLayerTemplateSpecs = (tools) => {
|
|
|
2258
2259
|
};
|
|
2259
2260
|
var computeProjectLayerSourceHash = (specs) => computeHash(specs.map((spec) => `${spec.path}:${spec.content}`));
|
|
2260
2261
|
|
|
2262
|
+
// src/features/project-layer/custom-project-rules.ts
|
|
2263
|
+
import { existsSync as existsSync5, readdirSync as readdirSync3, readFileSync as readFileSync9 } from "fs";
|
|
2264
|
+
var isMarkdownPath = (path) => path.endsWith(".md");
|
|
2265
|
+
var hasMarkdownFrontmatter = (content) => content.startsWith("---\n");
|
|
2266
|
+
var assertCustomProjectRuleContract = (params) => {
|
|
2267
|
+
if (params.owner !== "project") {
|
|
2268
|
+
throw new Error(`${params.path} owner\uB294 project\uC5EC\uC57C \uD569\uB2C8\uB2E4. \uD604\uC7AC \uAC12: ${params.owner}`);
|
|
2269
|
+
}
|
|
2270
|
+
if (params.layer !== "agent") {
|
|
2271
|
+
throw new Error(`${params.path} layer\uB294 agent\uC5EC\uC57C \uD569\uB2C8\uB2E4. \uD604\uC7AC \uAC12: ${params.layer}`);
|
|
2272
|
+
}
|
|
2273
|
+
};
|
|
2274
|
+
var isCustomProjectRulePath = (path) => path.startsWith(`${CUSTOM_PROJECT_RULES_DIR}/`) && isMarkdownPath(path);
|
|
2275
|
+
var collectMarkdownPaths = (params) => {
|
|
2276
|
+
const absoluteDir = resolveProjectLayerFilePath(params.basePath, params.relativeDir);
|
|
2277
|
+
if (!existsSync5(absoluteDir)) {
|
|
2278
|
+
return [];
|
|
2279
|
+
}
|
|
2280
|
+
return readdirSync3(absoluteDir, { withFileTypes: true }).flatMap((entry) => {
|
|
2281
|
+
const relativePath = `${params.relativeDir}/${entry.name}`;
|
|
2282
|
+
if (entry.isDirectory()) {
|
|
2283
|
+
return collectMarkdownPaths({ basePath: params.basePath, relativeDir: relativePath });
|
|
2284
|
+
}
|
|
2285
|
+
return entry.isFile() && isMarkdownPath(relativePath) ? [relativePath] : [];
|
|
2286
|
+
});
|
|
2287
|
+
};
|
|
2288
|
+
var discoverCustomProjectRuleFiles = (basePath) => collectMarkdownPaths({ basePath, relativeDir: CUSTOM_PROJECT_RULES_DIR }).sort((left, right) => left.localeCompare(right)).flatMap((path) => {
|
|
2289
|
+
const content = readFileSync9(resolveProjectLayerFilePath(basePath, path), "utf-8");
|
|
2290
|
+
if (!hasMarkdownFrontmatter(content)) {
|
|
2291
|
+
return [];
|
|
2292
|
+
}
|
|
2293
|
+
try {
|
|
2294
|
+
const document = parseProjectLayerDocument(path, content);
|
|
2295
|
+
assertCustomProjectRuleContract({
|
|
2296
|
+
path,
|
|
2297
|
+
owner: document.owner,
|
|
2298
|
+
layer: document.layer
|
|
2299
|
+
});
|
|
2300
|
+
return [
|
|
2301
|
+
{
|
|
2302
|
+
path,
|
|
2303
|
+
templateHash: document.contentHash,
|
|
2304
|
+
created: false
|
|
2305
|
+
}
|
|
2306
|
+
];
|
|
2307
|
+
} catch (error) {
|
|
2308
|
+
const reason = error instanceof Error ? error.message : "unknown error";
|
|
2309
|
+
throw new Error(`${path} frontmatter \uD30C\uC2F1 \uC2E4\uD328: ${reason}`);
|
|
2310
|
+
}
|
|
2311
|
+
});
|
|
2312
|
+
var syncCustomProjectRuleFiles = (params) => {
|
|
2313
|
+
const customFiles = discoverCustomProjectRuleFiles(params.basePath);
|
|
2314
|
+
const customPathSet = new Set(customFiles.map((file) => file.path));
|
|
2315
|
+
const projectFilesByPath = /* @__PURE__ */ new Map();
|
|
2316
|
+
for (const file of params.manifest.project_files) {
|
|
2317
|
+
if (!isCustomProjectRulePath(file.path) || customPathSet.has(file.path)) {
|
|
2318
|
+
projectFilesByPath.set(file.path, file);
|
|
2319
|
+
}
|
|
2320
|
+
}
|
|
2321
|
+
for (const file of customFiles) {
|
|
2322
|
+
projectFilesByPath.set(file.path, file);
|
|
2323
|
+
}
|
|
2324
|
+
return ProjectLayerManifestSchema.parse({
|
|
2325
|
+
...params.manifest,
|
|
2326
|
+
project_files: [...projectFilesByPath.values()].sort((left, right) => left.path.localeCompare(right.path))
|
|
2327
|
+
});
|
|
2328
|
+
};
|
|
2329
|
+
|
|
2261
2330
|
// src/features/project-layer/state-io.ts
|
|
2262
|
-
import { mkdirSync as mkdirSync6, readFileSync as
|
|
2331
|
+
import { mkdirSync as mkdirSync6, readFileSync as readFileSync11, writeFileSync as writeFileSync7 } from "fs";
|
|
2263
2332
|
import { dirname as dirname9 } from "path";
|
|
2264
2333
|
|
|
2265
2334
|
// src/features/project-layer/docs-status.logic.ts
|
|
2266
|
-
import { readFileSync as
|
|
2335
|
+
import { readFileSync as readFileSync10, writeFileSync as writeFileSync6 } from "fs";
|
|
2267
2336
|
var docsStatusIssue = (code, message) => ({
|
|
2268
2337
|
level: "error",
|
|
2269
2338
|
code,
|
|
2270
2339
|
message
|
|
2271
2340
|
});
|
|
2272
|
-
var computeDocsStatusFileHash = (basePath, relativePath) => computeHash([
|
|
2341
|
+
var computeDocsStatusFileHash = (basePath, relativePath) => computeHash([readFileSync10(resolveProjectLayerFilePath(basePath, relativePath), "utf-8").trimEnd()]);
|
|
2273
2342
|
var parseMarkdownTableCells = (line) => {
|
|
2274
2343
|
const trimmed = line.trim();
|
|
2275
2344
|
if (!trimmed.startsWith("|") || !trimmed.endsWith("|")) {
|
|
@@ -2319,7 +2388,7 @@ var parseDocsStatusEntries = (content) => {
|
|
|
2319
2388
|
});
|
|
2320
2389
|
};
|
|
2321
2390
|
var buildDocsStatusRowsFromDisk = (params) => params.documentPaths.map((path) => {
|
|
2322
|
-
const document = parseProjectLayerDocument(path,
|
|
2391
|
+
const document = parseProjectLayerDocument(path, readFileSync10(resolveProjectLayerFilePath(params.basePath, path), "utf-8"));
|
|
2323
2392
|
return `| ${document.path} | ${document.status} | ${document.owner} |`;
|
|
2324
2393
|
});
|
|
2325
2394
|
var replaceDocsStatusRows = (content, rows) => {
|
|
@@ -2332,10 +2401,10 @@ var replaceDocsStatusRows = (content, rows) => {
|
|
|
2332
2401
|
};
|
|
2333
2402
|
var updateDocsStatusTable = (basePath, documentPaths) => {
|
|
2334
2403
|
const docsStatusPath = "docs/docs-status.md";
|
|
2335
|
-
const absolutePath =
|
|
2404
|
+
const absolutePath = resolveProjectLayerFilePath(basePath, docsStatusPath);
|
|
2336
2405
|
const beforeHash = computeDocsStatusFileHash(basePath, docsStatusPath);
|
|
2337
2406
|
const rows = buildDocsStatusRowsFromDisk({ basePath, documentPaths });
|
|
2338
|
-
const nextContent = replaceDocsStatusRows(
|
|
2407
|
+
const nextContent = replaceDocsStatusRows(readFileSync10(absolutePath, "utf-8"), rows);
|
|
2339
2408
|
writeFileSync6(absolutePath, nextContent, "utf-8");
|
|
2340
2409
|
return {
|
|
2341
2410
|
beforeHash,
|
|
@@ -2372,7 +2441,7 @@ var compareDocsStatusEntry = (params) => {
|
|
|
2372
2441
|
// src/features/project-layer/state-io.ts
|
|
2373
2442
|
var readProjectLayerManifest = (basePath) => {
|
|
2374
2443
|
try {
|
|
2375
|
-
return parseProjectLayerManifest(
|
|
2444
|
+
return parseProjectLayerManifest(readFileSync11(resolveProjectLayerManifestPath(basePath), "utf-8"));
|
|
2376
2445
|
} catch (error) {
|
|
2377
2446
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
2378
2447
|
return null;
|
|
@@ -2387,7 +2456,7 @@ var writeProjectLayerManifest = (basePath, manifest) => {
|
|
|
2387
2456
|
};
|
|
2388
2457
|
var readProjectLayerContextIndex = (basePath) => {
|
|
2389
2458
|
try {
|
|
2390
|
-
return parseProjectLayerContextIndex(
|
|
2459
|
+
return parseProjectLayerContextIndex(readFileSync11(resolveProjectLayerContextIndexPath(basePath), "utf-8"));
|
|
2391
2460
|
} catch (error) {
|
|
2392
2461
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
2393
2462
|
return null;
|
|
@@ -2402,7 +2471,7 @@ var writeProjectLayerContextIndex = (basePath, contextIndex) => {
|
|
|
2402
2471
|
};
|
|
2403
2472
|
var buildContextIndexFromDisk = (params) => {
|
|
2404
2473
|
const documents = params.documentPaths.map(
|
|
2405
|
-
(path) => parseProjectLayerDocument(path,
|
|
2474
|
+
(path) => parseProjectLayerDocument(path, readFileSync11(resolveProjectLayerFilePath(params.basePath, path), "utf-8"))
|
|
2406
2475
|
);
|
|
2407
2476
|
return ProjectLayerContextIndexSchema.parse({
|
|
2408
2477
|
schemaVersion: 1,
|
|
@@ -2417,10 +2486,14 @@ var collectDocumentPathsFromManifest = (manifest) => [
|
|
|
2417
2486
|
...manifest.packs.flatMap((pack) => pack.documents.map((file) => file.path))
|
|
2418
2487
|
].sort();
|
|
2419
2488
|
var refreshProjectLayerDerivedState = (params) => {
|
|
2420
|
-
const
|
|
2489
|
+
const manifestWithCustomRules = syncCustomProjectRuleFiles({
|
|
2490
|
+
basePath: params.basePath,
|
|
2491
|
+
manifest: params.manifest
|
|
2492
|
+
});
|
|
2493
|
+
const documentPaths = collectDocumentPathsFromManifest(manifestWithCustomRules);
|
|
2421
2494
|
const docsStatusHashes = updateDocsStatusTable(params.basePath, documentPaths);
|
|
2422
2495
|
const manifest = updateDocsStatusProjectFileRecord({
|
|
2423
|
-
manifest:
|
|
2496
|
+
manifest: manifestWithCustomRules,
|
|
2424
2497
|
beforeHash: docsStatusHashes.beforeHash,
|
|
2425
2498
|
afterHash: docsStatusHashes.afterHash
|
|
2426
2499
|
});
|
|
@@ -2437,17 +2510,17 @@ var refreshProjectLayerDerivedState = (params) => {
|
|
|
2437
2510
|
};
|
|
2438
2511
|
|
|
2439
2512
|
// src/features/project-layer/lifecycle.logic.ts
|
|
2440
|
-
import { existsSync as
|
|
2513
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync7, readFileSync as readFileSync13, writeFileSync as writeFileSync9 } from "fs";
|
|
2441
2514
|
import { dirname as dirname10 } from "path";
|
|
2442
2515
|
|
|
2443
2516
|
// src/features/project-layer/uninstall.logic.ts
|
|
2444
|
-
import { existsSync as
|
|
2517
|
+
import { existsSync as existsSync6, readFileSync as readFileSync12, readdirSync as readdirSync4, rmSync as rmSync2, writeFileSync as writeFileSync8 } from "fs";
|
|
2445
2518
|
function removeManagedProjectFile(basePath, relativePath) {
|
|
2446
|
-
const absolutePath =
|
|
2447
|
-
if (!
|
|
2519
|
+
const absolutePath = resolveProjectLayerFilePath(basePath, relativePath);
|
|
2520
|
+
if (!existsSync6(absolutePath)) {
|
|
2448
2521
|
return { deleted: [], cleaned: [], preserved: [], notFound: [relativePath] };
|
|
2449
2522
|
}
|
|
2450
|
-
const content =
|
|
2523
|
+
const content = readFileSync12(absolutePath, "utf-8");
|
|
2451
2524
|
if (!hasAiOpsSection(content)) {
|
|
2452
2525
|
return { deleted: [], cleaned: [], preserved: [relativePath], notFound: [] };
|
|
2453
2526
|
}
|
|
@@ -2460,11 +2533,11 @@ function removeManagedProjectFile(basePath, relativePath) {
|
|
|
2460
2533
|
return { deleted: [], cleaned: [relativePath], preserved: [], notFound: [] };
|
|
2461
2534
|
}
|
|
2462
2535
|
var removeCreateOnlyProjectFile = (basePath, file) => {
|
|
2463
|
-
const absolutePath =
|
|
2464
|
-
if (!
|
|
2536
|
+
const absolutePath = resolveProjectLayerFilePath(basePath, file.path);
|
|
2537
|
+
if (!existsSync6(absolutePath)) {
|
|
2465
2538
|
return { deleted: [], cleaned: [], preserved: [], notFound: [file.path] };
|
|
2466
2539
|
}
|
|
2467
|
-
const content =
|
|
2540
|
+
const content = readFileSync12(absolutePath, "utf-8").trimEnd();
|
|
2468
2541
|
const currentHash = computeHash([content]);
|
|
2469
2542
|
if (file.created && currentHash === file.templateHash) {
|
|
2470
2543
|
rmSync2(absolutePath);
|
|
@@ -2473,11 +2546,11 @@ var removeCreateOnlyProjectFile = (basePath, file) => {
|
|
|
2473
2546
|
return { deleted: [], cleaned: [], preserved: [file.path], notFound: [] };
|
|
2474
2547
|
};
|
|
2475
2548
|
var removePackOwnedFile = (basePath, file) => {
|
|
2476
|
-
const absolutePath =
|
|
2477
|
-
if (!
|
|
2549
|
+
const absolutePath = resolveProjectLayerFilePath(basePath, file.path);
|
|
2550
|
+
if (!existsSync6(absolutePath)) {
|
|
2478
2551
|
return { deleted: [], cleaned: [], preserved: [], notFound: [file.path] };
|
|
2479
2552
|
}
|
|
2480
|
-
const currentHash = computeHash([
|
|
2553
|
+
const currentHash = computeHash([readFileSync12(absolutePath, "utf-8").trimEnd()]);
|
|
2481
2554
|
if (currentHash === file.sourceHash) {
|
|
2482
2555
|
rmSync2(absolutePath);
|
|
2483
2556
|
return { deleted: [file.path], cleaned: [], preserved: [], notFound: [] };
|
|
@@ -2495,10 +2568,10 @@ var removeEmptyDirs = (basePath, relativePaths) => {
|
|
|
2495
2568
|
(a, b) => b.length - a.length
|
|
2496
2569
|
);
|
|
2497
2570
|
for (const dir of [...dirs, ".ai-ops"]) {
|
|
2498
|
-
const absoluteDir =
|
|
2499
|
-
if (!
|
|
2571
|
+
const absoluteDir = resolveProjectLayerFilePath(basePath, dir);
|
|
2572
|
+
if (!existsSync6(absoluteDir)) continue;
|
|
2500
2573
|
try {
|
|
2501
|
-
if (
|
|
2574
|
+
if (readdirSync4(absoluteDir).length === 0) {
|
|
2502
2575
|
rmSync2(absoluteDir, { recursive: true });
|
|
2503
2576
|
}
|
|
2504
2577
|
} catch {
|
|
@@ -2513,7 +2586,7 @@ var uninstallProjectLayer = (basePath, manifest) => {
|
|
|
2513
2586
|
);
|
|
2514
2587
|
const stateFiles = [PROJECT_LAYER_CONTEXT_INDEX_RELATIVE_PATH, PROJECT_LAYER_MANIFEST_RELATIVE_PATH];
|
|
2515
2588
|
for (const stateFile of stateFiles) {
|
|
2516
|
-
rmSync2(
|
|
2589
|
+
rmSync2(resolveProjectLayerFilePath(basePath, stateFile), { force: true });
|
|
2517
2590
|
}
|
|
2518
2591
|
const result = mergeRemoveResults([...managedResults, ...projectResults, ...packResults]);
|
|
2519
2592
|
removeEmptyDirs(basePath, [...result.deleted, ...stateFiles]);
|
|
@@ -2525,15 +2598,15 @@ var installManagedFiles = (basePath, specs, meta) => {
|
|
|
2525
2598
|
const written = [];
|
|
2526
2599
|
const appended = [];
|
|
2527
2600
|
for (const spec of specs) {
|
|
2528
|
-
const absolutePath =
|
|
2601
|
+
const absolutePath = resolveProjectLayerFilePath(basePath, spec.path);
|
|
2529
2602
|
const wrappedContent = wrapWithSection(spec.content, meta);
|
|
2530
|
-
if (!
|
|
2603
|
+
if (!existsSync7(absolutePath)) {
|
|
2531
2604
|
mkdirSync7(dirname10(absolutePath), { recursive: true });
|
|
2532
2605
|
writeFileSync9(absolutePath, wrappedContent + "\n", "utf-8");
|
|
2533
2606
|
written.push(spec.path);
|
|
2534
2607
|
continue;
|
|
2535
2608
|
}
|
|
2536
|
-
const existing =
|
|
2609
|
+
const existing = readFileSync13(absolutePath, "utf-8");
|
|
2537
2610
|
if (hasAiOpsSection(existing)) {
|
|
2538
2611
|
writeFileSync9(absolutePath, replaceAiOpsSection(existing, wrappedContent), "utf-8");
|
|
2539
2612
|
const stripped = stripAiOpsSection(existing);
|
|
@@ -2557,9 +2630,9 @@ var installProjectFiles = (params) => {
|
|
|
2557
2630
|
const preserved = [];
|
|
2558
2631
|
const previousByPath = new Map((params.previousProjectFiles ?? []).map((file) => [file.path, file]));
|
|
2559
2632
|
for (const spec of params.specs) {
|
|
2560
|
-
const absolutePath =
|
|
2633
|
+
const absolutePath = resolveProjectLayerFilePath(params.basePath, spec.path);
|
|
2561
2634
|
const previous = previousByPath.get(spec.path);
|
|
2562
|
-
if (!
|
|
2635
|
+
if (!existsSync7(absolutePath)) {
|
|
2563
2636
|
mkdirSync7(dirname10(absolutePath), { recursive: true });
|
|
2564
2637
|
writeFileSync9(absolutePath, spec.content + "\n", "utf-8");
|
|
2565
2638
|
created.push(spec.path);
|
|
@@ -2570,7 +2643,7 @@ var installProjectFiles = (params) => {
|
|
|
2570
2643
|
});
|
|
2571
2644
|
continue;
|
|
2572
2645
|
}
|
|
2573
|
-
const existingContent =
|
|
2646
|
+
const existingContent = readFileSync13(absolutePath, "utf-8").trimEnd();
|
|
2574
2647
|
const existingHash = computeHash([existingContent]);
|
|
2575
2648
|
if (previous?.created === true && existingHash === previous.templateHash) {
|
|
2576
2649
|
if (existingHash !== spec.contentHash) {
|
|
@@ -2704,7 +2777,7 @@ var updateProjectLayer = (params) => {
|
|
|
2704
2777
|
};
|
|
2705
2778
|
|
|
2706
2779
|
// src/features/project-layer/audit.logic.ts
|
|
2707
|
-
import { existsSync as
|
|
2780
|
+
import { existsSync as existsSync8, readFileSync as readFileSync14 } from "fs";
|
|
2708
2781
|
var issue = (level, code, message) => ({
|
|
2709
2782
|
level,
|
|
2710
2783
|
code,
|
|
@@ -2712,11 +2785,11 @@ var issue = (level, code, message) => ({
|
|
|
2712
2785
|
});
|
|
2713
2786
|
var readDocumentSafely = (basePath, path) => {
|
|
2714
2787
|
try {
|
|
2715
|
-
const absolutePath =
|
|
2716
|
-
if (!
|
|
2788
|
+
const absolutePath = resolveProjectLayerFilePath(basePath, path);
|
|
2789
|
+
if (!existsSync8(absolutePath)) {
|
|
2717
2790
|
return issue("error", "missing-file", `\uD30C\uC77C \uC5C6\uC74C: ${path}`);
|
|
2718
2791
|
}
|
|
2719
|
-
return parseProjectLayerDocument(path,
|
|
2792
|
+
return parseProjectLayerDocument(path, readFileSync14(absolutePath, "utf-8"));
|
|
2720
2793
|
} catch (error) {
|
|
2721
2794
|
const reason = error instanceof Error ? error.message : "unknown error";
|
|
2722
2795
|
return issue("error", "invalid-frontmatter", `${path} frontmatter \uD30C\uC2F1 \uC2E4\uD328: ${reason}`);
|
|
@@ -2724,6 +2797,10 @@ var readDocumentSafely = (basePath, path) => {
|
|
|
2724
2797
|
};
|
|
2725
2798
|
var buildContextIndexMap = (contextIndex) => new Map((contextIndex?.documents ?? []).map((document) => [document.path, document]));
|
|
2726
2799
|
var compareArray = (left, right) => left.length === right.length && left.every((value, index) => value === right[index]);
|
|
2800
|
+
var compareProjectFileRecords = (left, right) => left.length === right.length && left.every((file, index) => {
|
|
2801
|
+
const other = right[index];
|
|
2802
|
+
return other !== void 0 && file.path === other.path && file.templateHash === other.templateHash && file.created === other.created;
|
|
2803
|
+
});
|
|
2727
2804
|
var compareContextDocument = (params) => {
|
|
2728
2805
|
const indexed = params.indexed;
|
|
2729
2806
|
if (indexed === void 0) {
|
|
@@ -2767,6 +2844,13 @@ var diffProjectLayer = (basePath) => {
|
|
|
2767
2844
|
const currentSourceHash = computeProjectLayerSourceHash(specs);
|
|
2768
2845
|
let contextIndex = null;
|
|
2769
2846
|
const issues = [];
|
|
2847
|
+
let syncedManifest = manifest;
|
|
2848
|
+
try {
|
|
2849
|
+
syncedManifest = syncCustomProjectRuleFiles({ basePath, manifest });
|
|
2850
|
+
} catch (error) {
|
|
2851
|
+
const reason = error instanceof Error ? error.message : "unknown error";
|
|
2852
|
+
issues.push(issue("error", "invalid-custom-project-rule", reason));
|
|
2853
|
+
}
|
|
2770
2854
|
try {
|
|
2771
2855
|
contextIndex = readProjectLayerContextIndex(basePath);
|
|
2772
2856
|
} catch (error) {
|
|
@@ -2786,18 +2870,27 @@ var diffProjectLayer = (basePath) => {
|
|
|
2786
2870
|
if (contextIndex === null) {
|
|
2787
2871
|
issues.push(issue("error", "missing-context-index", `${PROJECT_LAYER_CONTEXT_INDEX_RELATIVE_PATH}\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.`));
|
|
2788
2872
|
}
|
|
2873
|
+
if (!compareProjectFileRecords(manifest.project_files, syncedManifest.project_files)) {
|
|
2874
|
+
issues.push(
|
|
2875
|
+
issue(
|
|
2876
|
+
"warning",
|
|
2877
|
+
"custom-project-rules-drift",
|
|
2878
|
+
"`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."
|
|
2879
|
+
)
|
|
2880
|
+
);
|
|
2881
|
+
}
|
|
2789
2882
|
for (const expectedPath of expectedManagedPaths) {
|
|
2790
2883
|
if (!manifestManagedPaths.has(expectedPath)) {
|
|
2791
2884
|
issues.push(issue("error", "manifest-missing-managed-file", `manifest managed_files \uB204\uB77D: ${expectedPath}`));
|
|
2792
2885
|
}
|
|
2793
2886
|
}
|
|
2794
2887
|
for (const file of manifest.managed_files) {
|
|
2795
|
-
const absolutePath =
|
|
2796
|
-
if (!
|
|
2888
|
+
const absolutePath = resolveProjectLayerFilePath(basePath, file.path);
|
|
2889
|
+
if (!existsSync8(absolutePath)) {
|
|
2797
2890
|
issues.push(issue("error", "missing-file", `\uD30C\uC77C \uC5C6\uC74C: ${file.path}`));
|
|
2798
2891
|
continue;
|
|
2799
2892
|
}
|
|
2800
|
-
const content =
|
|
2893
|
+
const content = readFileSync14(absolutePath, "utf-8");
|
|
2801
2894
|
const meta = parseAiOpsMeta(content);
|
|
2802
2895
|
if (!meta) {
|
|
2803
2896
|
issues.push(issue("error", "missing-managed-section", `managed section \uBA54\uD0C0 \uC5C6\uC74C: ${file.path}`));
|
|
@@ -2809,19 +2902,19 @@ var diffProjectLayer = (basePath) => {
|
|
|
2809
2902
|
);
|
|
2810
2903
|
}
|
|
2811
2904
|
}
|
|
2812
|
-
for (const file of
|
|
2813
|
-
if (!
|
|
2905
|
+
for (const file of syncedManifest.project_files) {
|
|
2906
|
+
if (!existsSync8(resolveProjectLayerFilePath(basePath, file.path))) {
|
|
2814
2907
|
issues.push(issue("error", "missing-file", `\uD30C\uC77C \uC5C6\uC74C: ${file.path}`));
|
|
2815
2908
|
}
|
|
2816
2909
|
}
|
|
2817
|
-
for (const pack of
|
|
2910
|
+
for (const pack of syncedManifest.packs) {
|
|
2818
2911
|
for (const file of [...pack.documents, ...pack.files]) {
|
|
2819
|
-
if (!
|
|
2912
|
+
if (!existsSync8(resolveProjectLayerFilePath(basePath, file.path))) {
|
|
2820
2913
|
issues.push(issue("error", "missing-file", `\uD30C\uC77C \uC5C6\uC74C: ${file.path}`));
|
|
2821
2914
|
}
|
|
2822
2915
|
}
|
|
2823
2916
|
}
|
|
2824
|
-
for (const path of collectDocumentPathsFromManifest(
|
|
2917
|
+
for (const path of collectDocumentPathsFromManifest(syncedManifest)) {
|
|
2825
2918
|
const document = readDocumentSafely(basePath, path);
|
|
2826
2919
|
if ("code" in document) {
|
|
2827
2920
|
issues.push(document);
|
|
@@ -2848,18 +2941,24 @@ var auditProjectLayer = (basePath) => {
|
|
|
2848
2941
|
} catch {
|
|
2849
2942
|
contextIndex = null;
|
|
2850
2943
|
}
|
|
2851
|
-
|
|
2944
|
+
let syncedManifest = manifest;
|
|
2945
|
+
try {
|
|
2946
|
+
syncedManifest = syncCustomProjectRuleFiles({ basePath, manifest });
|
|
2947
|
+
} catch {
|
|
2948
|
+
return diffReport;
|
|
2949
|
+
}
|
|
2950
|
+
const documentPaths = collectDocumentPathsFromManifest(syncedManifest);
|
|
2852
2951
|
const documentPathSet = new Set(documentPaths);
|
|
2853
2952
|
const contextPathSet = new Set(contextIndex?.documents.map((document) => document.path) ?? []);
|
|
2854
2953
|
const issues = [...diffReport.issues];
|
|
2855
|
-
const docsStatusPath =
|
|
2856
|
-
if (!
|
|
2954
|
+
const docsStatusPath = resolveProjectLayerFilePath(basePath, "docs/docs-status.md");
|
|
2955
|
+
if (!existsSync8(docsStatusPath)) {
|
|
2857
2956
|
issues.push(issue("error", "missing-docs-status", "docs/docs-status.md\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4."));
|
|
2858
2957
|
return { currentSourceHash: diffReport.currentSourceHash, issues };
|
|
2859
2958
|
}
|
|
2860
2959
|
let docsStatusEntries = [];
|
|
2861
2960
|
try {
|
|
2862
|
-
docsStatusEntries = parseDocsStatusEntries(
|
|
2961
|
+
docsStatusEntries = parseDocsStatusEntries(readFileSync14(docsStatusPath, "utf-8"));
|
|
2863
2962
|
} catch (error) {
|
|
2864
2963
|
const reason = error instanceof Error ? error.message : "unknown error";
|
|
2865
2964
|
issues.push(issue("error", "invalid-docs-status", `docs/docs-status.md \uD30C\uC2F1 \uC2E4\uD328: ${reason}`));
|
|
@@ -2886,11 +2985,11 @@ var auditProjectLayer = (basePath) => {
|
|
|
2886
2985
|
};
|
|
2887
2986
|
|
|
2888
2987
|
// src/features/project-layer/pack.logic.ts
|
|
2889
|
-
import { existsSync as
|
|
2988
|
+
import { existsSync as existsSync9, mkdirSync as mkdirSync8, readFileSync as readFileSync16, readdirSync as readdirSync6, rmSync as rmSync3, writeFileSync as writeFileSync10 } from "fs";
|
|
2890
2989
|
import { dirname as dirname11 } from "path";
|
|
2891
2990
|
|
|
2892
2991
|
// src/features/project-layer/pack-source.logic.ts
|
|
2893
|
-
import { readFileSync as
|
|
2992
|
+
import { readFileSync as readFileSync15, readdirSync as readdirSync5 } from "fs";
|
|
2894
2993
|
import { isAbsolute as isAbsolute2, join as join15, relative as relative2, resolve as resolve7 } from "path";
|
|
2895
2994
|
var PACK_REGISTRY_FILENAME = "pack-registry.json";
|
|
2896
2995
|
var SPEC_LIFECYCLE_PACK_ID = "spec-lifecycle";
|
|
@@ -2901,7 +3000,7 @@ var RESERVED_DOCUMENT_WARNINGS2 = [
|
|
|
2901
3000
|
];
|
|
2902
3001
|
var DEFAULT_PACKS_DIR = join15(COMPILER_DATA_DIR, "packs");
|
|
2903
3002
|
var includesReservedDocumentWarning2 = (content) => RESERVED_DOCUMENT_WARNINGS2.some((warning) => content.includes(warning));
|
|
2904
|
-
var readPackCatalog = (packsDir) => PackCatalogSchema.parse(JSON.parse(
|
|
3003
|
+
var readPackCatalog = (packsDir) => PackCatalogSchema.parse(JSON.parse(readFileSync15(join15(packsDir, PACK_REGISTRY_FILENAME), "utf-8")));
|
|
2905
3004
|
var assertPackInstallPath = (path) => {
|
|
2906
3005
|
if (!isSafeProjectLayerPath(path) || !path.startsWith(PACK_INSTALL_ROOT)) {
|
|
2907
3006
|
throw new Error(`Unsafe pack path: ${path}`);
|
|
@@ -2911,7 +3010,7 @@ var readPackSourceFiles = (packDir) => {
|
|
|
2911
3010
|
const files = [];
|
|
2912
3011
|
const walk = (relativeDir = "") => {
|
|
2913
3012
|
const absoluteDir = relativeDir.length > 0 ? join15(packDir, relativeDir) : packDir;
|
|
2914
|
-
const entries =
|
|
3013
|
+
const entries = readdirSync5(absoluteDir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
|
|
2915
3014
|
for (const entry of entries) {
|
|
2916
3015
|
const nextRelativePath = relativeDir.length > 0 ? join15(relativeDir, entry.name) : entry.name;
|
|
2917
3016
|
if (entry.isDirectory()) {
|
|
@@ -2919,7 +3018,7 @@ var readPackSourceFiles = (packDir) => {
|
|
|
2919
3018
|
continue;
|
|
2920
3019
|
}
|
|
2921
3020
|
assertPackInstallPath(nextRelativePath);
|
|
2922
|
-
const content =
|
|
3021
|
+
const content = readFileSync15(join15(packDir, nextRelativePath), "utf-8");
|
|
2923
3022
|
files.push({
|
|
2924
3023
|
path: nextRelativePath,
|
|
2925
3024
|
content,
|
|
@@ -2979,9 +3078,9 @@ var resolvePackById = (packsDir, packId) => {
|
|
|
2979
3078
|
|
|
2980
3079
|
// src/features/project-layer/pack.logic.ts
|
|
2981
3080
|
var serializePackFileContent = (content) => content.length === 0 ? "" : content.trimEnd() + "\n";
|
|
2982
|
-
var readProjectFileHash = (basePath, relativePath) => computeHash([
|
|
3081
|
+
var readProjectFileHash = (basePath, relativePath) => computeHash([readFileSync16(resolveProjectLayerFilePath(basePath, relativePath), "utf-8").trimEnd()]);
|
|
2983
3082
|
var writePackFile = (basePath, file) => {
|
|
2984
|
-
const absolutePath =
|
|
3083
|
+
const absolutePath = resolveProjectLayerFilePath(basePath, file.path);
|
|
2985
3084
|
mkdirSync8(dirname11(absolutePath), { recursive: true });
|
|
2986
3085
|
writeFileSync10(absolutePath, serializePackFileContent(file.content), "utf-8");
|
|
2987
3086
|
};
|
|
@@ -3011,9 +3110,9 @@ var applyPackSourceFiles = (params) => {
|
|
|
3011
3110
|
])
|
|
3012
3111
|
);
|
|
3013
3112
|
for (const file of sourceFiles) {
|
|
3014
|
-
const absolutePath =
|
|
3113
|
+
const absolutePath = resolveProjectLayerFilePath(params.basePath, file.path);
|
|
3015
3114
|
const previous = previousByPath.get(file.path);
|
|
3016
|
-
if (!
|
|
3115
|
+
if (!existsSync9(absolutePath)) {
|
|
3017
3116
|
writePackFile(params.basePath, file);
|
|
3018
3117
|
written.push(file.path);
|
|
3019
3118
|
continue;
|
|
@@ -3036,8 +3135,8 @@ var applyPackSourceFiles = (params) => {
|
|
|
3036
3135
|
if (sourceByPath.has(previous.path)) {
|
|
3037
3136
|
continue;
|
|
3038
3137
|
}
|
|
3039
|
-
const absolutePath =
|
|
3040
|
-
if (!
|
|
3138
|
+
const absolutePath = resolveProjectLayerFilePath(params.basePath, previous.path);
|
|
3139
|
+
if (!existsSync9(absolutePath)) {
|
|
3041
3140
|
notFound.push(previous.path);
|
|
3042
3141
|
continue;
|
|
3043
3142
|
}
|
|
@@ -3055,8 +3154,8 @@ var removePackFiles = (basePath, record) => {
|
|
|
3055
3154
|
const preserved = [];
|
|
3056
3155
|
const notFound = [];
|
|
3057
3156
|
for (const file of [...record.documents, ...record.files]) {
|
|
3058
|
-
const absolutePath =
|
|
3059
|
-
if (!
|
|
3157
|
+
const absolutePath = resolveProjectLayerFilePath(basePath, file.path);
|
|
3158
|
+
if (!existsSync9(absolutePath)) {
|
|
3060
3159
|
notFound.push(file.path);
|
|
3061
3160
|
continue;
|
|
3062
3161
|
}
|
|
@@ -3074,12 +3173,12 @@ var removeEmptyDirs2 = (basePath, relativePaths) => {
|
|
|
3074
3173
|
(a, b) => b.length - a.length
|
|
3075
3174
|
);
|
|
3076
3175
|
for (const dir of dirs) {
|
|
3077
|
-
const absoluteDir =
|
|
3078
|
-
if (!
|
|
3176
|
+
const absoluteDir = resolveProjectLayerFilePath(basePath, dir);
|
|
3177
|
+
if (!existsSync9(absoluteDir)) {
|
|
3079
3178
|
continue;
|
|
3080
3179
|
}
|
|
3081
3180
|
try {
|
|
3082
|
-
if (
|
|
3181
|
+
if (readdirSync6(absoluteDir).length === 0) {
|
|
3083
3182
|
rmSync3(absoluteDir, { recursive: true });
|
|
3084
3183
|
}
|
|
3085
3184
|
} catch {
|
|
@@ -3190,8 +3289,8 @@ var diffProjectLayerPack = (params) => {
|
|
|
3190
3289
|
);
|
|
3191
3290
|
}
|
|
3192
3291
|
for (const file of [...record.documents, ...record.files]) {
|
|
3193
|
-
const absolutePath =
|
|
3194
|
-
if (!
|
|
3292
|
+
const absolutePath = resolveProjectLayerFilePath(params.basePath, file.path);
|
|
3293
|
+
if (!existsSync9(absolutePath)) {
|
|
3195
3294
|
issues.push(packIssue("error", "missing-file", `\uD30C\uC77C \uC5C6\uC74C: ${file.path}`));
|
|
3196
3295
|
}
|
|
3197
3296
|
}
|
|
@@ -3200,7 +3299,7 @@ var diffProjectLayerPack = (params) => {
|
|
|
3200
3299
|
};
|
|
3201
3300
|
|
|
3202
3301
|
// src/features/context-promotion/status.ts
|
|
3203
|
-
var hasContextPromotionLayer = (gitRoot) =>
|
|
3302
|
+
var hasContextPromotionLayer = (gitRoot) => existsSync10(join16(gitRoot, PROJECT_LAYER_CONTEXT_INDEX_RELATIVE_PATH));
|
|
3204
3303
|
var getContextPromotionStatus = (params) => {
|
|
3205
3304
|
const cwd = resolve8(params.cwd);
|
|
3206
3305
|
const gitRoot = resolveContextPromotionGitRoot(cwd);
|
|
@@ -3528,11 +3627,11 @@ import * as p5 from "@clack/prompts";
|
|
|
3528
3627
|
|
|
3529
3628
|
// src/features/pc/status.ts
|
|
3530
3629
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
3531
|
-
import { existsSync as
|
|
3630
|
+
import { existsSync as existsSync11, readdirSync as readdirSync7 } from "fs";
|
|
3532
3631
|
import { join as join17, resolve as resolve10, sep as sep2 } from "path";
|
|
3533
3632
|
|
|
3534
3633
|
// src/features/pc/markdown.ts
|
|
3535
|
-
import { readFileSync as
|
|
3634
|
+
import { readFileSync as readFileSync17 } from "fs";
|
|
3536
3635
|
import { resolve as resolve9, sep } from "path";
|
|
3537
3636
|
var normalizePath = (path) => resolve9(path.replace(/^~(?=$|\/)/, process.env.HOME ?? "~"));
|
|
3538
3637
|
var pathContains = (parentPath, childPath) => {
|
|
@@ -3571,7 +3670,7 @@ var parseListField = (content, labels) => {
|
|
|
3571
3670
|
};
|
|
3572
3671
|
var readTextFileOrNull = (filePath) => {
|
|
3573
3672
|
try {
|
|
3574
|
-
return
|
|
3673
|
+
return readFileSync17(filePath, "utf-8");
|
|
3575
3674
|
} catch {
|
|
3576
3675
|
return null;
|
|
3577
3676
|
}
|
|
@@ -3599,10 +3698,10 @@ var readGitHead2 = (cwd) => {
|
|
|
3599
3698
|
};
|
|
3600
3699
|
var listWorkspaceStatePaths = (contextRoot) => {
|
|
3601
3700
|
const workspacesDir = join17(contextRoot, "workspaces");
|
|
3602
|
-
if (!
|
|
3701
|
+
if (!existsSync11(workspacesDir)) {
|
|
3603
3702
|
return [];
|
|
3604
3703
|
}
|
|
3605
|
-
return
|
|
3704
|
+
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
3705
|
};
|
|
3607
3706
|
var parseWorkspaceCandidate = (statePath) => {
|
|
3608
3707
|
const content = readTextFileOrNull(statePath);
|
|
@@ -3646,10 +3745,10 @@ var parseRepoEntry = (entryPath) => {
|
|
|
3646
3745
|
};
|
|
3647
3746
|
var findCurrentEntry = (params) => {
|
|
3648
3747
|
const reposDir = join17(params.workspaceDir, "repos");
|
|
3649
|
-
if (!
|
|
3748
|
+
if (!existsSync11(reposDir)) {
|
|
3650
3749
|
return null;
|
|
3651
3750
|
}
|
|
3652
|
-
const entries =
|
|
3751
|
+
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
3752
|
const paths = [entry.path, entry.gitRoot].filter((path) => path !== null);
|
|
3654
3753
|
return paths.some((path) => pathContains(path, params.cwd));
|
|
3655
3754
|
}).sort((a, b) => {
|
|
@@ -3701,7 +3800,7 @@ var parseLastConfirmedCommitHash = (params) => {
|
|
|
3701
3800
|
var getPcHandoffStatus = (params) => {
|
|
3702
3801
|
const cwd = normalizePath(params.cwd);
|
|
3703
3802
|
const contextRoot = normalizePath(params.contextRoot);
|
|
3704
|
-
if (!
|
|
3803
|
+
if (!existsSync11(contextRoot)) {
|
|
3705
3804
|
return {
|
|
3706
3805
|
cwd,
|
|
3707
3806
|
contextRoot,
|
|
@@ -3864,7 +3963,7 @@ var evaluatePcPostToolUseHook = (params) => {
|
|
|
3864
3963
|
};
|
|
3865
3964
|
|
|
3866
3965
|
// src/features/integrations/manifest-io.ts
|
|
3867
|
-
import { mkdirSync as mkdirSync9, readFileSync as
|
|
3966
|
+
import { mkdirSync as mkdirSync9, readFileSync as readFileSync18, rmSync as rmSync4, writeFileSync as writeFileSync11 } from "fs";
|
|
3868
3967
|
import { dirname as dirname12, join as join18 } from "path";
|
|
3869
3968
|
var INTEGRATION_MANIFEST_FILENAME = "integrations-manifest.json";
|
|
3870
3969
|
var parseIntegrationManifest = (json) => IntegrationManifestSchema.parse(JSON.parse(json));
|
|
@@ -3873,7 +3972,7 @@ var resolveIntegrationManifestPath = (userBasePath) => join18(userBasePath, ".ai
|
|
|
3873
3972
|
var readIntegrationManifest = (manifestPath) => {
|
|
3874
3973
|
let raw;
|
|
3875
3974
|
try {
|
|
3876
|
-
raw =
|
|
3975
|
+
raw = readFileSync18(manifestPath, "utf-8");
|
|
3877
3976
|
} catch {
|
|
3878
3977
|
return null;
|
|
3879
3978
|
}
|
|
@@ -3906,7 +4005,7 @@ var writeUserIntegrationState = (params) => {
|
|
|
3906
4005
|
};
|
|
3907
4006
|
|
|
3908
4007
|
// src/features/integrations/components.ts
|
|
3909
|
-
import { existsSync as
|
|
4008
|
+
import { existsSync as existsSync12, rmSync as rmSync5 } from "fs";
|
|
3910
4009
|
import { join as join19 } from "path";
|
|
3911
4010
|
var readInstalledSkills2 = (basePath) => (readSkillRegistry(resolveSkillRegistryPath(basePath))?.skills ?? []).map((installedSkill) => ({
|
|
3912
4011
|
...installedSkill,
|
|
@@ -3921,7 +4020,7 @@ var resolveSkillById = (skillId) => {
|
|
|
3921
4020
|
};
|
|
3922
4021
|
var hasInstalledCodexSkill = (params) => {
|
|
3923
4022
|
const installedSkill = findInstalledSkill(readInstalledSkills2(params.basePath), params.skillId);
|
|
3924
|
-
return installedSkill?.tools.includes(SKILL_TOOL.CODEX) === true &&
|
|
4023
|
+
return installedSkill?.tools.includes(SKILL_TOOL.CODEX) === true && existsSync12(join19(params.basePath, ".agents/skills", params.skillId, "SKILL.md"));
|
|
3925
4024
|
};
|
|
3926
4025
|
var writeUserSkillState = (params) => {
|
|
3927
4026
|
const registryPath = resolveSkillRegistryPath(params.basePath);
|
|
@@ -3949,7 +4048,7 @@ var ensureSkillComponent = (params) => {
|
|
|
3949
4048
|
skill,
|
|
3950
4049
|
requestedTools
|
|
3951
4050
|
});
|
|
3952
|
-
const alreadyCurrent = existingInstalledSkill?.sourceHash === installedSkill.sourceHash && existingInstalledSkill.tools.includes(SKILL_TOOL.CODEX) &&
|
|
4051
|
+
const alreadyCurrent = existingInstalledSkill?.sourceHash === installedSkill.sourceHash && existingInstalledSkill.tools.includes(SKILL_TOOL.CODEX) && existsSync12(join19(params.basePath, ".agents/skills", params.skillId, "SKILL.md"));
|
|
3953
4052
|
if (alreadyCurrent) {
|
|
3954
4053
|
return {
|
|
3955
4054
|
type: INTEGRATION_COMPONENT_TYPE.SKILL,
|
|
@@ -4884,7 +4983,7 @@ var registerSkillCommands = (program) => {
|
|
|
4884
4983
|
import { join as join23 } from "path";
|
|
4885
4984
|
|
|
4886
4985
|
// src/features/studio/project-snapshot.ts
|
|
4887
|
-
import { existsSync as
|
|
4986
|
+
import { existsSync as existsSync13, readFileSync as readFileSync19 } from "fs";
|
|
4888
4987
|
import { resolve as resolve11 } from "path";
|
|
4889
4988
|
import { z as z14 } from "zod";
|
|
4890
4989
|
|
|
@@ -4951,7 +5050,9 @@ var AUDIT_ISSUE_SOURCES_BY_CODE = {
|
|
|
4951
5050
|
"invalid-frontmatter": "frontmatter",
|
|
4952
5051
|
"missing-managed-section": "managed-section",
|
|
4953
5052
|
"source-hash-drift": "source-hash",
|
|
4954
|
-
"managed-source-hash-drift": "source-hash"
|
|
5053
|
+
"managed-source-hash-drift": "source-hash",
|
|
5054
|
+
"invalid-custom-project-rule": "frontmatter",
|
|
5055
|
+
"custom-project-rules-drift": "manifest"
|
|
4955
5056
|
};
|
|
4956
5057
|
var AUDIT_ISSUE_ACTION_LABELS_BY_SOURCE = {
|
|
4957
5058
|
manifest: "Review manifest record",
|
|
@@ -4998,6 +5099,10 @@ var extractTrailingIssuePath = (message) => {
|
|
|
4998
5099
|
const [firstToken] = trailingSegment.trim().split(/\s+/);
|
|
4999
5100
|
return firstToken === void 0 ? null : parsePathLikeToken(firstToken);
|
|
5000
5101
|
};
|
|
5102
|
+
var extractLeadingIssuePath = (message) => {
|
|
5103
|
+
const [firstToken] = message.trim().split(/\s+/);
|
|
5104
|
+
return firstToken === void 0 ? null : parsePathLikeToken(firstToken);
|
|
5105
|
+
};
|
|
5001
5106
|
var resolveIssueSource = (issue2) => AUDIT_ISSUE_SOURCES_BY_CODE[issue2.code] ?? "unknown";
|
|
5002
5107
|
var resolveIssueAffectedPath = (params) => {
|
|
5003
5108
|
if (params.issue.code === "missing-manifest" || params.issue.code === "invalid-manifest") {
|
|
@@ -5012,6 +5117,9 @@ var resolveIssueAffectedPath = (params) => {
|
|
|
5012
5117
|
if (params.issue.code === "source-hash-drift") {
|
|
5013
5118
|
return null;
|
|
5014
5119
|
}
|
|
5120
|
+
if (params.issue.code === "invalid-custom-project-rule") {
|
|
5121
|
+
return extractLeadingIssuePath(params.issue.message);
|
|
5122
|
+
}
|
|
5015
5123
|
const knownPath = findKnownPathInMessage(params.issue.message, params.knownPaths);
|
|
5016
5124
|
if (knownPath !== null) {
|
|
5017
5125
|
return knownPath;
|
|
@@ -5051,7 +5159,7 @@ var RecoverableContextIndexSchema = z14.object({
|
|
|
5051
5159
|
});
|
|
5052
5160
|
var readProjectManifestSnapshot = (basePath) => {
|
|
5053
5161
|
const manifestPath = resolveProjectLayerManifestPath(basePath);
|
|
5054
|
-
if (!
|
|
5162
|
+
if (!existsSync13(manifestPath)) {
|
|
5055
5163
|
return {
|
|
5056
5164
|
source: createMissingSourceState(PROJECT_LAYER_MANIFEST_RELATIVE_PATH),
|
|
5057
5165
|
manifest: null
|
|
@@ -5082,14 +5190,14 @@ var readProjectManifestSnapshot = (basePath) => {
|
|
|
5082
5190
|
};
|
|
5083
5191
|
var readProjectContextIndexSnapshot = (basePath) => {
|
|
5084
5192
|
const contextIndexPath = resolveProjectLayerContextIndexPath(basePath);
|
|
5085
|
-
if (!
|
|
5193
|
+
if (!existsSync13(contextIndexPath)) {
|
|
5086
5194
|
return {
|
|
5087
5195
|
source: createMissingSourceState(PROJECT_LAYER_CONTEXT_INDEX_RELATIVE_PATH),
|
|
5088
5196
|
contextIndex: null
|
|
5089
5197
|
};
|
|
5090
5198
|
}
|
|
5091
5199
|
try {
|
|
5092
|
-
const parsedJson = JSON.parse(
|
|
5200
|
+
const parsedJson = JSON.parse(readFileSync19(contextIndexPath, "utf-8"));
|
|
5093
5201
|
const strictContextIndex = ProjectLayerContextIndexSchema.safeParse(parsedJson);
|
|
5094
5202
|
if (strictContextIndex.success) {
|
|
5095
5203
|
return {
|
|
@@ -5146,12 +5254,12 @@ var readProjectContextIndexSnapshot = (basePath) => {
|
|
|
5146
5254
|
}
|
|
5147
5255
|
};
|
|
5148
5256
|
var readDocsStatusSourceState = (basePath) => {
|
|
5149
|
-
const docsStatusPath =
|
|
5150
|
-
if (!
|
|
5257
|
+
const docsStatusPath = resolveProjectLayerFilePath(basePath, DOCS_STATUS_RELATIVE_PATH);
|
|
5258
|
+
if (!existsSync13(docsStatusPath)) {
|
|
5151
5259
|
return createMissingSourceState(DOCS_STATUS_RELATIVE_PATH);
|
|
5152
5260
|
}
|
|
5153
5261
|
try {
|
|
5154
|
-
parseProjectLayerDocument(DOCS_STATUS_RELATIVE_PATH,
|
|
5262
|
+
parseProjectLayerDocument(DOCS_STATUS_RELATIVE_PATH, readFileSync19(docsStatusPath, "utf-8"));
|
|
5155
5263
|
return buildSourceState({
|
|
5156
5264
|
path: DOCS_STATUS_RELATIVE_PATH,
|
|
5157
5265
|
exists: true,
|
|
@@ -5182,7 +5290,7 @@ var buildDocumentReadError = (code, message) => `${code}: ${message}`;
|
|
|
5182
5290
|
var buildProjectDocumentSnapshot = (params) => {
|
|
5183
5291
|
let absolutePath;
|
|
5184
5292
|
try {
|
|
5185
|
-
absolutePath =
|
|
5293
|
+
absolutePath = resolveProjectLayerFilePath(params.basePath, params.indexed.path);
|
|
5186
5294
|
} catch (error) {
|
|
5187
5295
|
return {
|
|
5188
5296
|
path: params.indexed.path,
|
|
@@ -5200,7 +5308,7 @@ var buildProjectDocumentSnapshot = (params) => {
|
|
|
5200
5308
|
readError: buildDocumentReadError("unsafe-path", getErrorMessage(error))
|
|
5201
5309
|
};
|
|
5202
5310
|
}
|
|
5203
|
-
if (!
|
|
5311
|
+
if (!existsSync13(absolutePath)) {
|
|
5204
5312
|
return {
|
|
5205
5313
|
path: params.indexed.path,
|
|
5206
5314
|
status: params.indexed.status,
|
|
@@ -5218,7 +5326,7 @@ var buildProjectDocumentSnapshot = (params) => {
|
|
|
5218
5326
|
};
|
|
5219
5327
|
}
|
|
5220
5328
|
try {
|
|
5221
|
-
const document = parseProjectLayerDocument(params.indexed.path,
|
|
5329
|
+
const document = parseProjectLayerDocument(params.indexed.path, readFileSync19(absolutePath, "utf-8"));
|
|
5222
5330
|
return {
|
|
5223
5331
|
path: params.indexed.path,
|
|
5224
5332
|
status: params.indexed.status,
|
|
@@ -5309,11 +5417,11 @@ var buildProjectSnapshot = (basePath) => {
|
|
|
5309
5417
|
};
|
|
5310
5418
|
|
|
5311
5419
|
// src/features/studio/runtime-snapshot.ts
|
|
5312
|
-
import { existsSync as
|
|
5420
|
+
import { existsSync as existsSync14, readFileSync as readFileSync21 } from "fs";
|
|
5313
5421
|
import { join as join22 } from "path";
|
|
5314
5422
|
|
|
5315
5423
|
// src/features/subagents/manifest-io.ts
|
|
5316
|
-
import { mkdirSync as mkdirSync10, readFileSync as
|
|
5424
|
+
import { mkdirSync as mkdirSync10, readFileSync as readFileSync20, writeFileSync as writeFileSync12 } from "fs";
|
|
5317
5425
|
import { dirname as dirname13, join as join21 } from "path";
|
|
5318
5426
|
var SUBAGENT_MANIFEST_FILENAME = "subagents-manifest.json";
|
|
5319
5427
|
var parseSubagentManifest = (json) => SubagentManifestSchema.parse(JSON.parse(json));
|
|
@@ -5322,7 +5430,7 @@ var resolveSubagentManifestPath = (userBasePath) => join21(userBasePath, ".ai-op
|
|
|
5322
5430
|
var readSubagentManifest = (manifestPath) => {
|
|
5323
5431
|
let raw;
|
|
5324
5432
|
try {
|
|
5325
|
-
raw =
|
|
5433
|
+
raw = readFileSync20(manifestPath, "utf-8");
|
|
5326
5434
|
} catch {
|
|
5327
5435
|
return null;
|
|
5328
5436
|
}
|
|
@@ -5352,7 +5460,7 @@ var readRuntimeManifest = (params) => {
|
|
|
5352
5460
|
value: null
|
|
5353
5461
|
};
|
|
5354
5462
|
}
|
|
5355
|
-
if (!
|
|
5463
|
+
if (!existsSync14(params.manifestPath)) {
|
|
5356
5464
|
return {
|
|
5357
5465
|
source: createMissingSourceState(params.manifestPath),
|
|
5358
5466
|
value: null
|
|
@@ -5390,11 +5498,11 @@ var readHooksSourceState = (codexHomePath, unavailableReason) => {
|
|
|
5390
5498
|
});
|
|
5391
5499
|
}
|
|
5392
5500
|
const hooksPath = resolveCodexHooksPath(codexHomePath);
|
|
5393
|
-
if (!
|
|
5501
|
+
if (!existsSync14(hooksPath)) {
|
|
5394
5502
|
return createMissingSourceState(hooksPath);
|
|
5395
5503
|
}
|
|
5396
5504
|
try {
|
|
5397
|
-
const parsed = JSON.parse(
|
|
5505
|
+
const parsed = JSON.parse(readFileSync21(hooksPath, "utf-8"));
|
|
5398
5506
|
if (!isJsonRecord4(parsed)) {
|
|
5399
5507
|
return buildSourceState({
|
|
5400
5508
|
path: hooksPath,
|
|
@@ -5455,7 +5563,7 @@ var buildInstalledPathStates = (params) => {
|
|
|
5455
5563
|
}
|
|
5456
5564
|
return params.installedPaths.map((path) => ({
|
|
5457
5565
|
path,
|
|
5458
|
-
exists:
|
|
5566
|
+
exists: existsSync14(join22(params.userBasePath ?? "", path))
|
|
5459
5567
|
}));
|
|
5460
5568
|
};
|
|
5461
5569
|
var buildInstalledSkillMap = (installedSkills) => new Map(
|
|
@@ -5659,7 +5767,7 @@ var registerStudioCommands = (program) => {
|
|
|
5659
5767
|
|
|
5660
5768
|
// src/features/subagents/commands.ts
|
|
5661
5769
|
import * as p14 from "@clack/prompts";
|
|
5662
|
-
import { existsSync as
|
|
5770
|
+
import { existsSync as existsSync16, rmSync as rmSync8 } from "fs";
|
|
5663
5771
|
|
|
5664
5772
|
// src/features/subagents/renderer.ts
|
|
5665
5773
|
import { resolve as resolve12 } from "path";
|
|
@@ -5782,7 +5890,7 @@ var buildSubagentInstallPlan = (params) => {
|
|
|
5782
5890
|
};
|
|
5783
5891
|
|
|
5784
5892
|
// src/features/subagents/install-files.ts
|
|
5785
|
-
import { existsSync as
|
|
5893
|
+
import { existsSync as existsSync15, mkdirSync as mkdirSync11, rmSync as rmSync7, writeFileSync as writeFileSync13 } from "fs";
|
|
5786
5894
|
import { dirname as dirname14, isAbsolute as isAbsolute3, relative as relative3, resolve as resolve13 } from "path";
|
|
5787
5895
|
var resolveInsideBasePath = (basePath, relativePath) => {
|
|
5788
5896
|
const absBasePath = resolve13(basePath);
|
|
@@ -5798,7 +5906,7 @@ var installSubagentPackages = (basePath, packages) => {
|
|
|
5798
5906
|
for (const subagentPackage of packages) {
|
|
5799
5907
|
for (const file of subagentPackage.files) {
|
|
5800
5908
|
const absPath = resolveInsideBasePath(basePath, file.relativePath);
|
|
5801
|
-
if (
|
|
5909
|
+
if (existsSync15(absPath)) {
|
|
5802
5910
|
rmSync7(absPath, { recursive: true, force: true });
|
|
5803
5911
|
}
|
|
5804
5912
|
mkdirSync11(dirname14(absPath), { recursive: true });
|
|
@@ -5812,7 +5920,7 @@ var removeSubagentFiles = (basePath, relativePaths) => {
|
|
|
5812
5920
|
const removed = [];
|
|
5813
5921
|
for (const relativePath of relativePaths) {
|
|
5814
5922
|
const absPath = resolveInsideBasePath(basePath, relativePath);
|
|
5815
|
-
if (!
|
|
5923
|
+
if (!existsSync15(absPath)) continue;
|
|
5816
5924
|
rmSync7(absPath, { recursive: true, force: true });
|
|
5817
5925
|
removed.push(relativePath);
|
|
5818
5926
|
}
|
|
@@ -5874,7 +5982,7 @@ var writeUserSubagentState = (params) => {
|
|
|
5874
5982
|
};
|
|
5875
5983
|
var readInstalledSubagents = (basePath) => readSubagentManifest(resolveSubagentManifestPath(basePath))?.subagents ?? [];
|
|
5876
5984
|
var warnMissingSkills = (requiredSkills) => {
|
|
5877
|
-
const missing = requiredSkills.filter((skill) => !
|
|
5985
|
+
const missing = requiredSkills.filter((skill) => !existsSync16(skill.path));
|
|
5878
5986
|
if (missing.length === 0) {
|
|
5879
5987
|
return;
|
|
5880
5988
|
}
|