@c4a/context-cli 0.7.20 → 0.7.25
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.md +6 -6
- package/README.zh-CN.md +6 -6
- package/cli.js +667 -651
- package/indexers/contracts/profile-contract.json +245 -245
- package/indexers/release-manifest.json +1 -1
- package/package.json +12 -12
- package/plugins/VERSION +1 -1
- package/plugins/claude/.claude-plugin/plugin.json +1 -1
- package/plugins/claude/commands/context.md +77 -6
- package/plugins/codex/.codex-plugin/plugin.json +2 -2
- package/plugins/codex/skills/context/SKILL.md +77 -6
- package/plugins/cursor/.cursor-plugin/plugin.json +1 -1
- package/plugins/cursor/commands/c4a-context.md +77 -6
- package/plugins/skills/context/SKILL.md +77 -6
- package/providers/context/codes.yaml +1 -1
- package/providers/context/graphs/indexer.yaml +11 -7
- package/providers/context/graphs/workspace.yaml +5 -0
- package/providers/context/manifest.json +30 -30
- package/providers/context/provider.yaml +1 -1
- package/providers/context/resources/manuals/guides/knowledge-updates.md +5 -1
- package/providers/context/resources/manuals/guides/workspace-prepare.md +4 -0
- package/providers/context/resources/manuals/guides/workspace-restore.md +5 -1
- package/providers/context/resources/procedures/knowledge-review.md +11 -4
- package/providers/context/resources/procedures/knowledge-updates.md +5 -1
- package/providers/context/resources/procedures/package-output.md +4 -0
- package/providers/context/resources/procedures/production-requirements.md +5 -3
- package/providers/context/resources/procedures/source-boundary.md +15 -5
- package/providers/context/resources/procedures/work-start-report.md +19 -6
- package/providers/context/resources/procedures/workspace-prepare.md +4 -0
- package/providers/context/resources/procedures/workspace-restore.md +5 -1
- package/providers/context/skills/resolve-current-indexer-gate/SKILL.md +7 -2
- package/providers/context/skills/run-indexer-lifecycle/SKILL.md +3 -2
- package/providers/context/skills/work-production-stage/SKILL.md +5 -3
package/cli.js
CHANGED
|
@@ -76442,12 +76442,22 @@ var init_packageTemplateUtils = __esm(() => {
|
|
|
76442
76442
|
TEMPLATE_ENGINE.registerHelper("json", (value) => JSON.stringify(value, null, 2));
|
|
76443
76443
|
});
|
|
76444
76444
|
|
|
76445
|
+
// src/project/packageDistributionMetadata.ts
|
|
76446
|
+
import { join as join15 } from "node:path";
|
|
76447
|
+
function packageDistributionMetadataPath(fileName) {
|
|
76448
|
+
return join15(PACKAGE_DISTRIBUTION_METADATA_DIR, fileName);
|
|
76449
|
+
}
|
|
76450
|
+
var PACKAGE_DISTRIBUTION_METADATA_DIR;
|
|
76451
|
+
var init_packageDistributionMetadata = __esm(() => {
|
|
76452
|
+
PACKAGE_DISTRIBUTION_METADATA_DIR = join15("others", "context");
|
|
76453
|
+
});
|
|
76454
|
+
|
|
76445
76455
|
// src/project/packageBuildInventory.ts
|
|
76446
76456
|
import { createHash as createHash9 } from "node:crypto";
|
|
76447
76457
|
import { mkdir as mkdir12, writeFile as writeFile7 } from "node:fs/promises";
|
|
76448
|
-
import { dirname as dirname14, join as
|
|
76458
|
+
import { dirname as dirname14, join as join16 } from "node:path";
|
|
76449
76459
|
function knowledgeStructurePath(projectRoot) {
|
|
76450
|
-
return
|
|
76460
|
+
return join16(projectRoot, "knowledge", "structure.yaml");
|
|
76451
76461
|
}
|
|
76452
76462
|
async function readKnowledgeStructure(projectRoot) {
|
|
76453
76463
|
const snapshot = await reuseCommandFileRead({
|
|
@@ -76594,11 +76604,19 @@ function packageBuildInventory(input) {
|
|
|
76594
76604
|
};
|
|
76595
76605
|
}
|
|
76596
76606
|
async function writePackageBuildInventory(input) {
|
|
76597
|
-
const outputPath =
|
|
76598
|
-
|
|
76599
|
-
|
|
76600
|
-
|
|
76601
|
-
|
|
76607
|
+
const outputPath = join16(input.projectRoot, input.pkg.outDir, PACKAGE_BUILD_INVENTORY_PATH);
|
|
76608
|
+
const distributionPath = join16(input.projectRoot, input.pkg.outDir, packageDistributionMetadataPath(PACKAGE_BUILD_INVENTORY_PATH));
|
|
76609
|
+
const content3 = `${JSON.stringify(input.inventory, null, 2)}
|
|
76610
|
+
`;
|
|
76611
|
+
await Promise.all([
|
|
76612
|
+
mkdir12(dirname14(outputPath), { recursive: true }),
|
|
76613
|
+
mkdir12(dirname14(distributionPath), { recursive: true })
|
|
76614
|
+
]);
|
|
76615
|
+
await Promise.all([
|
|
76616
|
+
writeFile7(outputPath, content3, "utf8"),
|
|
76617
|
+
writeFile7(distributionPath, content3, "utf8")
|
|
76618
|
+
]);
|
|
76619
|
+
return 2;
|
|
76602
76620
|
}
|
|
76603
76621
|
var PACKAGE_BUILD_INVENTORY_PATH = "context-build-inventory.json";
|
|
76604
76622
|
var init_packageBuildInventory = __esm(() => {
|
|
@@ -76609,6 +76627,7 @@ var init_packageBuildInventory = __esm(() => {
|
|
|
76609
76627
|
init_packageNavigation();
|
|
76610
76628
|
init_packageDistribution();
|
|
76611
76629
|
init_packageTemplateUtils();
|
|
76630
|
+
init_packageDistributionMetadata();
|
|
76612
76631
|
});
|
|
76613
76632
|
|
|
76614
76633
|
// src/project/codeAnalysisInput.ts
|
|
@@ -76763,7 +76782,7 @@ var init_indexerSourceBoundary = __esm(() => {
|
|
|
76763
76782
|
import { execFile as execFile3 } from "node:child_process";
|
|
76764
76783
|
import { lstat as lstat4, readFile as readFile18 } from "node:fs/promises";
|
|
76765
76784
|
import { promisify as promisify3 } from "node:util";
|
|
76766
|
-
import { basename as basename4, extname as extname8, join as
|
|
76785
|
+
import { basename as basename4, extname as extname8, join as join17 } from "node:path";
|
|
76767
76786
|
function sourceRefName(sourceRef) {
|
|
76768
76787
|
return sourceRef.startsWith("repo:") ? sourceRef.slice("repo:".length) : null;
|
|
76769
76788
|
}
|
|
@@ -76800,7 +76819,7 @@ function sourceRoot(input) {
|
|
|
76800
76819
|
const source2 = name2 === null ? undefined : input.sources.find((candidate) => candidate.name === name2 || candidate.id === name2);
|
|
76801
76820
|
if (source2 === undefined)
|
|
76802
76821
|
throw new TypeError(`parser plan uses unknown source ${input.sourceRef}`);
|
|
76803
|
-
return
|
|
76822
|
+
return join17(input.projectRoot, source2.materializedAt);
|
|
76804
76823
|
}
|
|
76805
76824
|
async function materializeProjectIndexerParserEntryInput(input) {
|
|
76806
76825
|
const sources = await loadSourcesRegistry({ rootDir: input.projectRoot });
|
|
@@ -76896,7 +76915,7 @@ __export(exports_processedScopeStorage, {
|
|
|
76896
76915
|
captureProcessedScopes: () => captureProcessedScopes
|
|
76897
76916
|
});
|
|
76898
76917
|
import { readFile as readFile20 } from "node:fs/promises";
|
|
76899
|
-
import { join as
|
|
76918
|
+
import { join as join18 } from "node:path";
|
|
76900
76919
|
async function currentScopeSourceVersion(projectRoot, sourceRef) {
|
|
76901
76920
|
const sources = await loadSourcesRegistry({ rootDir: projectRoot });
|
|
76902
76921
|
const split = sourceRef.indexOf(":");
|
|
@@ -76913,7 +76932,7 @@ async function currentScopeSourceVersion(projectRoot, sourceRef) {
|
|
|
76913
76932
|
const version3 = entries2[0].ref;
|
|
76914
76933
|
if (!/^[a-f0-9]{40}(?:[a-f0-9]{24})?$/u.test(version3))
|
|
76915
76934
|
throw new TypeError("Processing requires a fixed commit, not a moving ref");
|
|
76916
|
-
await assertPinnedSource(
|
|
76935
|
+
await assertPinnedSource(join18(projectRoot, entries2[0].materializedAt), version3);
|
|
76917
76936
|
return version3;
|
|
76918
76937
|
}
|
|
76919
76938
|
const entries = (type === "file" ? sources.files : type === "lark" ? sources.larks : []).filter((entry2) => entry2.id === name2 || entry2.name === name2);
|
|
@@ -76921,7 +76940,7 @@ async function currentScopeSourceVersion(projectRoot, sourceRef) {
|
|
|
76921
76940
|
throw new TypeError(`Source must identify one registered document: ${sourceRef}`);
|
|
76922
76941
|
const entry = entries[0];
|
|
76923
76942
|
const manifest = entry.snapshot?.manifest ?? `${entry.materializedAt}/manifest.json`;
|
|
76924
|
-
return parseDocumentSnapshotForSource(JSON.parse(await readFile20(
|
|
76943
|
+
return parseDocumentSnapshotForSource(JSON.parse(await readFile20(join18(projectRoot, manifest), "utf8")), entry.name).snapshot_hash;
|
|
76925
76944
|
}
|
|
76926
76945
|
async function captureProcessedScopes(projectRoot, requested) {
|
|
76927
76946
|
const scopes = processedScopesSchema.parse(requested);
|
|
@@ -76949,7 +76968,7 @@ async function commitProcessedScopes(projectRoot, scopes) {
|
|
|
76949
76968
|
if (structure.parsed === null)
|
|
76950
76969
|
throw new TypeError("A closed knowledge structure is required before recording processed scopes");
|
|
76951
76970
|
const processed = mergeProcessedScopes(readProcessedScopes(structure.parsed), scopes);
|
|
76952
|
-
await atomicWriteFile(
|
|
76971
|
+
await atomicWriteFile(join18(projectRoot, structure.path), import_yaml13.default.stringify({ ...structure.parsed, processed_scopes: processed }));
|
|
76953
76972
|
}
|
|
76954
76973
|
async function invalidateChangedProcessedRequirements(projectRoot, previous2, current2) {
|
|
76955
76974
|
const targets = new Map(current2.map((requirement2) => [requirement2.id, indexerProtocolDigest(requirement2)]));
|
|
@@ -76963,7 +76982,7 @@ async function invalidateChangedProcessedRequirements(projectRoot, previous2, cu
|
|
|
76963
76982
|
const retained = scopes.filter((scope2) => !changed.has(scope2.requirement_ref));
|
|
76964
76983
|
if (retained.length === scopes.length)
|
|
76965
76984
|
return;
|
|
76966
|
-
await atomicWriteFile(
|
|
76985
|
+
await atomicWriteFile(join18(projectRoot, structure.path), import_yaml13.default.stringify({ ...structure.parsed, processed_scopes: retained }));
|
|
76967
76986
|
}
|
|
76968
76987
|
var import_yaml13;
|
|
76969
76988
|
var init_processedScopeStorage = __esm(() => {
|
|
@@ -77102,7 +77121,7 @@ __export(exports_approvedRevisionPrograms, {
|
|
|
77102
77121
|
});
|
|
77103
77122
|
import { execFile as execFile4 } from "node:child_process";
|
|
77104
77123
|
import { promisify as promisify4 } from "node:util";
|
|
77105
|
-
import { extname as extname9, join as
|
|
77124
|
+
import { extname as extname9, join as join19 } from "node:path";
|
|
77106
77125
|
import { createRequire as createRequire3 } from "node:module";
|
|
77107
77126
|
import { pathToFileURL } from "node:url";
|
|
77108
77127
|
async function prepareRevisionProgramBlocks(root, sourceRefs, scopes, references) {
|
|
@@ -77118,7 +77137,7 @@ async function prepareRevisionProgramBlocks(root, sourceRefs, scopes, references
|
|
|
77118
77137
|
if (entries.length !== 1)
|
|
77119
77138
|
throw new TypeError(`Regeneration requires one registered source: ${source2}`);
|
|
77120
77139
|
const entry = entries[0];
|
|
77121
|
-
const directory =
|
|
77140
|
+
const directory = join19(root, entry.materializedAt);
|
|
77122
77141
|
const paths = [...new Set(references.filter((reference2) => reference2.source_ref === source2).map((reference2) => reference2.locator.path))];
|
|
77123
77142
|
if (!paths.length)
|
|
77124
77143
|
continue;
|
|
@@ -77248,14 +77267,14 @@ var init_approvedRevisionEdits = __esm(() => {
|
|
|
77248
77267
|
// src/project/articleRegionBaselines.ts
|
|
77249
77268
|
import { createHash as createHash10 } from "node:crypto";
|
|
77250
77269
|
import { lstatSync, mkdirSync, readFileSync as readFileSync3, realpathSync, writeFileSync } from "node:fs";
|
|
77251
|
-
import { join as
|
|
77270
|
+
import { join as join20 } from "node:path";
|
|
77252
77271
|
function baselinePath(root, digest2, create) {
|
|
77253
77272
|
const hash2 = DIGEST.exec(digest2)?.[1];
|
|
77254
77273
|
if (!hash2)
|
|
77255
77274
|
throw new TypeError("Invalid source region digest");
|
|
77256
77275
|
let path2 = realpathSync(root);
|
|
77257
77276
|
for (const part of [".tmp", "context-runtime", "source-regions"]) {
|
|
77258
|
-
path2 =
|
|
77277
|
+
path2 = join20(path2, part);
|
|
77259
77278
|
if (create) {
|
|
77260
77279
|
try {
|
|
77261
77280
|
mkdirSync(path2);
|
|
@@ -77274,7 +77293,7 @@ function baselinePath(root, digest2, create) {
|
|
|
77274
77293
|
throw error;
|
|
77275
77294
|
}
|
|
77276
77295
|
}
|
|
77277
|
-
return
|
|
77296
|
+
return join20(path2, `${hash2}.txt`);
|
|
77278
77297
|
}
|
|
77279
77298
|
function digestOf(text5) {
|
|
77280
77299
|
return `sha256:${createHash10("sha256").update(text5, "utf8").digest("hex")}`;
|
|
@@ -77390,10 +77409,10 @@ __export(exports_maintenanceStorage, {
|
|
|
77390
77409
|
APPROVED_REVISION_PATH: () => APPROVED_REVISION_PATH
|
|
77391
77410
|
});
|
|
77392
77411
|
import { readFile as readFile21 } from "node:fs/promises";
|
|
77393
|
-
import { join as
|
|
77412
|
+
import { join as join21 } from "node:path";
|
|
77394
77413
|
async function readMaintenance(root) {
|
|
77395
77414
|
try {
|
|
77396
|
-
return stateSchema.parse(JSON.parse(await readFile21(
|
|
77415
|
+
return stateSchema.parse(JSON.parse(await readFile21(join21(root, MAINTENANCE_ROOT, "current.json"), "utf8")));
|
|
77397
77416
|
} catch (error) {
|
|
77398
77417
|
if (error.code === "ENOENT")
|
|
77399
77418
|
return { protocol: "context.maintenance/v1", pending: [], completed: [] };
|
|
@@ -77401,18 +77420,18 @@ async function readMaintenance(root) {
|
|
|
77401
77420
|
}
|
|
77402
77421
|
}
|
|
77403
77422
|
function saveMaintenance(root, state) {
|
|
77404
|
-
return atomicWriteFile(
|
|
77423
|
+
return atomicWriteFile(join21(root, MAINTENANCE_ROOT, "current.json"), `${JSON.stringify(stateSchema.parse(state))}
|
|
77405
77424
|
`);
|
|
77406
77425
|
}
|
|
77407
77426
|
async function revisionStoragePath(root) {
|
|
77408
|
-
return (await readMaintenance(root)).active ?
|
|
77427
|
+
return (await readMaintenance(root)).active ? join21(MAINTENANCE_ROOT, "revision.json") : APPROVED_REVISION_PATH;
|
|
77409
77428
|
}
|
|
77410
77429
|
var MAINTENANCE_ROOT, APPROVED_REVISION_PATH, targetSchema, maintenanceInputSchema, requestSchema, stateSchema;
|
|
77411
77430
|
var init_maintenanceStorage = __esm(() => {
|
|
77412
77431
|
init_zod();
|
|
77413
77432
|
init_atomicWrite();
|
|
77414
|
-
MAINTENANCE_ROOT =
|
|
77415
|
-
APPROVED_REVISION_PATH =
|
|
77433
|
+
MAINTENANCE_ROOT = join21(".tmp", "context-runtime", "maintenance");
|
|
77434
|
+
APPROVED_REVISION_PATH = join21(".tmp", "context-runtime", "revision", "current.json");
|
|
77416
77435
|
targetSchema = exports_external.object({ path: exports_external.string().min(1), instruction: exports_external.string().trim().min(1) }).strict();
|
|
77417
77436
|
maintenanceInputSchema = exports_external.object({
|
|
77418
77437
|
id: exports_external.string().regex(/^[a-zA-Z0-9][a-zA-Z0-9._-]{0,95}$/u),
|
|
@@ -77439,24 +77458,24 @@ var init_maintenanceStorage = __esm(() => {
|
|
|
77439
77458
|
});
|
|
77440
77459
|
|
|
77441
77460
|
// src/project/lifecyclePaths.ts
|
|
77442
|
-
import { join as
|
|
77461
|
+
import { join as join22 } from "node:path";
|
|
77443
77462
|
var LIFECYCLE_ROOT, CANDIDATE_LEDGER_FILE, LIFECYCLE_STRUCTURE_FILE, REVIEW_RUNTIME_ROOT, REVIEW_ACTION_ROOT, STRUCTURE_REPORT_ROOT, CANDIDATE_SNAPSHOT_ROOT, INDEXER_RUNTIME_ROOT, INDEXER_WORKSET_VIEW_RUNTIME_ROOT;
|
|
77444
77463
|
var init_lifecyclePaths = __esm(() => {
|
|
77445
|
-
LIFECYCLE_ROOT =
|
|
77446
|
-
CANDIDATE_LEDGER_FILE =
|
|
77447
|
-
LIFECYCLE_STRUCTURE_FILE =
|
|
77448
|
-
REVIEW_RUNTIME_ROOT =
|
|
77449
|
-
REVIEW_ACTION_ROOT =
|
|
77450
|
-
STRUCTURE_REPORT_ROOT =
|
|
77451
|
-
CANDIDATE_SNAPSHOT_ROOT =
|
|
77452
|
-
INDEXER_RUNTIME_ROOT =
|
|
77453
|
-
INDEXER_WORKSET_VIEW_RUNTIME_ROOT =
|
|
77464
|
+
LIFECYCLE_ROOT = join22(".tmp", "context-runtime", "lifecycle");
|
|
77465
|
+
CANDIDATE_LEDGER_FILE = join22(LIFECYCLE_ROOT, "candidates.jsonl");
|
|
77466
|
+
LIFECYCLE_STRUCTURE_FILE = join22(LIFECYCLE_ROOT, "structure.yaml");
|
|
77467
|
+
REVIEW_RUNTIME_ROOT = join22(".tmp", "context-runtime", "review");
|
|
77468
|
+
REVIEW_ACTION_ROOT = join22(".tmp", "context-runtime", "review-actions");
|
|
77469
|
+
STRUCTURE_REPORT_ROOT = join22(".tmp", "context-runtime", "reports");
|
|
77470
|
+
CANDIDATE_SNAPSHOT_ROOT = join22(".tmp", "context-runtime", "extract", "candidates");
|
|
77471
|
+
INDEXER_RUNTIME_ROOT = join22(".tmp", "context-runtime", "indexer");
|
|
77472
|
+
INDEXER_WORKSET_VIEW_RUNTIME_ROOT = join22(INDEXER_RUNTIME_ROOT, "workset-views");
|
|
77454
77473
|
});
|
|
77455
77474
|
|
|
77456
77475
|
// src/project/candidateLedger.ts
|
|
77457
77476
|
import { existsSync as existsSync4 } from "node:fs";
|
|
77458
77477
|
import { mkdir as mkdir13, readFile as readFile22, rm as rm7, writeFile as writeFile8 } from "node:fs/promises";
|
|
77459
|
-
import { dirname as dirname16, join as
|
|
77478
|
+
import { dirname as dirname16, join as join23 } from "node:path";
|
|
77460
77479
|
function isRecord6(value) {
|
|
77461
77480
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
77462
77481
|
}
|
|
@@ -77637,7 +77656,7 @@ function parseCandidateLine(line, lineNumber) {
|
|
|
77637
77656
|
return parseCandidateRecord(parsed, lineNumber);
|
|
77638
77657
|
}
|
|
77639
77658
|
async function readCandidateRecords(projectRoot) {
|
|
77640
|
-
const filePath =
|
|
77659
|
+
const filePath = join23(projectRoot, CANDIDATE_LEDGER_FILE);
|
|
77641
77660
|
if (!existsSync4(filePath))
|
|
77642
77661
|
return [];
|
|
77643
77662
|
const records = await reuseCommandFileRead({ key: "candidate-records", paths: [filePath], read: async () => {
|
|
@@ -77720,7 +77739,7 @@ var init_newKnowledgePage = __esm(() => {
|
|
|
77720
77739
|
|
|
77721
77740
|
// src/project/approvedKnowledgeMetadata.ts
|
|
77722
77741
|
import { existsSync as existsSync5 } from "node:fs";
|
|
77723
|
-
import { join as
|
|
77742
|
+
import { join as join24 } from "node:path";
|
|
77724
77743
|
function isRecord7(value) {
|
|
77725
77744
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
77726
77745
|
}
|
|
@@ -77750,7 +77769,7 @@ function approvedKnowledgeMetadataIndex(structure) {
|
|
|
77750
77769
|
async function readApprovedKnowledgeMetadataIndex(projectRoot, structureOverride) {
|
|
77751
77770
|
if (structureOverride !== undefined)
|
|
77752
77771
|
return approvedKnowledgeMetadataIndex(structureOverride);
|
|
77753
|
-
const path2 =
|
|
77772
|
+
const path2 = join24(projectRoot, STRUCTURE_PATH);
|
|
77754
77773
|
if (!existsSync5(path2))
|
|
77755
77774
|
return approvedKnowledgeMetadataIndex(undefined);
|
|
77756
77775
|
try {
|
|
@@ -77827,7 +77846,7 @@ var init_approvedKnowledgeMetadata = __esm(() => {
|
|
|
77827
77846
|
init_src2();
|
|
77828
77847
|
init_packageKnowledgeProjection();
|
|
77829
77848
|
import_yaml15 = __toESM(require_dist(), 1);
|
|
77830
|
-
STRUCTURE_PATH =
|
|
77849
|
+
STRUCTURE_PATH = join24("knowledge", "structure.yaml");
|
|
77831
77850
|
FRONTMATTER_RE2 = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/u;
|
|
77832
77851
|
COMPACT_FIELDS = new Set([
|
|
77833
77852
|
"title",
|
|
@@ -77878,7 +77897,7 @@ function selectDeliveryPages(input) {
|
|
|
77878
77897
|
// src/project/knowledgeAssets.ts
|
|
77879
77898
|
import { existsSync as existsSync6 } from "node:fs";
|
|
77880
77899
|
import { readFile as readFile23, readdir as readdir8, rm as rm8 } from "node:fs/promises";
|
|
77881
|
-
import { dirname as dirname17, extname as extname10, join as
|
|
77900
|
+
import { dirname as dirname17, extname as extname10, join as join25, relative as relative13, resolve as resolve19, sep as sep3 } from "node:path";
|
|
77882
77901
|
function posixPath(value) {
|
|
77883
77902
|
return value.split(sep3).join("/");
|
|
77884
77903
|
}
|
|
@@ -77911,7 +77930,7 @@ function sourceAssetPath(documentPath, target) {
|
|
|
77911
77930
|
const decoded = decodedTarget(target);
|
|
77912
77931
|
if (/^[a-z][a-z0-9+.-]*:/iu.test(decoded) || decoded.startsWith("#") || decoded.startsWith("/"))
|
|
77913
77932
|
return;
|
|
77914
|
-
const normalized = posixPath(
|
|
77933
|
+
const normalized = posixPath(join25(dirname17(documentPath), decoded));
|
|
77915
77934
|
if (normalized === "assets" || normalized.startsWith("assets/"))
|
|
77916
77935
|
return normalized;
|
|
77917
77936
|
return;
|
|
@@ -77923,7 +77942,7 @@ function selectedAssets(input) {
|
|
|
77923
77942
|
const selected = new Map;
|
|
77924
77943
|
for (const link of markdownInlineLinks(input.content)) {
|
|
77925
77944
|
const target = link.target;
|
|
77926
|
-
const pageTarget = posixPath(
|
|
77945
|
+
const pageTarget = posixPath(join25(dirname17(input.pageRelPath), decodedTarget(target)));
|
|
77927
77946
|
const sourceRoot2 = posixPath(input.sourceMaterializedAt).replace(/\/$/u, "") + "/";
|
|
77928
77947
|
const path2 = sourceAssetPath(input.documentPath, target) ?? (pageTarget.startsWith(sourceRoot2) ? pageTarget.slice(sourceRoot2.length) : undefined);
|
|
77929
77948
|
if (path2 === undefined)
|
|
@@ -77968,7 +77987,7 @@ async function projectKnowledgeAssets(input) {
|
|
|
77968
77987
|
next: "Rerun the source capture and resolve resource materialization errors before Review."
|
|
77969
77988
|
});
|
|
77970
77989
|
}
|
|
77971
|
-
const sourcePath =
|
|
77990
|
+
const sourcePath = join25(input.projectRoot, input.sourceMaterializedAt, asset.path);
|
|
77972
77991
|
let bytes;
|
|
77973
77992
|
try {
|
|
77974
77993
|
bytes = await readFile23(sourcePath);
|
|
@@ -77984,7 +78003,7 @@ async function projectKnowledgeAssets(input) {
|
|
|
77984
78003
|
knowledgePathBySourcePath.set(asset.path, relPath);
|
|
77985
78004
|
assets.push({
|
|
77986
78005
|
relPath,
|
|
77987
|
-
absPath:
|
|
78006
|
+
absPath: join25(input.projectRoot, relPath),
|
|
77988
78007
|
bytes,
|
|
77989
78008
|
contentHash: asset.content_hash
|
|
77990
78009
|
});
|
|
@@ -78006,7 +78025,7 @@ function canonicalizeKnowledgeAssetLinks(input) {
|
|
|
78006
78025
|
let rewritten = 0;
|
|
78007
78026
|
const content3 = replaceMarkdownInlineLinkTargets(input.content, (link) => {
|
|
78008
78027
|
const sourcePath = sourceAssetPath(input.documentPath, link.target);
|
|
78009
|
-
const projectedPath = input.pageRelPath === undefined ? undefined : posixPath(
|
|
78028
|
+
const projectedPath = input.pageRelPath === undefined ? undefined : posixPath(join25(dirname17(input.pageRelPath), decodedTarget(link.target)));
|
|
78010
78029
|
const asset = (sourcePath === undefined ? undefined : bySourcePath.get(sourcePath)) ?? (projectedPath === undefined ? undefined : byKnowledgePath.get(projectedPath));
|
|
78011
78030
|
if (asset?.content_hash === undefined)
|
|
78012
78031
|
return;
|
|
@@ -78021,7 +78040,7 @@ function knowledgeAssetReferences(input) {
|
|
|
78021
78040
|
const target = link.target;
|
|
78022
78041
|
if (/^[a-z][a-z0-9+.-]*:/iu.test(target) || target.startsWith("#"))
|
|
78023
78042
|
continue;
|
|
78024
|
-
const resolved = posixPath(
|
|
78043
|
+
const resolved = posixPath(join25(dirname17(input.pageRelPath), decodedTarget(target)));
|
|
78025
78044
|
if (resolved.startsWith("knowledge/assets/"))
|
|
78026
78045
|
references.add(resolved);
|
|
78027
78046
|
}
|
|
@@ -78042,7 +78061,7 @@ async function walkFiles2(root) {
|
|
|
78042
78061
|
const files = [];
|
|
78043
78062
|
const visit3 = async (dir) => {
|
|
78044
78063
|
for (const entry of await readdir8(dir, { withFileTypes: true })) {
|
|
78045
|
-
const path2 =
|
|
78064
|
+
const path2 = join25(dir, entry.name);
|
|
78046
78065
|
if (entry.isDirectory())
|
|
78047
78066
|
await visit3(path2);
|
|
78048
78067
|
else if (entry.isFile())
|
|
@@ -78053,8 +78072,8 @@ async function walkFiles2(root) {
|
|
|
78053
78072
|
return files;
|
|
78054
78073
|
}
|
|
78055
78074
|
async function removeOrphanKnowledgeAssets(projectRoot, currentReferences) {
|
|
78056
|
-
const knowledgeRoot =
|
|
78057
|
-
const assetRoot =
|
|
78075
|
+
const knowledgeRoot = join25(projectRoot, "knowledge");
|
|
78076
|
+
const assetRoot = join25(knowledgeRoot, "assets");
|
|
78058
78077
|
if (!existsSync6(assetRoot))
|
|
78059
78078
|
return [];
|
|
78060
78079
|
const referenced = new Set(currentReferences ?? []);
|
|
@@ -78099,7 +78118,7 @@ var init_knowledgeAssets = __esm(() => {
|
|
|
78099
78118
|
// src/project/documentEvidenceIndex.ts
|
|
78100
78119
|
import { Buffer as Buffer3 } from "node:buffer";
|
|
78101
78120
|
import { mkdir as mkdir14, readFile as readFile24, writeFile as writeFile9 } from "node:fs/promises";
|
|
78102
|
-
import { dirname as dirname18, join as
|
|
78121
|
+
import { dirname as dirname18, join as join26 } from "node:path";
|
|
78103
78122
|
function workspaceStateError(message, detail = {}) {
|
|
78104
78123
|
return new ContextError(ExitCode.WorkspaceStateError, message, {
|
|
78105
78124
|
category: ErrorCategory.WorkspaceStateInvalid,
|
|
@@ -78113,10 +78132,10 @@ function userInputError(message, detail = {}) {
|
|
|
78113
78132
|
});
|
|
78114
78133
|
}
|
|
78115
78134
|
function committedManifestRelativePath(sourceType, sourceName) {
|
|
78116
|
-
return
|
|
78135
|
+
return join26("sources", sourceType, normalizeDocumentSourceName(sourceName), "manifest.json");
|
|
78117
78136
|
}
|
|
78118
78137
|
function runtimeEvidenceIndexRelativePath(sourceType, sourceName) {
|
|
78119
|
-
return
|
|
78138
|
+
return join26(".tmp", "context-runtime", "evidence", sourceType, normalizeDocumentSourceName(sourceName), "source-index.json");
|
|
78120
78139
|
}
|
|
78121
78140
|
async function readJsonFile(path2, next) {
|
|
78122
78141
|
try {
|
|
@@ -78138,7 +78157,7 @@ function assertManifestSource(input) {
|
|
|
78138
78157
|
}
|
|
78139
78158
|
}
|
|
78140
78159
|
async function readCommittedSnapshotFile(input) {
|
|
78141
|
-
const absolutePath =
|
|
78160
|
+
const absolutePath = join26(input.projectRoot, input.materializedAt, input.path);
|
|
78142
78161
|
try {
|
|
78143
78162
|
return await readFile24(absolutePath);
|
|
78144
78163
|
} catch (error) {
|
|
@@ -78185,9 +78204,9 @@ async function buildCommittedEvidenceIndex(input) {
|
|
|
78185
78204
|
});
|
|
78186
78205
|
}
|
|
78187
78206
|
const managed = input.sourceType === "note" || input.sourceType === "sessions" ? await (await Promise.resolve().then(() => (init_managedDocumentSnapshot(), exports_managedDocumentSnapshot))).readManagedDocumentSnapshot(input.projectRoot, input.sourceType, sourceName) : undefined;
|
|
78188
|
-
const materializedAt = managed?.materializedAt ?? input.materializedAt ??
|
|
78207
|
+
const materializedAt = managed?.materializedAt ?? input.materializedAt ?? join26("sources", input.sourceType, sourceName);
|
|
78189
78208
|
const manifestRelPath = managed ? `sources/${input.sourceType}/${sourceName}` : input.manifestPath ?? committedManifestRelativePath(input.sourceType, sourceName);
|
|
78190
|
-
const manifestAbsPath =
|
|
78209
|
+
const manifestAbsPath = join26(input.projectRoot, manifestRelPath);
|
|
78191
78210
|
let manifest;
|
|
78192
78211
|
try {
|
|
78193
78212
|
manifest = managed?.manifest ?? parseDocumentSnapshotForSource(await readJsonFile(manifestAbsPath, `rerun context run capture:${input.sourceType}:${sourceName} or restore ${manifestRelPath}`), sourceName);
|
|
@@ -78267,7 +78286,7 @@ async function buildCommittedEvidenceIndex(input) {
|
|
|
78267
78286
|
continue;
|
|
78268
78287
|
let bytes;
|
|
78269
78288
|
try {
|
|
78270
|
-
bytes = await readFile24(
|
|
78289
|
+
bytes = await readFile24(join26(input.projectRoot, materializedAt, asset.path));
|
|
78271
78290
|
} catch (error) {
|
|
78272
78291
|
const message = error instanceof Error ? error.message : String(error);
|
|
78273
78292
|
throw workspaceStateError(`document snapshot audit asset is missing: ${asset.path}`, {
|
|
@@ -78308,7 +78327,7 @@ async function buildCommittedEvidenceIndex(input) {
|
|
|
78308
78327
|
documents
|
|
78309
78328
|
};
|
|
78310
78329
|
const runtimeIndexPath = runtimeEvidenceIndexRelativePath(input.sourceType, sourceName);
|
|
78311
|
-
const absoluteRuntimeIndexPath =
|
|
78330
|
+
const absoluteRuntimeIndexPath = join26(input.projectRoot, runtimeIndexPath);
|
|
78312
78331
|
if (input.writeRuntimeIndex ?? true) {
|
|
78313
78332
|
await mkdir14(dirname18(absoluteRuntimeIndexPath), { recursive: true });
|
|
78314
78333
|
await writeFile9(absoluteRuntimeIndexPath, `${JSON.stringify(index2, null, 2)}
|
|
@@ -78332,7 +78351,7 @@ var init_documentEvidenceIndex = __esm(() => {
|
|
|
78332
78351
|
});
|
|
78333
78352
|
|
|
78334
78353
|
// src/project/assetSourceRegistry.ts
|
|
78335
|
-
import { join as
|
|
78354
|
+
import { join as join27 } from "node:path";
|
|
78336
78355
|
function emptySourceRegistryLookup(loaded) {
|
|
78337
78356
|
return {
|
|
78338
78357
|
loaded,
|
|
@@ -78402,10 +78421,10 @@ function registeredDocumentSource(registry2, sourceType, sourceName) {
|
|
|
78402
78421
|
return registry2.documents[sourceType].get(sourceName);
|
|
78403
78422
|
}
|
|
78404
78423
|
function defaultDocumentMaterializedAt(sourceType, sourceName) {
|
|
78405
|
-
return
|
|
78424
|
+
return join27("sources", sourceType, sourceName);
|
|
78406
78425
|
}
|
|
78407
78426
|
function defaultDocumentManifest(materializedAt) {
|
|
78408
|
-
return
|
|
78427
|
+
return join27(materializedAt, "manifest.json");
|
|
78409
78428
|
}
|
|
78410
78429
|
async function getCommittedEvidenceIndex(input) {
|
|
78411
78430
|
const key = `${input.sourceType}:${input.sourceName}:${input.materializedAt}:${input.manifestPath}`;
|
|
@@ -78698,7 +78717,7 @@ __export(exports_approvedRevisionBatch, {
|
|
|
78698
78717
|
approvedRevisionCandidateApplied: () => approvedRevisionCandidateApplied
|
|
78699
78718
|
});
|
|
78700
78719
|
import { readFile as readFile26 } from "node:fs/promises";
|
|
78701
|
-
import { join as
|
|
78720
|
+
import { join as join28 } from "node:path";
|
|
78702
78721
|
async function prepareRevisionBatchContinuation(root, request, batch) {
|
|
78703
78722
|
const [next, ...remaining] = request.pending_targets ?? [];
|
|
78704
78723
|
if (!next)
|
|
@@ -78778,13 +78797,13 @@ async function observeApprovedRevisionBatch(root, request) {
|
|
|
78778
78797
|
for (const original of expected) {
|
|
78779
78798
|
const candidate = rows.find((row) => row.candidate_id === original.candidate_id);
|
|
78780
78799
|
const revision = original.approved_revision;
|
|
78781
|
-
const bytes = await readFile26(
|
|
78800
|
+
const bytes = await readFile26(join28(root, "knowledge", revision.previous_path ?? original.path), "utf8").catch((error) => {
|
|
78782
78801
|
if (error.code === "ENOENT")
|
|
78783
78802
|
return;
|
|
78784
78803
|
throw error;
|
|
78785
78804
|
});
|
|
78786
78805
|
if (!candidate) {
|
|
78787
|
-
const applied = await readFile26(
|
|
78806
|
+
const applied = await readFile26(join28(root, "knowledge", original.path), "utf8").catch(() => {
|
|
78788
78807
|
return;
|
|
78789
78808
|
});
|
|
78790
78809
|
if (await approvedRevisionCandidateApplied(root, original, applied))
|
|
@@ -78954,7 +78973,7 @@ var init_verifyFrontmatter = __esm(() => {
|
|
|
78954
78973
|
// src/project/productionSubmissionFiles.ts
|
|
78955
78974
|
import { constants as constants3 } from "node:fs";
|
|
78956
78975
|
import { lstat as lstat5, open as open3, realpath as realpath4 } from "node:fs/promises";
|
|
78957
|
-
import { isAbsolute as isAbsolute11, join as
|
|
78976
|
+
import { isAbsolute as isAbsolute11, join as join29, relative as relative14 } from "node:path";
|
|
78958
78977
|
function invalidFile(path2, message) {
|
|
78959
78978
|
return new ContextError(ExitCode.UserError, message, {
|
|
78960
78979
|
category: ErrorCategory.UserInputInvalid,
|
|
@@ -78965,7 +78984,7 @@ function invalidFile(path2, message) {
|
|
|
78965
78984
|
});
|
|
78966
78985
|
}
|
|
78967
78986
|
function productionAgentDirectory(stage) {
|
|
78968
|
-
return
|
|
78987
|
+
return join29(".tmp", "agent-work", "production-stages", localId.parse(stage));
|
|
78969
78988
|
}
|
|
78970
78989
|
function assertRelativeFile(path2) {
|
|
78971
78990
|
if (isAbsolute11(path2) || /^[a-zA-Z]:/u.test(path2) || path2.includes("\\") || path2.includes("\x00") || path2.split("/").some((part) => !part || part === "." || part === "..")) {
|
|
@@ -78976,14 +78995,14 @@ async function readProductionFile(input) {
|
|
|
78976
78995
|
return readFixedProductionFile({ ...input, directory: productionAgentDirectory(input.stage) });
|
|
78977
78996
|
}
|
|
78978
78997
|
async function readProductionPlanningFile(input) {
|
|
78979
|
-
return readFixedProductionFile({ ...input, directory:
|
|
78998
|
+
return readFixedProductionFile({ ...input, directory: join29(".tmp", "agent-work") });
|
|
78980
78999
|
}
|
|
78981
79000
|
async function readFixedProductionFile(input) {
|
|
78982
79001
|
assertRelativeFile(input.path);
|
|
78983
79002
|
const limit = input.maxBytes ?? DEFAULT_LIMITS.file_bytes;
|
|
78984
79003
|
if (!Number.isSafeInteger(limit) || limit < 1)
|
|
78985
79004
|
throw invalidFile(input.path, "File budget must be a positive safe integer.");
|
|
78986
|
-
const local =
|
|
79005
|
+
const local = join29(input.directory, input.path);
|
|
78987
79006
|
let handle;
|
|
78988
79007
|
try {
|
|
78989
79008
|
const root = await realpath4(input.projectRoot);
|
|
@@ -78994,7 +79013,7 @@ async function readFixedProductionFile(input) {
|
|
|
78994
79013
|
handle = await open3(absolute, constants3.O_RDONLY | constants3.O_NOFOLLOW | constants3.O_NONBLOCK);
|
|
78995
79014
|
const opened = await handle.stat();
|
|
78996
79015
|
const resolved = await realpath4(absolute);
|
|
78997
|
-
const stageRoot =
|
|
79016
|
+
const stageRoot = join29(root, input.directory);
|
|
78998
79017
|
const within = relative14(stageRoot, resolved);
|
|
78999
79018
|
if (within.startsWith("..") || isAbsolute11(within) || opened.dev !== before.dev || opened.ino !== before.ino) {
|
|
79000
79019
|
throw invalidFile(input.path, "The draft path changed while opening it; restore a stage-local file and retry.");
|
|
@@ -79120,7 +79139,7 @@ var init_productionSubmissionFiles = __esm(() => {
|
|
|
79120
79139
|
|
|
79121
79140
|
// src/project/productionArticleTarget.ts
|
|
79122
79141
|
import { readFile as readFile27 } from "node:fs/promises";
|
|
79123
|
-
import { join as
|
|
79142
|
+
import { join as join30 } from "node:path";
|
|
79124
79143
|
function productionApprovedTargetsIndex(metadata) {
|
|
79125
79144
|
const articles = validateArticleStructureEntries(metadata.structure?.articles ?? []);
|
|
79126
79145
|
return {
|
|
@@ -79146,7 +79165,7 @@ async function readProductionArticleTarget(input) {
|
|
|
79146
79165
|
let markdown = existing[0]?.body;
|
|
79147
79166
|
if (markdown === undefined) {
|
|
79148
79167
|
try {
|
|
79149
|
-
markdown = await readFile27(await safeProjectTarget(input.projectRoot,
|
|
79168
|
+
markdown = await readFile27(await safeProjectTarget(input.projectRoot, join30("knowledge", task.path)), "utf8");
|
|
79150
79169
|
} catch (error) {
|
|
79151
79170
|
if (error.code !== "ENOENT")
|
|
79152
79171
|
throw error;
|
|
@@ -79166,7 +79185,7 @@ async function readProductionArticleTarget(input) {
|
|
|
79166
79185
|
}
|
|
79167
79186
|
let approvedBaseDigest = existing[0]?.approved_revision?.base_digest;
|
|
79168
79187
|
if (approvedBaseDigest === undefined) {
|
|
79169
|
-
const formalMarkdown = formal.length ? await readFile27(await safeProjectTarget(input.projectRoot,
|
|
79188
|
+
const formalMarkdown = formal.length ? await readFile27(await safeProjectTarget(input.projectRoot, join30("knowledge", task.path)), "utf8") : undefined;
|
|
79170
79189
|
approvedBaseDigest = formalMarkdown === undefined ? null : durableContentDigest(formalMarkdown);
|
|
79171
79190
|
}
|
|
79172
79191
|
return { visibility, approvedBaseDigest, ...sections ? { base: { markdown, sections } } : {} };
|
|
@@ -79405,10 +79424,10 @@ __export(exports_productionStageStore, {
|
|
|
79405
79424
|
});
|
|
79406
79425
|
import { constants as constants4 } from "node:fs";
|
|
79407
79426
|
import { readFile as readFile28, access as access2, stat as stat7 } from "node:fs/promises";
|
|
79408
|
-
import { join as
|
|
79427
|
+
import { join as join31 } from "node:path";
|
|
79409
79428
|
function productionStageDirectory(id3) {
|
|
79410
79429
|
productionAgentDirectory(id3);
|
|
79411
|
-
return
|
|
79430
|
+
return join31(PRODUCTION_STAGES_ROOT, id3);
|
|
79412
79431
|
}
|
|
79413
79432
|
async function readOptional(root, path2) {
|
|
79414
79433
|
const absolute = await safeProjectTarget(root, path2);
|
|
@@ -79459,7 +79478,7 @@ async function readProductionStageSnapshot(root, id3) {
|
|
|
79459
79478
|
}
|
|
79460
79479
|
id3 = value.stage;
|
|
79461
79480
|
}
|
|
79462
|
-
feedback.file =
|
|
79481
|
+
feedback.file = join31(productionStageDirectory(id3), "manifest.json");
|
|
79463
79482
|
const content3 = await readOptional(root, feedback.file);
|
|
79464
79483
|
if (content3 === undefined)
|
|
79465
79484
|
return;
|
|
@@ -79472,7 +79491,7 @@ async function readProductionStageSnapshot(root, id3) {
|
|
|
79472
79491
|
async function saveProductionStage(root, value) {
|
|
79473
79492
|
const stage = validateProductionStage(value);
|
|
79474
79493
|
await withProjectWriteLock(root, "production-stage", async () => {
|
|
79475
|
-
await writeProductionProjection(root,
|
|
79494
|
+
await writeProductionProjection(root, join31(productionStageDirectory(stage.id), "manifest.json"), `${JSON.stringify(stage)}
|
|
79476
79495
|
`);
|
|
79477
79496
|
await writeProductionProjection(root, CURRENT_PATH, `${JSON.stringify({ stage: stage.id })}
|
|
79478
79497
|
`);
|
|
@@ -79496,15 +79515,15 @@ function productionPlanMarkdown(stage) {
|
|
|
79496
79515
|
...stage.tasks.filter((task) => task.status === "replaced").map((task) => `- ${task.path}: ${task.reason ?? "Replaced by the current plan"}`)
|
|
79497
79516
|
] : [],
|
|
79498
79517
|
"",
|
|
79499
|
-
`Planned skill guidance: ${
|
|
79500
|
-
`Available skill entries: ${
|
|
79518
|
+
`Planned skill guidance: ${join31(directory, "indexer-usage.yaml")}`,
|
|
79519
|
+
`Available skill entries: ${join31(directory, "skills.md")}`,
|
|
79501
79520
|
"",
|
|
79502
79521
|
`Remaining investigation: ${stage.pending_scopes.join(", ") || "none"}`,
|
|
79503
79522
|
"",
|
|
79504
79523
|
...!stage.report_approved && stage.planning_complete ? [
|
|
79505
|
-
`If the user requests changes, edit ${productionAgentDirectory(stage.id)}/submissions/plan.yaml using ${
|
|
79524
|
+
`If the user requests changes, edit ${productionAgentDirectory(stage.id)}/submissions/plan.yaml using ${join31(directory, "planning.schema.json")}.`,
|
|
79506
79525
|
`Resubmit: context action complete-current --revision ${stage.id} --input ${productionAgentDirectory(stage.id)}/submissions/plan.yaml --format json`,
|
|
79507
|
-
"Then present the updated report and
|
|
79526
|
+
"Then present the updated report and apply context.gate.work_start_scope; an old decision does not approve changed article goals.",
|
|
79508
79527
|
""
|
|
79509
79528
|
] : [],
|
|
79510
79529
|
...stage.gaps.map((gap) => `- ${gap.scope}: ${gap.reason}`),
|
|
@@ -79528,12 +79547,12 @@ async function materializeProductionStage(input) {
|
|
|
79528
79547
|
changed += 1;
|
|
79529
79548
|
};
|
|
79530
79549
|
if (input.materials) {
|
|
79531
|
-
await write(
|
|
79532
|
-
} else if (dispatch.batches.length && !await hasReadableProjection(input.projectRoot,
|
|
79550
|
+
await write(join31(directory, "shared/requirements.md"), input.materials.requirements);
|
|
79551
|
+
} else if (dispatch.batches.length && !await hasReadableProjection(input.projectRoot, join31(directory, "shared/requirements.md"))) {
|
|
79533
79552
|
throw new TypeError("Stage materials are missing. Re-prepare the current plan's directory; accepted tasks remain saved.");
|
|
79534
79553
|
}
|
|
79535
|
-
await write(
|
|
79536
|
-
await write(
|
|
79554
|
+
await write(join31(directory, "capabilities.yaml"), import_yaml21.default.stringify(input.capabilities));
|
|
79555
|
+
await write(join31(directory, "skills.md"), [
|
|
79537
79556
|
"# Available skills",
|
|
79538
79557
|
"",
|
|
79539
79558
|
...input.capabilities.skills.map((skill) => `- ${skill.name}${skill.entry ? `: ${skill.entry}` : " (read through the host)"}`),
|
|
@@ -79542,13 +79561,13 @@ async function materializeProductionStage(input) {
|
|
|
79542
79561
|
""
|
|
79543
79562
|
].join(`
|
|
79544
79563
|
`));
|
|
79545
|
-
await write(
|
|
79546
|
-
await write(
|
|
79564
|
+
await write(join31(directory, "indexer-usage.yaml"), import_yaml21.default.stringify(stage.indexer_usage));
|
|
79565
|
+
await write(join31(directory, "plan.md"), productionPlanMarkdown(stage));
|
|
79547
79566
|
const issued = new Set(dispatch.batches.flatMap((batch) => batch.tasks));
|
|
79548
79567
|
const neededScopes = new Set(stage.tasks.filter((task) => issued.has(task.id)).flatMap((task) => task.sources.map((source2) => source2.scope)));
|
|
79549
79568
|
const scopePaths = new Map;
|
|
79550
79569
|
for (const scope2 of stage.scopes) {
|
|
79551
|
-
const path2 =
|
|
79570
|
+
const path2 = join31(directory, productionSourceFile(scope2.scope));
|
|
79552
79571
|
scopePaths.set(scope2.scope, path2);
|
|
79553
79572
|
if (input.materials) {
|
|
79554
79573
|
const content3 = input.materials.sources.get(scope2.scope);
|
|
@@ -79562,15 +79581,15 @@ async function materializeProductionStage(input) {
|
|
|
79562
79581
|
for (const [path2, content3] of input.materials?.guidance ?? []) {
|
|
79563
79582
|
if (!/^[a-zA-Z0-9][a-zA-Z0-9._-]*\.md$/u.test(path2))
|
|
79564
79583
|
throw new TypeError("Guidance files need a local Markdown basename");
|
|
79565
|
-
await write(
|
|
79584
|
+
await write(join31(directory, "guidance", path2), content3);
|
|
79566
79585
|
}
|
|
79567
79586
|
const submittedTasks = [];
|
|
79568
79587
|
let candidates;
|
|
79569
79588
|
let approved;
|
|
79570
79589
|
const tasksById = new Map(stage.tasks.map((task) => [task.id, task]));
|
|
79571
79590
|
for (const batch of dispatch.batches) {
|
|
79572
|
-
const batchPath =
|
|
79573
|
-
await write(
|
|
79591
|
+
const batchPath = join31(directory, "batches", batch.id);
|
|
79592
|
+
await write(join31(batchPath, "batch.md"), `# Batch ${batch.id}
|
|
79574
79593
|
|
|
79575
79594
|
Tasks: ${batch.tasks.join(", ")}
|
|
79576
79595
|
|
|
@@ -79579,10 +79598,10 @@ Read each task's scope and dependencies. Workers write drafts only; the coordina
|
|
|
79579
79598
|
for (let offset2 = 0;offset2 < batch.tasks.length; offset2 += 8) {
|
|
79580
79599
|
const projections = await Promise.allSettled(batch.tasks.slice(offset2, offset2 + 8).map(async (id3) => {
|
|
79581
79600
|
const task = tasksById.get(id3);
|
|
79582
|
-
const taskRoot =
|
|
79601
|
+
const taskRoot = join31(batchPath, "tasks", id3);
|
|
79583
79602
|
if (task.base !== null) {
|
|
79584
|
-
const basePath =
|
|
79585
|
-
const referencesPath =
|
|
79603
|
+
const basePath = join31(taskRoot, "base.md");
|
|
79604
|
+
const referencesPath = join31(taskRoot, "base-references.yaml");
|
|
79586
79605
|
let missing = false;
|
|
79587
79606
|
try {
|
|
79588
79607
|
await access2(await safeProjectTarget(input.projectRoot, basePath));
|
|
@@ -79606,7 +79625,7 @@ Read each task's scope and dependencies. Workers write drafts only; the coordina
|
|
|
79606
79625
|
await write(referencesPath, import_yaml21.default.stringify({ sections: target.base.sections }));
|
|
79607
79626
|
}
|
|
79608
79627
|
}
|
|
79609
|
-
await write(
|
|
79628
|
+
await write(join31(taskRoot, "task.md"), [
|
|
79610
79629
|
`# ${task.question}`,
|
|
79611
79630
|
"",
|
|
79612
79631
|
`Target: ${task.path}`,
|
|
@@ -79616,16 +79635,16 @@ Read each task's scope and dependencies. Workers write drafts only; the coordina
|
|
|
79616
79635
|
task.brief ?? "Read the authorized sources and write the complete article, or revise the existing article's affected fragments.",
|
|
79617
79636
|
"",
|
|
79618
79637
|
...task.base !== null ? [
|
|
79619
|
-
`Revision base: ${
|
|
79620
|
-
`Existing sections and references: ${
|
|
79638
|
+
`Revision base: ${join31(taskRoot, "base.md")}`,
|
|
79639
|
+
`Existing sections and references: ${join31(taskRoot, "base-references.yaml")}`,
|
|
79621
79640
|
""
|
|
79622
79641
|
] : [],
|
|
79623
|
-
`Shared requirements: ${
|
|
79624
|
-
`Relevant planned skills: ${
|
|
79642
|
+
`Shared requirements: ${join31(directory, "shared/requirements.md")}`,
|
|
79643
|
+
`Relevant planned skills: ${join31(directory, "indexer-usage.yaml")}`,
|
|
79625
79644
|
""
|
|
79626
79645
|
].join(`
|
|
79627
79646
|
`));
|
|
79628
|
-
await write(
|
|
79647
|
+
await write(join31(taskRoot, "sources.md"), [
|
|
79629
79648
|
"# Authorized sources",
|
|
79630
79649
|
"",
|
|
79631
79650
|
...task.sources.map((source2) => `- ${source2.scope}: ${scopePaths.get(source2.scope)}`),
|
|
@@ -79644,24 +79663,24 @@ Read each task's scope and dependencies. Workers write drafts only; the coordina
|
|
|
79644
79663
|
}
|
|
79645
79664
|
}
|
|
79646
79665
|
}
|
|
79647
|
-
const submission = dispatch.batches.length ?
|
|
79666
|
+
const submission = dispatch.batches.length ? join31(directory, "submission.yaml") : undefined;
|
|
79648
79667
|
if (submission)
|
|
79649
79668
|
await write(submission, import_yaml21.default.stringify({ stage: stage.id, tasks: submittedTasks }));
|
|
79650
|
-
await write(
|
|
79669
|
+
await write(join31(directory, "stage.md"), [
|
|
79651
79670
|
`# ${stage.purpose}`,
|
|
79652
79671
|
"",
|
|
79653
79672
|
`Stage: ${stage.id}`,
|
|
79654
79673
|
`State: ${dispatch.state}`,
|
|
79655
79674
|
`Scheduling: ${dispatch.mode}`,
|
|
79656
79675
|
"",
|
|
79657
|
-
...dispatch.batches.map((batch) => `- Batch ${batch.id}: ${
|
|
79676
|
+
...dispatch.batches.map((batch) => `- Batch ${batch.id}: ${join31(directory, "batches", batch.id, "batch.md")}`),
|
|
79658
79677
|
"",
|
|
79659
79678
|
`Agent output directory: ${agent}`,
|
|
79660
79679
|
`Remaining investigation: ${stage.pending_scopes.join(", ") || "none"}`,
|
|
79661
79680
|
"",
|
|
79662
79681
|
...stage.tasks.filter((task) => task.status === "blocked").map((task) => `- Blocked task ${task.id}: ${task.path} — ${task.reason ?? "Investigate the task's source and dependencies."}`),
|
|
79663
79682
|
"",
|
|
79664
|
-
`To add articles within this confirmed purpose and source scope, submit a plan amendment using ${
|
|
79683
|
+
`To add articles within this confirmed purpose and source scope, submit a plan amendment using ${join31(directory, "planning.schema.json")}.`,
|
|
79665
79684
|
"During writing, articles adds tasks; replaces explicitly names unfinished task IDs. Existing task IDs may be used in after. Do not resubmit the whole original plan or widen the purpose without user confirmation.",
|
|
79666
79685
|
`Plan amendment: context action complete-current --revision ${stage.id} --input ${agent}/submissions/plan-amendment.yaml --format json`,
|
|
79667
79686
|
"",
|
|
@@ -79689,7 +79708,7 @@ async function prepareNextProductionStage(input) {
|
|
|
79689
79708
|
return materializeProductionStage({ projectRoot: input.projectRoot, stage: input.stage, capabilities });
|
|
79690
79709
|
}
|
|
79691
79710
|
async function readProductionCapabilities(root, stage) {
|
|
79692
|
-
const saved = await readOptional(root,
|
|
79711
|
+
const saved = await readOptional(root, join31(productionStageDirectory(stage), "capabilities.yaml"));
|
|
79693
79712
|
return productionCapabilitiesSchema.parse(saved ? import_yaml21.default.parse(saved) : {});
|
|
79694
79713
|
}
|
|
79695
79714
|
var import_yaml21, PRODUCTION_STAGES_ROOT = ".tmp/context-runtime/production-stages", CURRENT_PATH;
|
|
@@ -79705,19 +79724,19 @@ var init_productionStageStore = __esm(() => {
|
|
|
79705
79724
|
init_productionFeedback();
|
|
79706
79725
|
init_productionStage();
|
|
79707
79726
|
import_yaml21 = __toESM(require_dist(), 1);
|
|
79708
|
-
CURRENT_PATH =
|
|
79727
|
+
CURRENT_PATH = join31(PRODUCTION_STAGES_ROOT, "current.json");
|
|
79709
79728
|
});
|
|
79710
79729
|
|
|
79711
79730
|
// src/project/indexerTemplateSnapshots.ts
|
|
79712
79731
|
import { readFile as readFile29, mkdir as mkdir16 } from "node:fs/promises";
|
|
79713
|
-
import { join as
|
|
79732
|
+
import { join as join32 } from "node:path";
|
|
79714
79733
|
function object3(value) {
|
|
79715
79734
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : undefined;
|
|
79716
79735
|
}
|
|
79717
79736
|
function snapshotPath(root, digest3) {
|
|
79718
79737
|
if (!/^sha256:[a-f0-9]{64}$/u.test(digest3))
|
|
79719
79738
|
throw new TypeError("Invalid template snapshot digest");
|
|
79720
|
-
return
|
|
79739
|
+
return join32(root, ...ROOT, `${digest3.slice(7)}.json`);
|
|
79721
79740
|
}
|
|
79722
79741
|
async function encodeTemplateSnapshots(root, value) {
|
|
79723
79742
|
const spec = object3(value);
|
|
@@ -79756,7 +79775,7 @@ async function encodeTemplateSnapshots(root, value) {
|
|
|
79756
79775
|
if (indexerProtocolDigest(JSON.parse(existing)) !== digest3)
|
|
79757
79776
|
throw new TypeError("Template snapshot integrity mismatch");
|
|
79758
79777
|
} else {
|
|
79759
|
-
await mkdir16(
|
|
79778
|
+
await mkdir16(join32(root, ...ROOT), { recursive: true });
|
|
79760
79779
|
await atomicWriteFile(path2, canonicalIndexerJson(shared));
|
|
79761
79780
|
}
|
|
79762
79781
|
return { protocol: REF, digest: digest3, ...binding ? { binding } : {} };
|
|
@@ -79838,7 +79857,7 @@ __export(exports_indexerMainRunStoreRecords, {
|
|
|
79838
79857
|
INDEXER_MAIN_RUN_CURRENT_PATH: () => INDEXER_MAIN_RUN_CURRENT_PATH
|
|
79839
79858
|
});
|
|
79840
79859
|
import { readFile as readFile30 } from "node:fs/promises";
|
|
79841
|
-
import { join as
|
|
79860
|
+
import { join as join33 } from "node:path";
|
|
79842
79861
|
function isRecord9(value) {
|
|
79843
79862
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
79844
79863
|
}
|
|
@@ -79849,13 +79868,13 @@ function digestName(digest3) {
|
|
|
79849
79868
|
return digest3.slice("sha256:".length);
|
|
79850
79869
|
}
|
|
79851
79870
|
function runSpecPath(requestDigest) {
|
|
79852
|
-
return
|
|
79871
|
+
return join33(INDEXER_MAIN_RUN_STORE_ROOT, "requests", `${digestName(requestDigest)}.json`);
|
|
79853
79872
|
}
|
|
79854
79873
|
function acceptedCachePath(requestDigest) {
|
|
79855
|
-
return
|
|
79874
|
+
return join33(INDEXER_MAIN_RUN_STORE_ROOT, "accepted", `${digestName(requestDigest)}.json`);
|
|
79856
79875
|
}
|
|
79857
79876
|
function partitionConvergencePath(attemptDigest) {
|
|
79858
|
-
return
|
|
79877
|
+
return join33(INDEXER_MAIN_RUN_STORE_ROOT, "partition-convergence", `${digestName(attemptDigest)}.json`);
|
|
79859
79878
|
}
|
|
79860
79879
|
function jsonContent(value) {
|
|
79861
79880
|
const canonical = canonicalIndexerJson(value);
|
|
@@ -79866,7 +79885,7 @@ function jsonContent(value) {
|
|
|
79866
79885
|
}
|
|
79867
79886
|
async function readMaybe3(projectRoot, path2) {
|
|
79868
79887
|
try {
|
|
79869
|
-
return await readFile30(
|
|
79888
|
+
return await readFile30(join33(projectRoot, path2), "utf8");
|
|
79870
79889
|
} catch (error) {
|
|
79871
79890
|
if (error !== null && typeof error === "object" && "code" in error && error.code === "ENOENT") {
|
|
79872
79891
|
return;
|
|
@@ -79951,7 +79970,7 @@ async function currentLedger(projectRoot) {
|
|
|
79951
79970
|
async function currentSpec(input) {
|
|
79952
79971
|
return reuseCommandFileRead({
|
|
79953
79972
|
key: "validated-main-run-spec",
|
|
79954
|
-
paths: [
|
|
79973
|
+
paths: [join33(input.projectRoot, runSpecPath(input.request_digest))],
|
|
79955
79974
|
read: async () => {
|
|
79956
79975
|
const value = await readJsonMaybe(input.projectRoot, runSpecPath(input.request_digest));
|
|
79957
79976
|
if (value === undefined)
|
|
@@ -80039,8 +80058,8 @@ var init_indexerMainRunStoreRecords = __esm(() => {
|
|
|
80039
80058
|
init_src2();
|
|
80040
80059
|
init_durableSingleFileTransaction();
|
|
80041
80060
|
init_durableMultiFileTransaction();
|
|
80042
|
-
INDEXER_MAIN_RUN_STORE_ROOT =
|
|
80043
|
-
INDEXER_MAIN_RUN_CURRENT_PATH =
|
|
80061
|
+
INDEXER_MAIN_RUN_STORE_ROOT = join33(".tmp", "context-runtime", "indexer", "main-index");
|
|
80062
|
+
INDEXER_MAIN_RUN_CURRENT_PATH = join33(INDEXER_MAIN_RUN_STORE_ROOT, "current.json");
|
|
80044
80063
|
});
|
|
80045
80064
|
|
|
80046
80065
|
// src/project/indexerPartitionConvergenceStore.ts
|
|
@@ -80058,7 +80077,7 @@ var init_indexerMainRunBatchStore = __esm(() => {
|
|
|
80058
80077
|
});
|
|
80059
80078
|
|
|
80060
80079
|
// src/project/indexerMainRunStore.ts
|
|
80061
|
-
import { join as
|
|
80080
|
+
import { join as join34 } from "node:path";
|
|
80062
80081
|
async function readAcceptedMainResultRecordsUnlocked(projectRoot, stage, allowPending = false) {
|
|
80063
80082
|
await recoverDurableMultiFileTransactions(projectRoot);
|
|
80064
80083
|
const ledger = await currentLedger(projectRoot);
|
|
@@ -80075,7 +80094,7 @@ async function readAcceptedMainResultRecordsUnlocked(projectRoot, stage, allowPe
|
|
|
80075
80094
|
paths: [INDEXER_MAIN_RUN_CURRENT_PATH, ...ledger.entries.filter((entry) => entry.state === "accepted").flatMap((entry) => [
|
|
80076
80095
|
runSpecPath(entry.execution_request_digest),
|
|
80077
80096
|
acceptedCachePath(entry.execution_request_digest)
|
|
80078
|
-
])].map((path2) =>
|
|
80097
|
+
])].map((path2) => join34(projectRoot, path2)),
|
|
80079
80098
|
read: async () => {
|
|
80080
80099
|
const records = [];
|
|
80081
80100
|
for (const entry of ledger.entries) {
|
|
@@ -80124,7 +80143,7 @@ var init_indexerMainRunStore = __esm(() => {
|
|
|
80124
80143
|
import { execFile as execFile5 } from "node:child_process";
|
|
80125
80144
|
import { promisify as promisify5 } from "node:util";
|
|
80126
80145
|
import { readFile as readFile31 } from "node:fs/promises";
|
|
80127
|
-
import { basename as basename6, join as
|
|
80146
|
+
import { basename as basename6, join as join35 } from "node:path";
|
|
80128
80147
|
function productionDocumentSkeleton(path2, markdown) {
|
|
80129
80148
|
const lines = markdown.split(/\r?\n/u);
|
|
80130
80149
|
let title;
|
|
@@ -80204,7 +80223,7 @@ This entire source is explicitly excluded from every selected requirement; no in
|
|
|
80204
80223
|
if (selected.length !== 1)
|
|
80205
80224
|
throw new TypeError(`Source must identify one registered input: ${scope2}`);
|
|
80206
80225
|
const entry = selected[0];
|
|
80207
|
-
const root =
|
|
80226
|
+
const root = join35(input.projectRoot, entry.materializedAt);
|
|
80208
80227
|
if (type === "repo") {
|
|
80209
80228
|
const repo = registry2.repos.find((repo2) => repo2.id === name3 || repo2.name === name3);
|
|
80210
80229
|
if (!/^[a-f0-9]{40}(?:[a-f0-9]{24})?$/u.test(repo.ref))
|
|
@@ -80255,7 +80274,7 @@ This entire source is explicitly excluded from every selected requirement; no in
|
|
|
80255
80274
|
}
|
|
80256
80275
|
const managed = type === "note" || type === "sessions";
|
|
80257
80276
|
const manifestPath = "snapshot" in entry ? entry.snapshot?.manifest : undefined;
|
|
80258
|
-
const paths = managed ? [basename6(entry.materializedAt)] : parseDocumentSnapshotForSource(JSON.parse(await readFile31(
|
|
80277
|
+
const paths = managed ? [basename6(entry.materializedAt)] : parseDocumentSnapshotForSource(JSON.parse(await readFile31(join35(input.projectRoot, manifestPath ?? `${entry.materializedAt}/manifest.json`), "utf8")), entry.name).files.map((file) => file.path);
|
|
80259
80278
|
const overviews = [];
|
|
80260
80279
|
const included = paths.filter((path2) => !sourceExcludes(input.requirements, scope2, path2));
|
|
80261
80280
|
for (const path2 of included) {
|
|
@@ -80616,9 +80635,9 @@ var init_productionArticle = __esm(() => {
|
|
|
80616
80635
|
|
|
80617
80636
|
// src/project/productionRepairDraft.ts
|
|
80618
80637
|
import { readFile as readFile32 } from "node:fs/promises";
|
|
80619
|
-
import { join as
|
|
80638
|
+
import { join as join36 } from "node:path";
|
|
80620
80639
|
function draftPath(stage, task) {
|
|
80621
|
-
return
|
|
80640
|
+
return join36(productionStageDirectory(stage), "repair-drafts", `${task.id}.json`);
|
|
80622
80641
|
}
|
|
80623
80642
|
async function retainProductionRepairDraft(input) {
|
|
80624
80643
|
if (!input.files.content || !input.files.references)
|
|
@@ -80659,7 +80678,7 @@ var init_productionRepairDraft = __esm(() => {
|
|
|
80659
80678
|
|
|
80660
80679
|
// src/project/productionSubmission.ts
|
|
80661
80680
|
import { readFile as readFile33 } from "node:fs/promises";
|
|
80662
|
-
import { join as
|
|
80681
|
+
import { join as join37 } from "node:path";
|
|
80663
80682
|
function submissionStateError(reason, message, command = "context status --format json") {
|
|
80664
80683
|
return new ContextError(ExitCode.WorkspaceStateError, message, {
|
|
80665
80684
|
category: ErrorCategory.WorkspaceStateInvalid,
|
|
@@ -80697,7 +80716,7 @@ async function completeProductionSubmission(input) {
|
|
|
80697
80716
|
if (!stage || stage.id !== input.stage)
|
|
80698
80717
|
throw submissionStateError("stale-production-stage", "Task stage no longer exists. Start a new production run; do not reuse a stale submission.");
|
|
80699
80718
|
if (!stage.report_approved)
|
|
80700
|
-
throw submissionStateError("production-report-approval-required", "Present the planned report and
|
|
80719
|
+
throw submissionStateError("production-report-approval-required", "Present the planned report and apply context.gate.work_start_scope before submitting bulk writing.");
|
|
80701
80720
|
if (stage.delivery)
|
|
80702
80721
|
throw submissionStateError("production-delivery-paused", "Writing is paused for delivery. Finish Review and build, or run context run --resume-writing --format json; existing task inputs remain valid.");
|
|
80703
80722
|
if ((await readMaintenance(input.projectRoot)).active)
|
|
@@ -80716,7 +80735,7 @@ async function completeProductionSubmission(input) {
|
|
|
80716
80735
|
byPath.set(key, [...byPath.get(key) ?? [], candidate]);
|
|
80717
80736
|
byArticle.set(candidate.article_id, [...byArticle.get(candidate.article_id) ?? [], candidate]);
|
|
80718
80737
|
}
|
|
80719
|
-
const manifestPath =
|
|
80738
|
+
const manifestPath = join37(productionStageDirectory(stage.id), "manifest.json");
|
|
80720
80739
|
const manifestText = snapshot.content;
|
|
80721
80740
|
const baselines = new Map;
|
|
80722
80741
|
let sourceReader;
|
|
@@ -80908,9 +80927,9 @@ var init_productionSubmission = __esm(() => {
|
|
|
80908
80927
|
// src/project/productionExistingArticles.ts
|
|
80909
80928
|
import { constants as constants5 } from "node:fs";
|
|
80910
80929
|
import { open as open4 } from "node:fs/promises";
|
|
80911
|
-
import { join as
|
|
80930
|
+
import { join as join38 } from "node:path";
|
|
80912
80931
|
async function readerHeader(root, path2) {
|
|
80913
|
-
const absolute = await safeProjectTarget(root,
|
|
80932
|
+
const absolute = await safeProjectTarget(root, join38("knowledge", path2));
|
|
80914
80933
|
const handle = await open4(absolute, constants5.O_RDONLY | constants5.O_NOFOLLOW | constants5.O_NONBLOCK);
|
|
80915
80934
|
try {
|
|
80916
80935
|
if (!(await handle.stat()).isFile())
|
|
@@ -81031,7 +81050,7 @@ async function resolveProductionExclusions(requirements, readBaseline) {
|
|
|
81031
81050
|
// src/project/productionPlanning.ts
|
|
81032
81051
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
81033
81052
|
import { readFile as readFile34, access as access3 } from "node:fs/promises";
|
|
81034
|
-
import { join as
|
|
81053
|
+
import { join as join39 } from "node:path";
|
|
81035
81054
|
function refreshRequired(stage, message) {
|
|
81036
81055
|
return new ContextError(ExitCode.UserError, message, {
|
|
81037
81056
|
category: ErrorCategory.UserInputInvalid,
|
|
@@ -81050,9 +81069,9 @@ async function productionPlanningIsPrepared(root, stage) {
|
|
|
81050
81069
|
try {
|
|
81051
81070
|
const directory = productionStageDirectory(stage.id);
|
|
81052
81071
|
const current2 = await productionPlanningRequest(root);
|
|
81053
|
-
const supplied = import_yaml27.default.parse(await readFile34(await safeProjectTarget(root,
|
|
81054
|
-
await access3(await safeProjectTarget(root,
|
|
81055
|
-
await access3(await safeProjectTarget(root,
|
|
81072
|
+
const supplied = import_yaml27.default.parse(await readFile34(await safeProjectTarget(root, join39(directory, "shared/requirements.md")), "utf8"));
|
|
81073
|
+
await access3(await safeProjectTarget(root, join39(directory, "planning.md")));
|
|
81074
|
+
await access3(await safeProjectTarget(root, join39(directory, "planning.schema.json")));
|
|
81056
81075
|
return !!current2 && current2.revision === indexerProtocolDigest(supplied);
|
|
81057
81076
|
} catch (error) {
|
|
81058
81077
|
if (error.code === "ENOENT")
|
|
@@ -81063,7 +81082,7 @@ async function productionPlanningIsPrepared(root, stage) {
|
|
|
81063
81082
|
async function productionRequirementsAreCurrent(root, stage) {
|
|
81064
81083
|
try {
|
|
81065
81084
|
const current2 = await productionPlanningRequest(root);
|
|
81066
|
-
const supplied = import_yaml27.default.parse(await readFile34(await safeProjectTarget(root,
|
|
81085
|
+
const supplied = import_yaml27.default.parse(await readFile34(await safeProjectTarget(root, join39(productionStageDirectory(stage.id), "shared/requirements.md")), "utf8"));
|
|
81067
81086
|
return !!current2 && current2.revision === indexerProtocolDigest(supplied);
|
|
81068
81087
|
} catch (error) {
|
|
81069
81088
|
if (error.code !== "ENOENT")
|
|
@@ -81122,17 +81141,17 @@ Restore the authorized source and retry preparation.
|
|
|
81122
81141
|
gaps: prepared.gaps
|
|
81123
81142
|
});
|
|
81124
81143
|
const directory = productionStageDirectory(stage.id);
|
|
81125
|
-
await writeProductionProjection(input.projectRoot,
|
|
81144
|
+
await writeProductionProjection(input.projectRoot, join39(directory, "planning.schema.json"), `${JSON.stringify(zodToJsonSchema(productionPlanInputSchema), null, 2)}
|
|
81126
81145
|
`);
|
|
81127
|
-
await writeProductionProjection(input.projectRoot,
|
|
81146
|
+
await writeProductionProjection(input.projectRoot, join39(directory, "planning.md"), [
|
|
81128
81147
|
"# Investigate and plan",
|
|
81129
81148
|
"",
|
|
81130
|
-
`Requirements: ${
|
|
81131
|
-
`Submission schema: ${
|
|
81132
|
-
`Existing reader topics: ${
|
|
81149
|
+
`Requirements: ${join39(directory, "shared/requirements.md")}`,
|
|
81150
|
+
`Submission schema: ${join39(directory, "planning.schema.json")}`,
|
|
81151
|
+
`Existing reader topics: ${join39(directory, "guidance/existing-articles.md")}`,
|
|
81133
81152
|
`Stage: ${stage.id}`,
|
|
81134
81153
|
"",
|
|
81135
|
-
...scopes.map((scope2) => `- ${scope2.scope}: ${
|
|
81154
|
+
...scopes.map((scope2) => `- ${scope2.scope}: ${join39(directory, productionSourceFile(scope2.scope))}`),
|
|
81136
81155
|
"",
|
|
81137
81156
|
"Use code skeletons and document outlines to identify the authorized capability families and document tasks, then selectively read full material to decide reader topics. Navigation is not a complete feature inventory. Keep unchecked scope pending; do not parse all code or maintain per-symbol disposition just to plan.",
|
|
81138
81157
|
"Configured sources are the knowledge workspace coverage boundary, not a new investigation assignment on every request. First distinguish the user's current task, its actual source dependencies, and unrelated configured sources. Reuse approved content; a source-level pending entry alone does not prove missing knowledge or require new articles.",
|
|
@@ -81212,7 +81231,7 @@ async function submitProductionPlan(input) {
|
|
|
81212
81231
|
}
|
|
81213
81232
|
const prior = candidates.find((candidate) => candidate.path === article.path);
|
|
81214
81233
|
const formal = approved.byPath.get(article.path);
|
|
81215
|
-
const markdown = prior?.body ?? (formal ? await readFile34(await safeProjectTarget(input.projectRoot,
|
|
81234
|
+
const markdown = prior?.body ?? (formal ? await readFile34(await safeProjectTarget(input.projectRoot, join39("knowledge", formal.path)), "utf8") : undefined);
|
|
81216
81235
|
const sections = prior?.indexer_candidate?.sections.map((section) => ({ id: section.section_key, references: section.references })) ?? formal?.sections;
|
|
81217
81236
|
const task = {
|
|
81218
81237
|
id: identities.get(article.path),
|
|
@@ -81305,7 +81324,7 @@ var init_productionPlanning = __esm(() => {
|
|
|
81305
81324
|
|
|
81306
81325
|
// src/project/productionDeliveryScope.ts
|
|
81307
81326
|
import { readFile as readFile35 } from "node:fs/promises";
|
|
81308
|
-
import { join as
|
|
81327
|
+
import { join as join40, posix as posix2 } from "node:path";
|
|
81309
81328
|
async function productionDeliverableArticles(root, phase = "delivery") {
|
|
81310
81329
|
return withProductionFeedback({ operation: "delivery-scope" }, async () => {
|
|
81311
81330
|
const stage = await readProductionStage(root);
|
|
@@ -81332,7 +81351,7 @@ async function productionDeliverableArticles(root, phase = "delivery") {
|
|
|
81332
81351
|
if (phase === "review")
|
|
81333
81352
|
return [...selected.values()];
|
|
81334
81353
|
for (const article of selected.values()) {
|
|
81335
|
-
const markdown = await readFile35(await safeProjectTarget(root,
|
|
81354
|
+
const markdown = await readFile35(await safeProjectTarget(root, join40("knowledge", article.path)), "utf8");
|
|
81336
81355
|
for (const link of markdownReaderLinks(markdown)) {
|
|
81337
81356
|
if (link.image || /^(?:[a-z][a-z\d+.-]*:|\/|#)/iu.test(link.target))
|
|
81338
81357
|
continue;
|
|
@@ -81348,7 +81367,7 @@ async function productionDeliverableArticles(root, phase = "delivery") {
|
|
|
81348
81367
|
if (path2.startsWith("../") || unresolved.has(path2) || !formal.byPath.has(path2)) {
|
|
81349
81368
|
throw new TypeError(`Partial delivery needs its linked approved article: ${article.path} → ${path2}. Finish that article's Review before delivery.`);
|
|
81350
81369
|
}
|
|
81351
|
-
await readFile35(await safeProjectTarget(root,
|
|
81370
|
+
await readFile35(await safeProjectTarget(root, join40("knowledge", path2)), "utf8");
|
|
81352
81371
|
}
|
|
81353
81372
|
}
|
|
81354
81373
|
return [...selected.values()];
|
|
@@ -81367,9 +81386,9 @@ var init_productionDeliveryScope = __esm(() => {
|
|
|
81367
81386
|
|
|
81368
81387
|
// src/project/siteTheme.ts
|
|
81369
81388
|
import { mkdir as mkdir17, readFile as readFile36, writeFile as writeFile11 } from "node:fs/promises";
|
|
81370
|
-
import { dirname as dirname20, join as
|
|
81389
|
+
import { dirname as dirname20, join as join41 } from "node:path";
|
|
81371
81390
|
async function resolveSiteTheme(root, overrides, scaffold = false) {
|
|
81372
|
-
const path2 =
|
|
81391
|
+
const path2 = join41(root, SITE_THEME_FILE);
|
|
81373
81392
|
let file = {};
|
|
81374
81393
|
try {
|
|
81375
81394
|
file = siteThemeSchema.parse(JSON.parse(await readFile36(path2, "utf8")));
|
|
@@ -81470,10 +81489,10 @@ import { createHash as createHash11 } from "node:crypto";
|
|
|
81470
81489
|
import { execFile as execFile7 } from "node:child_process";
|
|
81471
81490
|
import { promisify as promisify7 } from "node:util";
|
|
81472
81491
|
import { readFile as readFile37, lstat as lstat6, readdir as readdir9, realpath as realpath6 } from "node:fs/promises";
|
|
81473
|
-
import { join as
|
|
81492
|
+
import { join as join42 } from "node:path";
|
|
81474
81493
|
async function optionalWorkspaceText(root, path2) {
|
|
81475
81494
|
try {
|
|
81476
|
-
return await readFile37(
|
|
81495
|
+
return await readFile37(join42(root, path2), "utf8");
|
|
81477
81496
|
} catch (error) {
|
|
81478
81497
|
if (error.code === "ENOENT")
|
|
81479
81498
|
return;
|
|
@@ -81485,7 +81504,7 @@ async function readWorkspaceChangelog(root) {
|
|
|
81485
81504
|
return value === undefined ? [] : ledgerSchema.parse(import_yaml28.parse(value)).entries;
|
|
81486
81505
|
}
|
|
81487
81506
|
async function workspaceVersion(root) {
|
|
81488
|
-
const manifest = JSON.parse(await readFile37(
|
|
81507
|
+
const manifest = JSON.parse(await readFile37(join42(root, "package.json"), "utf8"));
|
|
81489
81508
|
return semver.parse(manifest.version ?? "0.0.0");
|
|
81490
81509
|
}
|
|
81491
81510
|
function excluded(path2) {
|
|
@@ -81506,7 +81525,7 @@ async function workspaceContentSnapshot(root) {
|
|
|
81506
81525
|
if (paths === undefined) {
|
|
81507
81526
|
const discovered = [];
|
|
81508
81527
|
const visit3 = async (dir) => {
|
|
81509
|
-
for (const entry of await readdir9(
|
|
81528
|
+
for (const entry of await readdir9(join42(root, dir), { withFileTypes: true })) {
|
|
81510
81529
|
const path2 = dir ? `${dir}/${entry.name}` : entry.name;
|
|
81511
81530
|
if (excluded(path2))
|
|
81512
81531
|
continue;
|
|
@@ -81523,9 +81542,9 @@ async function workspaceContentSnapshot(root) {
|
|
|
81523
81542
|
for (const path2 of [...new Set(paths)].filter((path3) => !excluded(path3)).sort()) {
|
|
81524
81543
|
let bytes;
|
|
81525
81544
|
try {
|
|
81526
|
-
if (!(await lstat6(
|
|
81545
|
+
if (!(await lstat6(join42(root, path2))).isFile())
|
|
81527
81546
|
continue;
|
|
81528
|
-
bytes = await readFile37(
|
|
81547
|
+
bytes = await readFile37(join42(root, path2));
|
|
81529
81548
|
} catch (error) {
|
|
81530
81549
|
if (error.code === "ENOENT")
|
|
81531
81550
|
continue;
|
|
@@ -81610,7 +81629,7 @@ async function recordWorkspaceVersion(root, value) {
|
|
|
81610
81629
|
const { expected_digest: _, base_ref: _base, ...fields } = input;
|
|
81611
81630
|
const entry = changelogEntrySchema.parse({ ...fields, date: new Date().toISOString(), ...actor ? { actor } : {} });
|
|
81612
81631
|
const entries = [entry, ...amend ? previousEntries.slice(1) : previousEntries];
|
|
81613
|
-
const manifest = JSON.parse(await readFile37(
|
|
81632
|
+
const manifest = JSON.parse(await readFile37(join42(root, "package.json"), "utf8"));
|
|
81614
81633
|
manifest.version = entry.version;
|
|
81615
81634
|
const writes = {
|
|
81616
81635
|
"package.json": JSON.stringify(manifest, null, 2) + `
|
|
@@ -81625,7 +81644,7 @@ async function recordWorkspaceVersion(root, value) {
|
|
|
81625
81644
|
targets.sort((a2, b2) => a2.path < b2.path ? -1 : a2.path > b2.path ? 1 : 0);
|
|
81626
81645
|
await runDurableMultiFileTransaction({ projectRoot: root, kind: "record-workspace-version", proposal_digest: hash2(writes), targets });
|
|
81627
81646
|
try {
|
|
81628
|
-
await atomicWriteFile(
|
|
81647
|
+
await atomicWriteFile(join42(root, VERSION_CHECKPOINT), JSON.stringify({ version: entry.version, digest: status.content_digest }) + `
|
|
81629
81648
|
`);
|
|
81630
81649
|
} catch {}
|
|
81631
81650
|
return { version: entry.version, next_action: { command: "context status --format json" } };
|
|
@@ -81664,7 +81683,7 @@ __export(exports_workspacePreparation, {
|
|
|
81664
81683
|
PREPARATION_ROOTS: () => PREPARATION_ROOTS
|
|
81665
81684
|
});
|
|
81666
81685
|
import { lstat as lstat7, readFile as readFile38, readdir as readdir10 } from "node:fs/promises";
|
|
81667
|
-
import { join as
|
|
81686
|
+
import { join as join43 } from "node:path";
|
|
81668
81687
|
function failure(reason, message, next) {
|
|
81669
81688
|
throw new ContextError(ExitCode.WorkspaceStateError, message, {
|
|
81670
81689
|
category: ErrorCategory.WorkspaceStateInvalid,
|
|
@@ -81676,7 +81695,7 @@ async function entries(root, path2) {
|
|
|
81676
81695
|
await safeProjectTarget(root, path2);
|
|
81677
81696
|
let stat8;
|
|
81678
81697
|
try {
|
|
81679
|
-
stat8 = await lstat7(
|
|
81698
|
+
stat8 = await lstat7(join43(root, path2));
|
|
81680
81699
|
} catch (error) {
|
|
81681
81700
|
if (error.code === "ENOENT")
|
|
81682
81701
|
return [];
|
|
@@ -81689,8 +81708,8 @@ async function entries(root, path2) {
|
|
|
81689
81708
|
if (!stat8.isDirectory())
|
|
81690
81709
|
failure("preparation-file-type", `Unsupported task-state file: ${path2}`, "Inspect this file before preparing the workspace.");
|
|
81691
81710
|
const result = [];
|
|
81692
|
-
for (const name3 of (await readdir10(
|
|
81693
|
-
result.push(...await entries(root,
|
|
81711
|
+
for (const name3 of (await readdir10(join43(root, path2))).sort())
|
|
81712
|
+
result.push(...await entries(root, join43(path2, name3)));
|
|
81694
81713
|
return result;
|
|
81695
81714
|
}
|
|
81696
81715
|
async function pendingJournals(root) {
|
|
@@ -81698,7 +81717,7 @@ async function pendingJournals(root) {
|
|
|
81698
81717
|
const result = [];
|
|
81699
81718
|
for (const path2 of files.filter((path3) => path3.endsWith("/journal.json") || path3.endsWith(".journal.json"))) {
|
|
81700
81719
|
try {
|
|
81701
|
-
result.push({ ...JSON.parse(await readFile38(
|
|
81720
|
+
result.push({ ...JSON.parse(await readFile38(join43(root, path2), "utf8")), path: path2 });
|
|
81702
81721
|
} catch {
|
|
81703
81722
|
result.push({ path: path2 });
|
|
81704
81723
|
}
|
|
@@ -81728,7 +81747,7 @@ async function prepareWorkspace(input) {
|
|
|
81728
81747
|
const targets = [];
|
|
81729
81748
|
for (const directory of PREPARATION_ROOTS)
|
|
81730
81749
|
for (const path2 of await entries(input.projectRoot, directory)) {
|
|
81731
|
-
const bytes = await readFile38(
|
|
81750
|
+
const bytes = await readFile38(join43(input.projectRoot, path2));
|
|
81732
81751
|
let content3;
|
|
81733
81752
|
try {
|
|
81734
81753
|
content3 = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(bytes);
|
|
@@ -81740,7 +81759,7 @@ async function prepareWorkspace(input) {
|
|
|
81740
81759
|
const markerContent = JSON.stringify(taskPreparationRecord("cleared"));
|
|
81741
81760
|
let oldMarker;
|
|
81742
81761
|
try {
|
|
81743
|
-
oldMarker = await readFile38(
|
|
81762
|
+
oldMarker = await readFile38(join43(input.projectRoot, TASK_PREPARATION_PATH), "utf8");
|
|
81744
81763
|
} catch (error) {
|
|
81745
81764
|
if (error.code !== "ENOENT")
|
|
81746
81765
|
throw error;
|
|
@@ -81814,14 +81833,14 @@ __export(exports_taskResumption, {
|
|
|
81814
81833
|
TASK_PREPARATION_PATH: () => TASK_PREPARATION_PATH
|
|
81815
81834
|
});
|
|
81816
81835
|
import { readFile as readFile39 } from "node:fs/promises";
|
|
81817
|
-
import { join as
|
|
81836
|
+
import { join as join44 } from "node:path";
|
|
81818
81837
|
function taskPreparationRecord(state) {
|
|
81819
81838
|
return { protocol: "context.task-preparation/v1", state };
|
|
81820
81839
|
}
|
|
81821
81840
|
async function readTaskPreparation(root) {
|
|
81822
81841
|
let text7;
|
|
81823
81842
|
try {
|
|
81824
|
-
text7 = await readFile39(
|
|
81843
|
+
text7 = await readFile39(join44(root, TASK_PREPARATION_PATH), "utf8");
|
|
81825
81844
|
} catch (error) {
|
|
81826
81845
|
if (error.code !== "ENOENT")
|
|
81827
81846
|
throw error;
|
|
@@ -81867,9 +81886,9 @@ var init_taskResumption = __esm(() => {
|
|
|
81867
81886
|
|
|
81868
81887
|
// src/project/productionCleanup.ts
|
|
81869
81888
|
import { readFile as readFile40, readdir as readdir11, rm as rm9 } from "node:fs/promises";
|
|
81870
|
-
import { join as
|
|
81889
|
+
import { join as join45 } from "node:path";
|
|
81871
81890
|
async function clearCompletedProduction(root, stage) {
|
|
81872
|
-
const pointerPath =
|
|
81891
|
+
const pointerPath = join45(PRODUCTION_STAGES_ROOT, "current.json");
|
|
81873
81892
|
const pointer = await readFile40(await safeProjectTarget(root, pointerPath), "utf8");
|
|
81874
81893
|
const current2 = JSON.parse(pointer);
|
|
81875
81894
|
if (!current2 || typeof current2 !== "object" || !("stage" in current2) || current2.stage !== stage.id) {
|
|
@@ -81881,9 +81900,9 @@ async function clearCompletedProduction(root, stage) {
|
|
|
81881
81900
|
const entries2 = await readdir11(await safeProjectTarget(root, directory));
|
|
81882
81901
|
for (const entry of entries2)
|
|
81883
81902
|
if (entry !== "manifest.json")
|
|
81884
|
-
await remove(
|
|
81903
|
+
await remove(join45(directory, entry));
|
|
81885
81904
|
const targets = [];
|
|
81886
|
-
for (const path2 of [
|
|
81905
|
+
for (const path2 of [join45(directory, "manifest.json"), pointerPath]) {
|
|
81887
81906
|
const content4 = path2 === pointerPath ? pointer : await readFile40(await safeProjectTarget(root, path2), "utf8");
|
|
81888
81907
|
targets.push({ path: path2, operation: "delete", base_digest: durableContentDigest(content4), target_digest: null });
|
|
81889
81908
|
}
|
|
@@ -81923,7 +81942,7 @@ __export(exports_lifecycleCleanup, {
|
|
|
81923
81942
|
clearCompletedLifecycle: () => clearCompletedLifecycle
|
|
81924
81943
|
});
|
|
81925
81944
|
import { readdir as readdir12, rm as rm10 } from "node:fs/promises";
|
|
81926
|
-
import { join as
|
|
81945
|
+
import { join as join46 } from "node:path";
|
|
81927
81946
|
async function clearCompletedLifecycle(projectRoot) {
|
|
81928
81947
|
const production = await readProductionStage(projectRoot);
|
|
81929
81948
|
if (production) {
|
|
@@ -81940,9 +81959,9 @@ async function clearCompletedLifecycle(projectRoot) {
|
|
|
81940
81959
|
}
|
|
81941
81960
|
for (const path2 of COMPLETED_RUNTIME_PATHS) {
|
|
81942
81961
|
if (path2 !== INDEXER_RUNTIME_ROOT)
|
|
81943
|
-
await rm10(
|
|
81962
|
+
await rm10(join46(projectRoot, path2), { recursive: true, force: true });
|
|
81944
81963
|
}
|
|
81945
|
-
const indexer =
|
|
81964
|
+
const indexer = join46(projectRoot, INDEXER_RUNTIME_ROOT);
|
|
81946
81965
|
const entries2 = await readdir12(indexer).catch((error) => {
|
|
81947
81966
|
if (error.code === "ENOENT")
|
|
81948
81967
|
return [];
|
|
@@ -81950,9 +81969,9 @@ async function clearCompletedLifecycle(projectRoot) {
|
|
|
81950
81969
|
});
|
|
81951
81970
|
for (const name3 of entries2)
|
|
81952
81971
|
if (name3 !== "candidate-compile") {
|
|
81953
|
-
await rm10(
|
|
81972
|
+
await rm10(join46(indexer, name3), { recursive: true, force: true });
|
|
81954
81973
|
}
|
|
81955
|
-
const compile =
|
|
81974
|
+
const compile = join46(indexer, "candidate-compile");
|
|
81956
81975
|
const compiled = await readdir12(compile).catch((error) => {
|
|
81957
81976
|
if (error.code === "ENOENT")
|
|
81958
81977
|
return [];
|
|
@@ -81960,11 +81979,11 @@ async function clearCompletedLifecycle(projectRoot) {
|
|
|
81960
81979
|
});
|
|
81961
81980
|
for (const name3 of compiled)
|
|
81962
81981
|
if (name3 !== "current.json") {
|
|
81963
|
-
await rm10(
|
|
81982
|
+
await rm10(join46(compile, name3), { recursive: true, force: true });
|
|
81964
81983
|
}
|
|
81965
|
-
await rm10(
|
|
81984
|
+
await rm10(join46(compile, "current.json"), { force: true });
|
|
81966
81985
|
await rm10(indexer, { recursive: true, force: true });
|
|
81967
|
-
await rm10(
|
|
81986
|
+
await rm10(join46(projectRoot, APPROVED_REVISION_PATH), { force: true });
|
|
81968
81987
|
if (production)
|
|
81969
81988
|
await clearCompletedProduction(projectRoot, production);
|
|
81970
81989
|
}
|
|
@@ -82138,7 +82157,7 @@ var init_indexerRequiredArticleReview = __esm(() => {
|
|
|
82138
82157
|
// src/project/partialDelivery.ts
|
|
82139
82158
|
import { existsSync as existsSync8 } from "node:fs";
|
|
82140
82159
|
import { readFile as readFile41 } from "node:fs/promises";
|
|
82141
|
-
import { join as
|
|
82160
|
+
import { join as join47, posix as posix3 } from "node:path";
|
|
82142
82161
|
async function selectPartialDelivery(root) {
|
|
82143
82162
|
const candidates = await readCandidateRecords(root);
|
|
82144
82163
|
if (!candidates.some((item) => item.status === "draft"))
|
|
@@ -82152,7 +82171,7 @@ async function selectPartialDelivery(root) {
|
|
|
82152
82171
|
}
|
|
82153
82172
|
const pages = [...revision.batch_candidates ?? [], ...revision.candidate ? [revision.candidate] : []].map((item) => ({ path: `knowledge/${item.path}`, ref: item.article_id }));
|
|
82154
82173
|
const unresolved = new Set(candidates.map((item) => `knowledge/${item.path}`));
|
|
82155
|
-
const approved = pages.filter((item) => !unresolved.has(item.path) && existsSync8(
|
|
82174
|
+
const approved = pages.filter((item) => !unresolved.has(item.path) && existsSync8(join47(root, item.path)));
|
|
82156
82175
|
if (approved.length === 0)
|
|
82157
82176
|
return;
|
|
82158
82177
|
await assertIndependentPages(root, approved.map((item) => item.path), unresolved);
|
|
@@ -82162,7 +82181,7 @@ async function assertIndependentPages(root, paths, unresolved) {
|
|
|
82162
82181
|
for (const path2 of paths) {
|
|
82163
82182
|
if (unresolved.has(path2))
|
|
82164
82183
|
throw new TypeError(`Selected delivery page now needs Review: ${path2}. Return to the current Route.`);
|
|
82165
|
-
const markdown = await readFile41(
|
|
82184
|
+
const markdown = await readFile41(join47(root, path2), "utf8");
|
|
82166
82185
|
for (const link of markdownReaderLinks(markdown)) {
|
|
82167
82186
|
if (link.image || /^(?:[a-z][a-z\d+.-]*:|\/|#)/iu.test(link.target))
|
|
82168
82187
|
continue;
|
|
@@ -82173,7 +82192,7 @@ async function assertIndependentPages(root, paths, unresolved) {
|
|
|
82173
82192
|
continue;
|
|
82174
82193
|
}
|
|
82175
82194
|
const target = posix3.normalize(posix3.join(posix3.dirname(path2), href));
|
|
82176
|
-
if (target.startsWith("knowledge/") && /\.md$/iu.test(target) && (unresolved.has(target) || !existsSync8(
|
|
82195
|
+
if (target.startsWith("knowledge/") && /\.md$/iu.test(target) && (unresolved.has(target) || !existsSync8(join47(root, target)))) {
|
|
82177
82196
|
throw new TypeError(`Partial delivery must include its linked page: ${path2} → ${target}. Finish that page's Review/repair, then request delivery again; existing approvals remain.`);
|
|
82178
82197
|
}
|
|
82179
82198
|
}
|
|
@@ -82201,10 +82220,10 @@ var init_partialDelivery = __esm(() => {
|
|
|
82201
82220
|
|
|
82202
82221
|
// src/project/revisionDelivery.ts
|
|
82203
82222
|
import { readFile as readFile42, rm as rm11 } from "node:fs/promises";
|
|
82204
|
-
import { join as
|
|
82223
|
+
import { join as join48 } from "node:path";
|
|
82205
82224
|
async function readRevisionDelivery(root) {
|
|
82206
82225
|
try {
|
|
82207
|
-
return stateSchema2.parse(JSON.parse(await readFile42(
|
|
82226
|
+
return stateSchema2.parse(JSON.parse(await readFile42(join48(root, FILE), "utf8")));
|
|
82208
82227
|
} catch (error) {
|
|
82209
82228
|
if (error.code === "ENOENT")
|
|
82210
82229
|
return;
|
|
@@ -82215,7 +82234,7 @@ function requestRevisionDelivery(root) {
|
|
|
82215
82234
|
return withProjectWriteLock(root, "request-revision-delivery", async () => {
|
|
82216
82235
|
const partial = await selectPartialDelivery(root);
|
|
82217
82236
|
if (partial) {
|
|
82218
|
-
await atomicWriteFile(
|
|
82237
|
+
await atomicWriteFile(join48(root, FILE), JSON.stringify(stateSchema2.parse({ partial, closed: false })) + `
|
|
82219
82238
|
`);
|
|
82220
82239
|
return;
|
|
82221
82240
|
}
|
|
@@ -82233,7 +82252,7 @@ function closeRevisionDelivery(root) {
|
|
|
82233
82252
|
const state = await readRevisionDelivery(root);
|
|
82234
82253
|
if (!state)
|
|
82235
82254
|
return false;
|
|
82236
|
-
await atomicWriteFile(
|
|
82255
|
+
await atomicWriteFile(join48(root, FILE), JSON.stringify({ ...state, closed: true }) + `
|
|
82237
82256
|
`);
|
|
82238
82257
|
return true;
|
|
82239
82258
|
});
|
|
@@ -82241,7 +82260,7 @@ function closeRevisionDelivery(root) {
|
|
|
82241
82260
|
function completeRevisionDelivery(root) {
|
|
82242
82261
|
return withProjectWriteLock(root, "complete-revision-delivery", async () => {
|
|
82243
82262
|
if ((await readRevisionDelivery(root))?.closed)
|
|
82244
|
-
await rm11(
|
|
82263
|
+
await rm11(join48(root, FILE), { force: true });
|
|
82245
82264
|
});
|
|
82246
82265
|
}
|
|
82247
82266
|
var FILE, stateSchema2;
|
|
@@ -82256,7 +82275,7 @@ var init_revisionDelivery = __esm(() => {
|
|
|
82256
82275
|
init_partialDelivery();
|
|
82257
82276
|
init_approvedRevision();
|
|
82258
82277
|
init_candidateLedger();
|
|
82259
|
-
FILE =
|
|
82278
|
+
FILE = join48(LIFECYCLE_ROOT, "revision-delivery.json");
|
|
82260
82279
|
stateSchema2 = exports_external.object({
|
|
82261
82280
|
partial: exports_external.object({
|
|
82262
82281
|
kind: exports_external.literal("revision"),
|
|
@@ -82269,7 +82288,7 @@ var init_revisionDelivery = __esm(() => {
|
|
|
82269
82288
|
|
|
82270
82289
|
// src/project/approvedKnowledgeSnapshots.ts
|
|
82271
82290
|
import { readFile as readFile43 } from "node:fs/promises";
|
|
82272
|
-
import { join as
|
|
82291
|
+
import { join as join49 } from "node:path";
|
|
82273
82292
|
function approvedKnowledgeSnapshotsFromStructure(structure) {
|
|
82274
82293
|
return validateArticleStructureEntries(structure?.articles ?? []);
|
|
82275
82294
|
}
|
|
@@ -82278,7 +82297,7 @@ async function prepareApprovedKnowledgeSnapshotTarget(input) {
|
|
|
82278
82297
|
return;
|
|
82279
82298
|
let before;
|
|
82280
82299
|
try {
|
|
82281
|
-
before = await readFile43(
|
|
82300
|
+
before = await readFile43(join49(input.projectRoot, STRUCTURE_PATH2), "utf8");
|
|
82282
82301
|
} catch (error) {
|
|
82283
82302
|
if (error.code !== "ENOENT")
|
|
82284
82303
|
throw error;
|
|
@@ -82341,7 +82360,7 @@ import {
|
|
|
82341
82360
|
unlinkSync,
|
|
82342
82361
|
writeFileSync as writeFileSync2
|
|
82343
82362
|
} from "node:fs";
|
|
82344
|
-
import { dirname as dirname21, join as
|
|
82363
|
+
import { dirname as dirname21, join as join50 } from "node:path";
|
|
82345
82364
|
function isRecord10(value) {
|
|
82346
82365
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
82347
82366
|
}
|
|
@@ -82359,7 +82378,7 @@ function parseEvent(value) {
|
|
|
82359
82378
|
};
|
|
82360
82379
|
}
|
|
82361
82380
|
function runtimeEventOutboxPath(projectRoot) {
|
|
82362
|
-
return
|
|
82381
|
+
return join50(projectRoot, OUTBOX_RELATIVE_PATH);
|
|
82363
82382
|
}
|
|
82364
82383
|
function readRuntimeEventOutboxFile(path2) {
|
|
82365
82384
|
if (!existsSync9(path2))
|
|
@@ -82490,7 +82509,7 @@ function acknowledgeRuntimeEventOutbox(projectRoot, eventIds) {
|
|
|
82490
82509
|
}
|
|
82491
82510
|
var OUTBOX_EVENT_SCHEMA = "context.runtime-event-outbox.event.v1", OUTBOX_ACK_SCHEMA = "context.runtime-event-outbox.ack.v1", OUTBOX_RELATIVE_PATH, OUTBOX_LOCK_STALE_MS = 30000, OUTBOX_LOCK_RETRY_MS = 10, OUTBOX_LOCK_RETRIES = 100;
|
|
82492
82511
|
var init_runtimeEventOutbox = __esm(() => {
|
|
82493
|
-
OUTBOX_RELATIVE_PATH =
|
|
82512
|
+
OUTBOX_RELATIVE_PATH = join50(".tmp", "context-runtime", "logs", "outbox.jsonl");
|
|
82494
82513
|
});
|
|
82495
82514
|
|
|
82496
82515
|
// src/runtimeEvents.ts
|
|
@@ -82503,7 +82522,7 @@ import {
|
|
|
82503
82522
|
writeFileSync as writeFileSync3
|
|
82504
82523
|
} from "node:fs";
|
|
82505
82524
|
import { spawn as spawn2 } from "node:child_process";
|
|
82506
|
-
import { dirname as dirname22, join as
|
|
82525
|
+
import { dirname as dirname22, join as join51 } from "node:path";
|
|
82507
82526
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
82508
82527
|
function isRecord11(value) {
|
|
82509
82528
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
@@ -82606,7 +82625,7 @@ function readRuntimePackageMetadata() {
|
|
|
82606
82625
|
try {
|
|
82607
82626
|
let dir = dirname22(fileURLToPath3(import.meta.url));
|
|
82608
82627
|
for (let index2 = 0;index2 < 8; index2++) {
|
|
82609
|
-
const packagePath =
|
|
82628
|
+
const packagePath = join51(dir, "package.json");
|
|
82610
82629
|
if (existsSync10(packagePath)) {
|
|
82611
82630
|
const parsed = JSON.parse(readFileSync5(packagePath, "utf8"));
|
|
82612
82631
|
if (isRecord11(parsed)) {
|
|
@@ -82743,7 +82762,7 @@ function dispatchCommand(sink, batch, cwd) {
|
|
|
82743
82762
|
});
|
|
82744
82763
|
}
|
|
82745
82764
|
function runtimeEventStatePath(cwd) {
|
|
82746
|
-
return
|
|
82765
|
+
return join51(cwd, ".tmp", "context-runtime", RUNTIME_EVENT_STATE_FILE);
|
|
82747
82766
|
}
|
|
82748
82767
|
function readRuntimeEventState(cwd) {
|
|
82749
82768
|
try {
|
|
@@ -83099,10 +83118,10 @@ var init_approvedStructureInputHash = () => {};
|
|
|
83099
83118
|
|
|
83100
83119
|
// src/project/verifyApprovedStructure.ts
|
|
83101
83120
|
import { existsSync as existsSync11 } from "node:fs";
|
|
83102
|
-
import { join as
|
|
83121
|
+
import { join as join52 } from "node:path";
|
|
83103
83122
|
async function validateApprovedStructure(input) {
|
|
83104
83123
|
const issue = (code, path3, message) => input.issues.push({ severity: "error", code, path: path3, message });
|
|
83105
|
-
const path2 =
|
|
83124
|
+
const path2 = join52(input.projectRoot, STRUCTURE_PATH3);
|
|
83106
83125
|
if (!input.structureOverride && !existsSync11(path2))
|
|
83107
83126
|
return;
|
|
83108
83127
|
let parsed;
|
|
@@ -83170,7 +83189,7 @@ var init_verifyApprovedStructure = __esm(() => {
|
|
|
83170
83189
|
import { createHash as createHash13 } from "node:crypto";
|
|
83171
83190
|
import { existsSync as existsSync12 } from "node:fs";
|
|
83172
83191
|
import { mkdir as mkdir18, readFile as readFile44, readdir as readdir13, writeFile as writeFile12 } from "node:fs/promises";
|
|
83173
|
-
import { dirname as dirname23, join as
|
|
83192
|
+
import { dirname as dirname23, join as join53, relative as relative15, resolve as resolve20 } from "node:path";
|
|
83174
83193
|
async function templateFiles(root) {
|
|
83175
83194
|
if (!existsSync12(root))
|
|
83176
83195
|
return [];
|
|
@@ -83178,7 +83197,7 @@ async function templateFiles(root) {
|
|
|
83178
83197
|
const visit3 = async (dir) => {
|
|
83179
83198
|
const entries2 = await readdir13(dir, { withFileTypes: true });
|
|
83180
83199
|
for (const entry of entries2) {
|
|
83181
|
-
const absolutePath =
|
|
83200
|
+
const absolutePath = join53(dir, entry.name);
|
|
83182
83201
|
if (entry.isDirectory()) {
|
|
83183
83202
|
await visit3(absolutePath);
|
|
83184
83203
|
continue;
|
|
@@ -83205,7 +83224,7 @@ function isMarker(value) {
|
|
|
83205
83224
|
return marker.schema === PACKAGE_TEMPLATE_REVIEW_SCHEMA && /^sha256:[a-f0-9]{64}$/u.test(marker.starter_digest ?? "") && (marker.disposition === "review-required" || marker.disposition === "starter-accepted");
|
|
83206
83225
|
}
|
|
83207
83226
|
async function readMarker(templateRoot) {
|
|
83208
|
-
const markerPath =
|
|
83227
|
+
const markerPath = join53(templateRoot, PACKAGE_TEMPLATE_REVIEW_FILE);
|
|
83209
83228
|
if (!existsSync12(markerPath))
|
|
83210
83229
|
return null;
|
|
83211
83230
|
try {
|
|
@@ -83216,7 +83235,7 @@ async function readMarker(templateRoot) {
|
|
|
83216
83235
|
}
|
|
83217
83236
|
}
|
|
83218
83237
|
async function writeStarterTemplateReviewMarker(templateRoot) {
|
|
83219
|
-
const markerPath =
|
|
83238
|
+
const markerPath = join53(templateRoot, PACKAGE_TEMPLATE_REVIEW_FILE);
|
|
83220
83239
|
if (existsSync12(markerPath))
|
|
83221
83240
|
return false;
|
|
83222
83241
|
const marker = {
|
|
@@ -83244,7 +83263,7 @@ async function inspectPackageTemplateReview(projectRoot, pkg) {
|
|
|
83244
83263
|
packageName: pkg.name,
|
|
83245
83264
|
templatePath: pkg.template.path,
|
|
83246
83265
|
state: "invalid",
|
|
83247
|
-
diagnostic: `${
|
|
83266
|
+
diagnostic: `${join53(pkg.template.path, PACKAGE_TEMPLATE_REVIEW_FILE)} is invalid`
|
|
83248
83267
|
};
|
|
83249
83268
|
}
|
|
83250
83269
|
const currentDigest2 = await templateDigest(templateRoot);
|
|
@@ -83285,8 +83304,8 @@ async function acceptStarterPackageTemplates(input) {
|
|
|
83285
83304
|
alreadyResolved.push(pkg.name);
|
|
83286
83305
|
continue;
|
|
83287
83306
|
}
|
|
83288
|
-
const markerPath =
|
|
83289
|
-
const marker = await readMarker(
|
|
83307
|
+
const markerPath = join53(input.projectRoot, pkg.template.path, PACKAGE_TEMPLATE_REVIEW_FILE);
|
|
83308
|
+
const marker = await readMarker(join53(input.projectRoot, pkg.template.path));
|
|
83290
83309
|
if (marker === null || marker === "invalid") {
|
|
83291
83310
|
throw new ContextError(ExitCode.WorkspaceStateError, "package template review marker changed before acceptance", {
|
|
83292
83311
|
category: ErrorCategory.WorkspaceStateInvalid,
|
|
@@ -83457,8 +83476,8 @@ function renderAgents(projectName, language) {
|
|
|
83457
83476
|
"",
|
|
83458
83477
|
"## 工作区契约",
|
|
83459
83478
|
"",
|
|
83460
|
-
"版本以 package.json.version 为准。正式内容变化收尾时通过 context version inspect / record 同步递增版本并生成 changelog.yaml 和 CHANGELOG.md,具体说明由 Agent 根据 diff 和会话撰写。新增模块或扩大知识覆盖升 minor,普通修补、目录和正式状态变化升 patch;major 只由人工明确指定。.tmp 进度不算变化,build 只记录 hash
|
|
83461
|
-
"版本差异使用 Git 比较正文、结构、资源、导航和模板;可通过 version inspect --base 指定交付 commit/tag
|
|
83479
|
+
"版本以 package.json.version 为准。正式内容变化收尾时通过 context version inspect / record 同步递增版本并生成 changelog.yaml 和 CHANGELOG.md,具体说明由 Agent 根据 diff 和会话撰写。新增模块或扩大知识覆盖升 minor,普通修补、目录和正式状态变化升 patch;major 只由人工明确指定。.tmp 进度不算变化,build 只记录 hash。仅主协调者记录版本;版本记录本身不提交或发布,后续交付按本次授权和已安装的分发技能执行。触发来源必填;触发用户优先使用会话中明确的飞书显示名,否则由 CLI 读取 Git 用户名。",
|
|
83480
|
+
"版本差异使用 Git 比较正文、结构、资源、导航和模板;可通过 version inspect --base 指定交付 commit/tag。构建预览不锁定版本,已发布内容发生变化时必须递增版本。无需维护根目录 Context 版本、构建或发布回执。",
|
|
83462
83481
|
"每个版本的 Changelog 详情不得超过 1500 字:标题、变更列表、触发来源说明及用户显示名的可见字符合计计数,含标点,不计协议字段名、版本号和日期。超出时由 Agent 在提交前合并同类变化、删除重复过程描述,压缩至上限内;保留主要变化、影响和触发来源,不直接截断,也不把一轮拆成多个版本规避限制。",
|
|
83463
83482
|
"",
|
|
83464
83483
|
"- 通过已安装的 Context Skill 开始或恢复工作;直接使用 CLI 时,从 `context status --format json` 开始。",
|
|
@@ -83503,8 +83522,8 @@ function renderAgents(projectName, language) {
|
|
|
83503
83522
|
"",
|
|
83504
83523
|
"## Workspace Contract",
|
|
83505
83524
|
"",
|
|
83506
|
-
"package.json.version is the workspace version. At formal-content completion, use context version inspect / record to increment SemVer and generate changelog.yaml and CHANGELOG.md together. Write descriptions from the diff and conversation. Added modules/coverage increment minor; repairs, navigation and persistent status changes increment patch. Major requires an explicit user instruction. Ignore .tmp progress; build only records hashes. The coordinator alone records versions
|
|
83507
|
-
"Compare bodies, structure, assets, navigation and templates using Git; version inspect --base selects a delivery commit/tag. Preview builds do not seal versions.
|
|
83525
|
+
"package.json.version is the workspace version. At formal-content completion, use context version inspect / record to increment SemVer and generate changelog.yaml and CHANGELOG.md together. Write descriptions from the diff and conversation. Added modules/coverage increment minor; repairs, navigation and persistent status changes increment patch. Major requires an explicit user instruction. Ignore .tmp progress; build only records hashes. The coordinator alone records versions; recording a version does not commit or publish, and later delivery follows this task's authorization and the installed distribution skill. Triggers are required; use an explicitly known conversational Lark display name, otherwise let CLI use Git user.name.",
|
|
83526
|
+
"Compare bodies, structure, assets, navigation and templates using Git; version inspect --base selects a delivery commit/tag. Preview builds do not seal versions. Changes to already published content must increment the version. No root Context version/build/publication receipts are required.",
|
|
83508
83527
|
"Each version's changelog details must total at most 1500 visible characters, including punctuation across the title, changes, trigger descriptions and user display name; exclude protocol keys, version and date. Before submission, compress longer entries by merging related changes and removing repeated process narration. Preserve the main changes, impact and triggers; never truncate blindly or split one iteration into multiple versions to evade the limit.",
|
|
83509
83528
|
"",
|
|
83510
83529
|
"- Start or resume through the installed Context Skill. When using the CLI directly, begin with `context status --format json`.",
|
|
@@ -83574,14 +83593,14 @@ __export(exports_workspace, {
|
|
|
83574
83593
|
import { existsSync as existsSync13, readFileSync as readFileSync6, statSync as statSync3 } from "node:fs";
|
|
83575
83594
|
import { mkdir as mkdir19, readFile as readFile45, readdir as readdir14, writeFile as writeFile13 } from "node:fs/promises";
|
|
83576
83595
|
import { createRequire as createRequire4 } from "node:module";
|
|
83577
|
-
import { basename as basename7, dirname as dirname24, isAbsolute as isAbsolute12, join as
|
|
83596
|
+
import { basename as basename7, dirname as dirname24, isAbsolute as isAbsolute12, join as join54, parse as parse9, relative as relative16, resolve as resolve21 } from "node:path";
|
|
83578
83597
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
83579
83598
|
import { createJiti } from "jiti";
|
|
83580
83599
|
function isRecord12(value) {
|
|
83581
83600
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
83582
83601
|
}
|
|
83583
83602
|
function readPackageJson(root) {
|
|
83584
|
-
const packagePath =
|
|
83603
|
+
const packagePath = join54(root, "package.json");
|
|
83585
83604
|
if (!existsSync13(packagePath))
|
|
83586
83605
|
return null;
|
|
83587
83606
|
try {
|
|
@@ -83605,22 +83624,22 @@ function resolveExportImportTarget(packageJsonPath) {
|
|
|
83605
83624
|
return null;
|
|
83606
83625
|
const exportsField = parsed.exports;
|
|
83607
83626
|
if (typeof exportsField === "string") {
|
|
83608
|
-
return
|
|
83627
|
+
return join54(dirname24(packageJsonPath), exportsField);
|
|
83609
83628
|
}
|
|
83610
83629
|
if (isRecord12(exportsField)) {
|
|
83611
83630
|
const rootExport = exportsField["."];
|
|
83612
83631
|
if (typeof rootExport === "string") {
|
|
83613
|
-
return
|
|
83632
|
+
return join54(dirname24(packageJsonPath), rootExport);
|
|
83614
83633
|
}
|
|
83615
83634
|
if (isRecord12(rootExport) && typeof rootExport.import === "string") {
|
|
83616
|
-
return
|
|
83635
|
+
return join54(dirname24(packageJsonPath), rootExport.import);
|
|
83617
83636
|
}
|
|
83618
83637
|
}
|
|
83619
83638
|
if (typeof parsed.module === "string") {
|
|
83620
|
-
return
|
|
83639
|
+
return join54(dirname24(packageJsonPath), parsed.module);
|
|
83621
83640
|
}
|
|
83622
83641
|
if (typeof parsed.main === "string") {
|
|
83623
|
-
return
|
|
83642
|
+
return join54(dirname24(packageJsonPath), parsed.main);
|
|
83624
83643
|
}
|
|
83625
83644
|
return null;
|
|
83626
83645
|
}
|
|
@@ -83638,7 +83657,7 @@ function resolveContextSdkImportAlias(entryPath) {
|
|
|
83638
83657
|
function readCurrentPackageVersion() {
|
|
83639
83658
|
let dir = dirname24(fileURLToPath4(import.meta.url));
|
|
83640
83659
|
for (let index2 = 0;index2 < 8; index2++) {
|
|
83641
|
-
const packagePath =
|
|
83660
|
+
const packagePath = join54(dir, "package.json");
|
|
83642
83661
|
if (existsSync13(packagePath)) {
|
|
83643
83662
|
const parsed = readPackageJson(dir);
|
|
83644
83663
|
if (typeof parsed?.version === "string" && parsed.version.trim().length > 0) {
|
|
@@ -83821,7 +83840,7 @@ async function listStaticTemplateFiles(root, dir = root) {
|
|
|
83821
83840
|
const entries2 = await readdir14(dir, { withFileTypes: true });
|
|
83822
83841
|
const files = [];
|
|
83823
83842
|
for (const entry of entries2) {
|
|
83824
|
-
const absolutePath =
|
|
83843
|
+
const absolutePath = join54(dir, entry.name);
|
|
83825
83844
|
if (entry.isDirectory()) {
|
|
83826
83845
|
files.push(...await listStaticTemplateFiles(root, absolutePath));
|
|
83827
83846
|
continue;
|
|
@@ -83838,7 +83857,7 @@ async function listStaticTemplateFiles(root, dir = root) {
|
|
|
83838
83857
|
function resolveContextPackageTemplatesRoot() {
|
|
83839
83858
|
try {
|
|
83840
83859
|
const packageJsonPath = createRequire4(import.meta.url).resolve("@c4a/context/package.json");
|
|
83841
|
-
const templateRoot =
|
|
83860
|
+
const templateRoot = join54(dirname24(packageJsonPath), "templates", "package-templates");
|
|
83842
83861
|
if (existsSync13(templateRoot))
|
|
83843
83862
|
return templateRoot;
|
|
83844
83863
|
} catch {}
|
|
@@ -83850,7 +83869,7 @@ function resolveContextPackageTemplatesRoot() {
|
|
|
83850
83869
|
}
|
|
83851
83870
|
async function writeDefaultPackageTemplates(projectRoot, result, language) {
|
|
83852
83871
|
const defaultRoot = resolveContextPackageTemplatesRoot();
|
|
83853
|
-
const templateRoot = language === "zh-CN" ?
|
|
83872
|
+
const templateRoot = language === "zh-CN" ? join54(dirname24(defaultRoot), "package-templates.zh-CN") : defaultRoot;
|
|
83854
83873
|
if (!existsSync13(templateRoot)) {
|
|
83855
83874
|
throw new ContextError(ExitCode.WorkspaceStateError, `missing ${language} @c4a/context package templates`, {
|
|
83856
83875
|
category: ErrorCategory.WorkspaceStateInvalid,
|
|
@@ -83860,15 +83879,15 @@ async function writeDefaultPackageTemplates(projectRoot, result, language) {
|
|
|
83860
83879
|
}
|
|
83861
83880
|
const files = await listStaticTemplateFiles(templateRoot);
|
|
83862
83881
|
for (const file of files) {
|
|
83863
|
-
await writeIfMissing(
|
|
83882
|
+
await writeIfMissing(join54(projectRoot, "src", "package-templates", ...file.relativePath.split("/")), await readFile45(file.absolutePath, "utf8"), result);
|
|
83864
83883
|
}
|
|
83865
83884
|
const templateKinds = [...new Set(files.map((file) => file.relativePath.split("/")[0]).filter((value) => value !== undefined && value.length > 0))];
|
|
83866
83885
|
for (const templateKind of templateKinds) {
|
|
83867
|
-
const root =
|
|
83886
|
+
const root = join54(projectRoot, "src", "package-templates", templateKind);
|
|
83868
83887
|
if (await writeStarterTemplateReviewMarker(root)) {
|
|
83869
|
-
result.created.push(
|
|
83888
|
+
result.created.push(join54(root, PACKAGE_TEMPLATE_REVIEW_FILE));
|
|
83870
83889
|
} else {
|
|
83871
|
-
result.kept.push(
|
|
83890
|
+
result.kept.push(join54(root, PACKAGE_TEMPLATE_REVIEW_FILE));
|
|
83872
83891
|
}
|
|
83873
83892
|
}
|
|
83874
83893
|
}
|
|
@@ -83958,23 +83977,23 @@ async function initContextProject(input) {
|
|
|
83958
83977
|
kept: []
|
|
83959
83978
|
};
|
|
83960
83979
|
for (const dir of PROJECT_DIRS) {
|
|
83961
|
-
await mkdir19(
|
|
83980
|
+
await mkdir19(join54(projectRoot, dir), { recursive: true });
|
|
83962
83981
|
}
|
|
83963
83982
|
for (const dir of PROJECT_SCRATCH_DIRS) {
|
|
83964
|
-
await mkdir19(
|
|
83983
|
+
await mkdir19(join54(projectRoot, dir), { recursive: true });
|
|
83965
83984
|
}
|
|
83966
|
-
await mkdir19(
|
|
83967
|
-
await mkdir19(
|
|
83968
|
-
await mkdir19(
|
|
83969
|
-
await writeIfMissing(
|
|
83970
|
-
await writeIfMissing(
|
|
83985
|
+
await mkdir19(join54(projectRoot, "sources", "repo"), { recursive: true });
|
|
83986
|
+
await mkdir19(join54(projectRoot, "sources", "file"), { recursive: true });
|
|
83987
|
+
await mkdir19(join54(projectRoot, "sources", "lark"), { recursive: true });
|
|
83988
|
+
await writeIfMissing(join54(projectRoot, "package.json"), renderPackageJson(projectName, readCurrentPackageVersion(), input.dev, language, input.debug), result);
|
|
83989
|
+
await writeIfMissing(join54(projectRoot, "src", "index.ts"), renderProjectEntry(language), result);
|
|
83971
83990
|
await writeDefaultPackageTemplates(projectRoot, result, language);
|
|
83972
|
-
await writeIfMissing(
|
|
83973
|
-
await writeIfMissing(
|
|
83974
|
-
await writeIfMissing(
|
|
83975
|
-
await writeIfMissing(
|
|
83976
|
-
await writeIfMissing(
|
|
83977
|
-
await writeIfMissing(
|
|
83991
|
+
await writeIfMissing(join54(projectRoot, "sources", "repo", "index.yaml"), renderRepoIndex(), result);
|
|
83992
|
+
await writeIfMissing(join54(projectRoot, "sources", "file", "index.yaml"), renderFileIndex(), result);
|
|
83993
|
+
await writeIfMissing(join54(projectRoot, "sources", "lark", "index.yaml"), renderLarkIndex(), result);
|
|
83994
|
+
await writeIfMissing(join54(projectRoot, ".gitignore"), renderGitignore(), result);
|
|
83995
|
+
await writeIfMissing(join54(projectRoot, "README.md"), renderReadme(projectName, language), result);
|
|
83996
|
+
await writeIfMissing(join54(projectRoot, "AGENTS.md"), renderAgents(projectName, language), result);
|
|
83978
83997
|
if (input.debug === true)
|
|
83979
83998
|
await enableContextDebug(projectRoot, "init");
|
|
83980
83999
|
return result;
|
|
@@ -83988,7 +84007,7 @@ async function loadContextProjectModule(root) {
|
|
|
83988
84007
|
next: "Ensure package.json declares context.project=true and context.entry points to src/index.ts, then rerun the command."
|
|
83989
84008
|
});
|
|
83990
84009
|
}
|
|
83991
|
-
const entryPath =
|
|
84010
|
+
const entryPath = join54(root, projectConfig.entry);
|
|
83992
84011
|
const jiti = createJiti(entryPath, {
|
|
83993
84012
|
alias: {
|
|
83994
84013
|
"@c4a/context": resolveContextSdkImportAlias(entryPath)
|
|
@@ -84058,7 +84077,7 @@ var init_workspace = __esm(() => {
|
|
|
84058
84077
|
init_debugTrace();
|
|
84059
84078
|
init_projectModulePolicy();
|
|
84060
84079
|
PROJECT_DIRS = ["src", "sources", "knowledge", "dist"];
|
|
84061
|
-
PROJECT_SCRATCH_DIRS = [
|
|
84080
|
+
PROJECT_SCRATCH_DIRS = [join54(".tmp", "agent-payloads")];
|
|
84062
84081
|
PROJECT_LANGUAGES = ["en", "zh-CN"];
|
|
84063
84082
|
});
|
|
84064
84083
|
|
|
@@ -84156,7 +84175,7 @@ var init_verifyDiagnostics = __esm(() => {
|
|
|
84156
84175
|
|
|
84157
84176
|
// src/project/verify.ts
|
|
84158
84177
|
import { existsSync as existsSync14 } from "node:fs";
|
|
84159
|
-
import { join as
|
|
84178
|
+
import { join as join55 } from "node:path";
|
|
84160
84179
|
function evidenceStatusForIssues(issues) {
|
|
84161
84180
|
if (issues.some((issue) => issue.severity === "error"))
|
|
84162
84181
|
return "fail";
|
|
@@ -84230,7 +84249,7 @@ async function verifyProjectWorkspace(projectRoot, options = {}) {
|
|
|
84230
84249
|
pageRelPath: `knowledge/${file.relPath}`,
|
|
84231
84250
|
content: content3
|
|
84232
84251
|
})) {
|
|
84233
|
-
if (!existsSync14(
|
|
84252
|
+
if (!existsSync14(join55(projectRoot, assetPath))) {
|
|
84234
84253
|
issues.push({
|
|
84235
84254
|
severity: "error",
|
|
84236
84255
|
code: "approved-resource-missing",
|
|
@@ -84367,7 +84386,7 @@ __export(exports_close, {
|
|
|
84367
84386
|
});
|
|
84368
84387
|
import { existsSync as existsSync15 } from "node:fs";
|
|
84369
84388
|
import { mkdir as mkdir20, writeFile as writeFile14 } from "node:fs/promises";
|
|
84370
|
-
import { dirname as dirname25, join as
|
|
84389
|
+
import { dirname as dirname25, join as join56 } from "node:path";
|
|
84371
84390
|
function parseFrontmatter4(content3) {
|
|
84372
84391
|
const match = /^---\r?\n([\s\S]*?)\r?\n---/u.exec(content3);
|
|
84373
84392
|
if (match?.[1] === undefined)
|
|
@@ -84431,7 +84450,7 @@ async function deriveApprovedStructure(projectRoot) {
|
|
|
84431
84450
|
}
|
|
84432
84451
|
async function writeApprovedStructureProjection(projectRoot) {
|
|
84433
84452
|
const { inputHash, structure, compactFiles } = await deriveApprovedStructure(projectRoot);
|
|
84434
|
-
const outputPath =
|
|
84453
|
+
const outputPath = join56(projectRoot, STRUCTURE_PATH4);
|
|
84435
84454
|
await mkdir20(dirname25(outputPath), { recursive: true });
|
|
84436
84455
|
await writeFile14(outputPath, import_yaml30.default.stringify(structure), "utf8");
|
|
84437
84456
|
await Promise.all(compactFiles.map((file) => writeFile14(file.absPath, file.content, "utf8")));
|
|
@@ -84442,7 +84461,7 @@ function referencesReceipt() {
|
|
|
84442
84461
|
}
|
|
84443
84462
|
async function readProjectCloseStatus(projectRoot) {
|
|
84444
84463
|
const approved = await approvedKnowledgeFiles(projectRoot);
|
|
84445
|
-
const structurePath =
|
|
84464
|
+
const structurePath = join56(projectRoot, STRUCTURE_PATH4);
|
|
84446
84465
|
if (approved.length === 0 && !existsSync15(structurePath))
|
|
84447
84466
|
return { state: "missing", diagnostics: [] };
|
|
84448
84467
|
const inputHash = await approvedKnowledgeInputHash(projectRoot);
|
|
@@ -84499,7 +84518,7 @@ async function closeProjectWorkspace(projectRoot) {
|
|
|
84499
84518
|
next: "Fix context verify errors, then rerun context close --format json."
|
|
84500
84519
|
});
|
|
84501
84520
|
}
|
|
84502
|
-
const outputPath =
|
|
84521
|
+
const outputPath = join56(projectRoot, STRUCTURE_PATH4);
|
|
84503
84522
|
await mkdir20(dirname25(outputPath), { recursive: true });
|
|
84504
84523
|
await writeFile14(outputPath, `${import_yaml30.default.stringify(structure)}`, "utf8");
|
|
84505
84524
|
await Promise.all(compactFiles.map((file) => writeFile14(file.absPath, file.content, "utf8")));
|
|
@@ -84576,7 +84595,7 @@ var init_close = __esm(() => {
|
|
|
84576
84595
|
init_knowledgeAssetRepair();
|
|
84577
84596
|
init_approvedKnowledgeMetadata();
|
|
84578
84597
|
import_yaml30 = __toESM(require_dist(), 1);
|
|
84579
|
-
STRUCTURE_PATH4 =
|
|
84598
|
+
STRUCTURE_PATH4 = join56(KNOWLEDGE_ROOT, "structure.yaml");
|
|
84580
84599
|
});
|
|
84581
84600
|
|
|
84582
84601
|
// src/project/packageOutputPaths.ts
|
|
@@ -84608,7 +84627,7 @@ var init_packageOutputPaths = __esm(() => {
|
|
|
84608
84627
|
|
|
84609
84628
|
// src/project/packageSiteAddress.ts
|
|
84610
84629
|
import { readFile as readFile46, writeFile as writeFile15, rename as rename6 } from "node:fs/promises";
|
|
84611
|
-
import { join as
|
|
84630
|
+
import { join as join57 } from "node:path";
|
|
84612
84631
|
function normalizeSiteUrl(value) {
|
|
84613
84632
|
const url = new URL(value);
|
|
84614
84633
|
if (!["https:", "http:"].includes(url.protocol) || url.username || url.password || url.search || url.hash) {
|
|
@@ -84621,7 +84640,7 @@ async function readPackageSiteUrl(root, pkg) {
|
|
|
84621
84640
|
if (pkg.kind !== "package.kb" || !pkg.site)
|
|
84622
84641
|
return;
|
|
84623
84642
|
try {
|
|
84624
|
-
const map2 = JSON.parse(await readFile46(
|
|
84643
|
+
const map2 = JSON.parse(await readFile46(join57(root, packageSiteOutputDir(pkg), SITE_MAP_FILE), "utf8"));
|
|
84625
84644
|
return typeof map2.site_url === "string" ? normalizeSiteUrl(map2.site_url) : undefined;
|
|
84626
84645
|
} catch (error) {
|
|
84627
84646
|
if (error.code === "ENOENT" || error instanceof SyntaxError || error instanceof TypeError)
|
|
@@ -84638,7 +84657,7 @@ async function recordPackageSiteUrl(root, packageName, value) {
|
|
|
84638
84657
|
if (!pkg || pkg.kind !== "package.kb" || !pkg.site) {
|
|
84639
84658
|
throw new TypeError("Select a declared knowledge package with a website");
|
|
84640
84659
|
}
|
|
84641
|
-
const siteMap =
|
|
84660
|
+
const siteMap = join57(root, packageSiteOutputDir(pkg), SITE_MAP_FILE);
|
|
84642
84661
|
let map2;
|
|
84643
84662
|
try {
|
|
84644
84663
|
map2 = JSON.parse(await readFile46(siteMap, "utf8"));
|
|
@@ -84652,7 +84671,11 @@ async function recordPackageSiteUrl(root, packageName, value) {
|
|
|
84652
84671
|
}
|
|
84653
84672
|
const content3 = JSON.stringify({ ...map2, site_url: siteUrl }, null, 2) + `
|
|
84654
84673
|
`;
|
|
84655
|
-
for (const path2 of [
|
|
84674
|
+
for (const path2 of [
|
|
84675
|
+
siteMap,
|
|
84676
|
+
join57(root, pkg.outDir, SITE_MAP_FILE),
|
|
84677
|
+
join57(root, pkg.outDir, packageDistributionMetadataPath(SITE_MAP_FILE))
|
|
84678
|
+
]) {
|
|
84656
84679
|
await writeFile15(`${path2}.tmp`, content3);
|
|
84657
84680
|
await rename6(`${path2}.tmp`, path2);
|
|
84658
84681
|
}
|
|
@@ -84662,6 +84685,7 @@ async function recordPackageSiteUrl(root, packageName, value) {
|
|
|
84662
84685
|
var SITE_MAP_FILE = "context-site-map.json";
|
|
84663
84686
|
var init_packageSiteAddress = __esm(() => {
|
|
84664
84687
|
init_packageOutputPaths();
|
|
84688
|
+
init_packageDistributionMetadata();
|
|
84665
84689
|
init_writeLock();
|
|
84666
84690
|
});
|
|
84667
84691
|
|
|
@@ -84713,7 +84737,7 @@ var init_productionReviewCandidates = __esm(() => {
|
|
|
84713
84737
|
import { createHash as createHash14 } from "node:crypto";
|
|
84714
84738
|
import { existsSync as existsSync16 } from "node:fs";
|
|
84715
84739
|
import { readFile as readFile47 } from "node:fs/promises";
|
|
84716
|
-
import { join as
|
|
84740
|
+
import { join as join58, relative as relative17 } from "node:path";
|
|
84717
84741
|
function parsePackageLinkWarnings(value) {
|
|
84718
84742
|
if (!Array.isArray(value))
|
|
84719
84743
|
return [];
|
|
@@ -84728,7 +84752,7 @@ async function walkPackageFiles(root) {
|
|
|
84728
84752
|
for (const entry of entries2) {
|
|
84729
84753
|
if (IGNORED_PACKAGE_FS_ENTRIES.has(entry.name))
|
|
84730
84754
|
continue;
|
|
84731
|
-
const absPath =
|
|
84755
|
+
const absPath = join58(dir, entry.name);
|
|
84732
84756
|
if (entry.isDirectory()) {
|
|
84733
84757
|
await visit3(absPath);
|
|
84734
84758
|
continue;
|
|
@@ -84759,16 +84783,16 @@ function classifyOutputFile(path2, knowledgeGroups) {
|
|
|
84759
84783
|
}
|
|
84760
84784
|
async function packageOutputSnapshot(projectRoot, pkg, knowledgeGroups, previousOutputs = []) {
|
|
84761
84785
|
const previousByPath = new Map(previousOutputs.map((file) => [file.path, file]));
|
|
84762
|
-
const files = (await Promise.all(packageOutputDirs(pkg).map(async (output) => (await walkPackageFiles(
|
|
84786
|
+
const files = (await Promise.all(packageOutputDirs(pkg).map(async (output) => (await walkPackageFiles(join58(projectRoot, output))).map((file) => ({
|
|
84763
84787
|
...file,
|
|
84764
|
-
relPath: toPosixPath6(relative17(
|
|
84788
|
+
relPath: toPosixPath6(relative17(join58(projectRoot, pkg.outDir), file.absPath))
|
|
84765
84789
|
}))))).flat();
|
|
84766
84790
|
return Promise.all(files.map(async (file) => {
|
|
84767
84791
|
const current2 = classifyOutputFile(file.relPath, knowledgeGroups);
|
|
84768
84792
|
const previous2 = previousByPath.get(file.relPath);
|
|
84769
84793
|
const classification = current2.kind === "file" && previous2 !== undefined ? { path: file.relPath, kind: previous2.kind, ...previous2.group === undefined ? {} : { group: previous2.group } } : current2;
|
|
84770
84794
|
let content3 = await readFile47(file.absPath);
|
|
84771
|
-
if (file.absPath ===
|
|
84795
|
+
if (file.absPath === join58(projectRoot, pkg.outDir, "context-site-map.json") || file.absPath === join58(projectRoot, pkg.outDir, packageDistributionMetadataPath("context-site-map.json")) || file.absPath === join58(projectRoot, packageSiteOutputDir(pkg), "context-site-map.json")) {
|
|
84772
84796
|
try {
|
|
84773
84797
|
const map2 = JSON.parse(content3.toString());
|
|
84774
84798
|
if (map2.protocol === "context.site-output/v1" && Array.isArray(map2.pages)) {
|
|
@@ -84787,8 +84811,8 @@ async function packageOutputFingerprint(projectRoot, pkg, observed) {
|
|
|
84787
84811
|
const snapshot = observed ?? await packageOutputSnapshot(projectRoot, pkg, new Map);
|
|
84788
84812
|
return {
|
|
84789
84813
|
fingerprint: createHash14("sha256").update(JSON.stringify({
|
|
84790
|
-
outDirExists: existsSync16(
|
|
84791
|
-
siteDirExists: pkg.kind === "package.kb" && pkg.site ? existsSync16(
|
|
84814
|
+
outDirExists: existsSync16(join58(projectRoot, pkg.outDir)),
|
|
84815
|
+
siteDirExists: pkg.kind === "package.kb" && pkg.site ? existsSync16(join58(projectRoot, packageSiteOutputDir(pkg))) : undefined,
|
|
84792
84816
|
files: snapshot.map(({ path: path2, sha256 }) => ({ path: path2, sha256 }))
|
|
84793
84817
|
})).digest("hex"),
|
|
84794
84818
|
files: snapshot.length
|
|
@@ -84872,12 +84896,13 @@ var init_packageBuildReceipt = __esm(() => {
|
|
|
84872
84896
|
init_packageIndexes();
|
|
84873
84897
|
init_packageTemplateUtils();
|
|
84874
84898
|
init_packageOutputPaths();
|
|
84899
|
+
init_packageDistributionMetadata();
|
|
84875
84900
|
IGNORED_PACKAGE_FS_ENTRIES = new Set([".DS_Store"]);
|
|
84876
84901
|
});
|
|
84877
84902
|
|
|
84878
84903
|
// src/project/knowledgeMapCoverage.ts
|
|
84879
84904
|
import { readFile as readFile48 } from "node:fs/promises";
|
|
84880
|
-
import { join as
|
|
84905
|
+
import { join as join59 } from "node:path";
|
|
84881
84906
|
function knowledgeMapArticleTargets(files) {
|
|
84882
84907
|
return files.flatMap((file) => {
|
|
84883
84908
|
const meta = parseKnowledgeFrontmatter(file.content);
|
|
@@ -84893,7 +84918,7 @@ function knowledgeMapArticleTargets(files) {
|
|
|
84893
84918
|
async function approvedKnowledgeMapTargets(root) {
|
|
84894
84919
|
const metadata = await readApprovedKnowledgeMetadataIndex(root);
|
|
84895
84920
|
const articles = new Map(validateArticleStructureEntries(metadata.structure?.articles ?? []).map((article) => [article.path, article]));
|
|
84896
|
-
const files = await walkPackageFiles(
|
|
84921
|
+
const files = await walkPackageFiles(join59(root, "knowledge"));
|
|
84897
84922
|
const content3 = await Promise.all(files.filter((file) => isApprovedKnowledgeMarkdownPath(file.relPath) && !file.relPath.startsWith("assets/")).map(async (file) => ({
|
|
84898
84923
|
article: articles.get(file.relPath),
|
|
84899
84924
|
content: hydrateApprovedKnowledgeMarkdown({ content: await readFile48(file.absPath, "utf8"), relPath: file.relPath, metadata })
|
|
@@ -84943,10 +84968,10 @@ var init_knowledgeMapCoverage = __esm(() => {
|
|
|
84943
84968
|
|
|
84944
84969
|
// src/project/knowledgeMap.ts
|
|
84945
84970
|
import { readFile as readFile49 } from "node:fs/promises";
|
|
84946
|
-
import { join as
|
|
84971
|
+
import { join as join60 } from "node:path";
|
|
84947
84972
|
async function optionalText(root, path2) {
|
|
84948
84973
|
try {
|
|
84949
|
-
return await readFile49(
|
|
84974
|
+
return await readFile49(join60(root, path2), "utf8");
|
|
84950
84975
|
} catch (error) {
|
|
84951
84976
|
if (error.code === "ENOENT")
|
|
84952
84977
|
return;
|
|
@@ -85007,7 +85032,7 @@ var init_knowledgeMap2 = __esm(() => {
|
|
|
85007
85032
|
|
|
85008
85033
|
// src/project/packageKnowledgeMap.ts
|
|
85009
85034
|
import { readFile as readFile50, writeFile as writeFile16 } from "node:fs/promises";
|
|
85010
|
-
import { join as
|
|
85035
|
+
import { join as join61 } from "node:path";
|
|
85011
85036
|
function knowledgeMapSectionAnchor(key) {
|
|
85012
85037
|
return `section-${encodeURIComponent(key)}`;
|
|
85013
85038
|
}
|
|
@@ -85032,8 +85057,8 @@ async function writePackageKnowledgeMap(input) {
|
|
|
85032
85057
|
return [];
|
|
85033
85058
|
const projected = projectKnowledgeMap(input.structure, packageKnowledgeMapTargets(input.pkg, input.selected));
|
|
85034
85059
|
projected.warnings = projected.warnings.filter((warning) => !warning.target.startsWith("site:"));
|
|
85035
|
-
const root =
|
|
85036
|
-
const mapPath =
|
|
85060
|
+
const root = join61(input.projectRoot, input.pkg.outDir);
|
|
85061
|
+
const mapPath = join61(root, "context-knowledge-map.json");
|
|
85037
85062
|
try {
|
|
85038
85063
|
await readFile50(mapPath);
|
|
85039
85064
|
throw new TypeError("package template uses reserved context-knowledge-map.json; rename that template output");
|
|
@@ -85054,7 +85079,7 @@ async function writePackageKnowledgeMap(input) {
|
|
|
85054
85079
|
}
|
|
85055
85080
|
render(projected.entries, 0);
|
|
85056
85081
|
if (lines.length) {
|
|
85057
|
-
const indexPath =
|
|
85082
|
+
const indexPath = join61(root, "index.md");
|
|
85058
85083
|
let existing = "";
|
|
85059
85084
|
try {
|
|
85060
85085
|
existing = await readFile50(indexPath, "utf8");
|
|
@@ -85081,7 +85106,7 @@ var init_packageKnowledgeMap = __esm(() => {
|
|
|
85081
85106
|
// src/project/packageLlms.ts
|
|
85082
85107
|
import { createHash as createHash15 } from "node:crypto";
|
|
85083
85108
|
import { access as access4, mkdir as mkdir21, writeFile as writeFile17 } from "node:fs/promises";
|
|
85084
|
-
import { dirname as dirname26, join as
|
|
85109
|
+
import { dirname as dirname26, join as join62, posix as posix5 } from "node:path";
|
|
85085
85110
|
function llmsArticles(pkg, selected) {
|
|
85086
85111
|
return selected.map((file) => {
|
|
85087
85112
|
const meta = parseKnowledgeFrontmatter(file.content);
|
|
@@ -85181,7 +85206,7 @@ async function writeLlmsDocuments(root, documents, options = {}) {
|
|
|
85181
85206
|
for (const [path2, content3] of documents.files) {
|
|
85182
85207
|
let exists = false;
|
|
85183
85208
|
try {
|
|
85184
|
-
await access4(
|
|
85209
|
+
await access4(join62(root, path2));
|
|
85185
85210
|
exists = true;
|
|
85186
85211
|
} catch (error) {
|
|
85187
85212
|
if (error.code !== "ENOENT")
|
|
@@ -85191,8 +85216,8 @@ async function writeLlmsDocuments(root, documents, options = {}) {
|
|
|
85191
85216
|
continue;
|
|
85192
85217
|
if (exists)
|
|
85193
85218
|
throw new Error(`Package template uses reserved LLMS output ${path2}; rename that template output.`);
|
|
85194
|
-
await mkdir21(dirname26(
|
|
85195
|
-
await writeFile17(
|
|
85219
|
+
await mkdir21(dirname26(join62(root, path2)), { recursive: true });
|
|
85220
|
+
await writeFile17(join62(root, path2), options.utf8Bom ? "\uFEFF" + content3.replace(/^\uFEFF/u, "") : content3, "utf8");
|
|
85196
85221
|
}
|
|
85197
85222
|
}
|
|
85198
85223
|
var PACKAGE_LLMS_VERSION = "knowledge-map-llms-v1", label = (text7) => text7.replace(/[\\[\]<>`*]/gu, "\\$&").replace(/[\r\n]/gu, " "), articlePath = (identity) => `llms/pages/${createHash15("sha256").update(identity).digest("hex").slice(0, 32)}.txt`;
|
|
@@ -86191,7 +86216,7 @@ var init_packageSiteBranding = __esm(() => {
|
|
|
86191
86216
|
// src/project/packageSiteExtensions.ts
|
|
86192
86217
|
import { createHash as createHash16 } from "node:crypto";
|
|
86193
86218
|
import { lstat as lstat8, readdir as readdir15, readFile as readFile51, mkdir as mkdir22, writeFile as writeFile18, symlink } from "node:fs/promises";
|
|
86194
|
-
import { join as
|
|
86219
|
+
import { join as join63, dirname as dirname27, resolve as resolve22 } from "node:path";
|
|
86195
86220
|
function invalidSiteExtension(message) {
|
|
86196
86221
|
throw new ContextError(ExitCode.UserError, `Site extensions: ${message}. Update site.extensions, its src files or the knowledge-map target, then retry the build.`, {
|
|
86197
86222
|
reason_code: "invalid-site-extension"
|
|
@@ -86210,7 +86235,7 @@ async function readSiteExtensions(projectRoot, extensions) {
|
|
|
86210
86235
|
invalid(`unsafe root ${root}`);
|
|
86211
86236
|
let cursor = projectRoot;
|
|
86212
86237
|
for (const part of root.split("/")) {
|
|
86213
|
-
cursor =
|
|
86238
|
+
cursor = join63(cursor, part);
|
|
86214
86239
|
const info = await lstat8(cursor).catch((error) => {
|
|
86215
86240
|
if (error.code === "ENOENT")
|
|
86216
86241
|
invalid(`missing directory ${root}`);
|
|
@@ -86230,9 +86255,9 @@ async function readSiteExtensions(projectRoot, extensions) {
|
|
|
86230
86255
|
if (entry.isSymbolicLink())
|
|
86231
86256
|
invalid(`symlink at ${path2}`);
|
|
86232
86257
|
if (entry.isDirectory())
|
|
86233
|
-
await walk(
|
|
86258
|
+
await walk(join63(directory, entry.name), path2 + "/");
|
|
86234
86259
|
else if (entry.isFile())
|
|
86235
|
-
files.push({ path: path2, bytes: await readFile51(
|
|
86260
|
+
files.push({ path: path2, bytes: await readFile51(join63(directory, entry.name)) });
|
|
86236
86261
|
}
|
|
86237
86262
|
}
|
|
86238
86263
|
await walk(cursor, "");
|
|
@@ -86252,7 +86277,7 @@ async function readSiteExtensions(projectRoot, extensions) {
|
|
|
86252
86277
|
hash3.update(file.path + "\x00").update(file.bytes).update("\x00");
|
|
86253
86278
|
for (const name3 of ["package.json", "bun.lock", "pnpm-lock.yaml", "package-lock.json"]) {
|
|
86254
86279
|
try {
|
|
86255
|
-
hash3.update(name3).update(await readFile51(
|
|
86280
|
+
hash3.update(name3).update(await readFile51(join63(projectRoot, name3)));
|
|
86256
86281
|
} catch (error) {
|
|
86257
86282
|
if (error.code !== "ENOENT")
|
|
86258
86283
|
throw error;
|
|
@@ -86265,9 +86290,9 @@ function siteExtensionTargets(site) {
|
|
|
86265
86290
|
}
|
|
86266
86291
|
async function writeSiteExtensions(projectRoot, temporary, extensions) {
|
|
86267
86292
|
const { files } = await readSiteExtensions(projectRoot, extensions);
|
|
86268
|
-
const root =
|
|
86293
|
+
const root = join63(temporary, "_site");
|
|
86269
86294
|
for (const file of files) {
|
|
86270
|
-
const path2 =
|
|
86295
|
+
const path2 = join63(root, file.path);
|
|
86271
86296
|
await mkdir22(dirname27(path2), { recursive: true });
|
|
86272
86297
|
await writeFile18(path2, file.bytes);
|
|
86273
86298
|
}
|
|
@@ -86276,7 +86301,7 @@ async function writeSiteExtensions(projectRoot, temporary, extensions) {
|
|
|
86276
86301
|
const modules = resolve22(projectRoot, "node_modules");
|
|
86277
86302
|
if ((await lstat8(modules)).isDirectory() || (await lstat8(modules)).isSymbolicLink()) {
|
|
86278
86303
|
await mkdir22(root, { recursive: true });
|
|
86279
|
-
await symlink(modules,
|
|
86304
|
+
await symlink(modules, join63(root, "node_modules"), "dir");
|
|
86280
86305
|
}
|
|
86281
86306
|
} catch (error) {
|
|
86282
86307
|
if (error.code !== "ENOENT")
|
|
@@ -86295,16 +86320,16 @@ async function writeSiteExtensions(projectRoot, temporary, extensions) {
|
|
|
86295
86320
|
imports.push(`const ${name3} = defineAsyncComponent(() => import(${JSON.stringify(`../../_site/${path2}`)}));`);
|
|
86296
86321
|
slots.push(`${JSON.stringify(name3)}: ${name3 === "floating" ? `() => h(resolveComponent('ClientOnly'), null, { default: () => h(${name3}) })` : `() => h(${name3})`}`);
|
|
86297
86322
|
}
|
|
86298
|
-
await writeFile18(
|
|
86323
|
+
await writeFile18(join63(temporary, ".vitepress/theme/extensions.js"), imports.join(`
|
|
86299
86324
|
`) + `
|
|
86300
86325
|
export default {${slots.join(",")}};
|
|
86301
86326
|
`);
|
|
86302
86327
|
for (const [key, path2] of Object.entries(extensions?.pages ?? {})) {
|
|
86303
|
-
await mkdir22(
|
|
86328
|
+
await mkdir22(join63(temporary, "custom"), { recursive: true });
|
|
86304
86329
|
const content3 = files.find((file) => file.path === path2).bytes.toString("utf8");
|
|
86305
86330
|
const metadata = parseKnowledgeFrontmatter(content3);
|
|
86306
86331
|
const title = metadata.title ?? /^#\s+(.+)$/m.exec(content3)?.[1] ?? key;
|
|
86307
|
-
await writeFile18(
|
|
86332
|
+
await writeFile18(join63(temporary, "custom", `${key}.md`), `---
|
|
86308
86333
|
${JSON.stringify({ layout: "page", ...metadata, title })}
|
|
86309
86334
|
---
|
|
86310
86335
|
<script setup>
|
|
@@ -86328,7 +86353,7 @@ import { createHash as createHash17 } from "node:crypto";
|
|
|
86328
86353
|
import { spawn as spawn3 } from "node:child_process";
|
|
86329
86354
|
import { mkdir as mkdir23, mkdtemp as mkdtemp2, readFile as readFile52, writeFile as writeFile19, rm as rm12, symlink as symlink2, cp, access as access5, stat as stat8 } from "node:fs/promises";
|
|
86330
86355
|
import { createRequire as createRequire5 } from "node:module";
|
|
86331
|
-
import { dirname as dirname28, join as
|
|
86356
|
+
import { dirname as dirname28, join as join64, posix as posix6 } from "node:path";
|
|
86332
86357
|
function sitePagePath(identity) {
|
|
86333
86358
|
return `pages/${createHash17("sha256").update(identity).digest("hex").slice(0, 32)}.html`;
|
|
86334
86359
|
}
|
|
@@ -86449,7 +86474,7 @@ function siteSections(entries2) {
|
|
|
86449
86474
|
async function compileSite(root, outDir) {
|
|
86450
86475
|
const vitepressRoot = dirname28(require2.resolve("vitepress/package.json"));
|
|
86451
86476
|
await new Promise((resolve8, reject) => {
|
|
86452
|
-
const child = spawn3(process.versions.bun ? "node" : process.execPath, [
|
|
86477
|
+
const child = spawn3(process.versions.bun ? "node" : process.execPath, [join64(vitepressRoot, "bin/vitepress.js"), "build", root, "--outDir", outDir], { stdio: ["ignore", "pipe", "pipe"] });
|
|
86453
86478
|
let tail = "";
|
|
86454
86479
|
const receive = (chunk) => {
|
|
86455
86480
|
tail = (tail + chunk.toString()).slice(-16000);
|
|
@@ -86480,8 +86505,8 @@ async function writePackageSite(input) {
|
|
|
86480
86505
|
const base = options.base ?? "/";
|
|
86481
86506
|
const history = await readWorkspaceChangelog(projectRoot);
|
|
86482
86507
|
const historyDate = history[0]?.date ?? null;
|
|
86483
|
-
const root =
|
|
86484
|
-
const output =
|
|
86508
|
+
const root = join64(projectRoot, pkg.outDir);
|
|
86509
|
+
const output = join64(projectRoot, packageSiteOutputDir(pkg));
|
|
86485
86510
|
try {
|
|
86486
86511
|
await access5(output);
|
|
86487
86512
|
throw new Error("Website output already exists; build through the staged package workflow.");
|
|
@@ -86489,9 +86514,9 @@ async function writePackageSite(input) {
|
|
|
86489
86514
|
if (error.code !== "ENOENT")
|
|
86490
86515
|
throw error;
|
|
86491
86516
|
}
|
|
86492
|
-
const temporaryRoot =
|
|
86517
|
+
const temporaryRoot = join64(projectRoot, ".tmp");
|
|
86493
86518
|
await mkdir23(temporaryRoot, { recursive: true });
|
|
86494
|
-
const temporary = await mkdtemp2(
|
|
86519
|
+
const temporary = await mkdtemp2(join64(temporaryRoot, "website-"));
|
|
86495
86520
|
try {
|
|
86496
86521
|
const registry2 = await loadSourcesRegistry({ rootDir: projectRoot });
|
|
86497
86522
|
const sourceContent = new Map(selected.map((file) => [packageKnowledgeOutputPath(pkg, file.relPath), file]));
|
|
@@ -86512,22 +86537,22 @@ async function writePackageSite(input) {
|
|
|
86512
86537
|
}
|
|
86513
86538
|
const sections = siteSections(mapping.entries);
|
|
86514
86539
|
const resources = new Set(delivered.filter((file) => file.relPath.startsWith("others/assets/") || file.relPath.startsWith("skills/") && !file.relPath.endsWith(".md")).map((file) => file.relPath));
|
|
86515
|
-
const configRoot =
|
|
86516
|
-
await mkdir23(
|
|
86517
|
-
await mkdir23(
|
|
86540
|
+
const configRoot = join64(temporary, ".vitepress");
|
|
86541
|
+
await mkdir23(join64(configRoot, "theme"), { recursive: true });
|
|
86542
|
+
await mkdir23(join64(temporary, "node_modules"), { recursive: true });
|
|
86518
86543
|
const vitepressRoot = dirname28(require2.resolve("vitepress/package.json"));
|
|
86519
|
-
const vueRequire = createRequire5(
|
|
86544
|
+
const vueRequire = createRequire5(join64(vitepressRoot, "package.json"));
|
|
86520
86545
|
for (const [name3, path2] of [
|
|
86521
86546
|
["vitepress", vitepressRoot],
|
|
86522
86547
|
["vue", dirname28(vueRequire.resolve("vue/package.json"))],
|
|
86523
86548
|
["@mermaid-js/layout-elk", dirname28(require2.resolve("@mermaid-js/layout-elk/package.json"))],
|
|
86524
86549
|
["mermaid", dirname28(require2.resolve("mermaid/package.json"))]
|
|
86525
86550
|
]) {
|
|
86526
|
-
await mkdir23(dirname28(
|
|
86527
|
-
await symlink2(path2,
|
|
86551
|
+
await mkdir23(dirname28(join64(temporary, "node_modules", name3)), { recursive: true });
|
|
86552
|
+
await symlink2(path2, join64(temporary, "node_modules", name3), "dir");
|
|
86528
86553
|
}
|
|
86529
|
-
await writeFile19(
|
|
86530
|
-
await writeFile19(
|
|
86554
|
+
await writeFile19(join64(configRoot, "theme/index.js"), siteThemeScript);
|
|
86555
|
+
await writeFile19(join64(configRoot, "theme/style.css"), siteThemeCss + siteThemeVariables(await resolveSiteTheme(projectRoot, options.theme, true)));
|
|
86531
86556
|
await writeSiteExtensions(projectRoot, temporary, options.extensions);
|
|
86532
86557
|
const config = {
|
|
86533
86558
|
title: options.title ?? pkg.name,
|
|
@@ -86553,11 +86578,11 @@ async function writePackageSite(input) {
|
|
|
86553
86578
|
nav: [...sections.map((section) => ({ text: section.title, link: section.href })), { text: "更多", items: [{ text: "LLM Docs", link: "/llms/index.html" }, { text: "Changelog", link: "/changelog.html" }] }]
|
|
86554
86579
|
}
|
|
86555
86580
|
};
|
|
86556
|
-
await writeFile19(
|
|
86581
|
+
await writeFile19(join64(configRoot, "config.mjs"), `export default { ...${JSON.stringify(config)}, markdown: { ${siteMarkdownConfig} } };
|
|
86557
86582
|
`);
|
|
86558
|
-
await mkdir23(
|
|
86583
|
+
await mkdir23(join64(temporary, "pages"), { recursive: true });
|
|
86559
86584
|
for (const page of byPath.values()) {
|
|
86560
|
-
const content3 = await readFile52(
|
|
86585
|
+
const content3 = await readFile52(join64(root, page.package_path), "utf8");
|
|
86561
86586
|
const original = sourceContent.get(page.package_path);
|
|
86562
86587
|
const provenance = articleProvenanceMarkdown(original?.article, registry2);
|
|
86563
86588
|
const pageContent = provenance && content3.endsWith(provenance) ? content3.slice(0, -provenance.length) : content3;
|
|
@@ -86565,7 +86590,7 @@ async function writePackageSite(input) {
|
|
|
86565
86590
|
const sources = siteArticleSources(original?.article, registry2);
|
|
86566
86591
|
const timestamp = parseKnowledgeFrontmatter(original?.content ?? content3).timestamp;
|
|
86567
86592
|
const updated = typeof timestamp === "string" && Number.isFinite(Date.parse(timestamp)) ? new Date(timestamp).toISOString() : null;
|
|
86568
|
-
await writeFile19(
|
|
86593
|
+
await writeFile19(join64(temporary, page.site_path.replace(/\.html$/u, ".md")), `---
|
|
86569
86594
|
title: ${JSON.stringify(page.title)}
|
|
86570
86595
|
contextSources: ${JSON.stringify(sources)}
|
|
86571
86596
|
contextUpdated: ${JSON.stringify(updated)}
|
|
@@ -86577,11 +86602,11 @@ ${body}`);
|
|
|
86577
86602
|
lines.push(`${" ".repeat(level)}- ${entry.href ? `[${mdLabel(entry.title)}](${entry.href})` : mdLabel(entry.title)}`);
|
|
86578
86603
|
menu(lines, entry.children, level + 1);
|
|
86579
86604
|
});
|
|
86580
|
-
await mkdir23(
|
|
86605
|
+
await mkdir23(join64(temporary, "sections"), { recursive: true });
|
|
86581
86606
|
for (const section of sections) {
|
|
86582
86607
|
const lines = [`# ${mdLabel(section.title)}`, ""];
|
|
86583
86608
|
menu(lines, section.entries, 0);
|
|
86584
|
-
await writeFile19(
|
|
86609
|
+
await writeFile19(join64(temporary, section.href.slice(1).replace(/\.html$/u, ".md")), lines.join(`
|
|
86585
86610
|
`) + `
|
|
86586
86611
|
`);
|
|
86587
86612
|
}
|
|
@@ -86600,12 +86625,12 @@ ${body}`);
|
|
|
86600
86625
|
};
|
|
86601
86626
|
const homeHero = options.extensions?.slots?.banner === undefined ? `hero: ${JSON.stringify(hero)}
|
|
86602
86627
|
` : "";
|
|
86603
|
-
await writeFile19(
|
|
86628
|
+
await writeFile19(join64(temporary, "index.md"), `---
|
|
86604
86629
|
layout: home
|
|
86605
86630
|
title: ${JSON.stringify(options.home?.title ?? options.title ?? pkg.name)}
|
|
86606
86631
|
${homeHero}---
|
|
86607
86632
|
`);
|
|
86608
|
-
await writeFile19(
|
|
86633
|
+
await writeFile19(join64(temporary, "changelog.md"), `---
|
|
86609
86634
|
title: Changelog
|
|
86610
86635
|
contextHistory: ${JSON.stringify(Buffer.from(JSON.stringify(history)).toString("base64"))}
|
|
86611
86636
|
---
|
|
@@ -86618,19 +86643,19 @@ contextHistory: ${JSON.stringify(Buffer.from(JSON.stringify(history)).toString("
|
|
|
86618
86643
|
assetsPrefix: "resources/",
|
|
86619
86644
|
articles: await Promise.all(llmsArticles(pkg, selected).map(async (article) => ({
|
|
86620
86645
|
...article,
|
|
86621
|
-
content: await readFile52(
|
|
86646
|
+
content: await readFile52(join64(root, article.path), "utf8")
|
|
86622
86647
|
}))),
|
|
86623
86648
|
...structure ? { map: structure } : {}
|
|
86624
86649
|
});
|
|
86625
|
-
await writeLlmsDocuments(
|
|
86626
|
-
await mkdir23(
|
|
86650
|
+
await writeLlmsDocuments(join64(temporary, "public"), llms, { utf8Bom: true });
|
|
86651
|
+
await mkdir23(join64(temporary, "llms"), { recursive: true });
|
|
86627
86652
|
let landingNavigation = llms.navigationMarkdown;
|
|
86628
86653
|
for (const link of markdownReaderLinks(landingNavigation).reverse()) {
|
|
86629
86654
|
if (!link.target.startsWith(base))
|
|
86630
86655
|
continue;
|
|
86631
86656
|
landingNavigation = landingNavigation.slice(0, link.start) + `[${link.label}](</${link.target.slice(base.length)}>)` + landingNavigation.slice(link.end);
|
|
86632
86657
|
}
|
|
86633
|
-
await writeFile19(
|
|
86658
|
+
await writeFile19(join64(temporary, "llms/index.md"), `---
|
|
86634
86659
|
title: LLM Docs
|
|
86635
86660
|
---
|
|
86636
86661
|
|
|
@@ -86640,9 +86665,9 @@ title: LLM Docs
|
|
|
86640
86665
|
|
|
86641
86666
|
` + landingNavigation);
|
|
86642
86667
|
for (const path2 of resources) {
|
|
86643
|
-
const destination =
|
|
86668
|
+
const destination = join64(temporary, "public/resources", path2);
|
|
86644
86669
|
await mkdir23(dirname28(destination), { recursive: true });
|
|
86645
|
-
await cp(
|
|
86670
|
+
await cp(join64(root, path2), destination);
|
|
86646
86671
|
}
|
|
86647
86672
|
await compileSite(temporary, output);
|
|
86648
86673
|
for (const file of await walkPackageFiles(output)) {
|
|
@@ -86666,8 +86691,14 @@ title: LLM Docs
|
|
|
86666
86691
|
warnings: mapping.warnings
|
|
86667
86692
|
}, null, 2) + `
|
|
86668
86693
|
`;
|
|
86669
|
-
|
|
86670
|
-
|
|
86694
|
+
const packageSiteMap = join64(projectRoot, pkg.outDir, "context-site-map.json");
|
|
86695
|
+
const distributedSiteMap = join64(projectRoot, pkg.outDir, packageDistributionMetadataPath("context-site-map.json"));
|
|
86696
|
+
await mkdir23(dirname28(distributedSiteMap), { recursive: true });
|
|
86697
|
+
await Promise.all([
|
|
86698
|
+
writeFile19(join64(output, "context-site-map.json"), siteMapContent),
|
|
86699
|
+
writeFile19(packageSiteMap, siteMapContent),
|
|
86700
|
+
writeFile19(distributedSiteMap, siteMapContent)
|
|
86701
|
+
]);
|
|
86671
86702
|
return mapping;
|
|
86672
86703
|
} finally {
|
|
86673
86704
|
await rm12(temporary, { recursive: true, force: true });
|
|
@@ -86688,12 +86719,13 @@ var init_packageSite2 = __esm(() => {
|
|
|
86688
86719
|
init_packageSiteTheme();
|
|
86689
86720
|
init_packageSiteBranding();
|
|
86690
86721
|
init_packageSiteExtensions();
|
|
86722
|
+
init_packageDistributionMetadata();
|
|
86691
86723
|
PACKAGE_SITE_VERSION = `vitepress-site-v44-site-address:${createHash17("sha256").update(JSON.stringify([siteThemeVariables.toString(), siteMarkdownConfig, siteThemeCss, siteThemeScript, siteThemeLabels("zh"), siteThemeLabels("en")])).digest("hex")}`;
|
|
86692
86724
|
require2 = createRequire5(import.meta.url);
|
|
86693
86725
|
});
|
|
86694
86726
|
|
|
86695
86727
|
// src/project/workspaceBuildVersion.ts
|
|
86696
|
-
import { join as
|
|
86728
|
+
import { join as join65 } from "node:path";
|
|
86697
86729
|
import { mkdir as mkdir24, writeFile as writeFile20 } from "node:fs/promises";
|
|
86698
86730
|
async function workspaceVersionFingerprint(root) {
|
|
86699
86731
|
return { version: await workspaceVersion(root), changelog: await readWorkspaceChangelog(root) };
|
|
@@ -86705,8 +86737,8 @@ async function writePackageVersion(projectRoot, output) {
|
|
|
86705
86737
|
throw new TypeError(`Package template uses reserved version output ${path2}; rename that template output.`);
|
|
86706
86738
|
}
|
|
86707
86739
|
await mkdir24(output, { recursive: true });
|
|
86708
|
-
await writeFile20(
|
|
86709
|
-
await writeFile20(
|
|
86740
|
+
await writeFile20(join65(output, "CHANGELOG.md"), renderChangelog(info.changelog));
|
|
86741
|
+
await writeFile20(join65(output, "context-version.json"), JSON.stringify({ version: info.version }) + `
|
|
86710
86742
|
`);
|
|
86711
86743
|
}
|
|
86712
86744
|
var init_workspaceBuildVersion = __esm(() => {
|
|
@@ -86716,11 +86748,11 @@ var init_workspaceBuildVersion = __esm(() => {
|
|
|
86716
86748
|
// src/project/packageRenderCache.ts
|
|
86717
86749
|
import { createHash as createHash18 } from "node:crypto";
|
|
86718
86750
|
import { readFile as readFile53 } from "node:fs/promises";
|
|
86719
|
-
import { join as
|
|
86751
|
+
import { join as join66 } from "node:path";
|
|
86720
86752
|
async function cachedPackageKnowledgeMarkdown(input) {
|
|
86721
86753
|
const fingerprint = digest3(`${PACKAGE_READER_MARKDOWN_VERSION}
|
|
86722
86754
|
${input.content}`);
|
|
86723
|
-
const path2 =
|
|
86755
|
+
const path2 = join66(input.projectRoot, ".tmp/context-runtime/package-render", `${digest3(input.key)}.json`);
|
|
86724
86756
|
try {
|
|
86725
86757
|
const cached = JSON.parse(await readFile53(path2, "utf8"));
|
|
86726
86758
|
if (cached !== null && typeof cached === "object" && "fingerprint" in cached && cached.fingerprint === fingerprint && "markdown" in cached && typeof cached.markdown === "string") {
|
|
@@ -86842,22 +86874,22 @@ var init_packageMarkdownAnchors = __esm(() => {
|
|
|
86842
86874
|
|
|
86843
86875
|
// src/project/packageBuildStage.ts
|
|
86844
86876
|
import { mkdir as mkdir25, mkdtemp as mkdtemp3, readFile as readFile55, rename as rename7, rm as rm13, rmdir } from "node:fs/promises";
|
|
86845
|
-
import { dirname as dirname29, join as
|
|
86877
|
+
import { dirname as dirname29, join as join67, relative as relative18 } from "node:path";
|
|
86846
86878
|
async function withStagedPackageOutput(projectRoot, pkg, render) {
|
|
86847
|
-
const tempRoot =
|
|
86879
|
+
const tempRoot = join67(projectRoot, ".tmp");
|
|
86848
86880
|
await mkdir25(tempRoot, { recursive: true });
|
|
86849
|
-
const stage = await mkdtemp3(
|
|
86850
|
-
const stagedPackage = { ...pkg, outDir: relative18(projectRoot,
|
|
86881
|
+
const stage = await mkdtemp3(join67(tempRoot, "package-build-"));
|
|
86882
|
+
const stagedPackage = { ...pkg, outDir: relative18(projectRoot, join67(stage, pkg.name)) };
|
|
86851
86883
|
try {
|
|
86852
|
-
await mkdir25(
|
|
86884
|
+
await mkdir25(join67(projectRoot, stagedPackage.outDir), { recursive: true });
|
|
86853
86885
|
const value = await render(stagedPackage);
|
|
86854
86886
|
await validatePackageIndexLinks({ projectRoot, pkg: stagedPackage });
|
|
86855
86887
|
const destinations = packageOutputDirs(pkg);
|
|
86856
86888
|
const staged = packageOutputDirs(stagedPackage);
|
|
86857
86889
|
for (const [index2, destination] of destinations.entries()) {
|
|
86858
|
-
const target =
|
|
86890
|
+
const target = join67(projectRoot, destination);
|
|
86859
86891
|
const previous2 = await walkPackageFiles(target);
|
|
86860
|
-
const next = await walkPackageFiles(
|
|
86892
|
+
const next = await walkPackageFiles(join67(projectRoot, staged[index2]));
|
|
86861
86893
|
const desired = new Set(next.map((file) => file.relPath));
|
|
86862
86894
|
for (const file of previous2) {
|
|
86863
86895
|
if (desired.has(file.relPath))
|
|
@@ -86875,7 +86907,7 @@ async function withStagedPackageOutput(projectRoot, pkg, render) {
|
|
|
86875
86907
|
}
|
|
86876
86908
|
for (let offset2 = 0;offset2 < next.length; offset2 += 8) {
|
|
86877
86909
|
const results = await Promise.allSettled(next.slice(offset2, offset2 + 8).map(async (file) => {
|
|
86878
|
-
const output =
|
|
86910
|
+
const output = join67(target, file.relPath);
|
|
86879
86911
|
const bytes = await readFile55(file.absPath);
|
|
86880
86912
|
const old = await readFile55(output).catch((error) => {
|
|
86881
86913
|
if (error.code === "ENOENT")
|
|
@@ -87283,7 +87315,7 @@ var init_packageAssetOptimization = __esm(() => {
|
|
|
87283
87315
|
// src/project/packageAssetDelivery.ts
|
|
87284
87316
|
import { execFile as execFile8 } from "node:child_process";
|
|
87285
87317
|
import { realpath as realpath7 } from "node:fs/promises";
|
|
87286
|
-
import { join as
|
|
87318
|
+
import { join as join68, relative as relative20, sep as sep5 } from "node:path";
|
|
87287
87319
|
import { promisify as promisify8 } from "node:util";
|
|
87288
87320
|
async function git(projectRoot, args) {
|
|
87289
87321
|
try {
|
|
@@ -87303,7 +87335,7 @@ async function git(projectRoot, args) {
|
|
|
87303
87335
|
}
|
|
87304
87336
|
}
|
|
87305
87337
|
function repositoryPath(repoRoot, projectRoot, asset) {
|
|
87306
|
-
const path2 = relative20(repoRoot,
|
|
87338
|
+
const path2 = relative20(repoRoot, join68(projectRoot, asset.knowledgeRelPath)).split(sep5).join("/");
|
|
87307
87339
|
if (path2 === ".." || path2.startsWith("../") || path2.startsWith("/")) {
|
|
87308
87340
|
throw new ContextError(ExitCode.WorkspaceStateError, "knowledge asset is outside the current Git repository", {
|
|
87309
87341
|
category: ErrorCategory.WorkspaceStateInvalid,
|
|
@@ -87484,7 +87516,7 @@ var init_packageAssetDelivery = __esm(() => {
|
|
|
87484
87516
|
// src/project/packageBuildContent.ts
|
|
87485
87517
|
import { existsSync as existsSync17 } from "node:fs";
|
|
87486
87518
|
import { mkdir as mkdir26, readFile as readFile57, writeFile as writeFile21 } from "node:fs/promises";
|
|
87487
|
-
import { dirname as dirname32, join as
|
|
87519
|
+
import { dirname as dirname32, join as join69 } from "node:path";
|
|
87488
87520
|
function globToRegExp(pattern) {
|
|
87489
87521
|
const normalized = toPosixPath6(pattern);
|
|
87490
87522
|
if (normalized.endsWith("/**")) {
|
|
@@ -87625,7 +87657,7 @@ async function writeRenderedPackageTemplate(input) {
|
|
|
87625
87657
|
templateRelPath: renderedRelPath,
|
|
87626
87658
|
logicalTemplateRelPath: renderedLogicalRelPath
|
|
87627
87659
|
});
|
|
87628
|
-
const outputPath =
|
|
87660
|
+
const outputPath = join69(input.projectRoot, input.pkg.outDir, renderedRelPath);
|
|
87629
87661
|
await mkdir26(dirname32(outputPath), { recursive: true });
|
|
87630
87662
|
await writeFile21(outputPath, renderTemplateText(file.content, contentVars), "utf8");
|
|
87631
87663
|
written++;
|
|
@@ -87658,7 +87690,7 @@ async function writeSelectedPackageKnowledge(input) {
|
|
|
87658
87690
|
for (let offset2 = 0;offset2 < projectedPages.length; offset2 += 8) {
|
|
87659
87691
|
const results = await Promise.allSettled(projectedPages.slice(offset2, offset2 + 8).map(async (projected) => {
|
|
87660
87692
|
assertSafeRenderedPath2(projected.pageOutputPath, "knowledge path");
|
|
87661
|
-
const outputPath =
|
|
87693
|
+
const outputPath = join69(input.projectRoot, input.pkg.outDir, projected.pageOutputPath);
|
|
87662
87694
|
let mediaContent = projected.content;
|
|
87663
87695
|
const omitted = new Set((delivered.omittedImages ?? []).map((path2) => packageMarkdownTarget(projected.pageOutputPath, path2)));
|
|
87664
87696
|
for (const link of markdownReaderLinks(mediaContent).reverse()) {
|
|
@@ -87695,7 +87727,7 @@ async function writeSelectedPackageKnowledge(input) {
|
|
|
87695
87727
|
const deliveredAssets = new Map(delivered.assets.map((asset) => [asset.packageRelPath, asset]));
|
|
87696
87728
|
for (const asset of deliveredAssets.values()) {
|
|
87697
87729
|
assertSafeRenderedPath2(asset.packageRelPath, "package resource path");
|
|
87698
|
-
const outputPath =
|
|
87730
|
+
const outputPath = join69(input.projectRoot, input.pkg.outDir, asset.packageRelPath);
|
|
87699
87731
|
await mkdir26(dirname32(outputPath), { recursive: true });
|
|
87700
87732
|
await writeFile21(outputPath, asset.bytes);
|
|
87701
87733
|
}
|
|
@@ -87710,7 +87742,7 @@ async function writeSelectedPackageKnowledge(input) {
|
|
|
87710
87742
|
async function appendLlmsKnowledge(input) {
|
|
87711
87743
|
if (packageKind2(input.pkg) !== "llms" || input.templateConsumesKnowledge || input.knowledgeCount === 0)
|
|
87712
87744
|
return 0;
|
|
87713
|
-
const outputPath =
|
|
87745
|
+
const outputPath = join69(input.projectRoot, input.pkg.outDir, "llms.txt");
|
|
87714
87746
|
const existed = existsSync17(outputPath);
|
|
87715
87747
|
const existing = existed ? await readFile57(outputPath, "utf8") : "";
|
|
87716
87748
|
const content3 = existing.trim().length > 0 ? `${existing.trimEnd()}
|
|
@@ -87937,7 +87969,7 @@ __export(exports_packageBuilder, {
|
|
|
87937
87969
|
import { createHash as createHash20 } from "node:crypto";
|
|
87938
87970
|
import { existsSync as existsSync18 } from "node:fs";
|
|
87939
87971
|
import { mkdir as mkdir27, readdir as readdir16, readFile as readFile58, rm as rm14, writeFile as writeFile22 } from "node:fs/promises";
|
|
87940
|
-
import { dirname as dirname33, join as
|
|
87972
|
+
import { dirname as dirname33, join as join70, resolve as resolve23 } from "node:path";
|
|
87941
87973
|
function packageAssetDeliverySummary(value) {
|
|
87942
87974
|
if (value === null || typeof value !== "object" || Array.isArray(value))
|
|
87943
87975
|
return;
|
|
@@ -87959,7 +87991,7 @@ function assertPackageOutputDir(pkg) {
|
|
|
87959
87991
|
}
|
|
87960
87992
|
function packageFingerprintPath(projectRoot, pkg) {
|
|
87961
87993
|
assertSafeRenderedPath2(`${pkg.name}.json`, "package fingerprint path");
|
|
87962
|
-
return
|
|
87994
|
+
return join70(projectRoot, PACKAGE_FINGERPRINT_ROOT, `${pkg.name}.json`);
|
|
87963
87995
|
}
|
|
87964
87996
|
async function listApprovedKnowledge(projectRoot) {
|
|
87965
87997
|
const metadata = await readApprovedKnowledgeMetadataIndex(projectRoot);
|
|
@@ -88112,12 +88144,12 @@ async function writePackageFingerprint(input) {
|
|
|
88112
88144
|
`, "utf8");
|
|
88113
88145
|
}
|
|
88114
88146
|
async function removeOrphanPackageDirs(projectRoot, packages) {
|
|
88115
|
-
const distRoot =
|
|
88147
|
+
const distRoot = join70(projectRoot, "dist");
|
|
88116
88148
|
if (!existsSync18(distRoot))
|
|
88117
88149
|
return;
|
|
88118
88150
|
const declaredNames = new Set(packages.flatMap((pkg) => packageOutputDirs(pkg).map((path2) => path2.slice("dist/".length))));
|
|
88119
88151
|
const entries2 = await readdir16(distRoot, { withFileTypes: true });
|
|
88120
|
-
await Promise.all(entries2.filter((entry) => entry.isDirectory() && !declaredNames.has(entry.name)).map((entry) => rm14(
|
|
88152
|
+
await Promise.all(entries2.filter((entry) => entry.isDirectory() && !declaredNames.has(entry.name)).map((entry) => rm14(join70(distRoot, entry.name), { recursive: true, force: true, maxRetries: 3, retryDelay: 100 })));
|
|
88121
88153
|
}
|
|
88122
88154
|
async function collectPackageFreshness(projectRoot, packages) {
|
|
88123
88155
|
assertDistinctPackageOutputs(packages);
|
|
@@ -88126,7 +88158,7 @@ async function collectPackageFreshness(projectRoot, packages) {
|
|
|
88126
88158
|
assertPackageOutputDir(pkg);
|
|
88127
88159
|
const selected = selectPackageKnowledge(approved, pkg);
|
|
88128
88160
|
assertSafeRenderedPath2(pkg.template.path, "package template path");
|
|
88129
|
-
const templateRoot =
|
|
88161
|
+
const templateRoot = join70(projectRoot, pkg.template.path);
|
|
88130
88162
|
const templateExists = existsSync18(templateRoot);
|
|
88131
88163
|
if (!templateExists) {
|
|
88132
88164
|
throw new ContextError(ExitCode.WorkspaceStateError, `package template path is missing: ${pkg.template.path}`, {
|
|
@@ -88355,19 +88387,19 @@ async function buildProjectPackagesInternal(projectRoot, options) {
|
|
|
88355
88387
|
if (stagedPkg.kind === "package.llms") {
|
|
88356
88388
|
const articles = await Promise.all(llmsArticles(stagedPkg, selected).map(async (article) => ({
|
|
88357
88389
|
...article,
|
|
88358
|
-
content: await readFile58(
|
|
88390
|
+
content: await readFile58(join70(projectRoot, stagedPkg.outDir, article.path), "utf8")
|
|
88359
88391
|
})));
|
|
88360
|
-
await writeLlmsDocuments(
|
|
88392
|
+
await writeLlmsDocuments(join70(projectRoot, stagedPkg.outDir), buildLlmsDocuments({
|
|
88361
88393
|
title: stagedPkg.name,
|
|
88362
88394
|
articles,
|
|
88363
88395
|
...reading ? { map: reading } : {}
|
|
88364
88396
|
}), { preserveIndex: true });
|
|
88365
88397
|
}
|
|
88366
|
-
await writePackageVersion(projectRoot,
|
|
88398
|
+
await writePackageVersion(projectRoot, join70(projectRoot, stagedPkg.outDir));
|
|
88367
88399
|
await writePackageSite({ projectRoot, pkg: stagedPkg, selected, ...siteUrl ? { siteUrl } : {}, ...reading ? { structure: reading } : {} });
|
|
88368
88400
|
const linkWarnings = [
|
|
88369
88401
|
...writtenKnowledge2.linkWarnings,
|
|
88370
|
-
...await inspectPackageMarkdownDirectory(
|
|
88402
|
+
...await inspectPackageMarkdownDirectory(join70(projectRoot, stagedPkg.outDir))
|
|
88371
88403
|
];
|
|
88372
88404
|
return { ...writtenKnowledge2, linkWarnings };
|
|
88373
88405
|
});
|
|
@@ -88559,7 +88591,7 @@ var init_packageBuilder = __esm(() => {
|
|
|
88559
88591
|
init_packageTemplateReview();
|
|
88560
88592
|
init_approvedKnowledgeMetadata();
|
|
88561
88593
|
import_yaml35 = __toESM(require_dist(), 1);
|
|
88562
|
-
PACKAGE_FINGERPRINT_ROOT =
|
|
88594
|
+
PACKAGE_FINGERPRINT_ROOT = join70(".tmp", "context-runtime", "packages");
|
|
88563
88595
|
});
|
|
88564
88596
|
|
|
88565
88597
|
// src/project/taskRollback.ts
|
|
@@ -88570,7 +88602,7 @@ __export(exports_taskRollback, {
|
|
|
88570
88602
|
finishTaskRollback: () => finishTaskRollback
|
|
88571
88603
|
});
|
|
88572
88604
|
import { readFile as readFile59 } from "node:fs/promises";
|
|
88573
|
-
import { join as
|
|
88605
|
+
import { join as join71 } from "node:path";
|
|
88574
88606
|
async function readTaskRollback(projectRoot) {
|
|
88575
88607
|
const raw = await readJsonMaybe(projectRoot, await revisionStoragePath(projectRoot));
|
|
88576
88608
|
if (!raw || typeof raw !== "object" || !("protocol" in raw) || raw.protocol !== "context.task-rollback/v1")
|
|
@@ -88579,7 +88611,7 @@ async function readTaskRollback(projectRoot) {
|
|
|
88579
88611
|
}
|
|
88580
88612
|
async function contents(projectRoot, path2) {
|
|
88581
88613
|
try {
|
|
88582
|
-
return await readFile59(
|
|
88614
|
+
return await readFile59(join71(projectRoot, path2), "utf8");
|
|
88583
88615
|
} catch (error) {
|
|
88584
88616
|
if (error && typeof error === "object" && "code" in error && error.code === "ENOENT")
|
|
88585
88617
|
return;
|
|
@@ -88747,11 +88779,11 @@ __export(exports_knowledgeUpdate, {
|
|
|
88747
88779
|
beginKnowledgeUpdate: () => beginKnowledgeUpdate
|
|
88748
88780
|
});
|
|
88749
88781
|
import { readFile as readFile60 } from "node:fs/promises";
|
|
88750
|
-
import { join as
|
|
88782
|
+
import { join as join72 } from "node:path";
|
|
88751
88783
|
async function readKnowledgeUpdate(projectRoot) {
|
|
88752
88784
|
let value;
|
|
88753
88785
|
try {
|
|
88754
|
-
value = JSON.parse(await readFile60(
|
|
88786
|
+
value = JSON.parse(await readFile60(join72(projectRoot, await revisionStoragePath(projectRoot)), "utf8"));
|
|
88755
88787
|
} catch (error) {
|
|
88756
88788
|
if (error && typeof error === "object" && "code" in error && error.code === "ENOENT")
|
|
88757
88789
|
return;
|
|
@@ -88802,7 +88834,7 @@ async function beginKnowledgeUpdate(projectRoot, value) {
|
|
|
88802
88834
|
...input.changes === undefined ? {} : { changes: input.changes }
|
|
88803
88835
|
};
|
|
88804
88836
|
const request = updateSchema.parse({ ...payload, revision: indexerProtocolDigest(payload) });
|
|
88805
|
-
await atomicWriteFile(
|
|
88837
|
+
await atomicWriteFile(join72(projectRoot, await revisionStoragePath(projectRoot)), `${JSON.stringify(request)}
|
|
88806
88838
|
`);
|
|
88807
88839
|
return {
|
|
88808
88840
|
outcome: "update-prepared",
|
|
@@ -88847,7 +88879,7 @@ async function completeKnowledgeUpdate(input) {
|
|
|
88847
88879
|
if (input.new_topics.length && !input.structure_approved) {
|
|
88848
88880
|
const { revision: _revision, ...rest } = request;
|
|
88849
88881
|
const payload = { ...rest, structure_proposal: { decisions: input.decisions, scope_summary: input.scope_summary, new_topics: input.new_topics } };
|
|
88850
|
-
await atomicWriteFile(
|
|
88882
|
+
await atomicWriteFile(join72(input.projectRoot, await revisionStoragePath(input.projectRoot)), `${JSON.stringify({ ...payload, revision: indexerProtocolDigest(payload) })}
|
|
88851
88883
|
`);
|
|
88852
88884
|
return { outcome: "structure-review-required" };
|
|
88853
88885
|
}
|
|
@@ -88884,7 +88916,7 @@ async function completeUpdateStructureReview(input) {
|
|
|
88884
88916
|
const { revision: _revision, structure_proposal: _proposal, ...rest } = request;
|
|
88885
88917
|
const payload = { ...rest, changes: `${rest.changes ?? ""}
|
|
88886
88918
|
Structure feedback: ${input.feedback}` };
|
|
88887
|
-
await atomicWriteFile(
|
|
88919
|
+
await atomicWriteFile(join72(input.projectRoot, await revisionStoragePath(input.projectRoot)), `${JSON.stringify({ ...payload, revision: indexerProtocolDigest(payload) })}
|
|
88888
88920
|
`);
|
|
88889
88921
|
return { outcome: "structure-adjustment-required" };
|
|
88890
88922
|
});
|
|
@@ -89058,14 +89090,14 @@ __export(exports_knowledgeMaintenance, {
|
|
|
89058
89090
|
advanceKnowledgeMaintenance: () => advanceKnowledgeMaintenance
|
|
89059
89091
|
});
|
|
89060
89092
|
import { readFile as readFile61, readdir as readdir17, rm as rm15 } from "node:fs/promises";
|
|
89061
|
-
import { join as
|
|
89093
|
+
import { join as join73 } from "node:path";
|
|
89062
89094
|
async function deliveryDigest(root) {
|
|
89063
|
-
const directory =
|
|
89095
|
+
const directory = join73(root, ".tmp/context-runtime/packages");
|
|
89064
89096
|
try {
|
|
89065
89097
|
const files = (await readdir17(directory)).filter((name3) => name3.endsWith(".json")).sort();
|
|
89066
89098
|
if (!files.length)
|
|
89067
89099
|
return indexerProtocolDigest(null);
|
|
89068
|
-
return indexerProtocolDigest(await Promise.all(files.map((name3) => readFile61(
|
|
89100
|
+
return indexerProtocolDigest(await Promise.all(files.map((name3) => readFile61(join73(directory, name3), "utf8"))));
|
|
89069
89101
|
} catch (error) {
|
|
89070
89102
|
if (error.code === "ENOENT")
|
|
89071
89103
|
return indexerProtocolDigest(null);
|
|
@@ -89164,7 +89196,7 @@ async function observeKnowledgeMaintenance(root) {
|
|
|
89164
89196
|
async function maintenanceRevision(root) {
|
|
89165
89197
|
const observed = await observeKnowledgeMaintenance(root);
|
|
89166
89198
|
const localInputs = observed.state.active ? {
|
|
89167
|
-
revision: await readFile61(
|
|
89199
|
+
revision: await readFile61(join73(root, MAINTENANCE_ROOT, "revision.json"), "utf8").catch((error) => {
|
|
89168
89200
|
if (error.code === "ENOENT")
|
|
89169
89201
|
return null;
|
|
89170
89202
|
throw error;
|
|
@@ -89241,7 +89273,7 @@ async function finishMaintenanceRevision(root, outcome = "completed") {
|
|
|
89241
89273
|
outcome = state.active.completion_outcome;
|
|
89242
89274
|
state.active.phase = "finishing";
|
|
89243
89275
|
await saveMaintenance(root, state);
|
|
89244
|
-
await rm15(
|
|
89276
|
+
await rm15(join73(root, MAINTENANCE_ROOT, "revision.json"), { force: true });
|
|
89245
89277
|
state.completed.push({ id: state.active.input.id, input_digest: indexerProtocolDigest(state.active.input), outcome });
|
|
89246
89278
|
delete state.active;
|
|
89247
89279
|
await saveMaintenance(root, state);
|
|
@@ -89275,8 +89307,8 @@ async function discardMaintenanceDraft(root) {
|
|
|
89275
89307
|
const owned = new Set([...request?.batch_candidates ?? [], ...request?.candidate ? [request.candidate] : []].map((item) => item.candidate_id));
|
|
89276
89308
|
if (candidates.some((item) => !owned.has(item.candidate_id)))
|
|
89277
89309
|
throw new TypeError("Unrelated Candidates are present; no draft was discarded. Inspect the current review before retrying cancellation.");
|
|
89278
|
-
await rm15(
|
|
89279
|
-
await rm15(
|
|
89310
|
+
await rm15(join73(root, CANDIDATE_LEDGER_FILE), { force: true });
|
|
89311
|
+
await rm15(join73(root, MAINTENANCE_ROOT, "revision.json"), { force: true });
|
|
89280
89312
|
const { closeProjectWorkspace: closeProjectWorkspace2 } = await Promise.resolve().then(() => (init_close(), exports_close));
|
|
89281
89313
|
const { buildProjectPackages: buildProjectPackages2 } = await Promise.resolve().then(() => (init_packageBuilder(), exports_packageBuilder));
|
|
89282
89314
|
await closeProjectWorkspace2(root);
|
|
@@ -89315,7 +89347,7 @@ __export(exports_approvedRevision, {
|
|
|
89315
89347
|
APPROVED_REVISION_PATH: () => APPROVED_REVISION_PATH
|
|
89316
89348
|
});
|
|
89317
89349
|
import { readFile as readFile62, realpath as realpath8, rm as rm16 } from "node:fs/promises";
|
|
89318
|
-
import { join as
|
|
89350
|
+
import { join as join74, relative as relative21, isAbsolute as isAbsolute13 } from "node:path";
|
|
89319
89351
|
function requestDigest(input) {
|
|
89320
89352
|
const scopes = input.processed_scopes?.filter((scope2) => input.target.source_refs.some((ref2) => ref2 === scope2.source_ref || ref2.startsWith(`${scope2.source_ref}#`) || ref2.startsWith(`${scope2.source_ref}/`)));
|
|
89321
89353
|
const ids = new Set(scopes?.map((scope2) => scope2.requirement_ref));
|
|
@@ -89353,7 +89385,7 @@ function revisionCandidateFingerprint(revision, markdown, sections) {
|
|
|
89353
89385
|
}
|
|
89354
89386
|
async function readApprovedRevision(projectRoot) {
|
|
89355
89387
|
try {
|
|
89356
|
-
return parseApprovedRevision(JSON.parse(await readFile62(
|
|
89388
|
+
return parseApprovedRevision(JSON.parse(await readFile62(join74(projectRoot, await revisionStoragePath(projectRoot)), "utf8")));
|
|
89357
89389
|
} catch (error) {
|
|
89358
89390
|
if (error && typeof error === "object" && "code" in error && error.code === "ENOENT")
|
|
89359
89391
|
return;
|
|
@@ -89412,12 +89444,12 @@ async function resolveApprovedRevisionAuthor(projectRoot, request) {
|
|
|
89412
89444
|
}
|
|
89413
89445
|
async function targetBytes(projectRoot, path2) {
|
|
89414
89446
|
const project = await realpath8(projectRoot);
|
|
89415
|
-
const root = await realpath8(
|
|
89447
|
+
const root = await realpath8(join74(projectRoot, "knowledge"));
|
|
89416
89448
|
const rootRelative = relative21(project, root);
|
|
89417
89449
|
if (isAbsolute13(rootRelative) || rootRelative === ".." || rootRelative.startsWith("../")) {
|
|
89418
89450
|
throw new TypeError("Approved knowledge directory leaves the Context workspace");
|
|
89419
89451
|
}
|
|
89420
|
-
const target = await realpath8(
|
|
89452
|
+
const target = await realpath8(join74(root, path2));
|
|
89421
89453
|
const rel = relative21(root, target);
|
|
89422
89454
|
if (isAbsolute13(rel) || rel === ".." || rel.startsWith("../"))
|
|
89423
89455
|
throw new TypeError("Approved revision target leaves knowledge/");
|
|
@@ -89573,7 +89605,7 @@ ${import_yaml36.default.stringify({ ...import_yaml36.default.parse(fields), type
|
|
|
89573
89605
|
revision: requestDigest(payload)
|
|
89574
89606
|
});
|
|
89575
89607
|
if (input.persist !== false)
|
|
89576
|
-
await atomicWriteFile(
|
|
89608
|
+
await atomicWriteFile(join74(input.projectRoot, await revisionStoragePath(input.projectRoot)), `${JSON.stringify(request)}
|
|
89577
89609
|
`);
|
|
89578
89610
|
return {
|
|
89579
89611
|
status: "author-reopened",
|
|
@@ -89684,17 +89716,17 @@ async function completeApprovedRevision(input) {
|
|
|
89684
89716
|
const { prepareRevisionBatchContinuation: prepareRevisionBatchContinuation3 } = await Promise.resolve().then(() => (init_approvedRevisionBatch(), exports_approvedRevisionBatch));
|
|
89685
89717
|
const next2 = await prepareRevisionBatchContinuation3(input.projectRoot, request, request.batch_candidates ?? []);
|
|
89686
89718
|
if (next2 || request.batch_candidates?.length || request.build_pending) {
|
|
89687
|
-
await atomicWriteFile(
|
|
89719
|
+
await atomicWriteFile(join74(input.projectRoot, await revisionStoragePath(input.projectRoot)), `${JSON.stringify(next2 ?? { ...request, review_ready: true })}
|
|
89688
89720
|
`);
|
|
89689
89721
|
} else {
|
|
89690
89722
|
await advanceApprovedRevision(input.projectRoot, request);
|
|
89691
89723
|
}
|
|
89692
89724
|
return;
|
|
89693
89725
|
}
|
|
89694
|
-
const current2 = await readFile62(
|
|
89726
|
+
const current2 = await readFile62(join74(input.projectRoot, await revisionStoragePath(input.projectRoot)), "utf8");
|
|
89695
89727
|
let previous2;
|
|
89696
89728
|
try {
|
|
89697
|
-
previous2 = await readFile62(
|
|
89729
|
+
previous2 = await readFile62(join74(input.projectRoot, CANDIDATE_LEDGER_FILE), "utf8");
|
|
89698
89730
|
} catch (error) {
|
|
89699
89731
|
if (!(error && typeof error === "object" && ("code" in error) && error.code === "ENOENT"))
|
|
89700
89732
|
throw error;
|
|
@@ -89776,7 +89808,7 @@ async function advanceApprovedRevision(projectRoot, request, buildPending = fals
|
|
|
89776
89808
|
return;
|
|
89777
89809
|
const { readProductionStage: readProductionStage2 } = await Promise.resolve().then(() => (init_productionStageStore(), exports_productionStageStore));
|
|
89778
89810
|
if (await readProductionStage2(projectRoot)) {
|
|
89779
|
-
await rm16(
|
|
89811
|
+
await rm16(join74(projectRoot, await revisionStoragePath(projectRoot)), { force: true });
|
|
89780
89812
|
return;
|
|
89781
89813
|
}
|
|
89782
89814
|
const { clearCompletedLifecycle: clearCompletedLifecycle2 } = await Promise.resolve().then(() => (init_lifecycleCleanup(), exports_lifecycleCleanup));
|
|
@@ -89847,12 +89879,12 @@ async function reopenApprovedRevision(input) {
|
|
|
89847
89879
|
}))
|
|
89848
89880
|
} : {}
|
|
89849
89881
|
} };
|
|
89850
|
-
const current2 = await readFile62(
|
|
89882
|
+
const current2 = await readFile62(join74(input.projectRoot, await revisionStoragePath(input.projectRoot)), "utf8");
|
|
89851
89883
|
const content3 = `${JSON.stringify({ ...payload, revision: requestDigest(payload) })}
|
|
89852
89884
|
`;
|
|
89853
89885
|
let ledger;
|
|
89854
89886
|
try {
|
|
89855
|
-
ledger = await readFile62(
|
|
89887
|
+
ledger = await readFile62(join74(input.projectRoot, CANDIDATE_LEDGER_FILE), "utf8");
|
|
89856
89888
|
} catch (error) {
|
|
89857
89889
|
if (!(error && typeof error === "object" && ("code" in error) && error.code === "ENOENT"))
|
|
89858
89890
|
throw error;
|
|
@@ -89965,7 +89997,7 @@ var init_sourceInputMutation = __esm(() => {
|
|
|
89965
89997
|
// src/project/documentCapture.ts
|
|
89966
89998
|
import { createHash as createHash21 } from "node:crypto";
|
|
89967
89999
|
import { mkdir as mkdir28, readdir as readdir18, readFile as readFile63, rm as rm17, stat as stat9, writeFile as writeFile23 } from "node:fs/promises";
|
|
89968
|
-
import { basename as basename8, dirname as dirname34, extname as extname12, join as
|
|
90000
|
+
import { basename as basename8, dirname as dirname34, extname as extname12, join as join75, relative as relative22, resolve as resolve24 } from "node:path";
|
|
89969
90001
|
function toPosixPath7(path2) {
|
|
89970
90002
|
return path2.split(/[\\/]+/u).filter((part) => part.length > 0).join("/");
|
|
89971
90003
|
}
|
|
@@ -90088,7 +90120,7 @@ async function walkMarkdownFiles(input) {
|
|
|
90088
90120
|
const visit3 = async (dir) => {
|
|
90089
90121
|
const entries2 = await readdir18(dir, { withFileTypes: true });
|
|
90090
90122
|
for (const entry of entries2) {
|
|
90091
|
-
const absolutePath =
|
|
90123
|
+
const absolutePath = join75(dir, entry.name);
|
|
90092
90124
|
if (entry.isDirectory()) {
|
|
90093
90125
|
await visit3(absolutePath);
|
|
90094
90126
|
continue;
|
|
@@ -90117,7 +90149,7 @@ async function writeTextIfChanged(path2, content3) {
|
|
|
90117
90149
|
await writeFile23(path2, content3, "utf8");
|
|
90118
90150
|
}
|
|
90119
90151
|
function sourceManifestPath(entry) {
|
|
90120
|
-
return entry.snapshot?.manifest ??
|
|
90152
|
+
return entry.snapshot?.manifest ?? join75(entry.materializedAt, "manifest.json");
|
|
90121
90153
|
}
|
|
90122
90154
|
function runtimeError3(message, detail) {
|
|
90123
90155
|
return new ContextError(ExitCode.UserError, message, {
|
|
@@ -90190,7 +90222,7 @@ async function removeEmptySnapshotDirs(root, dir = root) {
|
|
|
90190
90222
|
for (const entry of entries2) {
|
|
90191
90223
|
if (!entry.isDirectory() || entry.name === ".tmp" || entry.name === ".cache")
|
|
90192
90224
|
continue;
|
|
90193
|
-
await removeEmptySnapshotDirs(root,
|
|
90225
|
+
await removeEmptySnapshotDirs(root, join75(dir, entry.name));
|
|
90194
90226
|
}
|
|
90195
90227
|
if (dir === root)
|
|
90196
90228
|
return;
|
|
@@ -90202,7 +90234,7 @@ async function removeEmptySnapshotDirs(root, dir = root) {
|
|
|
90202
90234
|
async function cleanupStaleSnapshotFiles(input) {
|
|
90203
90235
|
for (const path2 of input.previousPaths) {
|
|
90204
90236
|
if (!input.currentPaths.has(path2)) {
|
|
90205
|
-
await rm17(
|
|
90237
|
+
await rm17(join75(input.materializedAtAbsPath, path2), { force: true });
|
|
90206
90238
|
}
|
|
90207
90239
|
}
|
|
90208
90240
|
await removeEmptySnapshotDirs(input.materializedAtAbsPath);
|
|
@@ -90385,9 +90417,9 @@ async function runCaptureFilePhaseUnlocked(input) {
|
|
|
90385
90417
|
documentSnapshot
|
|
90386
90418
|
});
|
|
90387
90419
|
const manifestPath = sourceManifestPath(entry);
|
|
90388
|
-
const manifestAbsPath =
|
|
90420
|
+
const manifestAbsPath = join75(input.projectRoot, manifestPath);
|
|
90389
90421
|
const materializedAt = entry.materializedAt;
|
|
90390
|
-
const materializedAtAbsPath =
|
|
90422
|
+
const materializedAtAbsPath = join75(input.projectRoot, materializedAt);
|
|
90391
90423
|
const manifestInput = {
|
|
90392
90424
|
sourceType: "file",
|
|
90393
90425
|
sourceName: resolved.sourceName,
|
|
@@ -90437,13 +90469,13 @@ async function runCaptureFilePhaseUnlocked(input) {
|
|
|
90437
90469
|
}));
|
|
90438
90470
|
try {
|
|
90439
90471
|
for (const file of snapshotFiles) {
|
|
90440
|
-
await writeTextIfChanged(
|
|
90472
|
+
await writeTextIfChanged(join75(materializedAtAbsPath, file.path), String(file.bytes));
|
|
90441
90473
|
}
|
|
90442
90474
|
for (const file of files.metadata) {
|
|
90443
|
-
await writeTextIfChanged(
|
|
90475
|
+
await writeTextIfChanged(join75(materializedAtAbsPath, file.snapshotPath), routeMetadata.rawByPath.get(file.snapshotPath) ?? "");
|
|
90444
90476
|
}
|
|
90445
90477
|
for (const asset of linkedAssets) {
|
|
90446
|
-
await writeCaptureAssetIfChanged(
|
|
90478
|
+
await writeCaptureAssetIfChanged(join75(materializedAtAbsPath, asset.snapshotPath), asset.bytes);
|
|
90447
90479
|
}
|
|
90448
90480
|
await writeTextIfChanged(manifestAbsPath, manifestContent);
|
|
90449
90481
|
await cleanupStaleSnapshotFiles({
|
|
@@ -90621,7 +90653,7 @@ var init_larkCaptureReport = __esm(() => {
|
|
|
90621
90653
|
|
|
90622
90654
|
// src/project/documentSnapshotFidelity.ts
|
|
90623
90655
|
import { readFileSync as readFileSync7 } from "node:fs";
|
|
90624
|
-
import { join as
|
|
90656
|
+
import { join as join76 } from "node:path";
|
|
90625
90657
|
function readDocumentSnapshotCaptureReport(input) {
|
|
90626
90658
|
const summary = input.manifest.metadata?.capture?.report;
|
|
90627
90659
|
if (summary === undefined)
|
|
@@ -90630,7 +90662,7 @@ function readDocumentSnapshotCaptureReport(input) {
|
|
|
90630
90662
|
if (asset === undefined || asset.role !== "audit" || asset.content_hash === undefined) {
|
|
90631
90663
|
throw new TypeError(`snapshot capture report is not registered as a hashed audit asset: ${summary.path}`);
|
|
90632
90664
|
}
|
|
90633
|
-
const bytes = readFileSync7(
|
|
90665
|
+
const bytes = readFileSync7(join76(input.projectRoot, input.materializedAt, summary.path));
|
|
90634
90666
|
if (computeDocumentContentHash(bytes) !== asset.content_hash) {
|
|
90635
90667
|
throw new TypeError(`snapshot capture report hash does not match manifest: ${summary.path}`);
|
|
90636
90668
|
}
|
|
@@ -90728,7 +90760,7 @@ function larkSnapshotIdentityDiagnostic(source2, manifest) {
|
|
|
90728
90760
|
// src/project/repoSourceModules.ts
|
|
90729
90761
|
import { existsSync as existsSync19 } from "node:fs";
|
|
90730
90762
|
import { readFile as readFile64, readdir as readdir19 } from "node:fs/promises";
|
|
90731
|
-
import { join as
|
|
90763
|
+
import { join as join77, resolve as resolve25 } from "node:path";
|
|
90732
90764
|
async function rootNames(root) {
|
|
90733
90765
|
try {
|
|
90734
90766
|
return (await readdir19(root)).sort();
|
|
@@ -90737,7 +90769,7 @@ async function rootNames(root) {
|
|
|
90737
90769
|
}
|
|
90738
90770
|
}
|
|
90739
90771
|
async function packageEntries(root) {
|
|
90740
|
-
const path2 =
|
|
90772
|
+
const path2 = join77(root, "package.json");
|
|
90741
90773
|
if (!existsSync19(path2))
|
|
90742
90774
|
return [];
|
|
90743
90775
|
try {
|
|
@@ -90749,9 +90781,9 @@ async function packageEntries(root) {
|
|
|
90749
90781
|
}
|
|
90750
90782
|
}
|
|
90751
90783
|
async function planningEvidence(inspectPath, module) {
|
|
90752
|
-
const root = module.path === "." ? inspectPath :
|
|
90784
|
+
const root = module.path === "." ? inspectPath : join77(inspectPath, module.path);
|
|
90753
90785
|
const names = await rootNames(root);
|
|
90754
|
-
const commonEntries = ["src/index.ts", "src/index.tsx", "src/main.ts", "src/main.tsx", "main.go"].filter((path2) => existsSync19(
|
|
90786
|
+
const commonEntries = ["src/index.ts", "src/index.tsx", "src/main.ts", "src/main.tsx", "main.go"].filter((path2) => existsSync19(join77(root, path2)));
|
|
90755
90787
|
const protocolNames = names.filter((name3) => /(?:openapi|swagger|schema|protocol|idl)/iu.test(name3) || /\.(?:proto|thrift)$/iu.test(name3));
|
|
90756
90788
|
const lifecycleNames = names.filter((name3) => /(?:generated|vendor|mirror|legacy|sync)/iu.test(name3));
|
|
90757
90789
|
return {
|
|
@@ -90789,7 +90821,7 @@ function suggestedModuleName(module) {
|
|
|
90789
90821
|
return slug || "module";
|
|
90790
90822
|
}
|
|
90791
90823
|
async function inspectRepoSourceModules(input) {
|
|
90792
|
-
const inspectPath = input.scopedAbs !== null && existsSync19(input.scopedAbs) ? input.scopedAbs :
|
|
90824
|
+
const inspectPath = input.scopedAbs !== null && existsSync19(input.scopedAbs) ? input.scopedAbs : join77(input.projectRoot, input.status.materializedAt);
|
|
90793
90825
|
const modules = existsSync19(inspectPath) ? await detectModuleBoundaries(inspectPath, input.status.head ?? input.status.ref, DEFAULT_PATH_FILTER) : [];
|
|
90794
90826
|
const recommended_sources = modules.filter((module) => module.path !== "." || modules.length === 1).map((module) => {
|
|
90795
90827
|
const local = sourceModuleLocalForDisplay({ source: input.source, status: input.status, module });
|
|
@@ -90829,7 +90861,7 @@ var init_repoSourceModules = __esm(() => {
|
|
|
90829
90861
|
|
|
90830
90862
|
// src/project/repoSourceRegistry.ts
|
|
90831
90863
|
import { existsSync as existsSync20 } from "node:fs";
|
|
90832
|
-
import { join as
|
|
90864
|
+
import { join as join78 } from "node:path";
|
|
90833
90865
|
function assertRepoModuleName(name3) {
|
|
90834
90866
|
if (!SOURCE_NAME_PATTERN2.test(name3)) {
|
|
90835
90867
|
throw new ContextError(ExitCode.UserError, `repo source name must be a lowercase path-safe slug: ${name3}`, {
|
|
@@ -90880,7 +90912,7 @@ function registryEntryToRecord(entry) {
|
|
|
90880
90912
|
};
|
|
90881
90913
|
}
|
|
90882
90914
|
function registryPath(projectRoot) {
|
|
90883
|
-
return
|
|
90915
|
+
return join78(projectRoot, DEFAULT_REPO_SOURCES_REGISTRY_PATH);
|
|
90884
90916
|
}
|
|
90885
90917
|
function defaultRepoMaterializedAt(source2) {
|
|
90886
90918
|
return `sources/repo/${source2.namespace}/${source2.module}`;
|
|
@@ -90942,7 +90974,7 @@ import { existsSync as existsSync21 } from "node:fs";
|
|
|
90942
90974
|
import { lstat as lstat9, mkdir as mkdir29, readFile as readFile65, readlink, realpath as realpath9, rm as rm18, symlink as symlink3 } from "node:fs/promises";
|
|
90943
90975
|
import { execFile as execFile9 } from "node:child_process";
|
|
90944
90976
|
import { promisify as promisify9 } from "node:util";
|
|
90945
|
-
import { dirname as dirname35, isAbsolute as isAbsolute14, join as
|
|
90977
|
+
import { dirname as dirname35, isAbsolute as isAbsolute14, join as join79, relative as relative23, resolve as resolve26 } from "node:path";
|
|
90946
90978
|
function nonEmpty(value) {
|
|
90947
90979
|
if (value == null)
|
|
90948
90980
|
return null;
|
|
@@ -90996,13 +91028,13 @@ async function gitOutput(cwd, args) {
|
|
|
90996
91028
|
}
|
|
90997
91029
|
}
|
|
90998
91030
|
async function readGitOriginRemote(cwd) {
|
|
90999
|
-
const directConfigPath =
|
|
91031
|
+
const directConfigPath = join79(cwd, ".git", "config");
|
|
91000
91032
|
let config = await readFile65(directConfigPath, "utf8").catch(() => "");
|
|
91001
91033
|
if (config.length === 0) {
|
|
91002
91034
|
const gitDir = await resolveGitDir(cwd);
|
|
91003
91035
|
if (gitDir === null)
|
|
91004
91036
|
return null;
|
|
91005
|
-
config = await readFile65(
|
|
91037
|
+
config = await readFile65(join79(gitDir, "config"), "utf8").catch(() => "");
|
|
91006
91038
|
}
|
|
91007
91039
|
let inOriginBlock = false;
|
|
91008
91040
|
for (const line of config.split(/\r?\n/u)) {
|
|
@@ -91022,7 +91054,7 @@ async function readGitOriginRemote(cwd) {
|
|
|
91022
91054
|
async function resolveGitRoot(cwd) {
|
|
91023
91055
|
let current2 = resolve26(cwd);
|
|
91024
91056
|
while (true) {
|
|
91025
|
-
if (existsSync21(
|
|
91057
|
+
if (existsSync21(join79(current2, ".git")))
|
|
91026
91058
|
return current2;
|
|
91027
91059
|
const parent = dirname35(current2);
|
|
91028
91060
|
if (parent === current2)
|
|
@@ -91031,7 +91063,7 @@ async function resolveGitRoot(cwd) {
|
|
|
91031
91063
|
}
|
|
91032
91064
|
}
|
|
91033
91065
|
async function resolveGitDir(cwd) {
|
|
91034
|
-
const dotGit =
|
|
91066
|
+
const dotGit = join79(cwd, ".git");
|
|
91035
91067
|
if (!existsSync21(dotGit))
|
|
91036
91068
|
return null;
|
|
91037
91069
|
const stats = await lstat9(dotGit);
|
|
@@ -91049,17 +91081,17 @@ async function readGitHead(cwd) {
|
|
|
91049
91081
|
const gitDir = await resolveGitDir(cwd);
|
|
91050
91082
|
if (gitDir === null)
|
|
91051
91083
|
return null;
|
|
91052
|
-
const headRaw = (await readFile65(
|
|
91084
|
+
const headRaw = (await readFile65(join79(gitDir, "HEAD"), "utf8").catch(() => "")).trim();
|
|
91053
91085
|
if (/^[a-f0-9]{40}$/iu.test(headRaw))
|
|
91054
91086
|
return headRaw.toLowerCase();
|
|
91055
91087
|
const match = /^ref:\s*(.+)\s*$/iu.exec(headRaw);
|
|
91056
91088
|
const refPath = match?.[1];
|
|
91057
91089
|
if (refPath === undefined)
|
|
91058
91090
|
return null;
|
|
91059
|
-
const looseRef = (await readFile65(
|
|
91091
|
+
const looseRef = (await readFile65(join79(gitDir, refPath), "utf8").catch(() => "")).trim();
|
|
91060
91092
|
if (/^[a-f0-9]{40}$/iu.test(looseRef))
|
|
91061
91093
|
return looseRef.toLowerCase();
|
|
91062
|
-
const packedRefs = await readFile65(
|
|
91094
|
+
const packedRefs = await readFile65(join79(gitDir, "packed-refs"), "utf8").catch(() => "");
|
|
91063
91095
|
for (const line of packedRefs.split(/\r?\n/u)) {
|
|
91064
91096
|
if (line.startsWith("#") || line.startsWith("^"))
|
|
91065
91097
|
continue;
|
|
@@ -91070,7 +91102,7 @@ async function readGitHead(cwd) {
|
|
|
91070
91102
|
return null;
|
|
91071
91103
|
}
|
|
91072
91104
|
async function ensureMaterializedSymlink(input) {
|
|
91073
|
-
const linkPath =
|
|
91105
|
+
const linkPath = join79(input.projectRoot, input.materializedAt);
|
|
91074
91106
|
await mkdir29(dirname35(linkPath), { recursive: true });
|
|
91075
91107
|
if (existsSync21(linkPath)) {
|
|
91076
91108
|
const stats = await lstat9(linkPath);
|
|
@@ -91089,7 +91121,7 @@ async function ensureMaterializedSymlink(input) {
|
|
|
91089
91121
|
return true;
|
|
91090
91122
|
}
|
|
91091
91123
|
async function diagnoseMaterializedSymlink(input) {
|
|
91092
|
-
const linkPath =
|
|
91124
|
+
const linkPath = join79(input.projectRoot, input.materializedAt);
|
|
91093
91125
|
if (!existsSync21(linkPath)) {
|
|
91094
91126
|
input.diagnostics.push(`materialized path is missing: ${input.materializedAt}`);
|
|
91095
91127
|
input.agent_hints.push(`Run context source ensure ${input.sourceName} to materialize the local source link.`);
|
|
@@ -91312,7 +91344,7 @@ async function inspectRepoSource(input) {
|
|
|
91312
91344
|
const subpath = normalizeSubpath2(source2.subpath);
|
|
91313
91345
|
const scopedAbs = localAbs === null ? null : scopedLocalPath(localAbs, subpath);
|
|
91314
91346
|
const scopeExists = scopedAbs !== null && existsSync21(scopedAbs);
|
|
91315
|
-
let materialized = existsSync21(
|
|
91347
|
+
let materialized = existsSync21(join79(input.projectRoot, materializedAt));
|
|
91316
91348
|
const checkout = await inspectRepoCheckout({
|
|
91317
91349
|
source: source2,
|
|
91318
91350
|
localAbs,
|
|
@@ -91498,7 +91530,7 @@ var init_entityId = __esm(() => {
|
|
|
91498
91530
|
// src/project/reviewShared.ts
|
|
91499
91531
|
import { createHash as createHash22 } from "node:crypto";
|
|
91500
91532
|
import { mkdir as mkdir30, writeFile as writeFile24 } from "node:fs/promises";
|
|
91501
|
-
import { dirname as dirname36, join as
|
|
91533
|
+
import { dirname as dirname36, join as join80 } from "node:path";
|
|
91502
91534
|
function isRecord14(value) {
|
|
91503
91535
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
91504
91536
|
}
|
|
@@ -91541,7 +91573,7 @@ async function buildApprovedArticleIndex(projectRoot) {
|
|
|
91541
91573
|
if (!isApprovedKnowledgeMarkdownPath(rel))
|
|
91542
91574
|
continue;
|
|
91543
91575
|
const { absPath, content: content3 } = file;
|
|
91544
|
-
const relPath =
|
|
91576
|
+
const relPath = join80("knowledge", collection, rel);
|
|
91545
91577
|
assetReferencesByRelPath.set(relPath, knowledgeAssetReferences({
|
|
91546
91578
|
pageRelPath: relPath,
|
|
91547
91579
|
content: content3
|
|
@@ -91554,7 +91586,7 @@ async function buildApprovedArticleIndex(projectRoot) {
|
|
|
91554
91586
|
continue;
|
|
91555
91587
|
const frontmatter2 = hydrateApprovedFrontmatter({
|
|
91556
91588
|
frontmatter: parsed,
|
|
91557
|
-
relPath:
|
|
91589
|
+
relPath: join80(collection, rel),
|
|
91558
91590
|
metadata
|
|
91559
91591
|
});
|
|
91560
91592
|
const article = articlesByPath.get(`${collection}/${rel}`);
|
|
@@ -91609,8 +91641,8 @@ ${yaml3}
|
|
|
91609
91641
|
}
|
|
91610
91642
|
async function writeReviewActionLog(input) {
|
|
91611
91643
|
const stamp = new Date().toISOString().replace(/[-:.TZ]/gu, "");
|
|
91612
|
-
const relPath =
|
|
91613
|
-
const path2 =
|
|
91644
|
+
const relPath = join80(REVIEW_ACTION_ROOT2, `${stamp}-${input.action}-${input.id.replace(/[\\/]+/gu, "_")}.json`);
|
|
91645
|
+
const path2 = join80(input.projectRoot, relPath);
|
|
91614
91646
|
await mkdir30(dirname36(path2), { recursive: true });
|
|
91615
91647
|
await writeFile24(path2, `${JSON.stringify({
|
|
91616
91648
|
action: input.action,
|
|
@@ -91643,7 +91675,7 @@ var init_reviewShared = __esm(() => {
|
|
|
91643
91675
|
init_knowledgeAssets();
|
|
91644
91676
|
init_entityId();
|
|
91645
91677
|
import_yaml38 = __toESM(require_dist(), 1);
|
|
91646
|
-
REVIEW_ACTION_ROOT2 =
|
|
91678
|
+
REVIEW_ACTION_ROOT2 = join80(".tmp", "context-runtime", "review-actions");
|
|
91647
91679
|
});
|
|
91648
91680
|
|
|
91649
91681
|
// src/project/managedDocumentStatus.ts
|
|
@@ -91719,7 +91751,7 @@ __export(exports_statusReaders, {
|
|
|
91719
91751
|
countFiles: () => countFiles
|
|
91720
91752
|
});
|
|
91721
91753
|
import { existsSync as existsSync22, readFileSync as readFileSync8 } from "node:fs";
|
|
91722
|
-
import { join as
|
|
91754
|
+
import { join as join81 } from "node:path";
|
|
91723
91755
|
async function countFiles(root, predicate) {
|
|
91724
91756
|
if (!existsSync22(root))
|
|
91725
91757
|
return 0;
|
|
@@ -91728,7 +91760,7 @@ async function countFiles(root, predicate) {
|
|
|
91728
91760
|
const entries2 = await readCommandDirectory(dir);
|
|
91729
91761
|
for (const entry of entries2) {
|
|
91730
91762
|
const rel = prefix.length === 0 ? entry.name : `${prefix}/${entry.name}`;
|
|
91731
|
-
const abs =
|
|
91763
|
+
const abs = join81(dir, entry.name);
|
|
91732
91764
|
if (entry.isDirectory())
|
|
91733
91765
|
await visit3(abs, rel);
|
|
91734
91766
|
else if (entry.isFile() && predicate(rel))
|
|
@@ -91919,7 +91951,7 @@ async function documentSourceSiteHint(input) {
|
|
|
91919
91951
|
});
|
|
91920
91952
|
}
|
|
91921
91953
|
function documentSnapshotReadiness(input) {
|
|
91922
|
-
const manifestPath =
|
|
91954
|
+
const manifestPath = join81(input.projectRoot, input.manifest);
|
|
91923
91955
|
if (!existsSync22(manifestPath)) {
|
|
91924
91956
|
return {
|
|
91925
91957
|
ready: false,
|
|
@@ -91989,7 +92021,7 @@ function documentSnapshotReadiness(input) {
|
|
|
91989
92021
|
const missingFiles = [
|
|
91990
92022
|
...manifest.files.map((file) => file.path),
|
|
91991
92023
|
...(manifest.assets ?? []).filter((asset) => asset.content_hash !== undefined).map((asset) => asset.path)
|
|
91992
|
-
].filter((path2) => !existsSync22(
|
|
92024
|
+
].filter((path2) => !existsSync22(join81(input.projectRoot, input.materializedAt, path2)));
|
|
91993
92025
|
if (missingFiles.length > 0) {
|
|
91994
92026
|
return {
|
|
91995
92027
|
ready: false,
|
|
@@ -92780,7 +92812,7 @@ var init_workflowProvider = __esm(() => {
|
|
|
92780
92812
|
|
|
92781
92813
|
// src/project/productionStageRefresh.ts
|
|
92782
92814
|
import { readFile as readFile67 } from "node:fs/promises";
|
|
92783
|
-
import { join as
|
|
92815
|
+
import { join as join83 } from "node:path";
|
|
92784
92816
|
async function refreshProductionStageSources(projectRoot, stage) {
|
|
92785
92817
|
const affected = new Set(stage.gaps.map((gap) => gap.scope));
|
|
92786
92818
|
const unavailable = new Map;
|
|
@@ -92820,8 +92852,8 @@ Restore the authorized source and retry preparation.
|
|
|
92820
92852
|
tasks: stage.tasks.map((task) => !["accepted", "excluded", "replaced"].includes(task.status) && task.sources.some((source2) => affected.has(source2.scope)) ? { ...task, status: "blocked", reason: "Source material refreshed; investigate and explicitly replace this unfinished task." } : task)
|
|
92821
92853
|
});
|
|
92822
92854
|
const directory = productionStageDirectory(stage.id);
|
|
92823
|
-
const contents2 = new Map([...sourceMaterials].map(([scope2, content3]) => [
|
|
92824
|
-
contents2.set(
|
|
92855
|
+
const contents2 = new Map([...sourceMaterials].map(([scope2, content3]) => [join83(directory, productionSourceFile(scope2)), content3]));
|
|
92856
|
+
contents2.set(join83(directory, "manifest.json"), `${JSON.stringify(updated)}
|
|
92825
92857
|
`);
|
|
92826
92858
|
const targets = [];
|
|
92827
92859
|
for (const [path2, content3] of contents2) {
|
|
@@ -92951,7 +92983,7 @@ var init_productionReport = __esm(() => {
|
|
|
92951
92983
|
});
|
|
92952
92984
|
|
|
92953
92985
|
// src/project/productionPlanningRoute.ts
|
|
92954
|
-
import { join as
|
|
92986
|
+
import { join as join84 } from "node:path";
|
|
92955
92987
|
async function productionPlanningRoute(input, stage) {
|
|
92956
92988
|
const request = stage ? undefined : await productionPlanningRequest(input.projectRoot);
|
|
92957
92989
|
const present = !!stage || !!request;
|
|
@@ -92989,7 +93021,7 @@ async function productionPlanningRoute(input, stage) {
|
|
|
92989
93021
|
id: `production/${stage.id}/planning`,
|
|
92990
93022
|
kind: "context-view",
|
|
92991
93023
|
media_type: "text/markdown",
|
|
92992
|
-
path:
|
|
93024
|
+
path: join84(input.projectRoot, productionStageDirectory(stage.id), "planning.md"),
|
|
92993
93025
|
read_state: "read-required"
|
|
92994
93026
|
}] : []
|
|
92995
93027
|
],
|
|
@@ -93008,7 +93040,7 @@ var init_productionPlanningRoute = __esm(() => {
|
|
|
93008
93040
|
|
|
93009
93041
|
// src/project/productionWorkflowRoute.ts
|
|
93010
93042
|
import { existsSync as existsSync24 } from "node:fs";
|
|
93011
|
-
import { join as
|
|
93043
|
+
import { join as join85 } from "node:path";
|
|
93012
93044
|
async function productionWorkflowRoute(input) {
|
|
93013
93045
|
const stage = await readProductionStage(input.projectRoot);
|
|
93014
93046
|
if (!stage || !stage.planning_complete)
|
|
@@ -93026,7 +93058,7 @@ async function productionWorkflowRoute(input) {
|
|
|
93026
93058
|
const selected = new Set(dispatch.batches.flatMap((batch) => batch.tasks));
|
|
93027
93059
|
const context = { workspace: input.projectRoot, authorities: [...input.authorities], facts: { production: {
|
|
93028
93060
|
report_approved: stage.report_approved,
|
|
93029
|
-
prepared: !dispatch.batches.length || existsSync24(
|
|
93061
|
+
prepared: !dispatch.batches.length || existsSync24(join85(input.projectRoot, directory, "stage.md")) && stage.tasks.filter((task) => selected.has(task.id)).every((task) => task.status === "issued"),
|
|
93030
93062
|
writing_complete: dispatch.batches.length === 0,
|
|
93031
93063
|
complete: dispatch.state === "ended",
|
|
93032
93064
|
review_clear: rejected.length === 0,
|
|
@@ -93043,7 +93075,7 @@ async function productionWorkflowRoute(input) {
|
|
|
93043
93075
|
const resolved = await resolveRoute(provider, "indexer", "production", primary.routeId, context, evaluated.evaluation.revision);
|
|
93044
93076
|
const report = resolved.node === "confirm-production-report";
|
|
93045
93077
|
if (report)
|
|
93046
|
-
await writeProductionProjection(input.projectRoot,
|
|
93078
|
+
await writeProductionProjection(input.projectRoot, join85(directory, "plan.md"), productionPlanMarkdown(stage));
|
|
93047
93079
|
const prepare = resolved.node === "prepare-production-stage";
|
|
93048
93080
|
const writing = resolved.node === "work-production-stage";
|
|
93049
93081
|
const repair = resolved.node === "repair-production-articles";
|
|
@@ -93058,7 +93090,7 @@ async function productionWorkflowRoute(input) {
|
|
|
93058
93090
|
id: `production/${stage.id}/${report ? "plan" : "stage"}`,
|
|
93059
93091
|
kind: "context-view",
|
|
93060
93092
|
media_type: "text/markdown",
|
|
93061
|
-
path:
|
|
93093
|
+
path: join85(input.projectRoot, directory, path3),
|
|
93062
93094
|
read_state: "read-required"
|
|
93063
93095
|
});
|
|
93064
93096
|
if (report || writing)
|
|
@@ -93069,18 +93101,18 @@ async function productionWorkflowRoute(input) {
|
|
|
93069
93101
|
id: `production/${stage.id}/planning`,
|
|
93070
93102
|
kind: "context-view",
|
|
93071
93103
|
media_type: "text/markdown",
|
|
93072
|
-
path:
|
|
93104
|
+
path: join85(input.projectRoot, directory, "planning.md"),
|
|
93073
93105
|
read_state: "read-required"
|
|
93074
93106
|
});
|
|
93075
93107
|
}
|
|
93076
93108
|
if (repair) {
|
|
93077
|
-
await writeProductionProjection(input.projectRoot,
|
|
93109
|
+
await writeProductionProjection(input.projectRoot, join85(directory, "repair.md"), [
|
|
93078
93110
|
"# Revise rejected articles",
|
|
93079
93111
|
"",
|
|
93080
93112
|
...rejected.map((candidate) => `- ${candidate.path}: ${candidate.review.title}`),
|
|
93081
93113
|
"",
|
|
93082
93114
|
"Use the user's Review feedback to add revision tasks for these article paths. Rejection does not cancel their planned responsibilities. Ask for missing feedback instead of guessing the reason.",
|
|
93083
|
-
`Submit the plan amendment to ${path2} using ${
|
|
93115
|
+
`Submit the plan amendment to ${path2} using ${join85(directory, "planning.schema.json")}. Keep accepted task identities unchanged; the CLI assigns the revision tasks and preserves article identities.`,
|
|
93084
93116
|
"Once issued, repair the affected sections through the existing edits submission. Unchanged sections and references do not need resubmission.",
|
|
93085
93117
|
""
|
|
93086
93118
|
].join(`
|
|
@@ -93089,7 +93121,7 @@ async function productionWorkflowRoute(input) {
|
|
|
93089
93121
|
id: `production/${stage.id}/repair`,
|
|
93090
93122
|
kind: "context-view",
|
|
93091
93123
|
media_type: "text/markdown",
|
|
93092
|
-
path:
|
|
93124
|
+
path: join85(input.projectRoot, directory, "repair.md"),
|
|
93093
93125
|
read_state: "read-required"
|
|
93094
93126
|
});
|
|
93095
93127
|
}
|
|
@@ -93106,7 +93138,7 @@ async function productionWorkflowRoute(input) {
|
|
|
93106
93138
|
revision,
|
|
93107
93139
|
reason_code: resolved.reasonCode,
|
|
93108
93140
|
availability: resolved.availability,
|
|
93109
|
-
summary: report ? `Present the report and
|
|
93141
|
+
summary: report ? `Present the report and apply context.gate.work_start_scope. After the applicable scope decision, write {stage: ${stage.id}, decision: approved} to ${path2}.` : writing ? "Read the issued task directories. Coordinate them sequentially unless this caller supports independent Agents; only the coordinator submits shared state." : repair ? "Add revision tasks for rejected articles using the Review feedback; accepted production responsibilities remain unchanged." : investigate ? `Review pending configured scopes: ${stage.pending_scopes.filter((scope2) => !stage.gaps.some((gap2) => gap2.scope === scope2)).join(", ")}. Check their relevance to the current request and existing approved content before assigning investigation. Submit supported article tasks and remaining pending_scopes; do not infer missing articles from this list or repeat accepted work. If the requested articles are already accepted, context run --deliver --format json enters their Review while retaining unrelated pending scopes.` : resolved.node === "resolve-production-gap" ? `Source availability gaps: ${stage.gaps.map((gap2) => `${gap2.scope}: ${gap2.reason}`).join("; ")}. These failures do not establish missing knowledge or a new investigation assignment. Identify which sources the current task actually depends on; report unrelated configured-source failures separately. Preserve the configuration. To review completed articles independently, use context run --deliver --format json; this retains pending scopes and does not approve or publish content. If these sources are required, use context source recovery-plan --format json and context source restore with explicit local or clone decisions before preparation.` : "Prepare the current stage's eligible task directories.",
|
|
93110
93142
|
commands: report || prepare || writing || repair || investigate || gap ? [{
|
|
93111
93143
|
command: command2,
|
|
93112
93144
|
effect: "write",
|
|
@@ -97873,7 +97905,7 @@ var init_larkResourceCommand = __esm(() => {
|
|
|
97873
97905
|
// src/lib/larkResourceMaterialization.ts
|
|
97874
97906
|
import { createHash as createHash28 } from "node:crypto";
|
|
97875
97907
|
import { mkdtemp as mkdtemp4, readFile as readFile74, readdir as readdir21, rm as rm20 } from "node:fs/promises";
|
|
97876
|
-
import { extname as extname13, join as
|
|
97908
|
+
import { extname as extname13, join as join94 } from "node:path";
|
|
97877
97909
|
import { tmpdir } from "node:os";
|
|
97878
97910
|
function countByKind(items, status) {
|
|
97879
97911
|
const counts2 = new Map;
|
|
@@ -97981,7 +98013,7 @@ async function downloadedFile(input) {
|
|
|
97981
98013
|
const bytes = await readFile74(input.localPath);
|
|
97982
98014
|
return { path: input.localPath, bytes, mediaType: mediaTypeFor(input.localPath, bytes) };
|
|
97983
98015
|
}
|
|
97984
|
-
const tempRoot = await mkdtemp4(
|
|
98016
|
+
const tempRoot = await mkdtemp4(join94(tmpdir(), "context-lark-resource-"));
|
|
97985
98017
|
try {
|
|
97986
98018
|
await runLarkResourceCommand(input.runner, [
|
|
97987
98019
|
"docs",
|
|
@@ -98002,7 +98034,7 @@ async function downloadedFile(input) {
|
|
|
98002
98034
|
if (entries2.length !== 1)
|
|
98003
98035
|
throw new Error(`media download produced ${entries2.length} files, expected exactly one`);
|
|
98004
98036
|
const path3 = entries2[0]?.name ?? "resource.bin";
|
|
98005
|
-
const bytes = await readFile74(
|
|
98037
|
+
const bytes = await readFile74(join94(tempRoot, path3));
|
|
98006
98038
|
return { path: path3, bytes, mediaType: mediaTypeFor(path3, bytes) };
|
|
98007
98039
|
} finally {
|
|
98008
98040
|
await rm20(tempRoot, { recursive: true, force: true });
|
|
@@ -98093,9 +98125,9 @@ async function sheetMaterialization(resource, runner2, identity2) {
|
|
|
98093
98125
|
const sheetId = resource.attributes["sheet-id"];
|
|
98094
98126
|
if (token === undefined || sheetId === undefined)
|
|
98095
98127
|
throw new Error("embedded Sheet requires token and sheet-id");
|
|
98096
|
-
const tempRoot = await mkdtemp4(
|
|
98128
|
+
const tempRoot = await mkdtemp4(join94(tmpdir(), "context-lark-sheet-"));
|
|
98097
98129
|
try {
|
|
98098
|
-
const outputPath =
|
|
98130
|
+
const outputPath = join94(tempRoot, "sheet.json");
|
|
98099
98131
|
const stdout = await runLarkResourceCommand(runner2, [
|
|
98100
98132
|
"sheets",
|
|
98101
98133
|
"+csv-get",
|
|
@@ -98251,7 +98283,7 @@ async function whiteboardMaterialization(resource, runner2, identity2) {
|
|
|
98251
98283
|
if (token === undefined)
|
|
98252
98284
|
throw new Error(`${resource.kind} has no whiteboard token`);
|
|
98253
98285
|
const preview = await downloadedFile({ runner: runner2, identity: identity2, token, type: "whiteboard" });
|
|
98254
|
-
const tempRoot = await mkdtemp4(
|
|
98286
|
+
const tempRoot = await mkdtemp4(join94(tmpdir(), "context-lark-whiteboard-"));
|
|
98255
98287
|
let rawPayload;
|
|
98256
98288
|
try {
|
|
98257
98289
|
await runLarkResourceCommand(runner2, [
|
|
@@ -98269,7 +98301,7 @@ async function whiteboardMaterialization(resource, runner2, identity2) {
|
|
|
98269
98301
|
"--format",
|
|
98270
98302
|
"json"
|
|
98271
98303
|
], { cwd: tempRoot });
|
|
98272
|
-
rawPayload = JSON.parse(await readFile74(
|
|
98304
|
+
rawPayload = JSON.parse(await readFile74(join94(tempRoot, "raw.json"), "utf8"));
|
|
98273
98305
|
} finally {
|
|
98274
98306
|
await rm20(tempRoot, { recursive: true, force: true });
|
|
98275
98307
|
}
|
|
@@ -98631,7 +98663,7 @@ function resolveDocsFetchPlan(requested, runner2) {
|
|
|
98631
98663
|
}
|
|
98632
98664
|
return capabilitiesPromise.then((capabilities) => {
|
|
98633
98665
|
if (!capabilities.supportsDocFormat) {
|
|
98634
|
-
throw new LarkCliError(`${LARK_BIN} docs +fetch does not support --doc-format xml;
|
|
98666
|
+
throw new LarkCliError(`${LARK_BIN} docs +fetch does not support --doc-format xml; a compatible @larksuite/cli is required to capture Lark sources`, 0, "");
|
|
98635
98667
|
}
|
|
98636
98668
|
return { apiVersion: capabilities.apiVersion, docFormat: "xml" };
|
|
98637
98669
|
});
|
|
@@ -98642,7 +98674,7 @@ function docsFetchFailureMessage(stderr, apiVersion) {
|
|
|
98642
98674
|
const mentionsV2 = /api-version|--api-version|v2|deprecated|lark-cli update/iu.test(stderr);
|
|
98643
98675
|
if (apiVersion === "v1" && mentionsV2) {
|
|
98644
98676
|
return `${base}
|
|
98645
|
-
Detected docs API v2 guidance from lark-cli
|
|
98677
|
+
Detected docs API v2 guidance from lark-cli; a compatible CLI with \`--api-version v2\` is required.`;
|
|
98646
98678
|
}
|
|
98647
98679
|
return base;
|
|
98648
98680
|
}
|
|
@@ -98707,7 +98739,7 @@ function extractDocsFetchContent(payload, requestedFormat) {
|
|
|
98707
98739
|
const withTitle = (result) => title2 === undefined ? result : { ...result, title: title2 };
|
|
98708
98740
|
if (markdown !== undefined) {
|
|
98709
98741
|
if (requestedFormat === "xml") {
|
|
98710
|
-
throw new LarkCliError(`${LARK_BIN} docs +fetch returned Markdown despite --doc-format xml; capture stopped because the response cannot provide auditable rich-block fidelity.
|
|
98742
|
+
throw new LarkCliError(`${LARK_BIN} docs +fetch returned Markdown despite --doc-format xml; capture stopped because the response cannot provide auditable rich-block fidelity. Use a compatible CLI and retry.`, 0, "");
|
|
98711
98743
|
}
|
|
98712
98744
|
return withTitle({ body: markdown, format: "markdown", recognizedShape: true });
|
|
98713
98745
|
}
|
|
@@ -99038,7 +99070,7 @@ ${body2}`,
|
|
|
99038
99070
|
};
|
|
99039
99071
|
}
|
|
99040
99072
|
var LARK_BIN = "lark-cli", MAX_FETCH_PAGES = 50, MAX_STRUCTURAL_FETCH_ATTEMPTS = 2, LarkCliNotInstalledError, LarkCliError, defaultRunner = (args, options) => new Promise((resolve8, reject) => {
|
|
99041
|
-
const child = spawn4(LARK_BIN, args, {
|
|
99073
|
+
const child = spawn4(process.env.CONTEXT_LARK_CLI_BIN?.trim() || LARK_BIN, args, {
|
|
99042
99074
|
...options?.cwd === undefined ? {} : { cwd: options.cwd },
|
|
99043
99075
|
stdio: ["ignore", "pipe", "pipe"]
|
|
99044
99076
|
});
|
|
@@ -99119,7 +99151,7 @@ var init_sensitiveSourceLiteral = __esm(() => {
|
|
|
99119
99151
|
|
|
99120
99152
|
// src/project/documentCaptureLark.ts
|
|
99121
99153
|
import { readdir as readdir22, readFile as readFile75 } from "node:fs/promises";
|
|
99122
|
-
import { basename as basename10, extname as extname14, join as
|
|
99154
|
+
import { basename as basename10, extname as extname14, join as join95 } from "node:path";
|
|
99123
99155
|
function titleFromMarkdown2(markdown, fallbackPath) {
|
|
99124
99156
|
const heading2 = markdown.split(`
|
|
99125
99157
|
`).find((line) => /^#\s+\S/u.test(line));
|
|
@@ -99146,7 +99178,7 @@ async function fileContentMatches(path3, content3) {
|
|
|
99146
99178
|
}
|
|
99147
99179
|
}
|
|
99148
99180
|
function sourceManifestPath2(entry) {
|
|
99149
|
-
return entry.snapshot?.manifest ??
|
|
99181
|
+
return entry.snapshot?.manifest ?? join95(entry.materializedAt, "manifest.json");
|
|
99150
99182
|
}
|
|
99151
99183
|
function larkRuntimeError(message, detail) {
|
|
99152
99184
|
return new ContextError(ExitCode.ExternalToolError, message, {
|
|
@@ -99193,6 +99225,7 @@ function larkTarget(entry) {
|
|
|
99193
99225
|
}
|
|
99194
99226
|
function larkErrorRecovery(error, sourceName) {
|
|
99195
99227
|
const message = error instanceof Error ? error.message : String(error);
|
|
99228
|
+
const localCliRecovery = `Install @larksuite/cli in a private directory with \`npm install --prefix "$HOME/.cache/context/lark-cli" @larksuite/cli@latest\`, then rerun \`CONTEXT_LARK_CLI_BIN="$HOME/.cache/context/lark-cli/node_modules/.bin/lark-cli" context run capture:lark:${sourceName}\`. Keep this variable on subsequent Context commands that access Lark; do not replace the global lark-cli.`;
|
|
99196
99229
|
const environmentIssue = detectExternalEnvironmentIssue(message);
|
|
99197
99230
|
if (environmentIssue !== undefined) {
|
|
99198
99231
|
return {
|
|
@@ -99207,13 +99240,13 @@ function larkErrorRecovery(error, sourceName) {
|
|
|
99207
99240
|
if (error instanceof LarkCliNotInstalledError || /not installed|ENOENT/iu.test(message)) {
|
|
99208
99241
|
return {
|
|
99209
99242
|
reasonCode: "external.dependency-missing",
|
|
99210
|
-
next:
|
|
99243
|
+
next: localCliRecovery
|
|
99211
99244
|
};
|
|
99212
99245
|
}
|
|
99213
99246
|
if (/does not support --doc-format|api-version|deprecated|unsupported tool version|tool version unsupported/iu.test(message)) {
|
|
99214
99247
|
return {
|
|
99215
99248
|
reasonCode: "external.tool-version-unsupported",
|
|
99216
|
-
next:
|
|
99249
|
+
next: localCliRecovery
|
|
99217
99250
|
};
|
|
99218
99251
|
}
|
|
99219
99252
|
if (/empty|unsupported payload shape|not JSON|parse/iu.test(message)) {
|
|
@@ -99272,7 +99305,7 @@ function assetManifestEntry(asset, assetRoot) {
|
|
|
99272
99305
|
};
|
|
99273
99306
|
}
|
|
99274
99307
|
async function listSnapshotAssetFiles(root2, assetRoot) {
|
|
99275
|
-
const assetsRoot =
|
|
99308
|
+
const assetsRoot = join95(root2, assetRoot);
|
|
99276
99309
|
const files = [];
|
|
99277
99310
|
const visit4 = async (dir, prefix = assetRoot) => {
|
|
99278
99311
|
let entries2;
|
|
@@ -99285,7 +99318,7 @@ async function listSnapshotAssetFiles(root2, assetRoot) {
|
|
|
99285
99318
|
}
|
|
99286
99319
|
for (const entry of entries2) {
|
|
99287
99320
|
const relPath = `${prefix}/${entry.name}`;
|
|
99288
|
-
const absolutePath =
|
|
99321
|
+
const absolutePath = join95(dir, entry.name);
|
|
99289
99322
|
if (entry.isDirectory()) {
|
|
99290
99323
|
await visit4(absolutePath, relPath);
|
|
99291
99324
|
continue;
|
|
@@ -99300,7 +99333,7 @@ async function listSnapshotAssetFiles(root2, assetRoot) {
|
|
|
99300
99333
|
}
|
|
99301
99334
|
async function staleSnapshotAssetPaths(input) {
|
|
99302
99335
|
const existingPaths = await listSnapshotAssetFiles(input.materializedAtAbsPath, input.assetRoot);
|
|
99303
|
-
return existingPaths.filter((path3) => !input.currentPaths.has(path3)).map((path3) =>
|
|
99336
|
+
return existingPaths.filter((path3) => !input.currentPaths.has(path3)).map((path3) => join95(input.materializedAtAbsPath, path3));
|
|
99304
99337
|
}
|
|
99305
99338
|
function normalizeLarkError(error, sourceName) {
|
|
99306
99339
|
if (error instanceof ContextError)
|
|
@@ -99412,9 +99445,9 @@ async function runCaptureLarkPhaseUnlocked(input) {
|
|
|
99412
99445
|
locator
|
|
99413
99446
|
}];
|
|
99414
99447
|
const manifestPath = sourceManifestPath2(entry);
|
|
99415
|
-
const manifestAbsPath =
|
|
99448
|
+
const manifestAbsPath = join95(input.projectRoot, manifestPath);
|
|
99416
99449
|
const materializedAt = entry.materializedAt;
|
|
99417
|
-
const materializedAtAbsPath =
|
|
99450
|
+
const materializedAtAbsPath = join95(input.projectRoot, materializedAt);
|
|
99418
99451
|
const manifest = createDocumentSnapshotManifest({
|
|
99419
99452
|
sourceType: "lark",
|
|
99420
99453
|
sourceName: resolved.sourceName,
|
|
@@ -99448,13 +99481,13 @@ async function runCaptureLarkPhaseUnlocked(input) {
|
|
|
99448
99481
|
}));
|
|
99449
99482
|
try {
|
|
99450
99483
|
const requestedWrites = [{
|
|
99451
|
-
path:
|
|
99484
|
+
path: join95(materializedAtAbsPath, documentPath),
|
|
99452
99485
|
bytes: normalized
|
|
99453
99486
|
}];
|
|
99454
99487
|
for (const asset of assets) {
|
|
99455
99488
|
if (asset.bytes !== undefined) {
|
|
99456
99489
|
requestedWrites.push({
|
|
99457
|
-
path:
|
|
99490
|
+
path: join95(materializedAtAbsPath, asset.entry.path),
|
|
99458
99491
|
bytes: asset.bytes
|
|
99459
99492
|
});
|
|
99460
99493
|
}
|
|
@@ -99471,7 +99504,7 @@ async function runCaptureLarkPhaseUnlocked(input) {
|
|
|
99471
99504
|
currentPaths: new Set(assets.filter((asset) => asset.bytes !== undefined).map((asset) => asset.entry.path))
|
|
99472
99505
|
});
|
|
99473
99506
|
await applyAtomicFileBatch({
|
|
99474
|
-
transactionRoot:
|
|
99507
|
+
transactionRoot: join95(input.projectRoot, ".tmp", "context-runtime", "capture-transactions"),
|
|
99475
99508
|
writes,
|
|
99476
99509
|
removals
|
|
99477
99510
|
});
|
|
@@ -99901,7 +99934,7 @@ __export(exports_writeLockRecovery, {
|
|
|
99901
99934
|
inspectWriterLock: () => inspectWriterLock
|
|
99902
99935
|
});
|
|
99903
99936
|
import { lstat as lstat10, mkdir as mkdir34, readFile as readFile82, readdir as readdir24, rename as rename8, rmdir as rmdir2 } from "node:fs/promises";
|
|
99904
|
-
import { join as
|
|
99937
|
+
import { join as join100 } from "node:path";
|
|
99905
99938
|
import { createHash as createHash30, randomUUID as randomUUID7 } from "node:crypto";
|
|
99906
99939
|
async function inspectWriterLock(root2) {
|
|
99907
99940
|
const path3 = await safeProjectTarget(root2, lockRelative);
|
|
@@ -99948,8 +99981,8 @@ async function recoverWriterLock(input) {
|
|
|
99948
99981
|
};
|
|
99949
99982
|
if (input.plan_digest !== before.digest)
|
|
99950
99983
|
throw new Error("Writer lock changed; preview recovery again.");
|
|
99951
|
-
const path3 =
|
|
99952
|
-
const guard =
|
|
99984
|
+
const path3 = join100(input.projectRoot, lockRelative);
|
|
99985
|
+
const guard = join100(path3, ".recovery");
|
|
99953
99986
|
await mkdir34(guard);
|
|
99954
99987
|
let archived = false;
|
|
99955
99988
|
try {
|
|
@@ -99960,7 +99993,7 @@ async function recoverWriterLock(input) {
|
|
|
99960
99993
|
if (names.some((name3) => name3 !== "owner.json" && name3 !== ".recovery"))
|
|
99961
99994
|
throw new Error("Unexpected lock contents; preserve for diagnosis.");
|
|
99962
99995
|
const archive = `.tmp/context-runtime/locks/recovered-write-${randomUUID7()}.lock`;
|
|
99963
|
-
await rename8(path3,
|
|
99996
|
+
await rename8(path3, join100(input.projectRoot, archive));
|
|
99964
99997
|
archived = true;
|
|
99965
99998
|
return { action: "writer-lock-recovered", archived_lock: archive, next: "context task recover --format json" };
|
|
99966
99999
|
} finally {
|
|
@@ -99984,7 +100017,7 @@ __export(exports_taskRecovery, {
|
|
|
99984
100017
|
RECOVERY_COMMAND: () => RECOVERY_COMMAND
|
|
99985
100018
|
});
|
|
99986
100019
|
import { existsSync as existsSync26 } from "node:fs";
|
|
99987
|
-
import { dirname as dirname41, join as
|
|
100020
|
+
import { dirname as dirname41, join as join101 } from "node:path";
|
|
99988
100021
|
import { lstat as lstat11, readdir as readdir25, readFile as readFile83 } from "node:fs/promises";
|
|
99989
100022
|
async function recoveryText(root2, path3) {
|
|
99990
100023
|
const target = await safeProjectTarget(root2, path3);
|
|
@@ -100002,7 +100035,7 @@ async function recoveryJournals(root2) {
|
|
|
100002
100035
|
await safeProjectTarget(root2, path3);
|
|
100003
100036
|
let stat10;
|
|
100004
100037
|
try {
|
|
100005
|
-
stat10 = await lstat11(
|
|
100038
|
+
stat10 = await lstat11(join101(root2, path3));
|
|
100006
100039
|
} catch (error) {
|
|
100007
100040
|
if (error.code === "ENOENT")
|
|
100008
100041
|
return;
|
|
@@ -100013,7 +100046,7 @@ async function recoveryJournals(root2) {
|
|
|
100013
100046
|
if (stat10.isDirectory()) {
|
|
100014
100047
|
if (depth > 3)
|
|
100015
100048
|
throw new TypeError("Unexpected transaction directory depth; preserve it for diagnosis.");
|
|
100016
|
-
for (const name3 of (await readdir25(
|
|
100049
|
+
for (const name3 of (await readdir25(join101(root2, path3))).sort())
|
|
100017
100050
|
await visit4(`${path3}/${name3}`, depth + 1);
|
|
100018
100051
|
} else if (stat10.isFile())
|
|
100019
100052
|
entries2.push({ path: path3, digest: indexerProtocolDigest(await recoveryText(root2, path3)) });
|
|
@@ -100025,8 +100058,8 @@ function recoveryResources() {
|
|
|
100025
100058
|
try {
|
|
100026
100059
|
const root2 = dirname41(contextWorkflowProviderPath());
|
|
100027
100060
|
const resources = {
|
|
100028
|
-
skill:
|
|
100029
|
-
issue_template:
|
|
100061
|
+
skill: join101(root2, "skills/recover-workspace/SKILL.md"),
|
|
100062
|
+
issue_template: join101(root2, "resources/templates/recovery-issue.md")
|
|
100030
100063
|
};
|
|
100031
100064
|
if (!Object.values(resources).every((path3) => existsSync26(path3)))
|
|
100032
100065
|
throw new Error("Recovery resources are absent from this Provider.");
|
|
@@ -100112,7 +100145,7 @@ __export(exports_taskLocalSourceAdjustment, {
|
|
|
100112
100145
|
adjustLocalRevisionSources: () => adjustLocalRevisionSources
|
|
100113
100146
|
});
|
|
100114
100147
|
import { readFile as readFile84 } from "node:fs/promises";
|
|
100115
|
-
import { join as
|
|
100148
|
+
import { join as join102 } from "node:path";
|
|
100116
100149
|
async function adjustLocalRevisionSources(root2, input) {
|
|
100117
100150
|
const { readMaintenance: readMaintenance2 } = await Promise.resolve().then(() => (init_maintenanceStorage(), exports_maintenanceStorage));
|
|
100118
100151
|
if ((await readMaintenance2(root2)).active && await readProductionStage(root2))
|
|
@@ -100155,7 +100188,7 @@ async function adjustLocalRevisionSources(root2, input) {
|
|
|
100155
100188
|
if (input.refresh && (!current2.refresh_sources || indexerProtocolDigest([...current2.refresh_sources].sort()) !== indexerProtocolDigest([...selected].sort()))) {
|
|
100156
100189
|
throw new TypeError("No matching acquisition adjustment exists. Run task adjust without refresh first.");
|
|
100157
100190
|
}
|
|
100158
|
-
const raw = await readFile84(
|
|
100191
|
+
const raw = await readFile84(join102(root2, await revisionStoragePath(root2)), "utf8");
|
|
100159
100192
|
let next2;
|
|
100160
100193
|
const discardIds = new Set;
|
|
100161
100194
|
if (!input.refresh) {
|
|
@@ -100258,7 +100291,7 @@ ${input.instruction}` : revision.instruction
|
|
|
100258
100291
|
content: content3
|
|
100259
100292
|
}];
|
|
100260
100293
|
if (discardIds.size > 0) {
|
|
100261
|
-
const ledger = await readFile84(
|
|
100294
|
+
const ledger = await readFile84(join102(root2, CANDIDATE_LEDGER_FILE), "utf8").catch((error) => {
|
|
100262
100295
|
if (error.code === "ENOENT")
|
|
100263
100296
|
return;
|
|
100264
100297
|
throw error;
|
|
@@ -100515,7 +100548,7 @@ __export(exports_managedDocumentRename, {
|
|
|
100515
100548
|
renameManagedDocument: () => renameManagedDocument
|
|
100516
100549
|
});
|
|
100517
100550
|
import { readFile as readFile92 } from "node:fs/promises";
|
|
100518
|
-
import { join as
|
|
100551
|
+
import { join as join110, posix as posix11 } from "node:path";
|
|
100519
100552
|
async function optionalText2(path3) {
|
|
100520
100553
|
try {
|
|
100521
100554
|
return await readFile92(path3, "utf8");
|
|
@@ -100602,7 +100635,7 @@ async function renameManagedDocument(input) {
|
|
|
100602
100635
|
if (path3.split("/").includes("..") || path3.startsWith("/"))
|
|
100603
100636
|
throw new TypeError("Source references contain an unsafe knowledge path; repair it before renaming.");
|
|
100604
100637
|
await safeProjectTarget(input.projectRoot, path3);
|
|
100605
|
-
const before = await optionalText2(
|
|
100638
|
+
const before = await optionalText2(join110(input.projectRoot, path3));
|
|
100606
100639
|
if (before === undefined)
|
|
100607
100640
|
continue;
|
|
100608
100641
|
let after;
|
|
@@ -100691,7 +100724,7 @@ var init_managedDocumentRename = __esm(() => {
|
|
|
100691
100724
|
|
|
100692
100725
|
// src/cli.ts
|
|
100693
100726
|
import { existsSync as existsSync36, realpathSync as realpathSync3 } from "node:fs";
|
|
100694
|
-
import { dirname as
|
|
100727
|
+
import { dirname as dirname49, join as join116 } from "node:path";
|
|
100695
100728
|
import { fileURLToPath as fileURLToPath11, pathToFileURL as pathToFileURL3 } from "node:url";
|
|
100696
100729
|
|
|
100697
100730
|
// ../../node_modules/.bun/commander@11.1.0/node_modules/commander/esm.mjs
|
|
@@ -100746,7 +100779,7 @@ init_dist();
|
|
|
100746
100779
|
init_cliFeedback();
|
|
100747
100780
|
init_errors3();
|
|
100748
100781
|
init_exitCode();
|
|
100749
|
-
import { join as
|
|
100782
|
+
import { join as join92 } from "node:path";
|
|
100750
100783
|
|
|
100751
100784
|
// src/project/documentCaptureAvailability.ts
|
|
100752
100785
|
init_atomicFileBatch();
|
|
@@ -100755,11 +100788,11 @@ init_documentRun();
|
|
|
100755
100788
|
init_writeLock();
|
|
100756
100789
|
import { createHash as createHash23 } from "node:crypto";
|
|
100757
100790
|
import { readFile as readFile66, rm as rm19 } from "node:fs/promises";
|
|
100758
|
-
import { join as
|
|
100791
|
+
import { join as join82 } from "node:path";
|
|
100759
100792
|
import { isDeepStrictEqual } from "node:util";
|
|
100760
100793
|
function receiptPath(root, phaseId) {
|
|
100761
100794
|
const key = createHash23("sha256").update(phaseId).digest("hex");
|
|
100762
|
-
return
|
|
100795
|
+
return join82(root, ".tmp/context-runtime/document-acquisition", `${key}.json`);
|
|
100763
100796
|
}
|
|
100764
100797
|
async function identity(root, phase) {
|
|
100765
100798
|
const resolved = await resolveDocumentPhaseSource({ projectRoot: root, phase });
|
|
@@ -100791,7 +100824,7 @@ async function runDocumentCaptureWithAvailability(root, phase, capture2) {
|
|
|
100791
100824
|
retry_command: `context run ${phase.id}`,
|
|
100792
100825
|
message: source2.snapshotReady ? "Document refresh unavailable. Retain the validated registered snapshot; it is not confirmed current upstream." : "Document acquisition unavailable. Keep this source registered as a pending evidence gap; do not cite it or invent content. Unrelated work may continue."
|
|
100793
100826
|
};
|
|
100794
|
-
await applyAtomicFileBatch({ transactionRoot:
|
|
100827
|
+
await applyAtomicFileBatch({ transactionRoot: join82(root, ".tmp/context-runtime/transactions"), writes: [{ path: path2, bytes: `${JSON.stringify({ configuration, warning }, null, 2)}
|
|
100795
100828
|
` }] });
|
|
100796
100829
|
return {
|
|
100797
100830
|
kind: "document.capture.warning",
|
|
@@ -100834,7 +100867,7 @@ init_revisionDelivery();
|
|
|
100834
100867
|
init_workspacePreparation();
|
|
100835
100868
|
init_src2();
|
|
100836
100869
|
init_statusReaders();
|
|
100837
|
-
import { join as
|
|
100870
|
+
import { join as join86 } from "node:path";
|
|
100838
100871
|
|
|
100839
100872
|
// src/project/statusEvidence.ts
|
|
100840
100873
|
function evidenceWarningState(issues) {
|
|
@@ -101274,7 +101307,7 @@ async function collectProjectStatusSnapshotInternal(projectRoot, options = {}) {
|
|
|
101274
101307
|
const authoring = production && !production.delivery && (dispatchProductionStage(production, productionCapabilitiesSchema.parse({})).state !== "ended" || draftStatus.count > 0 && draftStatus.diagnostics.length === 0);
|
|
101275
101308
|
const deferDeliveryChecks = !maintenance && !localRevision && !localUpdate && !localRollback && (taskPreparation === "cleared" && !production || !!authoring);
|
|
101276
101309
|
const collectionsWithPages = new Set;
|
|
101277
|
-
const approvedPages = await countFiles(
|
|
101310
|
+
const approvedPages = await countFiles(join86(projectRoot, "knowledge"), (rel) => {
|
|
101278
101311
|
if (!isApprovedKnowledgeMarkdownPath(rel) || rel.startsWith("assets/"))
|
|
101279
101312
|
return false;
|
|
101280
101313
|
collectionsWithPages.add(rel.split("/")[0]);
|
|
@@ -101282,7 +101315,7 @@ async function collectProjectStatusSnapshotInternal(projectRoot, options = {}) {
|
|
|
101282
101315
|
});
|
|
101283
101316
|
const approvedCollections = KNOWLEDGE_COLLECTIONS.filter((collection) => collectionsWithPages.has(collection));
|
|
101284
101317
|
const closeStatus = deferDeliveryChecks ? { state: "not-checked", diagnostics: [] } : await readCloseStatus(projectRoot);
|
|
101285
|
-
const distFiles = await countFiles(
|
|
101318
|
+
const distFiles = await countFiles(join86(projectRoot, "dist"), () => true);
|
|
101286
101319
|
const verifyStatus = !deferDeliveryChecks && draftStatus.diagnostics.length === 0 ? await readVerifyStatus(projectRoot) : { issues: [], diagnostics: [] };
|
|
101287
101320
|
const revisionDocuments = localRevision ? documentSources.filter((source2) => localRevision.target.source_refs.some((ref2) => [source2.name, source2.id].filter(Boolean).some((name3) => ref2 === `${source2.type}:${name3}` || ref2 === `docs:${name3}` || ref2.startsWith(`${source2.type}:${name3}#`) || ref2.startsWith(`${source2.type}:${name3}/`)))) : documentSources;
|
|
101288
101321
|
const pendingCapture = pendingDocumentCaptureCommands({
|
|
@@ -101653,14 +101686,14 @@ function bindWorkflowExecutionContext(result, context) {
|
|
|
101653
101686
|
// src/project/workflow/workflowRouteOutput.ts
|
|
101654
101687
|
init_atomicWrite();
|
|
101655
101688
|
import { createHash as createHash24 } from "node:crypto";
|
|
101656
|
-
import { join as
|
|
101689
|
+
import { join as join87 } from "node:path";
|
|
101657
101690
|
async function workflowRouteOutput(projectRoot, route) {
|
|
101658
101691
|
if (!route)
|
|
101659
101692
|
return null;
|
|
101660
101693
|
const body = `${JSON.stringify(route, null, 2)}
|
|
101661
101694
|
`;
|
|
101662
101695
|
const digest6 = createHash24("sha256").update(body).digest("hex");
|
|
101663
|
-
const file =
|
|
101696
|
+
const file = join87(projectRoot, ".tmp/context-runtime/routes", `${digest6}.json`);
|
|
101664
101697
|
await atomicWriteFile(file, body);
|
|
101665
101698
|
return {
|
|
101666
101699
|
file,
|
|
@@ -101676,7 +101709,7 @@ async function workflowRunResultFile(projectRoot, result) {
|
|
|
101676
101709
|
const body = `${JSON.stringify(result, null, 2)}
|
|
101677
101710
|
`;
|
|
101678
101711
|
const digest6 = createHash24("sha256").update(body).digest("hex");
|
|
101679
|
-
const file =
|
|
101712
|
+
const file = join87(projectRoot, ".tmp/context-runtime/action-results", `${digest6}.run.json`);
|
|
101680
101713
|
await atomicWriteFile(file, body);
|
|
101681
101714
|
return file;
|
|
101682
101715
|
}
|
|
@@ -101820,7 +101853,7 @@ init_candidateLedger();
|
|
|
101820
101853
|
init_reviewShared();
|
|
101821
101854
|
import { mkdir as mkdir31, readFile as readFile71, writeFile as writeFile25 } from "node:fs/promises";
|
|
101822
101855
|
import { fileURLToPath as fileURLToPath6 } from "node:url";
|
|
101823
|
-
import { dirname as dirname38, isAbsolute as isAbsolute15, join as
|
|
101856
|
+
import { dirname as dirname38, isAbsolute as isAbsolute15, join as join90, resolve as resolve28 } from "node:path";
|
|
101824
101857
|
|
|
101825
101858
|
// src/project/reviewSiteModel.ts
|
|
101826
101859
|
init_siteTheme2();
|
|
@@ -101829,7 +101862,7 @@ init_unified();
|
|
|
101829
101862
|
init_remark_parse();
|
|
101830
101863
|
var import_yaml40 = __toESM(require_dist(), 1);
|
|
101831
101864
|
import { readFile as readFile70 } from "node:fs/promises";
|
|
101832
|
-
import { join as
|
|
101865
|
+
import { join as join89 } from "node:path";
|
|
101833
101866
|
import { execFile as execFile10 } from "node:child_process";
|
|
101834
101867
|
import { promisify as promisify10 } from "node:util";
|
|
101835
101868
|
import { createHash as createHash25 } from "node:crypto";
|
|
@@ -104795,9 +104828,9 @@ init_workspace();
|
|
|
104795
104828
|
|
|
104796
104829
|
// src/project/reviewFeedback.ts
|
|
104797
104830
|
import { readdir as readdir20, readFile as readFile69 } from "node:fs/promises";
|
|
104798
|
-
import { join as
|
|
104831
|
+
import { join as join88 } from "node:path";
|
|
104799
104832
|
async function readPendingReviewFeedback(root2, candidates) {
|
|
104800
|
-
const directory =
|
|
104833
|
+
const directory = join88(root2, ".tmp/context-runtime/review-feedback");
|
|
104801
104834
|
let files;
|
|
104802
104835
|
try {
|
|
104803
104836
|
files = await readdir20(directory);
|
|
@@ -104810,7 +104843,7 @@ async function readPendingReviewFeedback(root2, candidates) {
|
|
|
104810
104843
|
const results = new Map;
|
|
104811
104844
|
const receipts = [];
|
|
104812
104845
|
for (const file of files.filter((f) => /^[a-f0-9]+\.json$/u.test(f)).sort()) {
|
|
104813
|
-
const receipt2 = JSON.parse(await readFile69(
|
|
104846
|
+
const receipt2 = JSON.parse(await readFile69(join88(directory, file), "utf8"));
|
|
104814
104847
|
receipts.push(receipt2);
|
|
104815
104848
|
}
|
|
104816
104849
|
for (const receipt2 of receipts.sort((a, b) => a.created_at.localeCompare(b.created_at))) {
|
|
@@ -104930,7 +104963,7 @@ async function optional2(path3) {
|
|
|
104930
104963
|
async function reviewSiteBaselineHash(root2, reviewedPaths) {
|
|
104931
104964
|
const files = await readApprovedMarkdownFiles(root2);
|
|
104932
104965
|
return hash3(JSON.stringify([
|
|
104933
|
-
await optional2(
|
|
104966
|
+
await optional2(join89(root2, "src/knowledge-map.yaml")) ?? null,
|
|
104934
104967
|
files.map((f) => [f.relPath, reviewedPaths.includes(f.relPath) ? hash3(f.content) : title(f.content, f.relPath)]).sort((a, b) => a[0].localeCompare(b[0]))
|
|
104935
104968
|
]));
|
|
104936
104969
|
}
|
|
@@ -105043,9 +105076,9 @@ async function collectReviewSiteModel(root2, candidates) {
|
|
|
105043
105076
|
for (const [i2, p] of unplaced.entries())
|
|
105044
105077
|
nodes.push({ key: `review-page-${p.id}`, parent: "review-unplaced", title: p.title, order: i2, page: p.id, change: p.change });
|
|
105045
105078
|
}
|
|
105046
|
-
const pkgText = await optional2(
|
|
105079
|
+
const pkgText = await optional2(join89(root2, "package.json"));
|
|
105047
105080
|
const pkg = pkgText ? JSON.parse(pkgText) : {};
|
|
105048
|
-
const project = await optional2(
|
|
105081
|
+
const project = await optional2(join89(root2, "src/index.ts")) === undefined ? undefined : await loadContextProjectModule(root2);
|
|
105049
105082
|
const siteTitle = project?.project.packages.flatMap((p) => p.kind === "package.kb" && p.site?.title ? [p.site.title] : [])[0];
|
|
105050
105083
|
const sitePackages = project?.project.packages.flatMap((p) => p.kind === "package.kb" && p.site ? [p.site] : []) ?? [];
|
|
105051
105084
|
const themeCss = siteThemeVariables(await resolveSiteTheme(root2, sitePackages.length === 1 ? sitePackages[0]?.theme : undefined));
|
|
@@ -105214,7 +105247,7 @@ article.review-new-page .context-diagram-shell,article .changed .context-diagram
|
|
|
105214
105247
|
`;
|
|
105215
105248
|
|
|
105216
105249
|
// src/project/reviewHtml.ts
|
|
105217
|
-
var REVIEW_HTML_ROOT =
|
|
105250
|
+
var REVIEW_HTML_ROOT = join90(".tmp", "context-runtime", "review");
|
|
105218
105251
|
async function collectReviewCandidates(projectRoot, collection) {
|
|
105219
105252
|
const rows = await readCandidateRecords(projectRoot);
|
|
105220
105253
|
const draftRows = rows.filter((row) => row.collection === collection && row.status === "draft");
|
|
@@ -105247,7 +105280,7 @@ ${diagramScript ? `<script>${diagramScript}</script>` : ""}<script>const DATA=${
|
|
|
105247
105280
|
}
|
|
105248
105281
|
function resolveOutputPath(projectRoot, outPath, reviewScope) {
|
|
105249
105282
|
if (outPath === undefined)
|
|
105250
|
-
return
|
|
105283
|
+
return join90(projectRoot, REVIEW_HTML_ROOT, `${reviewScope}.html`);
|
|
105251
105284
|
return isAbsolute15(outPath) ? outPath : resolve28(projectRoot, outPath);
|
|
105252
105285
|
}
|
|
105253
105286
|
async function writeReviewHtml(input) {
|
|
@@ -105263,7 +105296,7 @@ async function writeReviewHtml(input) {
|
|
|
105263
105296
|
if (model.pages.some((page) => page.html.includes('class="language-mermaid"'))) {
|
|
105264
105297
|
const here = dirname38(fileURLToPath6(import.meta.url));
|
|
105265
105298
|
try {
|
|
105266
|
-
diagramScript = await readFile71(
|
|
105299
|
+
diagramScript = await readFile71(join90(here, "browser/diagrams.js"), "utf8");
|
|
105267
105300
|
} catch (error) {
|
|
105268
105301
|
if (error.code !== "ENOENT")
|
|
105269
105302
|
throw error;
|
|
@@ -105285,7 +105318,7 @@ init_dist();
|
|
|
105285
105318
|
init_atomicWrite();
|
|
105286
105319
|
init_reviewShared();
|
|
105287
105320
|
import { mkdir as mkdir32, readFile as readFile72 } from "node:fs/promises";
|
|
105288
|
-
import { join as
|
|
105321
|
+
import { join as join91 } from "node:path";
|
|
105289
105322
|
var REVIEW_BATCH_MAX_CANDIDATES = 6;
|
|
105290
105323
|
var REVIEW_BATCH_MAX_BYTES = 512 * 1024;
|
|
105291
105324
|
async function readerPurposes(projectRoot, sources) {
|
|
@@ -105365,11 +105398,11 @@ async function materializeCurrentReviewBatchSet(input) {
|
|
|
105365
105398
|
const batches = buildCurrentReviewBatchDocuments(input.candidates);
|
|
105366
105399
|
const setDigest = digestText(batches.map((batch) => `${batch.task_key}:${batch.digest}`).join(`
|
|
105367
105400
|
`));
|
|
105368
|
-
const root2 =
|
|
105401
|
+
const root2 = join91(input.projectRoot, ".tmp", "context-runtime", "review", `current-${setDigest.slice("sha256:".length)}`);
|
|
105369
105402
|
await mkdir32(root2, { recursive: true });
|
|
105370
105403
|
const entries2 = [];
|
|
105371
105404
|
for (const batch of batches) {
|
|
105372
|
-
const path4 =
|
|
105405
|
+
const path4 = join91(input.projectRoot, ".tmp", "context-runtime", "review", `${batch.task_key}-${batch.digest.slice("sha256:".length)}.md`);
|
|
105373
105406
|
const existing = await readFile72(path4, "utf8").catch((error) => {
|
|
105374
105407
|
if (error.code === "ENOENT")
|
|
105375
105408
|
return;
|
|
@@ -105423,7 +105456,7 @@ async function materializeCurrentReviewBatchSet(input) {
|
|
|
105423
105456
|
].join(`
|
|
105424
105457
|
`);
|
|
105425
105458
|
const digest6 = digestText(content3);
|
|
105426
|
-
const path3 =
|
|
105459
|
+
const path3 = join91(root2, "index.md");
|
|
105427
105460
|
await atomicWriteFile(path3, `${content3}
|
|
105428
105461
|
`);
|
|
105429
105462
|
return {
|
|
@@ -105456,11 +105489,11 @@ function shellQuote6(value) {
|
|
|
105456
105489
|
}
|
|
105457
105490
|
function receiptSetPath(receipts) {
|
|
105458
105491
|
const token = digestText(JSON.stringify(receipts)).slice("sha256:".length);
|
|
105459
|
-
return
|
|
105492
|
+
return join92(".tmp", "context-runtime", "workflow", "read-receipts", `${token}.json`);
|
|
105460
105493
|
}
|
|
105461
105494
|
async function writeReceiptContinuation(input) {
|
|
105462
105495
|
const path3 = receiptSetPath(input.receipts);
|
|
105463
|
-
const absolutePath =
|
|
105496
|
+
const absolutePath = join92(input.projectRoot, path3);
|
|
105464
105497
|
await writeJsonAtomic(absolutePath, input.receipts);
|
|
105465
105498
|
const contextCommand = input.managed ? [
|
|
105466
105499
|
"context",
|
|
@@ -105555,7 +105588,7 @@ async function materializeContextWorkflowResource(input) {
|
|
|
105555
105588
|
const resourceId = workflowResourceId(input.resourceId);
|
|
105556
105589
|
const content3 = renderContextWorkflowResource(resourceId, status);
|
|
105557
105590
|
const location = await materializeResource(await loadContextWorkflowProvider(), resourceId, {
|
|
105558
|
-
cache:
|
|
105591
|
+
cache: join92(found.projectRoot, ".tmp", "context-runtime", "workflow", "resources"),
|
|
105559
105592
|
workspace: found.projectRoot,
|
|
105560
105593
|
revision: input.revision,
|
|
105561
105594
|
input: {
|
|
@@ -105587,7 +105620,7 @@ async function materializeContextWorkflowResource(input) {
|
|
|
105587
105620
|
receipts: afterReadReceipts
|
|
105588
105621
|
});
|
|
105589
105622
|
const directResources = (status.workflow.current?.resources.required ?? []).filter((resource) => resource.read_state === "read-required" && resource.path !== undefined && resource.digest !== undefined);
|
|
105590
|
-
const afterReadCommand = directResources.length === 0 ? continuation.command : `context resource acknowledge-current --revision ${shellQuote6(input.revision)}${authorityCommandOptions(authorities, "resource")} --resource-receipts ${shellQuote6(`@${
|
|
105623
|
+
const afterReadCommand = directResources.length === 0 ? continuation.command : `context resource acknowledge-current --revision ${shellQuote6(input.revision)}${authorityCommandOptions(authorities, "resource")} --resource-receipts ${shellQuote6(`@${join92(found.projectRoot, continuation.path)}`)} --format json`;
|
|
105591
105624
|
return {
|
|
105592
105625
|
protocol: "context.workflow.resource.v1",
|
|
105593
105626
|
id: resourceId,
|
|
@@ -105648,14 +105681,14 @@ async function acknowledgeCurrentWorkflowResources(input) {
|
|
|
105648
105681
|
const reevaluated = await reevaluateProjectStatusWorkflow({
|
|
105649
105682
|
snapshot,
|
|
105650
105683
|
resourceReceipts: normalizedReceipts,
|
|
105651
|
-
resourceReceiptsReference: `@${
|
|
105684
|
+
resourceReceiptsReference: `@${join92(found.projectRoot, continuation.path)}`
|
|
105652
105685
|
});
|
|
105653
105686
|
return {
|
|
105654
105687
|
...reevaluated,
|
|
105655
105688
|
resourceAcknowledgement: {
|
|
105656
105689
|
protocol: "context.workflow.resource-receipts.v1",
|
|
105657
105690
|
acknowledged: directResources.length,
|
|
105658
|
-
receiptReference: `@${
|
|
105691
|
+
receiptReference: `@${join92(found.projectRoot, continuation.path)}`
|
|
105659
105692
|
}
|
|
105660
105693
|
};
|
|
105661
105694
|
}
|
|
@@ -105702,8 +105735,8 @@ init_errors3();
|
|
|
105702
105735
|
init_exitCode();
|
|
105703
105736
|
init_workspace();
|
|
105704
105737
|
import { readFile as readFile73 } from "node:fs/promises";
|
|
105705
|
-
import { isAbsolute as isAbsolute16, join as
|
|
105706
|
-
var RECEIPT_DIRECTORY =
|
|
105738
|
+
import { isAbsolute as isAbsolute16, join as join93, sep as sep6, resolve as resolve29 } from "node:path";
|
|
105739
|
+
var RECEIPT_DIRECTORY = join93(".tmp", "context-runtime", "workflow", "read-receipts");
|
|
105707
105740
|
function workflowResourceReceiptCwd(value, cwd) {
|
|
105708
105741
|
if (value === undefined || !value.startsWith("@"))
|
|
105709
105742
|
return cwd;
|
|
@@ -105974,14 +106007,14 @@ function compactJsonResult(result, verbose) {
|
|
|
105974
106007
|
// src/project/runLog.ts
|
|
105975
106008
|
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
105976
106009
|
import { mkdir as mkdir33, writeFile as writeFile26 } from "node:fs/promises";
|
|
105977
|
-
import { dirname as dirname39, join as
|
|
106010
|
+
import { dirname as dirname39, join as join96 } from "node:path";
|
|
105978
106011
|
var createPhaseRunId = () => {
|
|
105979
106012
|
const timestamp = new Date().toISOString().replace(/[-:.TZ]/gu, "");
|
|
105980
106013
|
return `run_${timestamp}_${randomUUID5().slice(0, 8)}`;
|
|
105981
106014
|
};
|
|
105982
106015
|
async function writePhaseRunLog(input) {
|
|
105983
|
-
const relPath =
|
|
105984
|
-
const absPath =
|
|
106016
|
+
const relPath = join96(".tmp", "context-runtime", "runs", `${input.runId}.json`);
|
|
106017
|
+
const absPath = join96(input.projectRoot, relPath);
|
|
105985
106018
|
await mkdir33(dirname39(absPath), { recursive: true });
|
|
105986
106019
|
await writeFile26(absPath, `${JSON.stringify({
|
|
105987
106020
|
run_id: input.runId,
|
|
@@ -107081,7 +107114,7 @@ init_reviewApplyIndexer();
|
|
|
107081
107114
|
init_approvedKnowledgeSnapshots();
|
|
107082
107115
|
import { existsSync as existsSync25 } from "node:fs";
|
|
107083
107116
|
import { readFile as readFile76 } from "node:fs/promises";
|
|
107084
|
-
import { join as
|
|
107117
|
+
import { join as join97 } from "node:path";
|
|
107085
107118
|
|
|
107086
107119
|
// src/project/reviewCandidateAuthority.ts
|
|
107087
107120
|
init_src2();
|
|
@@ -107144,7 +107177,7 @@ async function prepareApprovedPage(input) {
|
|
|
107144
107177
|
next: "Refresh the current production or article revision, then reopen Review before approval."
|
|
107145
107178
|
});
|
|
107146
107179
|
}
|
|
107147
|
-
const relPath =
|
|
107180
|
+
const relPath = join97("knowledge", input.record.path);
|
|
107148
107181
|
const existingView = findApprovedPageForArticleId(input.record.indexer_candidate.artifact_ref, input.approvedPageIndex);
|
|
107149
107182
|
const previousPath = input.record.approved_revision?.previous_path;
|
|
107150
107183
|
if (previousPath !== undefined && (!isSafeKnowledgeTargetPath(previousPath.split("/")[0], previousPath) || previousPath.includes("\\")))
|
|
@@ -107159,13 +107192,13 @@ async function prepareApprovedPage(input) {
|
|
|
107159
107192
|
next: "Resolve the approved page path migration explicitly before approving this candidate."
|
|
107160
107193
|
});
|
|
107161
107194
|
}
|
|
107162
|
-
const absPath =
|
|
107195
|
+
const absPath = join97(input.projectRoot, relPath);
|
|
107163
107196
|
const existing = existsSync25(absPath) ? await readFile76(absPath, "utf8") : undefined;
|
|
107164
107197
|
let previous3;
|
|
107165
107198
|
if (previousPath !== undefined) {
|
|
107166
107199
|
if (existing !== undefined || existingView?.relPath !== `knowledge/${previousPath}`)
|
|
107167
107200
|
throw new TypeError("Page move destination or original identity changed; refresh its revision.");
|
|
107168
|
-
previous3 = { path: `knowledge/${previousPath}`, content: await readFile76(
|
|
107201
|
+
previous3 = { path: `knowledge/${previousPath}`, content: await readFile76(join97(input.projectRoot, "knowledge", previousPath), "utf8") };
|
|
107169
107202
|
}
|
|
107170
107203
|
if (input.record.approved_revision !== undefined) {
|
|
107171
107204
|
const base = previous3?.content ?? existing;
|
|
@@ -107212,7 +107245,7 @@ async function prepareApprovedPage(input) {
|
|
|
107212
107245
|
}
|
|
107213
107246
|
async function readProjectFileMaybe(projectRoot, relPath) {
|
|
107214
107247
|
try {
|
|
107215
|
-
return await readFile76(
|
|
107248
|
+
return await readFile76(join97(projectRoot, relPath), "utf8");
|
|
107216
107249
|
} catch (error) {
|
|
107217
107250
|
if (error !== null && typeof error === "object" && "code" in error && error.code === "ENOENT") {
|
|
107218
107251
|
return;
|
|
@@ -107435,7 +107468,7 @@ async function applyReviewDecisions(input) {
|
|
|
107435
107468
|
});
|
|
107436
107469
|
}
|
|
107437
107470
|
seenApprovedIds.set(approvedRef, row.candidate_id);
|
|
107438
|
-
const approvedPath =
|
|
107471
|
+
const approvedPath = join97("knowledge", row.path);
|
|
107439
107472
|
const previousPathCandidate = seenApprovedPaths.get(knowledgeTargetPathKey(approvedPath));
|
|
107440
107473
|
if (previousPathCandidate !== undefined) {
|
|
107441
107474
|
throw new ContextError(ExitCode.UserError, `multiple approved review decisions target the same knowledge path: ${approvedPath}`, {
|
|
@@ -107485,7 +107518,7 @@ async function applyReviewDecisions(input) {
|
|
|
107485
107518
|
for (const path3 of approvedPageIndex.byRelPath.keys()) {
|
|
107486
107519
|
if (pagesToWrite.some((page) => page.relPath === path3 || page.previous?.path === path3))
|
|
107487
107520
|
continue;
|
|
107488
|
-
const before = await readFile76(
|
|
107521
|
+
const before = await readFile76(join97(input.projectRoot, path3), "utf8");
|
|
107489
107522
|
const local = path3.replace(/^knowledge\//u, "");
|
|
107490
107523
|
const after = moveKnowledgeLinkTargets2(before, local, local, moved);
|
|
107491
107524
|
navigationTargets.push(reviewFileTarget({ path: path3, baseContent: before, targetContent: after }));
|
|
@@ -107569,12 +107602,12 @@ init_candidateLedger();
|
|
|
107569
107602
|
|
|
107570
107603
|
// src/project/localHtmlReport.ts
|
|
107571
107604
|
import { execFile as execFile11 } from "node:child_process";
|
|
107572
|
-
import { isAbsolute as isAbsolute17, join as
|
|
107605
|
+
import { isAbsolute as isAbsolute17, join as join98 } from "node:path";
|
|
107573
107606
|
import { pathToFileURL as pathToFileURL2 } from "node:url";
|
|
107574
107607
|
import { promisify as promisify11 } from "node:util";
|
|
107575
107608
|
var execFileAsync5 = promisify11(execFile11);
|
|
107576
107609
|
function htmlReportReference(input) {
|
|
107577
|
-
const absolutePath = isAbsolute17(input.path) ? input.path :
|
|
107610
|
+
const absolutePath = isAbsolute17(input.path) ? input.path : join98(input.projectRoot, input.path);
|
|
107578
107611
|
return {
|
|
107579
107612
|
format: "html",
|
|
107580
107613
|
path: input.path,
|
|
@@ -108598,7 +108631,7 @@ init_maintenanceStorage();
|
|
|
108598
108631
|
init_productionFeedback();
|
|
108599
108632
|
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
108600
108633
|
import { readFile as readFile79 } from "node:fs/promises";
|
|
108601
|
-
import { join as
|
|
108634
|
+
import { join as join99 } from "node:path";
|
|
108602
108635
|
async function beginProductionRevision(input) {
|
|
108603
108636
|
return withProductionFeedback({ operation: "revision" }, () => withProjectWriteLock(input.projectRoot, "production-revision", async () => {
|
|
108604
108637
|
await recoverDurableMultiFileTransactions(input.projectRoot);
|
|
@@ -108637,7 +108670,7 @@ async function beginProductionRevision(input) {
|
|
|
108637
108670
|
const formal = approved.byPath.get(path3);
|
|
108638
108671
|
if (!prior && !formal)
|
|
108639
108672
|
throw invalid2("Write the current task first; there is no article draft to revise yet.");
|
|
108640
|
-
const markdown = prior?.body ?? await readFile79(await safeProjectTarget(input.projectRoot,
|
|
108673
|
+
const markdown = prior?.body ?? await readFile79(await safeProjectTarget(input.projectRoot, join99("knowledge", path3)), "utf8");
|
|
108641
108674
|
const sections = prior?.indexer_candidate.sections.map((section) => ({ id: section.section_key, references: section.references })) ?? formal?.sections;
|
|
108642
108675
|
const sources = [];
|
|
108643
108676
|
for (const source2 of owner.sources) {
|
|
@@ -109277,7 +109310,7 @@ init_atomicWrite();
|
|
|
109277
109310
|
var import_yaml44 = __toESM(require_dist(), 1);
|
|
109278
109311
|
import { Buffer as Buffer4 } from "node:buffer";
|
|
109279
109312
|
import { createHash as createHash31 } from "node:crypto";
|
|
109280
|
-
import { join as
|
|
109313
|
+
import { join as join103 } from "node:path";
|
|
109281
109314
|
var INLINE_LIMIT = 16 * 1024;
|
|
109282
109315
|
function record4(value) {
|
|
109283
109316
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : undefined;
|
|
@@ -109303,8 +109336,8 @@ async function prepareActionCompletionOutput(input) {
|
|
|
109303
109336
|
if (production && Buffer4.byteLength(full) <= INLINE_LIMIT)
|
|
109304
109337
|
return input.result;
|
|
109305
109338
|
const digest6 = createHash31("sha256").update(full).digest("hex");
|
|
109306
|
-
const root2 =
|
|
109307
|
-
const resultFile =
|
|
109339
|
+
const root2 = join103(input.projectRoot, ".tmp/context-runtime/action-results");
|
|
109340
|
+
const resultFile = join103(root2, `${digest6}.json`);
|
|
109308
109341
|
await atomicWriteFile(resultFile, full);
|
|
109309
109342
|
if (production)
|
|
109310
109343
|
return {
|
|
@@ -109315,7 +109348,7 @@ async function prepareActionCompletionOutput(input) {
|
|
|
109315
109348
|
...pick(result, ["next", "next_preparation"])
|
|
109316
109349
|
};
|
|
109317
109350
|
const next2 = record4(result.next) ?? record4(record4(result.workflow)?.current) ?? record4(record4(result.continuation)?.next);
|
|
109318
|
-
const nextFile = next2 === undefined ? undefined :
|
|
109351
|
+
const nextFile = next2 === undefined ? undefined : join103(root2, `${digest6}.next.json`);
|
|
109319
109352
|
if (nextFile !== undefined)
|
|
109320
109353
|
await atomicWriteFile(nextFile, serializeActionCompletion(next2, "json"));
|
|
109321
109354
|
const outcomes = (Array.isArray(result.outcomes) ? result.outcomes : []).map(record4).filter((item) => item !== undefined);
|
|
@@ -109722,7 +109755,7 @@ init_cliFeedback();
|
|
|
109722
109755
|
import { existsSync as existsSync27 } from "node:fs";
|
|
109723
109756
|
import { readdir as readdir26, rm as rm21 } from "node:fs/promises";
|
|
109724
109757
|
import { homedir } from "node:os";
|
|
109725
|
-
import { join as
|
|
109758
|
+
import { join as join104 } from "node:path";
|
|
109726
109759
|
var ORPHAN_MARKER = ".orphaned_at";
|
|
109727
109760
|
var CLAUDE_PLUGIN_CACHE_ROOT_ENV = "C4A_CLAUDE_PLUGIN_CACHE_ROOT";
|
|
109728
109761
|
var CLAUDE_PLUGIN_CACHE_HOME_ENV = "C4A_CLAUDE_PLUGIN_CACHE_HOME";
|
|
@@ -109739,19 +109772,19 @@ async function cleanClaudePluginCache(opts = {}) {
|
|
|
109739
109772
|
for (const mp of marketplaces) {
|
|
109740
109773
|
if (!mp.isDirectory())
|
|
109741
109774
|
continue;
|
|
109742
|
-
const mpDir =
|
|
109775
|
+
const mpDir = join104(cacheRoot, mp.name);
|
|
109743
109776
|
const plugins = await readdir26(mpDir, { withFileTypes: true });
|
|
109744
109777
|
for (const pl of plugins) {
|
|
109745
109778
|
if (!pl.isDirectory())
|
|
109746
109779
|
continue;
|
|
109747
|
-
const plDir =
|
|
109780
|
+
const plDir = join104(mpDir, pl.name);
|
|
109748
109781
|
const versions = await readdir26(plDir, { withFileTypes: true });
|
|
109749
109782
|
for (const ver of versions) {
|
|
109750
109783
|
if (!ver.isDirectory())
|
|
109751
109784
|
continue;
|
|
109752
109785
|
scanned += 1;
|
|
109753
|
-
const verDir =
|
|
109754
|
-
const markerPath =
|
|
109786
|
+
const verDir = join104(plDir, ver.name);
|
|
109787
|
+
const markerPath = join104(verDir, ORPHAN_MARKER);
|
|
109755
109788
|
if (!existsSync27(markerPath))
|
|
109756
109789
|
continue;
|
|
109757
109790
|
const label2 = `${mp.name}/${pl.name}/${ver.name}`;
|
|
@@ -109783,7 +109816,7 @@ function resolveClaudePluginCacheRoot(opts) {
|
|
|
109783
109816
|
if (explicitRoot)
|
|
109784
109817
|
return explicitRoot;
|
|
109785
109818
|
const home = opts.home ?? process.env[CLAUDE_PLUGIN_CACHE_HOME_ENV] ?? homedir();
|
|
109786
|
-
return
|
|
109819
|
+
return join104(home, ".claude", "plugins", "cache");
|
|
109787
109820
|
}
|
|
109788
109821
|
async function isEmptyDir(dir) {
|
|
109789
109822
|
try {
|
|
@@ -109815,13 +109848,13 @@ init_exitCode();
|
|
|
109815
109848
|
|
|
109816
109849
|
// src/lib/packageVersion.ts
|
|
109817
109850
|
import { existsSync as existsSync28, readFileSync as readFileSync9 } from "node:fs";
|
|
109818
|
-
import { dirname as dirname42, join as
|
|
109851
|
+
import { dirname as dirname42, join as join105 } from "node:path";
|
|
109819
109852
|
import { fileURLToPath as fileURLToPath8 } from "node:url";
|
|
109820
109853
|
function readPackageVersion() {
|
|
109821
109854
|
try {
|
|
109822
109855
|
let dir = dirname42(fileURLToPath8(import.meta.url));
|
|
109823
109856
|
for (let depth = 0;depth < 8; depth += 1) {
|
|
109824
|
-
const packagePath =
|
|
109857
|
+
const packagePath = join105(dir, "package.json");
|
|
109825
109858
|
if (existsSync28(packagePath)) {
|
|
109826
109859
|
const parsed = JSON.parse(readFileSync9(packagePath, "utf8"));
|
|
109827
109860
|
if (typeof parsed.version === "string" && parsed.version.length > 0) {
|
|
@@ -110208,14 +110241,14 @@ init_src2();
|
|
|
110208
110241
|
init_documentCapture();
|
|
110209
110242
|
import { existsSync as existsSync30 } from "node:fs";
|
|
110210
110243
|
import { readFile as readFile86 } from "node:fs/promises";
|
|
110211
|
-
import { join as
|
|
110244
|
+
import { join as join107 } from "node:path";
|
|
110212
110245
|
|
|
110213
110246
|
// src/project/sourceCommandViews.ts
|
|
110214
110247
|
init_documentSiteDetection();
|
|
110215
110248
|
init_workspace();
|
|
110216
110249
|
init_documentBatchManifest();
|
|
110217
110250
|
import { readFile as readFile85 } from "node:fs/promises";
|
|
110218
|
-
import { join as
|
|
110251
|
+
import { join as join106 } from "node:path";
|
|
110219
110252
|
function repoSourceAgentView(source2) {
|
|
110220
110253
|
return {
|
|
110221
110254
|
id: source2.id ?? source2.name,
|
|
@@ -110276,7 +110309,7 @@ async function fileSourceAgentViewWithNextAction(input) {
|
|
|
110276
110309
|
};
|
|
110277
110310
|
}
|
|
110278
110311
|
function documentSourceManifestPath(source2) {
|
|
110279
|
-
return source2.snapshot?.manifest ??
|
|
110312
|
+
return source2.snapshot?.manifest ?? join106(source2.materializedAt, "manifest.json");
|
|
110280
110313
|
}
|
|
110281
110314
|
async function fileSourceDocumentSiteHint(input) {
|
|
110282
110315
|
const detection = await detectDocumentSiteFiles({
|
|
@@ -110286,7 +110319,7 @@ async function fileSourceDocumentSiteHint(input) {
|
|
|
110286
110319
|
let snapshotConfigured = false;
|
|
110287
110320
|
const manifest = documentSourceManifestPath(input.source);
|
|
110288
110321
|
try {
|
|
110289
|
-
const parsed = parseDocumentSnapshotForSource(JSON.parse(await readFile85(
|
|
110322
|
+
const parsed = parseDocumentSnapshotForSource(JSON.parse(await readFile85(join106(input.projectRoot, manifest), "utf8")), input.source.name);
|
|
110290
110323
|
snapshotConfigured = manifestUsesMdxJsonDocs(parsed);
|
|
110291
110324
|
} catch {
|
|
110292
110325
|
snapshotConfigured = false;
|
|
@@ -110319,11 +110352,11 @@ async function larkSourceAgentViewWithNextAction(input) {
|
|
|
110319
110352
|
init_documentBatchManifest();
|
|
110320
110353
|
init_documentSnapshotFidelity();
|
|
110321
110354
|
function documentSourceManifestPath2(source2) {
|
|
110322
|
-
return source2.snapshot?.manifest ??
|
|
110355
|
+
return source2.snapshot?.manifest ?? join107(source2.materializedAt, "manifest.json");
|
|
110323
110356
|
}
|
|
110324
110357
|
async function documentSnapshotState(input) {
|
|
110325
110358
|
const manifest = documentSourceManifestPath2(input.source);
|
|
110326
|
-
const manifestPath =
|
|
110359
|
+
const manifestPath = join107(input.projectRoot, manifest);
|
|
110327
110360
|
if (!existsSync30(manifestPath)) {
|
|
110328
110361
|
return {
|
|
110329
110362
|
snapshotReady: false,
|
|
@@ -110402,7 +110435,7 @@ async function documentSnapshotState(input) {
|
|
|
110402
110435
|
const missing = [
|
|
110403
110436
|
...parsed.files.map((file) => file.path),
|
|
110404
110437
|
...(parsed.assets ?? []).filter((asset) => asset.content_hash !== undefined).map((asset) => asset.path)
|
|
110405
|
-
].find((path3) => !existsSync30(
|
|
110438
|
+
].find((path3) => !existsSync30(join107(input.projectRoot, input.source.materializedAt, path3)));
|
|
110406
110439
|
if (missing !== undefined) {
|
|
110407
110440
|
return {
|
|
110408
110441
|
snapshotReady: false,
|
|
@@ -110504,7 +110537,7 @@ init_exitCode();
|
|
|
110504
110537
|
var import_yaml47 = __toESM(require_dist(), 1);
|
|
110505
110538
|
import { createHash as createHash32 } from "node:crypto";
|
|
110506
110539
|
import { readFile as readFile87, realpath as realpath11 } from "node:fs/promises";
|
|
110507
|
-
import { basename as basename12, extname as extname15, isAbsolute as isAbsolute20, join as
|
|
110540
|
+
import { basename as basename12, extname as extname15, isAbsolute as isAbsolute20, join as join108, relative as relative27, resolve as resolve35 } from "node:path";
|
|
110508
110541
|
init_writeLock();
|
|
110509
110542
|
var SOURCE_NAME_PATTERN3 = /^[a-z0-9][a-z0-9._-]*$/u;
|
|
110510
110543
|
function isDateSourceNamespace(value) {
|
|
@@ -110600,7 +110633,7 @@ function assertSafeFileInclude(value) {
|
|
|
110600
110633
|
}
|
|
110601
110634
|
async function readRegistryDocument(projectRoot, registryPath2) {
|
|
110602
110635
|
try {
|
|
110603
|
-
const content3 = await readFile87(
|
|
110636
|
+
const content3 = await readFile87(join108(projectRoot, registryPath2), "utf8");
|
|
110604
110637
|
return content3.trim().length === 0 ? { sources: [] } : import_yaml47.default.parse(content3);
|
|
110605
110638
|
} catch (error) {
|
|
110606
110639
|
if (error instanceof Error && "code" in error && error.code === "ENOENT")
|
|
@@ -110718,7 +110751,7 @@ async function addFileSourceUnlocked(input) {
|
|
|
110718
110751
|
const record6 = entry2;
|
|
110719
110752
|
return record6.name !== input.name && record6.id !== input.name;
|
|
110720
110753
|
}), nextEntry];
|
|
110721
|
-
await atomicWriteFile(
|
|
110754
|
+
await atomicWriteFile(join108(input.projectRoot, DEFAULT_FILE_SOURCES_REGISTRY_PATH), import_yaml47.default.stringify({ sources: nextSources }));
|
|
110722
110755
|
const updated = await loadSourcesRegistry({ rootDir: input.projectRoot });
|
|
110723
110756
|
const entry = updated.files.find((source2) => source2.name === input.name || source2.id === input.name);
|
|
110724
110757
|
if (entry === undefined) {
|
|
@@ -110774,7 +110807,7 @@ async function addLarkSourceUnlocked(input) {
|
|
|
110774
110807
|
const record6 = entry2;
|
|
110775
110808
|
return record6.name !== input.name && record6.id !== input.name;
|
|
110776
110809
|
}), nextEntry];
|
|
110777
|
-
await atomicWriteFile(
|
|
110810
|
+
await atomicWriteFile(join108(input.projectRoot, DEFAULT_LARK_SOURCES_REGISTRY_PATH), import_yaml47.default.stringify({ sources: nextSources }));
|
|
110778
110811
|
const updated = await loadSourcesRegistry({ rootDir: input.projectRoot });
|
|
110779
110812
|
const entry = updated.larks.find((source2) => source2.name === input.name || source2.id === input.name);
|
|
110780
110813
|
if (entry === undefined) {
|
|
@@ -110979,7 +111012,7 @@ var import_yaml48 = __toESM(require_dist(), 1);
|
|
|
110979
111012
|
import { existsSync as existsSync31 } from "node:fs";
|
|
110980
111013
|
import { createHash as createHash33 } from "node:crypto";
|
|
110981
111014
|
import { readFile as readFile88, readdir as readdir27, rm as rm23 } from "node:fs/promises";
|
|
110982
|
-
import { isAbsolute as isAbsolute21, join as
|
|
111015
|
+
import { isAbsolute as isAbsolute21, join as join109, relative as relative28, resolve as resolve36, sep as sep8 } from "node:path";
|
|
110983
111016
|
function sourceIdentity(source2) {
|
|
110984
111017
|
if (source2.kind === "source.collection")
|
|
110985
111018
|
return;
|
|
@@ -111011,7 +111044,7 @@ function collectStrings(value, output) {
|
|
|
111011
111044
|
}
|
|
111012
111045
|
}
|
|
111013
111046
|
async function yamlReferences(input) {
|
|
111014
|
-
const absolutePath =
|
|
111047
|
+
const absolutePath = join109(input.projectRoot, input.path);
|
|
111015
111048
|
if (!existsSync31(absolutePath))
|
|
111016
111049
|
return false;
|
|
111017
111050
|
const parsed = import_yaml48.default.parse(await readFile88(absolutePath, "utf8"));
|
|
@@ -111140,7 +111173,7 @@ async function registryRemovalWrite(projectRoot, source2) {
|
|
|
111140
111173
|
const path3 = registryPath2(source2.type);
|
|
111141
111174
|
if (path3 === null)
|
|
111142
111175
|
return;
|
|
111143
|
-
const absolutePath =
|
|
111176
|
+
const absolutePath = join109(projectRoot, path3);
|
|
111144
111177
|
const document4 = existsSync31(absolutePath) ? import_yaml48.default.parse(await readFile88(absolutePath, "utf8")) : { sources: [] };
|
|
111145
111178
|
return {
|
|
111146
111179
|
path: absolutePath,
|
|
@@ -111159,7 +111192,7 @@ function safeManagedMaterializedPath(projectRoot, source2) {
|
|
|
111159
111192
|
return absolute;
|
|
111160
111193
|
}
|
|
111161
111194
|
function safeManagedManifestPath(projectRoot, source2) {
|
|
111162
|
-
const manifest = source2.manifest ??
|
|
111195
|
+
const manifest = source2.manifest ?? join109(source2.materializedAt, "manifest.json");
|
|
111163
111196
|
if (isAbsolute21(manifest))
|
|
111164
111197
|
throw unsafeOwnership(source2, manifest);
|
|
111165
111198
|
const absolute = resolve36(projectRoot, manifest);
|
|
@@ -111321,7 +111354,7 @@ function publicRemovalResult(plan, action) {
|
|
|
111321
111354
|
};
|
|
111322
111355
|
}
|
|
111323
111356
|
async function pruneExtractRuntime(projectRoot, source2) {
|
|
111324
|
-
const fingerprintPath =
|
|
111357
|
+
const fingerprintPath = join109(projectRoot, ".tmp/context-runtime/extract/source-fingerprints.json");
|
|
111325
111358
|
const removedPhaseIds = new Set;
|
|
111326
111359
|
if (existsSync31(fingerprintPath)) {
|
|
111327
111360
|
const parsed = JSON.parse(await readFile88(fingerprintPath, "utf8"));
|
|
@@ -111338,14 +111371,14 @@ async function pruneExtractRuntime(projectRoot, source2) {
|
|
|
111338
111371
|
await atomicWriteFile(fingerprintPath, `${JSON.stringify({ ...parsed, phases: next2 }, null, 2)}
|
|
111339
111372
|
`);
|
|
111340
111373
|
}
|
|
111341
|
-
const phaseOwnershipPath =
|
|
111374
|
+
const phaseOwnershipPath = join109(projectRoot, ".tmp/context-runtime/extract/custom-phase-candidates.json");
|
|
111342
111375
|
if (existsSync31(phaseOwnershipPath) && removedPhaseIds.size > 0) {
|
|
111343
111376
|
const parsed = JSON.parse(await readFile88(phaseOwnershipPath, "utf8"));
|
|
111344
111377
|
const phases = Object.fromEntries(Object.entries(parsed.phases ?? {}).filter(([phaseId]) => !removedPhaseIds.has(phaseId)));
|
|
111345
111378
|
await atomicWriteFile(phaseOwnershipPath, `${JSON.stringify({ ...parsed, phases }, null, 2)}
|
|
111346
111379
|
`);
|
|
111347
111380
|
}
|
|
111348
|
-
const symbolPath =
|
|
111381
|
+
const symbolPath = join109(projectRoot, ".tmp/context-runtime/extract/source-symbols.json");
|
|
111349
111382
|
if (existsSync31(symbolPath)) {
|
|
111350
111383
|
const parsed = JSON.parse(await readFile88(symbolPath, "utf8"));
|
|
111351
111384
|
const symbols = Array.isArray(parsed.symbols) ? parsed.symbols.filter((entry) => entry === null || typeof entry !== "object" || Array.isArray(entry) || entry.source !== source2.name) : [];
|
|
@@ -111353,12 +111386,12 @@ async function pruneExtractRuntime(projectRoot, source2) {
|
|
|
111353
111386
|
await atomicWriteFile(symbolPath, `${JSON.stringify({ ...parsed, phaseFingerprints, symbols }, null, 2)}
|
|
111354
111387
|
`);
|
|
111355
111388
|
}
|
|
111356
|
-
const snapshotRoot =
|
|
111389
|
+
const snapshotRoot = join109(projectRoot, ".tmp/context-runtime/extract/candidates");
|
|
111357
111390
|
const visit4 = async (directory) => {
|
|
111358
111391
|
if (!existsSync31(directory))
|
|
111359
111392
|
return;
|
|
111360
111393
|
for (const entry of await readdir27(directory, { withFileTypes: true })) {
|
|
111361
|
-
const path3 =
|
|
111394
|
+
const path3 = join109(directory, entry.name);
|
|
111362
111395
|
if (entry.isDirectory()) {
|
|
111363
111396
|
await visit4(path3);
|
|
111364
111397
|
continue;
|
|
@@ -111408,7 +111441,7 @@ async function removeProjectSource(input) {
|
|
|
111408
111441
|
});
|
|
111409
111442
|
}
|
|
111410
111443
|
await applyAtomicFileBatch({
|
|
111411
|
-
transactionRoot:
|
|
111444
|
+
transactionRoot: join109(input.projectRoot, ".tmp", "context-runtime", "source-remove-transactions"),
|
|
111412
111445
|
writes: [...plan.registryWrite === undefined ? [] : [plan.registryWrite], ...plan.manifestWrite !== undefined ? [plan.manifestWrite] : []],
|
|
111413
111446
|
removals: plan.absoluteRemovals
|
|
111414
111447
|
});
|
|
@@ -112051,7 +112084,7 @@ init_exitCode();
|
|
|
112051
112084
|
var import_yaml51 = __toESM(require_dist(), 1);
|
|
112052
112085
|
import { constants as constants6, existsSync as existsSync32 } from "node:fs";
|
|
112053
112086
|
import { lstat as lstat13, open as open5, readdir as readdir28 } from "node:fs/promises";
|
|
112054
|
-
import { dirname as dirname44, join as
|
|
112087
|
+
import { dirname as dirname44, join as join111, resolve as resolve38 } from "node:path";
|
|
112055
112088
|
import { fileURLToPath as fileURLToPath9 } from "node:url";
|
|
112056
112089
|
function bundledSkillRoot() {
|
|
112057
112090
|
const directory = dirname44(fileURLToPath9(import.meta.url));
|
|
@@ -112081,7 +112114,7 @@ async function readProductionSkills(root2) {
|
|
|
112081
112114
|
const entries2 = (await readdir28(root2, { withFileTypes: true })).filter((entry) => entry.isDirectory()).sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0);
|
|
112082
112115
|
const skills = [];
|
|
112083
112116
|
for (const directory of entries2) {
|
|
112084
|
-
const entry =
|
|
112117
|
+
const entry = join111(root2, directory.name, "SKILL.md");
|
|
112085
112118
|
if (!(await lstat13(entry)).isFile())
|
|
112086
112119
|
throw new TypeError(`Skill entry must be a regular file: ${entry}`);
|
|
112087
112120
|
const handle2 = await open5(entry, constants6.O_RDONLY | constants6.O_NOFOLLOW | constants6.O_NONBLOCK);
|
|
@@ -112490,7 +112523,7 @@ init_errors3();
|
|
|
112490
112523
|
init_exitCode();
|
|
112491
112524
|
import { createHash as createHash34 } from "node:crypto";
|
|
112492
112525
|
import { cp as cp2, lstat as lstat14, mkdir as mkdir36, mkdtemp as mkdtemp5, readFile as readFile94, readdir as readdir29, rename as rename9, rm as rm24, writeFile as writeFile28 } from "node:fs/promises";
|
|
112493
|
-
import { dirname as dirname46, join as
|
|
112526
|
+
import { dirname as dirname46, join as join112, resolve as resolve40 } from "node:path";
|
|
112494
112527
|
var MARKER = ".context-skill-install.json";
|
|
112495
112528
|
function conflict(path3) {
|
|
112496
112529
|
throw new ContextError(ExitCode.UserError, `Local skill install conflict: ${path3}`, {
|
|
@@ -112521,7 +112554,7 @@ async function digest7(root2) {
|
|
|
112521
112554
|
for (const name3 of (await readdir29(dir)).sort()) {
|
|
112522
112555
|
if (!prefix && name3 === MARKER)
|
|
112523
112556
|
continue;
|
|
112524
|
-
const path3 =
|
|
112557
|
+
const path3 = join112(dir, name3);
|
|
112525
112558
|
const entry = await lstat14(path3);
|
|
112526
112559
|
if (entry.isSymbolicLink())
|
|
112527
112560
|
conflict(path3);
|
|
@@ -112541,31 +112574,31 @@ async function installLocalSkills(root2, path3, dryRun, agent) {
|
|
|
112541
112574
|
if (!path3.trim())
|
|
112542
112575
|
conflict("--local requires a non-empty path");
|
|
112543
112576
|
const targetRoot = resolve40(path3);
|
|
112544
|
-
const skillsRoot =
|
|
112577
|
+
const skillsRoot = join112(targetRoot, "skills");
|
|
112545
112578
|
await checkParents(skillsRoot);
|
|
112546
|
-
const sourceRoot2 =
|
|
112579
|
+
const sourceRoot2 = join112(root2, "skills");
|
|
112547
112580
|
const commandPlans = [];
|
|
112548
112581
|
const commandEntries = new Set;
|
|
112549
112582
|
if (agent === "claude" || agent === "cursor") {
|
|
112550
|
-
for (const name3 of await readdir29(
|
|
112583
|
+
for (const name3 of await readdir29(join112(root2, "claude", "commands"))) {
|
|
112551
112584
|
if (name3.endsWith(".md"))
|
|
112552
112585
|
commandEntries.add(name3.slice(0, -3));
|
|
112553
112586
|
}
|
|
112554
|
-
const commandsRoot =
|
|
112587
|
+
const commandsRoot = join112(targetRoot, "commands");
|
|
112555
112588
|
await checkParents(commandsRoot);
|
|
112556
|
-
for (const entry of await readdir29(
|
|
112589
|
+
for (const entry of await readdir29(join112(root2, agent, "commands"), { withFileTypes: true })) {
|
|
112557
112590
|
if (!entry.isFile() || !entry.name.endsWith(".md"))
|
|
112558
112591
|
continue;
|
|
112559
|
-
let content3 = await readFile94(
|
|
112592
|
+
let content3 = await readFile94(join112(root2, agent, "commands", entry.name), "utf8");
|
|
112560
112593
|
if (agent === "claude") {
|
|
112561
112594
|
const frontmatter2 = /^(---\r?\n)([\s\S]*?)(\r?\n---(?:\r?\n|$))/.exec(content3);
|
|
112562
112595
|
if (!frontmatter2)
|
|
112563
|
-
conflict(
|
|
112596
|
+
conflict(join112(root2, agent, "commands", entry.name));
|
|
112564
112597
|
content3 = `${frontmatter2[1]}disable-model-invocation: true
|
|
112565
112598
|
${frontmatter2[2].replace(/^disable-model-invocation:.*\r?\n?/mu, "")}${frontmatter2[3]}${content3.slice(frontmatter2[0].length)}`;
|
|
112566
112599
|
}
|
|
112567
|
-
const target =
|
|
112568
|
-
const marker =
|
|
112600
|
+
const target = join112(commandsRoot, entry.name);
|
|
112601
|
+
const marker = join112(commandsRoot, `.context-${entry.name}.json`);
|
|
112569
112602
|
for (const file of [target, marker]) {
|
|
112570
112603
|
const existing = await stat10(file);
|
|
112571
112604
|
if (existing && (!existing.isFile() || existing.isSymbolicLink()))
|
|
@@ -112586,14 +112619,14 @@ ${frontmatter2[2].replace(/^disable-model-invocation:.*\r?\n?/mu, "")}${frontmat
|
|
|
112586
112619
|
commandPlans.push({ name: entry.name, target, marker, content: content3, hash: createHash34("sha256").update(content3).digest("hex") });
|
|
112587
112620
|
}
|
|
112588
112621
|
if (!commandPlans.length)
|
|
112589
|
-
conflict(
|
|
112622
|
+
conflict(join112(root2, agent, "commands"));
|
|
112590
112623
|
}
|
|
112591
112624
|
const plans = [];
|
|
112592
112625
|
for (const entry of (await readdir29(sourceRoot2, { withFileTypes: true })).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
112593
|
-
if (!entry.isDirectory() || !await stat10(
|
|
112626
|
+
if (!entry.isDirectory() || !await stat10(join112(sourceRoot2, entry.name, "SKILL.md")))
|
|
112594
112627
|
continue;
|
|
112595
|
-
const source2 =
|
|
112596
|
-
const target =
|
|
112628
|
+
const source2 = join112(sourceRoot2, entry.name);
|
|
112629
|
+
const target = join112(skillsRoot, entry.name);
|
|
112597
112630
|
if (commandEntries.has(entry.name)) {
|
|
112598
112631
|
if (await stat10(target))
|
|
112599
112632
|
conflict(`${target} (use a fresh host directory to avoid duplicate command/skill entries)`);
|
|
@@ -112603,7 +112636,7 @@ ${frontmatter2[2].replace(/^disable-model-invocation:.*\r?\n?/mu, "")}${frontmat
|
|
|
112603
112636
|
if (existing) {
|
|
112604
112637
|
if (!existing.isDirectory() || existing.isSymbolicLink())
|
|
112605
112638
|
conflict(target);
|
|
112606
|
-
const markerPath =
|
|
112639
|
+
const markerPath = join112(target, MARKER);
|
|
112607
112640
|
if (!(await stat10(markerPath))?.isFile())
|
|
112608
112641
|
conflict(target);
|
|
112609
112642
|
let marker;
|
|
@@ -112622,14 +112655,14 @@ ${frontmatter2[2].replace(/^disable-model-invocation:.*\r?\n?/mu, "")}${frontmat
|
|
|
112622
112655
|
if (!dryRun) {
|
|
112623
112656
|
await mkdir36(skillsRoot, { recursive: true });
|
|
112624
112657
|
for (const plan of plans) {
|
|
112625
|
-
const staging = await mkdtemp5(
|
|
112626
|
-
const candidate =
|
|
112627
|
-
const previous3 =
|
|
112658
|
+
const staging = await mkdtemp5(join112(skillsRoot, ".context-install-"));
|
|
112659
|
+
const candidate = join112(staging, "candidate");
|
|
112660
|
+
const previous3 = join112(staging, "previous");
|
|
112628
112661
|
let moved = false;
|
|
112629
112662
|
try {
|
|
112630
112663
|
await cp2(plan.source, candidate, { recursive: true });
|
|
112631
112664
|
if (agent === "claude") {
|
|
112632
|
-
const skillFile =
|
|
112665
|
+
const skillFile = join112(candidate, "SKILL.md");
|
|
112633
112666
|
const content3 = await readFile94(skillFile, "utf8");
|
|
112634
112667
|
const parts = /^(---\r?\n)([\s\S]*?)(\r?\n---(?:\r?\n|$))/.exec(content3);
|
|
112635
112668
|
if (parts && /^\s*context-public-entry:\s*["']?false["']?\s*$/mu.test(parts[2])) {
|
|
@@ -112638,7 +112671,7 @@ ${frontmatter2[2].replace(/^disable-model-invocation:.*\r?\n?/mu, "")}${frontmat
|
|
|
112638
112671
|
${frontmatter2}${parts[3]}${content3.slice(parts[0].length)}`);
|
|
112639
112672
|
}
|
|
112640
112673
|
}
|
|
112641
|
-
await writeFile28(
|
|
112674
|
+
await writeFile28(join112(candidate, MARKER), JSON.stringify({ owner: "context-plugin-local", digest: await digest7(candidate) }) + `
|
|
112642
112675
|
`);
|
|
112643
112676
|
if (plan.exists) {
|
|
112644
112677
|
await rename9(plan.target, previous3);
|
|
@@ -112662,12 +112695,12 @@ ${frontmatter2}${parts[3]}${content3.slice(parts[0].length)}`);
|
|
|
112662
112695
|
}
|
|
112663
112696
|
for (const command3 of commandPlans) {
|
|
112664
112697
|
await mkdir36(dirname46(command3.target), { recursive: true });
|
|
112665
|
-
const staging = await mkdtemp5(
|
|
112666
|
-
await writeFile28(
|
|
112667
|
-
await writeFile28(
|
|
112698
|
+
const staging = await mkdtemp5(join112(dirname46(command3.target), ".context-install-"));
|
|
112699
|
+
await writeFile28(join112(staging, "command"), command3.content);
|
|
112700
|
+
await writeFile28(join112(staging, "marker"), JSON.stringify({ owner: "context-plugin-local", digest: command3.hash }) + `
|
|
112668
112701
|
`);
|
|
112669
|
-
await rename9(
|
|
112670
|
-
await rename9(
|
|
112702
|
+
await rename9(join112(staging, "command"), command3.target);
|
|
112703
|
+
await rename9(join112(staging, "marker"), command3.marker);
|
|
112671
112704
|
await rm24(staging, { recursive: true, force: true });
|
|
112672
112705
|
}
|
|
112673
112706
|
}
|
|
@@ -112690,66 +112723,49 @@ ${frontmatter2}${parts[3]}${content3.slice(parts[0].length)}`);
|
|
|
112690
112723
|
init_cliFeedback();
|
|
112691
112724
|
init_errors3();
|
|
112692
112725
|
init_exitCode();
|
|
112693
|
-
import {
|
|
112694
|
-
import {
|
|
112695
|
-
import { homedir as homedir2 } from "node:os";
|
|
112696
|
-
import { basename as basename13, delimiter, dirname as dirname47, join as join112, resolve as resolve41 } from "node:path";
|
|
112726
|
+
import { lstat as lstat15 } from "node:fs/promises";
|
|
112727
|
+
import { join as join113, resolve as resolve41 } from "node:path";
|
|
112697
112728
|
var HOST_DIRS = { claude: ".claude", cursor: ".cursor", codex: ".agents" };
|
|
112698
|
-
async function detectLocalAgent(agent) {
|
|
112699
|
-
const
|
|
112700
|
-
|
|
112701
|
-
|
|
112702
|
-
|
|
112703
|
-
|
|
112704
|
-
try {
|
|
112705
|
-
if (!(await stat11(file)).isFile())
|
|
112706
|
-
continue;
|
|
112707
|
-
await access6(file, constants7.X_OK);
|
|
112708
|
-
return true;
|
|
112709
|
-
} catch {}
|
|
112710
|
-
}
|
|
112711
|
-
}
|
|
112712
|
-
}
|
|
112713
|
-
if (process.platform === "darwin") {
|
|
112714
|
-
const app = { claude: "Claude.app", cursor: "Cursor.app", codex: "Codex.app" }[agent];
|
|
112715
|
-
if (agent !== "claude") {
|
|
112716
|
-
for (const directory of ["/Applications", join112(homedir2(), "Applications")]) {
|
|
112717
|
-
try {
|
|
112718
|
-
if ((await stat11(join112(directory, app))).isDirectory())
|
|
112719
|
-
return true;
|
|
112720
|
-
} catch {}
|
|
112721
|
-
}
|
|
112729
|
+
async function detectLocalAgent(agent, repo) {
|
|
112730
|
+
const path3 = join113(repo, HOST_DIRS[agent]);
|
|
112731
|
+
try {
|
|
112732
|
+
const entry = await lstat15(path3);
|
|
112733
|
+
if (!entry.isDirectory() || entry.isSymbolicLink()) {
|
|
112734
|
+
throw new ContextError(ExitCode.UserError, `Local host directory is not a regular directory: ${path3}`);
|
|
112722
112735
|
}
|
|
112736
|
+
return true;
|
|
112737
|
+
} catch (error) {
|
|
112738
|
+
if (error.code === "ENOENT")
|
|
112739
|
+
return false;
|
|
112740
|
+
throw error;
|
|
112723
112741
|
}
|
|
112724
|
-
return false;
|
|
112725
112742
|
}
|
|
112726
|
-
async function installAutoLocalSkills(root2, path3, dryRun, detect = detectLocalAgent) {
|
|
112743
|
+
async function installAutoLocalSkills(root2, path3, dryRun, detect = detectLocalAgent, selectedAgent) {
|
|
112727
112744
|
if (!path3.trim())
|
|
112728
112745
|
throw new ContextError(ExitCode.UserError, "--local requires a non-empty repository path", {
|
|
112729
112746
|
category: ErrorCategory.UserInputInvalid,
|
|
112730
|
-
next: "Run context plugin install --local /path/to/repository."
|
|
112747
|
+
next: "Run context plugin install --local /path/to/repository --agent auto-detect."
|
|
112731
112748
|
});
|
|
112732
|
-
const
|
|
112733
|
-
const repo = Object.values(HOST_DIRS).some((name3) => name3 === basename13(requested)) ? dirname47(requested) : requested;
|
|
112749
|
+
const repo = resolve41(path3);
|
|
112734
112750
|
const agents = [];
|
|
112735
112751
|
for (const agent of ["claude", "cursor", "codex"]) {
|
|
112736
|
-
if (await detect(agent))
|
|
112752
|
+
if (selectedAgent ? selectedAgent === "all" || agent === selectedAgent : await detect(agent, repo))
|
|
112737
112753
|
agents.push(agent);
|
|
112738
112754
|
}
|
|
112739
|
-
const targets = agents.length ? agents.map((agent) => ({ agent, path:
|
|
112755
|
+
const targets = agents.length ? agents.map((agent) => ({ agent, path: join113(repo, HOST_DIRS[agent]) })) : [{ path: join113(repo, ".agents") }];
|
|
112740
112756
|
const previews = [];
|
|
112741
112757
|
for (const target of targets)
|
|
112742
112758
|
previews.push(await installLocalSkills(root2, target.path, true, target.agent));
|
|
112743
112759
|
const header = formatFeedback({
|
|
112744
112760
|
symbol: agents.length ? "✓" : "⚠",
|
|
112745
|
-
action: "detected",
|
|
112761
|
+
action: selectedAgent ? "selected" : "detected",
|
|
112746
112762
|
subject: "local agent targets",
|
|
112747
|
-
headline: agents.length ? agents.join(", ") : "No supported
|
|
112763
|
+
headline: agents.length ? agents.join(", ") : "No supported host directory found",
|
|
112748
112764
|
body: [
|
|
112749
112765
|
`repository: ${repo}`,
|
|
112750
112766
|
...targets.map((target) => `${target.agent ?? "standalone"}: ${target.path}`),
|
|
112751
|
-
...!agents.length ? ["Installing only .agents/skills. Configure a supported host to read this directory, or
|
|
112752
|
-
"
|
|
112767
|
+
...!agents.length ? ["Installing only .agents/skills. Configure a supported host to read this directory, or select an explicit --agent with the same repository root."] : [],
|
|
112768
|
+
"Repository directory discovery does not verify runtime skill loading; refresh the host after installation."
|
|
112753
112769
|
]
|
|
112754
112770
|
});
|
|
112755
112771
|
if (dryRun)
|
|
@@ -112769,7 +112785,7 @@ init_cliFeedback();
|
|
|
112769
112785
|
init_errors3();
|
|
112770
112786
|
init_exitCode();
|
|
112771
112787
|
import { existsSync as existsSync35 } from "node:fs";
|
|
112772
|
-
import { dirname as
|
|
112788
|
+
import { dirname as dirname48, join as join115, resolve as resolve42 } from "node:path";
|
|
112773
112789
|
import { fileURLToPath as fileURLToPath10 } from "node:url";
|
|
112774
112790
|
|
|
112775
112791
|
// src/project/pluginInstallTargets.ts
|
|
@@ -112779,8 +112795,8 @@ init_exitCode();
|
|
|
112779
112795
|
import { execFile as execFile13 } from "node:child_process";
|
|
112780
112796
|
import { existsSync as existsSync34 } from "node:fs";
|
|
112781
112797
|
import { cp as cp3, mkdir as mkdir37, readdir as readdir30, readFile as readFile95, rename as rename10, rm as rm25, writeFile as writeFile29 } from "node:fs/promises";
|
|
112782
|
-
import { homedir as
|
|
112783
|
-
import { dirname as
|
|
112798
|
+
import { homedir as homedir2 } from "node:os";
|
|
112799
|
+
import { dirname as dirname47, join as join114 } from "node:path";
|
|
112784
112800
|
import { promisify as promisify13 } from "node:util";
|
|
112785
112801
|
var execFileAsync7 = promisify13(execFile13);
|
|
112786
112802
|
var MARKETPLACE_NAME = "c4a";
|
|
@@ -112834,23 +112850,23 @@ async function claudePluginInstalled(pluginId) {
|
|
|
112834
112850
|
}
|
|
112835
112851
|
}
|
|
112836
112852
|
function codexHome() {
|
|
112837
|
-
return process.env.CODEX_HOME?.trim() ||
|
|
112853
|
+
return process.env.CODEX_HOME?.trim() || join114(homedir2(), ".codex");
|
|
112838
112854
|
}
|
|
112839
112855
|
function claudePluginCacheRoot() {
|
|
112840
112856
|
const explicitRoot = process.env[CLAUDE_PLUGIN_CACHE_ROOT_ENV2]?.trim();
|
|
112841
112857
|
if (explicitRoot)
|
|
112842
112858
|
return explicitRoot;
|
|
112843
|
-
const home = process.env[CLAUDE_PLUGIN_CACHE_HOME_ENV2]?.trim() ||
|
|
112844
|
-
return
|
|
112859
|
+
const home = process.env[CLAUDE_PLUGIN_CACHE_HOME_ENV2]?.trim() || homedir2();
|
|
112860
|
+
return join114(home, ".claude", "plugins", "cache");
|
|
112845
112861
|
}
|
|
112846
112862
|
function sharedSkillsRoot() {
|
|
112847
|
-
return process.env[SHARED_SKILLS_ROOT_ENV]?.trim() ||
|
|
112863
|
+
return process.env[SHARED_SKILLS_ROOT_ENV]?.trim() || join114(homedir2(), ".agents", "skills");
|
|
112848
112864
|
}
|
|
112849
112865
|
function claudeSkillsRoot() {
|
|
112850
|
-
return process.env[CLAUDE_SKILLS_ROOT_ENV]?.trim() ||
|
|
112866
|
+
return process.env[CLAUDE_SKILLS_ROOT_ENV]?.trim() || join114(homedir2(), ".claude", "skills");
|
|
112851
112867
|
}
|
|
112852
112868
|
function cursorPluginRoot() {
|
|
112853
|
-
return process.env[CURSOR_PLUGIN_ROOT_ENV]?.trim() ||
|
|
112869
|
+
return process.env[CURSOR_PLUGIN_ROOT_ENV]?.trim() || join114(homedir2(), ".cursor", "plugins", "local", PLUGIN_NAME);
|
|
112854
112870
|
}
|
|
112855
112871
|
function blockHeader(line) {
|
|
112856
112872
|
const match = line.match(/^\s*\[([^\]]+)\]\s*$/u);
|
|
@@ -112901,7 +112917,7 @@ function pruneLegacyCodexConfigContent(content3) {
|
|
|
112901
112917
|
`), removed };
|
|
112902
112918
|
}
|
|
112903
112919
|
async function pruneLegacyCodexConfig(dryRun, steps) {
|
|
112904
|
-
const configPath =
|
|
112920
|
+
const configPath = join114(codexHome(), "config.toml");
|
|
112905
112921
|
const current2 = await readFile95(configPath, "utf8").catch(() => "");
|
|
112906
112922
|
if (!current2)
|
|
112907
112923
|
return;
|
|
@@ -112918,7 +112934,7 @@ async function pruneLegacyCodexConfig(dryRun, steps) {
|
|
|
112918
112934
|
}
|
|
112919
112935
|
}
|
|
112920
112936
|
async function pruneCodexPluginCacheForName(pluginName, keepVersion, dryRun, steps) {
|
|
112921
|
-
const cacheRoot =
|
|
112937
|
+
const cacheRoot = join114(codexHome(), "plugins", "cache", MARKETPLACE_NAME, pluginName);
|
|
112922
112938
|
if (!existsSync34(cacheRoot))
|
|
112923
112939
|
return;
|
|
112924
112940
|
const versions = (await readdir30(cacheRoot, { withFileTypes: true }).catch(() => [])).filter((entry) => entry.isDirectory() && entry.name !== keepVersion).map((entry) => entry.name).sort();
|
|
@@ -112930,7 +112946,7 @@ async function pruneCodexPluginCacheForName(pluginName, keepVersion, dryRun, ste
|
|
|
112930
112946
|
status: dryRun ? "planned" : "ran"
|
|
112931
112947
|
});
|
|
112932
112948
|
if (!dryRun)
|
|
112933
|
-
await Promise.all(versions.map((version3) => rm25(
|
|
112949
|
+
await Promise.all(versions.map((version3) => rm25(join114(cacheRoot, version3), { recursive: true, force: true })));
|
|
112934
112950
|
}
|
|
112935
112951
|
async function pruneCodexPluginCache(currentVersion, dryRun, steps) {
|
|
112936
112952
|
await pruneCodexPluginCacheForName(PLUGIN_NAME, currentVersion, dryRun, steps);
|
|
@@ -112954,15 +112970,15 @@ async function pruneClaudeOrphanContextCache(dryRun, steps) {
|
|
|
112954
112970
|
for (const marketplace of marketplaces) {
|
|
112955
112971
|
if (!marketplace.isDirectory())
|
|
112956
112972
|
continue;
|
|
112957
|
-
const pluginDir =
|
|
112973
|
+
const pluginDir = join114(cacheRoot, marketplace.name, PLUGIN_NAME);
|
|
112958
112974
|
if (!existsSync34(pluginDir))
|
|
112959
112975
|
continue;
|
|
112960
112976
|
const versions = await readdir30(pluginDir, { withFileTypes: true }).catch(() => []);
|
|
112961
112977
|
for (const version3 of versions) {
|
|
112962
112978
|
if (!version3.isDirectory())
|
|
112963
112979
|
continue;
|
|
112964
|
-
const versionDir =
|
|
112965
|
-
if (!existsSync34(
|
|
112980
|
+
const versionDir = join114(pluginDir, version3.name);
|
|
112981
|
+
if (!existsSync34(join114(versionDir, ORPHAN_MARKER2)))
|
|
112966
112982
|
continue;
|
|
112967
112983
|
removed.push(`${marketplace.name}/${PLUGIN_NAME}/${version3.name}`);
|
|
112968
112984
|
if (!dryRun) {
|
|
@@ -112972,7 +112988,7 @@ async function pruneClaudeOrphanContextCache(dryRun, steps) {
|
|
|
112972
112988
|
if (!dryRun && await isEmptyDir2(pluginDir)) {
|
|
112973
112989
|
await rm25(pluginDir, { recursive: true, force: true });
|
|
112974
112990
|
}
|
|
112975
|
-
const marketplaceDir =
|
|
112991
|
+
const marketplaceDir = join114(cacheRoot, marketplace.name);
|
|
112976
112992
|
if (!dryRun && await isEmptyDir2(marketplaceDir)) {
|
|
112977
112993
|
await rm25(marketplaceDir, { recursive: true, force: true });
|
|
112978
112994
|
}
|
|
@@ -112993,7 +113009,7 @@ async function pruneClaudeLegacyPluginCache(dryRun, steps) {
|
|
|
112993
113009
|
return;
|
|
112994
113010
|
const removed = [];
|
|
112995
113011
|
for (const pluginName of LEGACY_PLUGIN_NAMES) {
|
|
112996
|
-
const pluginDir =
|
|
113012
|
+
const pluginDir = join114(cacheRoot, MARKETPLACE_NAME, pluginName);
|
|
112997
113013
|
if (!existsSync34(pluginDir))
|
|
112998
113014
|
continue;
|
|
112999
113015
|
removed.push(`${MARKETPLACE_NAME}/${pluginName}`);
|
|
@@ -113010,11 +113026,11 @@ async function pruneClaudeLegacyPluginCache(dryRun, steps) {
|
|
|
113010
113026
|
}
|
|
113011
113027
|
}
|
|
113012
113028
|
async function pruneClaudeSupersededContextCache(root2, dryRun, steps) {
|
|
113013
|
-
const manifest = await readFile95(
|
|
113029
|
+
const manifest = await readFile95(join114(root2, "claude", ".claude-plugin", "plugin.json"), "utf8").then((content3) => JSON.parse(content3)).catch(() => null);
|
|
113014
113030
|
const currentVersion = typeof manifest?.version === "string" ? manifest.version : null;
|
|
113015
113031
|
if (!currentVersion)
|
|
113016
113032
|
return;
|
|
113017
|
-
const pluginDir =
|
|
113033
|
+
const pluginDir = join114(claudePluginCacheRoot(), MARKETPLACE_NAME, PLUGIN_NAME);
|
|
113018
113034
|
const staleVersions = (await readdir30(pluginDir, { withFileTypes: true }).catch(() => [])).filter((entry) => entry.isDirectory() && entry.name !== currentVersion).map((entry) => entry.name);
|
|
113019
113035
|
if (staleVersions.length === 0)
|
|
113020
113036
|
return;
|
|
@@ -113024,7 +113040,7 @@ async function pruneClaudeSupersededContextCache(root2, dryRun, steps) {
|
|
|
113024
113040
|
status: dryRun ? "planned" : "ran"
|
|
113025
113041
|
});
|
|
113026
113042
|
if (!dryRun) {
|
|
113027
|
-
await Promise.all(staleVersions.map((version3) => rm25(
|
|
113043
|
+
await Promise.all(staleVersions.map((version3) => rm25(join114(pluginDir, version3), { recursive: true, force: true })));
|
|
113028
113044
|
}
|
|
113029
113045
|
}
|
|
113030
113046
|
function enableCodexPluginConfig(content3) {
|
|
@@ -113088,8 +113104,8 @@ source = ${JSON.stringify(root2)}
|
|
|
113088
113104
|
`;
|
|
113089
113105
|
}
|
|
113090
113106
|
async function ensureCodexPluginEnabled() {
|
|
113091
|
-
const configPath =
|
|
113092
|
-
await mkdir37(
|
|
113107
|
+
const configPath = join114(codexHome(), "config.toml");
|
|
113108
|
+
await mkdir37(dirname47(configPath), { recursive: true });
|
|
113093
113109
|
const current2 = await readFile95(configPath, "utf8").catch(() => "");
|
|
113094
113110
|
const next2 = enableCodexPluginConfig(current2);
|
|
113095
113111
|
if (next2 !== current2) {
|
|
@@ -113097,8 +113113,8 @@ async function ensureCodexPluginEnabled() {
|
|
|
113097
113113
|
}
|
|
113098
113114
|
}
|
|
113099
113115
|
async function ensureCodexLocalMarketplace(root2) {
|
|
113100
|
-
const configPath =
|
|
113101
|
-
await mkdir37(
|
|
113116
|
+
const configPath = join114(codexHome(), "config.toml");
|
|
113117
|
+
await mkdir37(dirname47(configPath), { recursive: true });
|
|
113102
113118
|
const current2 = await readFile95(configPath, "utf8").catch(() => "");
|
|
113103
113119
|
const next2 = upsertCodexLocalMarketplaceConfig(current2, root2);
|
|
113104
113120
|
if (next2 !== current2) {
|
|
@@ -113106,7 +113122,7 @@ async function ensureCodexLocalMarketplace(root2) {
|
|
|
113106
113122
|
}
|
|
113107
113123
|
}
|
|
113108
113124
|
async function codexPluginVersion(root2) {
|
|
113109
|
-
const manifestPath =
|
|
113125
|
+
const manifestPath = join114(root2, "codex", ".codex-plugin", "plugin.json");
|
|
113110
113126
|
const manifest = JSON.parse(await readFile95(manifestPath, "utf8"));
|
|
113111
113127
|
if (typeof manifest.version !== "string" || !/^[A-Za-z0-9][A-Za-z0-9._-]*$/u.test(manifest.version)) {
|
|
113112
113128
|
throw new Error(`Codex plugin manifest has an invalid version: ${manifestPath}`);
|
|
@@ -113114,10 +113130,10 @@ async function codexPluginVersion(root2) {
|
|
|
113114
113130
|
return manifest.version;
|
|
113115
113131
|
}
|
|
113116
113132
|
function codexPluginCacheDir(version3) {
|
|
113117
|
-
return
|
|
113133
|
+
return join114(codexHome(), "plugins", "cache", MARKETPLACE_NAME, PLUGIN_NAME, version3);
|
|
113118
113134
|
}
|
|
113119
113135
|
async function replaceDirectoryFromSource(source2, target) {
|
|
113120
|
-
await mkdir37(
|
|
113136
|
+
await mkdir37(dirname47(target), { recursive: true });
|
|
113121
113137
|
const temporary = `${target}.tmp-${process.pid}-${Date.now()}`;
|
|
113122
113138
|
const previous3 = `${target}.previous-${process.pid}-${Date.now()}`;
|
|
113123
113139
|
await rm25(temporary, { recursive: true, force: true });
|
|
@@ -113137,7 +113153,7 @@ async function replaceDirectoryFromSource(source2, target) {
|
|
|
113137
113153
|
}
|
|
113138
113154
|
}
|
|
113139
113155
|
async function materializeCodexPluginCache(root2, version3, dryRun, steps) {
|
|
113140
|
-
const source2 =
|
|
113156
|
+
const source2 = join114(root2, "codex");
|
|
113141
113157
|
const target = codexPluginCacheDir(version3);
|
|
113142
113158
|
steps.push({
|
|
113143
113159
|
agent: "codex",
|
|
@@ -113149,13 +113165,13 @@ async function materializeCodexPluginCache(root2, version3, dryRun, steps) {
|
|
|
113149
113165
|
await replaceDirectoryFromSource(source2, target);
|
|
113150
113166
|
}
|
|
113151
113167
|
async function bundledProviderSkillNames(root2) {
|
|
113152
|
-
const skillsRoot =
|
|
113168
|
+
const skillsRoot = join114(root2, "skills");
|
|
113153
113169
|
const entries2 = await readdir30(skillsRoot, { withFileTypes: true });
|
|
113154
113170
|
const names = [];
|
|
113155
113171
|
for (const entry of entries2) {
|
|
113156
113172
|
if (!entry.isDirectory() || entry.name === "context")
|
|
113157
113173
|
continue;
|
|
113158
|
-
const skillPath =
|
|
113174
|
+
const skillPath = join114(skillsRoot, entry.name, "SKILL.md");
|
|
113159
113175
|
if (!existsSync34(skillPath))
|
|
113160
113176
|
continue;
|
|
113161
113177
|
const skill = await readFile95(skillPath, "utf8");
|
|
@@ -113170,10 +113186,10 @@ async function bundledProviderSkillNames(root2) {
|
|
|
113170
113186
|
return names;
|
|
113171
113187
|
}
|
|
113172
113188
|
async function materializeProviderSkills(root2, targetRoot, agent, dryRun, steps) {
|
|
113173
|
-
const sourceRoot2 =
|
|
113189
|
+
const sourceRoot2 = join114(root2, "skills");
|
|
113174
113190
|
for (const name3 of await bundledProviderSkillNames(root2)) {
|
|
113175
|
-
const source2 =
|
|
113176
|
-
const target =
|
|
113191
|
+
const source2 = join114(sourceRoot2, name3);
|
|
113192
|
+
const target = join114(targetRoot, name3);
|
|
113177
113193
|
steps.push({
|
|
113178
113194
|
agent,
|
|
113179
113195
|
command: `materialize lifecycle Provider skill: ${shellQuote8(source2)} -> ${shellQuote8(target)}`,
|
|
@@ -113184,7 +113200,7 @@ async function materializeProviderSkills(root2, targetRoot, agent, dryRun, steps
|
|
|
113184
113200
|
}
|
|
113185
113201
|
}
|
|
113186
113202
|
async function installCursor(root2, dryRun, steps) {
|
|
113187
|
-
const source2 =
|
|
113203
|
+
const source2 = join114(root2, "cursor");
|
|
113188
113204
|
const target = cursorPluginRoot();
|
|
113189
113205
|
steps.push({
|
|
113190
113206
|
agent: "cursor",
|
|
@@ -113239,12 +113255,12 @@ async function installCodex(root2, dryRun, steps) {
|
|
|
113239
113255
|
steps.push({ agent: "codex", command: commandLine("codex", addArgs), status: dryRun ? "planned" : "ran" });
|
|
113240
113256
|
steps.push({
|
|
113241
113257
|
agent: "codex",
|
|
113242
|
-
command: `ensure ${shellQuote8(
|
|
113258
|
+
command: `ensure ${shellQuote8(join114(codexHome(), "config.toml"))} registers local marketplace ${shellQuote8(MARKETPLACE_NAME)}`,
|
|
113243
113259
|
status: dryRun ? "planned" : "ran"
|
|
113244
113260
|
});
|
|
113245
113261
|
steps.push({
|
|
113246
113262
|
agent: "codex",
|
|
113247
|
-
command: `ensure ${shellQuote8(
|
|
113263
|
+
command: `ensure ${shellQuote8(join114(codexHome(), "config.toml"))} enables ${shellQuote8(PLUGIN_ID)}`,
|
|
113248
113264
|
status: dryRun ? "planned" : "ran"
|
|
113249
113265
|
});
|
|
113250
113266
|
if (dryRun) {
|
|
@@ -113283,10 +113299,10 @@ function pluginAgentOption(value) {
|
|
|
113283
113299
|
}
|
|
113284
113300
|
function packageCandidateDirs() {
|
|
113285
113301
|
const dirs = [];
|
|
113286
|
-
let dir =
|
|
113302
|
+
let dir = dirname48(fileURLToPath10(import.meta.url));
|
|
113287
113303
|
for (let index2 = 0;index2 < 8; index2++) {
|
|
113288
113304
|
dirs.push(dir);
|
|
113289
|
-
const parent =
|
|
113305
|
+
const parent = dirname48(dir);
|
|
113290
113306
|
if (parent === dir)
|
|
113291
113307
|
break;
|
|
113292
113308
|
dir = parent;
|
|
@@ -113299,13 +113315,13 @@ function pluginRootCandidates() {
|
|
|
113299
113315
|
return [resolve42(envRoot)];
|
|
113300
113316
|
const candidates = [];
|
|
113301
113317
|
for (const dir of packageCandidateDirs()) {
|
|
113302
|
-
candidates.push(
|
|
113303
|
-
candidates.push(
|
|
113318
|
+
candidates.push(join115(dir, "plugins"));
|
|
113319
|
+
candidates.push(join115(dir, "dist", "plugins"));
|
|
113304
113320
|
}
|
|
113305
113321
|
return [...new Set(candidates)];
|
|
113306
113322
|
}
|
|
113307
113323
|
function isInstallablePluginRoot(root2) {
|
|
113308
|
-
return existsSync35(
|
|
113324
|
+
return existsSync35(join115(root2, ".claude-plugin", "marketplace.json")) && existsSync35(join115(root2, ".agents", "plugins", "marketplace.json")) && existsSync35(join115(root2, "claude", ".claude-plugin", "plugin.json")) && existsSync35(join115(root2, "codex", ".codex-plugin", "plugin.json")) && existsSync35(join115(root2, "cursor", ".cursor-plugin", "plugin.json")) && existsSync35(join115(root2, "skills"));
|
|
113309
113325
|
}
|
|
113310
113326
|
function resolveBundledPluginsRoot() {
|
|
113311
113327
|
const candidates = pluginRootCandidates();
|
|
@@ -113455,14 +113471,14 @@ function registerPluginCommands(program2) {
|
|
|
113455
113471
|
const agent = pluginAgentOption(options.agent);
|
|
113456
113472
|
process.stdout.write(formatPluginStatusResult(await runPluginStatusCommand({ agent })));
|
|
113457
113473
|
});
|
|
113458
|
-
plugin.command("install").description("Install globally by default, or copy standalone skills with --local <path>").option("--agent <agent>", "agent target: claude | codex | cursor | all", "all").option("--local <path>", "
|
|
113474
|
+
plugin.command("install").description("Install globally by default, or copy standalone skills with --local <path>").option("--agent <agent>", "agent target: claude | codex | cursor | all; local only: auto-detect | standalone", "all").option("--local <path>", "Repository root; install selected or detected hosts into their corresponding subdirectories").option("--dry-run", "Preview installation without writing files or configuration").action(async (options, command3) => {
|
|
113459
113475
|
if (options.local !== undefined) {
|
|
113460
|
-
|
|
113461
|
-
|
|
113462
|
-
throw new ContextError(ExitCode.UserError, "--local requires one --agent (claude, cursor or codex), or omit --agent for automatic detection.");
|
|
113476
|
+
if (command3.getOptionValueSource("agent") !== "cli") {
|
|
113477
|
+
throw new ContextError(ExitCode.UserError, "--local requires explicit --agent: claude, cursor, codex, all, auto-detect or standalone.");
|
|
113463
113478
|
}
|
|
113479
|
+
const agent2 = options.agent === "auto-detect" || options.agent === "standalone" ? options.agent : pluginAgentOption(options.agent);
|
|
113464
113480
|
const { pluginsRoot } = await runPluginPathCommand();
|
|
113465
|
-
process.stdout.write(agent2 ? await installLocalSkills(pluginsRoot, String(options.local), options.dryRun === true
|
|
113481
|
+
process.stdout.write(agent2 === "standalone" ? await installLocalSkills(pluginsRoot, String(options.local), options.dryRun === true) : await installAutoLocalSkills(pluginsRoot, String(options.local), options.dryRun === true, undefined, agent2 === "auto-detect" ? undefined : agent2));
|
|
113466
113482
|
return;
|
|
113467
113483
|
}
|
|
113468
113484
|
const agent = pluginAgentOption(options.agent);
|
|
@@ -113550,21 +113566,21 @@ function inferErrorCategory(message) {
|
|
|
113550
113566
|
}
|
|
113551
113567
|
function readQuickstartPath() {
|
|
113552
113568
|
try {
|
|
113553
|
-
let dir =
|
|
113569
|
+
let dir = dirname49(fileURLToPath11(import.meta.url));
|
|
113554
113570
|
for (let i2 = 0;i2 < 8; i2++) {
|
|
113555
|
-
const candidate =
|
|
113571
|
+
const candidate = join116(dir, "docs", "quickstart.md");
|
|
113556
113572
|
if (existsSync36(candidate))
|
|
113557
113573
|
return candidate;
|
|
113558
|
-
const pkg =
|
|
113574
|
+
const pkg = join116(dir, "package.json");
|
|
113559
113575
|
if (existsSync36(pkg))
|
|
113560
113576
|
return candidate;
|
|
113561
|
-
const parent =
|
|
113577
|
+
const parent = dirname49(dir);
|
|
113562
113578
|
if (parent === dir)
|
|
113563
113579
|
break;
|
|
113564
113580
|
dir = parent;
|
|
113565
113581
|
}
|
|
113566
113582
|
} catch {}
|
|
113567
|
-
return
|
|
113583
|
+
return join116(dirname49(fileURLToPath11(import.meta.url)), "docs", "quickstart.md");
|
|
113568
113584
|
}
|
|
113569
113585
|
var GREEN = "\x1B[32m";
|
|
113570
113586
|
var RESET = "\x1B[0m";
|