snipara-companion 3.6.21 → 3.6.22
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/CHANGELOG.md +9 -0
- package/README.md +15 -0
- package/dist/index.d.ts +13 -2
- package/dist/index.js +918 -737
- package/docs/FULL_REFERENCE.md +12 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -405,9 +405,9 @@ function warnIfCompanionUpdateAvailable(currentVersion) {
|
|
|
405
405
|
|
|
406
406
|
// src/commands/init.ts
|
|
407
407
|
var readline = __toESM(require("readline"));
|
|
408
|
-
var
|
|
409
|
-
var
|
|
410
|
-
var
|
|
408
|
+
var fs11 = __toESM(require("fs"));
|
|
409
|
+
var path11 = __toESM(require("path"));
|
|
410
|
+
var import_node_crypto2 = require("crypto");
|
|
411
411
|
|
|
412
412
|
// src/config/store.ts
|
|
413
413
|
var fs2 = __toESM(require("fs"));
|
|
@@ -608,9 +608,9 @@ function getConfigPath(options = {}) {
|
|
|
608
608
|
}
|
|
609
609
|
|
|
610
610
|
// src/api/client.ts
|
|
611
|
-
var
|
|
611
|
+
var fs5 = __toESM(require("fs"));
|
|
612
612
|
var os3 = __toESM(require("os"));
|
|
613
|
-
var
|
|
613
|
+
var path5 = __toESM(require("path"));
|
|
614
614
|
|
|
615
615
|
// src/project/resolver.ts
|
|
616
616
|
var fs3 = __toESM(require("fs"));
|
|
@@ -690,6 +690,70 @@ function readGitRemote(cwd) {
|
|
|
690
690
|
return `${match[1]}/${match[2]}`;
|
|
691
691
|
}
|
|
692
692
|
|
|
693
|
+
// src/session/checkpoint.ts
|
|
694
|
+
var fs4 = __toESM(require("fs"));
|
|
695
|
+
var path4 = __toESM(require("path"));
|
|
696
|
+
var import_node_crypto = require("crypto");
|
|
697
|
+
function checkpointText(value, limit = 12e3) {
|
|
698
|
+
return value.replace(
|
|
699
|
+
/-----BEGIN [^-]*PRIVATE KEY-----[\s\S]*?-----END [^-]*PRIVATE KEY-----/g,
|
|
700
|
+
"[REDACTED PRIVATE KEY]"
|
|
701
|
+
).replace(/\bBearer\s+[A-Za-z0-9._~+/=-]{12,}/gi, "Bearer [REDACTED]").replace(/\b(?:sk|snp|rlm)[_-][A-Za-z0-9_-]{16,}\b/g, "[REDACTED KEY]").replace(
|
|
702
|
+
/\b([\w-]*(?:api[_-]?key|token|password|passwd|secret)[\w-]*)\s*[:=]\s*(?:"[^"]*"|'[^']*'|[^\s,;]+)/gi,
|
|
703
|
+
"$1=[REDACTED]"
|
|
704
|
+
).trim().slice(0, limit);
|
|
705
|
+
}
|
|
706
|
+
function normalizeSessionCheckpoint(input) {
|
|
707
|
+
if (!/^[A-Za-z0-9_.:-]{1,200}$/.test(input.sessionId)) {
|
|
708
|
+
throw new Error(
|
|
709
|
+
"Session id must contain 1-200 letters, digits, dots, colons, underscores or hyphens"
|
|
710
|
+
);
|
|
711
|
+
}
|
|
712
|
+
return {
|
|
713
|
+
sessionId: input.sessionId,
|
|
714
|
+
summary: checkpointText(input.summary ?? ""),
|
|
715
|
+
files: [
|
|
716
|
+
...new Set((input.files ?? []).map((file) => checkpointText(file, 500)).filter(Boolean))
|
|
717
|
+
].sort().slice(0, 100)
|
|
718
|
+
};
|
|
719
|
+
}
|
|
720
|
+
function sessionCloseoutPath(cwd, projectId, checkpoint) {
|
|
721
|
+
const digest = (0, import_node_crypto.createHash)("sha256").update(JSON.stringify({ projectId, checkpoint })).digest("hex");
|
|
722
|
+
return path4.join(cwd, ".snipara", "companion", "session-closeouts", `${digest}.json`);
|
|
723
|
+
}
|
|
724
|
+
function lockSessionCloseout(file) {
|
|
725
|
+
const lockPath = `${file}.lock`;
|
|
726
|
+
if (fs4.existsSync(lockPath)) {
|
|
727
|
+
const owner = Number(fs4.readFileSync(lockPath, "utf8"));
|
|
728
|
+
if (Number.isSafeInteger(owner) && owner > 0) {
|
|
729
|
+
try {
|
|
730
|
+
process.kill(owner, 0);
|
|
731
|
+
} catch (error) {
|
|
732
|
+
if (error instanceof Error && "code" in error && error.code === "ESRCH") {
|
|
733
|
+
fs4.unlinkSync(lockPath);
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
const lock = fs4.openSync(lockPath, "wx", 384);
|
|
739
|
+
fs4.writeSync(lock, String(process.pid));
|
|
740
|
+
return lock;
|
|
741
|
+
}
|
|
742
|
+
function readSessionCloseout(file) {
|
|
743
|
+
if (!fs4.existsSync(file)) return void 0;
|
|
744
|
+
const value = JSON.parse(fs4.readFileSync(file, "utf8"));
|
|
745
|
+
if (value.version !== "snipara.session_closeout.v1" || typeof value.workspace !== "string" || typeof value.projectId !== "string" || typeof value.checkpoint?.sessionId !== "string" || typeof value.checkpoint.summary !== "string" || !Array.isArray(value.checkpoint.files) || !value.checkpoint.files.every((file2) => typeof file2 === "string") || value.status === "saved" && (typeof value.entryId !== "string" || !value.entryId.trim()) || !["pending", "saved", "skipped", "error"].includes(value.status)) {
|
|
746
|
+
throw new Error("Invalid session closeout receipt");
|
|
747
|
+
}
|
|
748
|
+
return value;
|
|
749
|
+
}
|
|
750
|
+
function writeSessionCloseout(file, value) {
|
|
751
|
+
fs4.mkdirSync(path4.dirname(file), { recursive: true, mode: 448 });
|
|
752
|
+
const temporary = `${file}.${(0, import_node_crypto.randomUUID)()}.tmp`;
|
|
753
|
+
fs4.writeFileSync(temporary, JSON.stringify(value, null, 2) + "\n", { mode: 384 });
|
|
754
|
+
fs4.renameSync(temporary, file);
|
|
755
|
+
}
|
|
756
|
+
|
|
693
757
|
// src/api/client.ts
|
|
694
758
|
var CORRELATED_RETRIEVAL_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
695
759
|
"snipara_context_query",
|
|
@@ -708,15 +772,15 @@ function withCompanionRetrievalClient(toolName, args) {
|
|
|
708
772
|
};
|
|
709
773
|
}
|
|
710
774
|
function getSniparaTokenStorePath() {
|
|
711
|
-
return
|
|
775
|
+
return path5.join(os3.homedir(), ".snipara", "tokens.json");
|
|
712
776
|
}
|
|
713
777
|
function loadProjectApiKeyFromTokenStore(projectIdentifier, currentApiKey) {
|
|
714
778
|
const tokensPath = getSniparaTokenStorePath();
|
|
715
|
-
if (!
|
|
779
|
+
if (!fs5.existsSync(tokensPath)) {
|
|
716
780
|
return null;
|
|
717
781
|
}
|
|
718
782
|
try {
|
|
719
|
-
const raw =
|
|
783
|
+
const raw = fs5.readFileSync(tokensPath, "utf8");
|
|
720
784
|
const parsed = JSON.parse(raw);
|
|
721
785
|
const direct = parsed[projectIdentifier];
|
|
722
786
|
if (direct?.api_key && direct.api_key !== currentApiKey) {
|
|
@@ -1100,13 +1164,41 @@ var RLMClient = class {
|
|
|
1100
1164
|
};
|
|
1101
1165
|
}
|
|
1102
1166
|
/**
|
|
1103
|
-
* Persist
|
|
1167
|
+
* Persist an explicit bounded checkpoint to the hosted journal. An event
|
|
1168
|
+
* acknowledgement is not a persistence receipt.
|
|
1104
1169
|
*/
|
|
1105
|
-
async persistSession() {
|
|
1170
|
+
async persistSession(input = {}) {
|
|
1171
|
+
const checkpoint = normalizeSessionCheckpoint({
|
|
1172
|
+
...input,
|
|
1173
|
+
sessionId: input.sessionId ?? this.config.sessionId ?? "unknown"
|
|
1174
|
+
});
|
|
1175
|
+
if (!checkpoint.summary && checkpoint.files.length === 0) {
|
|
1176
|
+
return {
|
|
1177
|
+
success: false,
|
|
1178
|
+
status: "skipped",
|
|
1179
|
+
session_id: checkpoint.sessionId,
|
|
1180
|
+
files_tracked: 0
|
|
1181
|
+
};
|
|
1182
|
+
}
|
|
1183
|
+
const receipt = await this.journalAppend(
|
|
1184
|
+
[
|
|
1185
|
+
"Checkpoint: session-end",
|
|
1186
|
+
`Session: ${checkpoint.sessionId}`,
|
|
1187
|
+
checkpoint.summary ? `Summary: ${checkpoint.summary}` : "Summary: Session file checkpoint",
|
|
1188
|
+
checkpoint.files.length ? `Files: ${checkpoint.files.join(", ")}` : ""
|
|
1189
|
+
].filter(Boolean).join("\n"),
|
|
1190
|
+
["companion", "checkpoint", "session-end"]
|
|
1191
|
+
);
|
|
1192
|
+
if (receipt.success === false || typeof receipt.entry_id !== "string" || !receipt.entry_id.trim()) {
|
|
1193
|
+
throw new Error("Hosted journal did not confirm a persisted entry");
|
|
1194
|
+
}
|
|
1106
1195
|
return {
|
|
1107
1196
|
success: true,
|
|
1108
|
-
|
|
1109
|
-
|
|
1197
|
+
status: "saved",
|
|
1198
|
+
session_id: checkpoint.sessionId,
|
|
1199
|
+
files_tracked: checkpoint.files.length,
|
|
1200
|
+
entry_id: receipt.entry_id,
|
|
1201
|
+
date: receipt.date
|
|
1110
1202
|
};
|
|
1111
1203
|
}
|
|
1112
1204
|
/**
|
|
@@ -1748,9 +1840,9 @@ var RLMClient = class {
|
|
|
1748
1840
|
...maxTokens ? { max_tokens: maxTokens } : {}
|
|
1749
1841
|
});
|
|
1750
1842
|
}
|
|
1751
|
-
async uploadDocument(
|
|
1843
|
+
async uploadDocument(path46, content, options = {}) {
|
|
1752
1844
|
return this.mcpCall("snipara_upload_document", {
|
|
1753
|
-
path:
|
|
1845
|
+
path: path46,
|
|
1754
1846
|
content,
|
|
1755
1847
|
...options.kind ? { kind: options.kind } : {},
|
|
1756
1848
|
...options.format ? { format: options.format } : {},
|
|
@@ -1877,9 +1969,9 @@ var RLMClient = class {
|
|
|
1877
1969
|
...maxTokens ? { max_tokens: maxTokens } : {}
|
|
1878
1970
|
});
|
|
1879
1971
|
}
|
|
1880
|
-
async loadDocument(
|
|
1972
|
+
async loadDocument(path46) {
|
|
1881
1973
|
return this.mcpCall("snipara_load_document", {
|
|
1882
|
-
path:
|
|
1974
|
+
path: path46
|
|
1883
1975
|
});
|
|
1884
1976
|
}
|
|
1885
1977
|
async getSessionMemories(maxCriticalTokens, maxDailyTokens, includeYesterday) {
|
|
@@ -1945,8 +2037,8 @@ function createClient(timeout, options = {}) {
|
|
|
1945
2037
|
|
|
1946
2038
|
// src/commands/automations.ts
|
|
1947
2039
|
var crypto = __toESM(require("crypto"));
|
|
1948
|
-
var
|
|
1949
|
-
var
|
|
2040
|
+
var fs6 = __toESM(require("fs"));
|
|
2041
|
+
var path6 = __toESM(require("path"));
|
|
1950
2042
|
var AUTOMATION_MANIFEST_RELATIVE_PATH = ".snipara/automations/manifest.json";
|
|
1951
2043
|
var MANIFEST_VERSION = 1;
|
|
1952
2044
|
var SUPPORTED_CLIENTS = /* @__PURE__ */ new Set([
|
|
@@ -2061,20 +2153,20 @@ function canInstallNativeHookBundle(client) {
|
|
|
2061
2153
|
return NATIVE_HOOK_CAPABLE_CLIENTS.has(client);
|
|
2062
2154
|
}
|
|
2063
2155
|
function normalizeProjectDir(dir) {
|
|
2064
|
-
return
|
|
2156
|
+
return path6.resolve(dir || process.cwd());
|
|
2065
2157
|
}
|
|
2066
2158
|
function normalizeRelativePath(filePath) {
|
|
2067
|
-
const normalized =
|
|
2068
|
-
if (normalized === "." || normalized.startsWith("../") || normalized.includes("/../") ||
|
|
2159
|
+
const normalized = path6.posix.normalize(filePath.replace(/\\/g, "/"));
|
|
2160
|
+
if (normalized === "." || normalized.startsWith("../") || normalized.includes("/../") || path6.isAbsolute(filePath)) {
|
|
2069
2161
|
throw new Error(`Unsafe automation file path: ${filePath}`);
|
|
2070
2162
|
}
|
|
2071
2163
|
return normalized;
|
|
2072
2164
|
}
|
|
2073
2165
|
function resolveTargetPath(projectDir, filePath) {
|
|
2074
2166
|
const normalized = normalizeRelativePath(filePath);
|
|
2075
|
-
const target =
|
|
2076
|
-
const root =
|
|
2077
|
-
if (target !== root && !target.startsWith(`${root}${
|
|
2167
|
+
const target = path6.resolve(projectDir, normalized);
|
|
2168
|
+
const root = path6.resolve(projectDir);
|
|
2169
|
+
if (target !== root && !target.startsWith(`${root}${path6.sep}`)) {
|
|
2078
2170
|
throw new Error(`Automation file escapes project directory: ${filePath}`);
|
|
2079
2171
|
}
|
|
2080
2172
|
return target;
|
|
@@ -2234,21 +2326,21 @@ function prepareBundleForLocalInstall(client, bundle) {
|
|
|
2234
2326
|
};
|
|
2235
2327
|
}
|
|
2236
2328
|
function readFileIfExists(filePath) {
|
|
2237
|
-
if (!
|
|
2329
|
+
if (!fs6.existsSync(filePath)) {
|
|
2238
2330
|
return null;
|
|
2239
2331
|
}
|
|
2240
|
-
return
|
|
2332
|
+
return fs6.readFileSync(filePath, "utf8");
|
|
2241
2333
|
}
|
|
2242
2334
|
function getAutomationManifestPath(projectDir = process.cwd()) {
|
|
2243
|
-
return
|
|
2335
|
+
return path6.join(normalizeProjectDir(projectDir), AUTOMATION_MANIFEST_RELATIVE_PATH);
|
|
2244
2336
|
}
|
|
2245
2337
|
function loadAutomationManifest(projectDir = process.cwd()) {
|
|
2246
2338
|
const manifestPath2 = getAutomationManifestPath(projectDir);
|
|
2247
|
-
if (!
|
|
2339
|
+
if (!fs6.existsSync(manifestPath2)) {
|
|
2248
2340
|
return null;
|
|
2249
2341
|
}
|
|
2250
2342
|
try {
|
|
2251
|
-
const parsed = JSON.parse(
|
|
2343
|
+
const parsed = JSON.parse(fs6.readFileSync(manifestPath2, "utf8"));
|
|
2252
2344
|
if (!Array.isArray(parsed.files)) {
|
|
2253
2345
|
return null;
|
|
2254
2346
|
}
|
|
@@ -2259,8 +2351,8 @@ function loadAutomationManifest(projectDir = process.cwd()) {
|
|
|
2259
2351
|
}
|
|
2260
2352
|
function writeAutomationManifest(projectDir, manifest) {
|
|
2261
2353
|
const manifestPath2 = getAutomationManifestPath(projectDir);
|
|
2262
|
-
|
|
2263
|
-
|
|
2354
|
+
fs6.mkdirSync(path6.dirname(manifestPath2), { recursive: true });
|
|
2355
|
+
fs6.writeFileSync(manifestPath2, `${JSON.stringify(manifest, null, 2)}
|
|
2264
2356
|
`, "utf8");
|
|
2265
2357
|
}
|
|
2266
2358
|
function findManifestFile(manifest, filePath) {
|
|
@@ -2373,10 +2465,10 @@ function manifestFromBundle(args) {
|
|
|
2373
2465
|
function writeBundleFile(projectDir, file, content = file.content) {
|
|
2374
2466
|
const relativePath2 = normalizeRelativePath(file.path);
|
|
2375
2467
|
const targetPath = resolveTargetPath(projectDir, relativePath2);
|
|
2376
|
-
|
|
2377
|
-
|
|
2468
|
+
fs6.mkdirSync(path6.dirname(targetPath), { recursive: true });
|
|
2469
|
+
fs6.writeFileSync(targetPath, content, "utf8");
|
|
2378
2470
|
if (shouldMakeExecutable(relativePath2)) {
|
|
2379
|
-
|
|
2471
|
+
fs6.chmodSync(targetPath, 493);
|
|
2380
2472
|
}
|
|
2381
2473
|
}
|
|
2382
2474
|
async function fetchAutomationBundle(args) {
|
|
@@ -2578,13 +2670,13 @@ var import_typescript = __toESM(require("typescript"));
|
|
|
2578
2670
|
|
|
2579
2671
|
// src/commands/context-pack.ts
|
|
2580
2672
|
var crypto2 = __toESM(require("crypto"));
|
|
2581
|
-
var
|
|
2582
|
-
var
|
|
2673
|
+
var fs7 = __toESM(require("fs"));
|
|
2674
|
+
var path7 = __toESM(require("path"));
|
|
2583
2675
|
var DEFAULT_MAX_BYTES = 2 * 1024 * 1024;
|
|
2584
|
-
var BASE_RELATIVE_PATH =
|
|
2585
|
-
var BLOBS_RELATIVE_PATH =
|
|
2586
|
-
var MANIFESTS_RELATIVE_PATH =
|
|
2587
|
-
var LATEST_RELATIVE_PATH =
|
|
2676
|
+
var BASE_RELATIVE_PATH = path7.join(".snipara", "context-pack");
|
|
2677
|
+
var BLOBS_RELATIVE_PATH = path7.join(BASE_RELATIVE_PATH, "blobs");
|
|
2678
|
+
var MANIFESTS_RELATIVE_PATH = path7.join(BASE_RELATIVE_PATH, "items");
|
|
2679
|
+
var LATEST_RELATIVE_PATH = path7.join(BASE_RELATIVE_PATH, "latest.json");
|
|
2588
2680
|
var STORAGE_GITIGNORE_CONTENT = "*\n!.gitignore\n";
|
|
2589
2681
|
var SECRET_REDACTION_PATTERNS = [
|
|
2590
2682
|
[
|
|
@@ -2600,14 +2692,14 @@ var SECRET_REDACTION_PATTERNS = [
|
|
|
2600
2692
|
]
|
|
2601
2693
|
];
|
|
2602
2694
|
function resolveRepoRoot(cwd) {
|
|
2603
|
-
return findWorkspaceRoot(
|
|
2695
|
+
return findWorkspaceRoot(path7.resolve(cwd), true) ?? path7.resolve(cwd);
|
|
2604
2696
|
}
|
|
2605
2697
|
function normalizeRelativePath2(value) {
|
|
2606
|
-
return value.split(
|
|
2698
|
+
return value.split(path7.sep).join("/");
|
|
2607
2699
|
}
|
|
2608
2700
|
function toRepoRelative(repoRoot, absolutePath) {
|
|
2609
|
-
const relative15 =
|
|
2610
|
-
return normalizeRelativePath2(relative15 ||
|
|
2701
|
+
const relative15 = path7.relative(repoRoot, absolutePath);
|
|
2702
|
+
return normalizeRelativePath2(relative15 || path7.basename(absolutePath));
|
|
2611
2703
|
}
|
|
2612
2704
|
function sha2562(content) {
|
|
2613
2705
|
return crypto2.createHash("sha256").update(content, "utf8").digest("hex");
|
|
@@ -2641,18 +2733,18 @@ function optionalPositiveInteger(value) {
|
|
|
2641
2733
|
return Number.isFinite(value) && value !== void 0 && value > 0 ? Math.floor(value) : void 0;
|
|
2642
2734
|
}
|
|
2643
2735
|
function ensureDir(dir, mode = 448) {
|
|
2644
|
-
|
|
2736
|
+
fs7.mkdirSync(dir, { recursive: true, mode });
|
|
2645
2737
|
}
|
|
2646
2738
|
function maybeReadJsonFile(filePath) {
|
|
2647
2739
|
try {
|
|
2648
|
-
return JSON.parse(
|
|
2740
|
+
return JSON.parse(fs7.readFileSync(filePath, "utf8"));
|
|
2649
2741
|
} catch {
|
|
2650
2742
|
return null;
|
|
2651
2743
|
}
|
|
2652
2744
|
}
|
|
2653
2745
|
function writeJsonFile(filePath, value) {
|
|
2654
|
-
ensureDir(
|
|
2655
|
-
|
|
2746
|
+
ensureDir(path7.dirname(filePath));
|
|
2747
|
+
fs7.writeFileSync(filePath, `${JSON.stringify(value, null, 2)}
|
|
2656
2748
|
`, {
|
|
2657
2749
|
encoding: "utf8",
|
|
2658
2750
|
mode: 384
|
|
@@ -2660,9 +2752,9 @@ function writeJsonFile(filePath, value) {
|
|
|
2660
2752
|
}
|
|
2661
2753
|
function ensureStorageGitignore(paths) {
|
|
2662
2754
|
ensureDir(paths.baseDir);
|
|
2663
|
-
const gitignorePath =
|
|
2664
|
-
if (!
|
|
2665
|
-
|
|
2755
|
+
const gitignorePath = path7.join(paths.baseDir, ".gitignore");
|
|
2756
|
+
if (!fs7.existsSync(gitignorePath)) {
|
|
2757
|
+
fs7.writeFileSync(gitignorePath, STORAGE_GITIGNORE_CONTENT, {
|
|
2666
2758
|
encoding: "utf8",
|
|
2667
2759
|
mode: 384
|
|
2668
2760
|
});
|
|
@@ -2725,19 +2817,19 @@ function readManifest(paths, manifestPath2) {
|
|
|
2725
2817
|
};
|
|
2726
2818
|
}
|
|
2727
2819
|
function listManifestPaths(paths) {
|
|
2728
|
-
if (!
|
|
2820
|
+
if (!fs7.existsSync(paths.manifestsDir)) {
|
|
2729
2821
|
return [];
|
|
2730
2822
|
}
|
|
2731
|
-
return
|
|
2823
|
+
return fs7.readdirSync(paths.manifestsDir).filter((name) => name.endsWith(".json")).sort().map((name) => path7.join(paths.manifestsDir, name));
|
|
2732
2824
|
}
|
|
2733
2825
|
function loadRecords(paths) {
|
|
2734
2826
|
return listManifestPaths(paths).map((manifestPath2) => readManifest(paths, manifestPath2)).filter((record2) => record2 !== null);
|
|
2735
2827
|
}
|
|
2736
2828
|
function recordManifestPath(paths, id) {
|
|
2737
|
-
return
|
|
2829
|
+
return path7.join(paths.manifestsDir, `${id}.json`);
|
|
2738
2830
|
}
|
|
2739
2831
|
function recordBlobPath(paths, sha) {
|
|
2740
|
-
return
|
|
2832
|
+
return path7.join(paths.blobsDir, `${sha}.txt`);
|
|
2741
2833
|
}
|
|
2742
2834
|
function writeLatestPointer(paths, record2) {
|
|
2743
2835
|
writeJsonFile(paths.latestPath, {
|
|
@@ -2750,8 +2842,8 @@ function writeLatestPointer(paths, record2) {
|
|
|
2750
2842
|
function refreshLatestPointer(paths) {
|
|
2751
2843
|
const records = loadRecords(paths).sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));
|
|
2752
2844
|
if (records.length === 0) {
|
|
2753
|
-
if (
|
|
2754
|
-
|
|
2845
|
+
if (fs7.existsSync(paths.latestPath)) {
|
|
2846
|
+
fs7.rmSync(paths.latestPath);
|
|
2755
2847
|
}
|
|
2756
2848
|
return;
|
|
2757
2849
|
}
|
|
@@ -2759,13 +2851,13 @@ function refreshLatestPointer(paths) {
|
|
|
2759
2851
|
}
|
|
2760
2852
|
function getContextPackStoragePaths(cwd = process.cwd()) {
|
|
2761
2853
|
const repoRoot = resolveRepoRoot(cwd);
|
|
2762
|
-
const baseDir =
|
|
2854
|
+
const baseDir = path7.join(repoRoot, BASE_RELATIVE_PATH);
|
|
2763
2855
|
return {
|
|
2764
2856
|
repoRoot,
|
|
2765
2857
|
baseDir,
|
|
2766
|
-
blobsDir:
|
|
2767
|
-
manifestsDir:
|
|
2768
|
-
latestPath:
|
|
2858
|
+
blobsDir: path7.join(repoRoot, BLOBS_RELATIVE_PATH),
|
|
2859
|
+
manifestsDir: path7.join(repoRoot, MANIFESTS_RELATIVE_PATH),
|
|
2860
|
+
latestPath: path7.join(repoRoot, LATEST_RELATIVE_PATH)
|
|
2769
2861
|
};
|
|
2770
2862
|
}
|
|
2771
2863
|
function packContext(options) {
|
|
@@ -2823,15 +2915,15 @@ function packContext(options) {
|
|
|
2823
2915
|
warnings,
|
|
2824
2916
|
storage: {
|
|
2825
2917
|
baseRelativePath: normalizeRelativePath2(BASE_RELATIVE_PATH),
|
|
2826
|
-
manifestRelativePath: normalizeRelativePath2(
|
|
2827
|
-
blobRelativePath: normalizeRelativePath2(
|
|
2918
|
+
manifestRelativePath: normalizeRelativePath2(path7.relative(paths.repoRoot, manifestPath2)),
|
|
2919
|
+
blobRelativePath: normalizeRelativePath2(path7.relative(paths.repoRoot, blobPath))
|
|
2828
2920
|
}
|
|
2829
2921
|
};
|
|
2830
2922
|
ensureStorageGitignore(paths);
|
|
2831
2923
|
ensureDir(paths.blobsDir);
|
|
2832
2924
|
ensureDir(paths.manifestsDir);
|
|
2833
|
-
if (!
|
|
2834
|
-
|
|
2925
|
+
if (!fs7.existsSync(blobPath)) {
|
|
2926
|
+
fs7.writeFileSync(blobPath, content, { encoding: "utf8", mode: 384 });
|
|
2835
2927
|
}
|
|
2836
2928
|
writeJsonFile(manifestPath2, record2);
|
|
2837
2929
|
writeLatestPointer(paths, record2);
|
|
@@ -2854,7 +2946,7 @@ function resolveContextPackRecord(idOrRef, cwd = process.cwd()) {
|
|
|
2854
2946
|
if (!pointer) {
|
|
2855
2947
|
throw new Error("No latest context pack is available.");
|
|
2856
2948
|
}
|
|
2857
|
-
const manifestPath2 =
|
|
2949
|
+
const manifestPath2 = path7.join(paths.repoRoot, pointer.manifestRelativePath);
|
|
2858
2950
|
const record3 = readManifest(paths, manifestPath2);
|
|
2859
2951
|
if (!record3) {
|
|
2860
2952
|
throw new Error(`Latest context pack manifest is missing or invalid: ${pointer.id}`);
|
|
@@ -2881,13 +2973,13 @@ function resolveContextPackRecord(idOrRef, cwd = process.cwd()) {
|
|
|
2881
2973
|
}
|
|
2882
2974
|
function retrieveContextPack(idOrRef, cwd = process.cwd()) {
|
|
2883
2975
|
const { paths, record: record2, manifestPath: manifestPath2 } = resolveContextPackRecord(idOrRef, cwd);
|
|
2884
|
-
const blobPath =
|
|
2885
|
-
if (!
|
|
2976
|
+
const blobPath = path7.join(paths.repoRoot, record2.storage.blobRelativePath);
|
|
2977
|
+
if (!fs7.existsSync(blobPath)) {
|
|
2886
2978
|
throw new Error(`Context pack blob is missing for ${record2.id}`);
|
|
2887
2979
|
}
|
|
2888
2980
|
return {
|
|
2889
2981
|
record: record2,
|
|
2890
|
-
content:
|
|
2982
|
+
content: fs7.readFileSync(blobPath, "utf8"),
|
|
2891
2983
|
baseDir: paths.baseDir,
|
|
2892
2984
|
manifestPath: manifestPath2,
|
|
2893
2985
|
blobPath
|
|
@@ -2935,8 +3027,8 @@ function cleanContextPacks(options = {}) {
|
|
|
2935
3027
|
});
|
|
2936
3028
|
if (!options.dryRun) {
|
|
2937
3029
|
for (const record2 of selected) {
|
|
2938
|
-
|
|
2939
|
-
|
|
3030
|
+
fs7.rmSync(recordManifestPath(paths, record2.id), { force: true });
|
|
3031
|
+
fs7.rmSync(path7.join(paths.repoRoot, record2.storage.blobRelativePath), { force: true });
|
|
2940
3032
|
}
|
|
2941
3033
|
refreshLatestPointer(paths);
|
|
2942
3034
|
}
|
|
@@ -2951,8 +3043,8 @@ function cleanContextPacks(options = {}) {
|
|
|
2951
3043
|
}
|
|
2952
3044
|
function readPackContent(options) {
|
|
2953
3045
|
if (options.file) {
|
|
2954
|
-
const filePath =
|
|
2955
|
-
const content =
|
|
3046
|
+
const filePath = path7.resolve(options.cwd ?? process.cwd(), options.file);
|
|
3047
|
+
const content = fs7.readFileSync(filePath, "utf8");
|
|
2956
3048
|
const paths = getContextPackStoragePaths(options.cwd ?? process.cwd());
|
|
2957
3049
|
return {
|
|
2958
3050
|
content,
|
|
@@ -3016,9 +3108,9 @@ async function contextPackPackCommand(options) {
|
|
|
3016
3108
|
async function contextPackRetrieveCommand(idOrRef, options = {}) {
|
|
3017
3109
|
const result = retrieveContextPack(idOrRef, options.cwd);
|
|
3018
3110
|
if (options.output) {
|
|
3019
|
-
const outputPath =
|
|
3020
|
-
ensureDir(
|
|
3021
|
-
|
|
3111
|
+
const outputPath = path7.resolve(options.cwd ?? process.cwd(), options.output);
|
|
3112
|
+
ensureDir(path7.dirname(outputPath));
|
|
3113
|
+
fs7.writeFileSync(outputPath, result.content, { encoding: "utf8", mode: 384 });
|
|
3022
3114
|
if (options.json) {
|
|
3023
3115
|
const payload = options.metadataOnly ? {
|
|
3024
3116
|
record: result.record,
|
|
@@ -7252,7 +7344,7 @@ async function startLocalCodeHttpServer(options) {
|
|
|
7252
7344
|
const server = import_http.default.createServer((req, res) => {
|
|
7253
7345
|
void handleLocalCodeHttpRequest(req, res, options);
|
|
7254
7346
|
});
|
|
7255
|
-
await new Promise((
|
|
7347
|
+
await new Promise((resolve26, reject) => {
|
|
7256
7348
|
server.once("error", reject);
|
|
7257
7349
|
server.listen(port, host, () => {
|
|
7258
7350
|
server.off("error", reject);
|
|
@@ -7270,12 +7362,12 @@ async function startLocalCodeHttpServer(options) {
|
|
|
7270
7362
|
} else {
|
|
7271
7363
|
console.log(`Snipara local code overlay HTTP server listening on ${ready.baseUrl}`);
|
|
7272
7364
|
}
|
|
7273
|
-
|
|
7365
|
+
resolve26();
|
|
7274
7366
|
});
|
|
7275
7367
|
});
|
|
7276
|
-
await new Promise((
|
|
7368
|
+
await new Promise((resolve26) => {
|
|
7277
7369
|
const shutdown = () => {
|
|
7278
|
-
server.close(() =>
|
|
7370
|
+
server.close(() => resolve26());
|
|
7279
7371
|
};
|
|
7280
7372
|
process.once("SIGINT", shutdown);
|
|
7281
7373
|
process.once("SIGTERM", shutdown);
|
|
@@ -7375,8 +7467,8 @@ async function startLocalCodeMcpStdioServer(options) {
|
|
|
7375
7467
|
}
|
|
7376
7468
|
}
|
|
7377
7469
|
});
|
|
7378
|
-
await new Promise((
|
|
7379
|
-
process.stdin.once("end",
|
|
7470
|
+
await new Promise((resolve26) => {
|
|
7471
|
+
process.stdin.once("end", resolve26);
|
|
7380
7472
|
process.once("SIGINT", () => process.exit(0));
|
|
7381
7473
|
process.once("SIGTERM", () => process.exit(0));
|
|
7382
7474
|
});
|
|
@@ -7394,8 +7486,8 @@ async function codeMcpCommand(options) {
|
|
|
7394
7486
|
}
|
|
7395
7487
|
|
|
7396
7488
|
// src/commands/project-auth.ts
|
|
7397
|
-
var
|
|
7398
|
-
var
|
|
7489
|
+
var fs10 = __toESM(require("fs"));
|
|
7490
|
+
var path10 = __toESM(require("path"));
|
|
7399
7491
|
var os4 = __toESM(require("os"));
|
|
7400
7492
|
var import_child_process3 = require("child_process");
|
|
7401
7493
|
var PROJECT_DEVICE_CLIENT_ID = "snipara-companion";
|
|
@@ -7403,7 +7495,7 @@ var DEVICE_GRANT_TYPE = "urn:ietf:params:oauth:grant-type:device_code";
|
|
|
7403
7495
|
var DEVICE_POLL_TIMEOUT_MS = 15 * 60 * 1e3;
|
|
7404
7496
|
var DEFAULT_DEVICE_POLL_INTERVAL_SECONDS = 5;
|
|
7405
7497
|
function sleep(ms) {
|
|
7406
|
-
return new Promise((
|
|
7498
|
+
return new Promise((resolve26) => setTimeout(resolve26, ms));
|
|
7407
7499
|
}
|
|
7408
7500
|
function openBrowser(url) {
|
|
7409
7501
|
try {
|
|
@@ -7418,14 +7510,14 @@ function openBrowser(url) {
|
|
|
7418
7510
|
}
|
|
7419
7511
|
}
|
|
7420
7512
|
function getSniparaTokenStorePath2() {
|
|
7421
|
-
return
|
|
7513
|
+
return path10.join(os4.homedir(), ".snipara", "tokens.json");
|
|
7422
7514
|
}
|
|
7423
7515
|
function rememberProjectApiKey(projectId, projectSlug, apiKey) {
|
|
7424
7516
|
const tokensPath = getSniparaTokenStorePath2();
|
|
7425
7517
|
let tokens = {};
|
|
7426
|
-
if (
|
|
7518
|
+
if (fs10.existsSync(tokensPath)) {
|
|
7427
7519
|
try {
|
|
7428
|
-
const parsed = JSON.parse(
|
|
7520
|
+
const parsed = JSON.parse(fs10.readFileSync(tokensPath, "utf8"));
|
|
7429
7521
|
if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
|
|
7430
7522
|
tokens = parsed;
|
|
7431
7523
|
}
|
|
@@ -7439,15 +7531,15 @@ function rememberProjectApiKey(projectId, projectSlug, apiKey) {
|
|
|
7439
7531
|
project_slug: projectSlug,
|
|
7440
7532
|
api_key: apiKey
|
|
7441
7533
|
};
|
|
7442
|
-
|
|
7443
|
-
|
|
7534
|
+
fs10.mkdirSync(path10.dirname(tokensPath), { recursive: true });
|
|
7535
|
+
fs10.writeFileSync(tokensPath, `${JSON.stringify(tokens, null, 2)}
|
|
7444
7536
|
`, "utf8");
|
|
7445
7537
|
}
|
|
7446
7538
|
function writeProjectBinding(projectDir, projectSlug) {
|
|
7447
|
-
const bindingDir =
|
|
7448
|
-
const bindingPath =
|
|
7449
|
-
|
|
7450
|
-
|
|
7539
|
+
const bindingDir = path10.join(projectDir, ".snipara");
|
|
7540
|
+
const bindingPath = path10.join(bindingDir, "project");
|
|
7541
|
+
fs10.mkdirSync(bindingDir, { recursive: true });
|
|
7542
|
+
fs10.writeFileSync(bindingPath, `${projectSlug}
|
|
7451
7543
|
`, "utf8");
|
|
7452
7544
|
}
|
|
7453
7545
|
function normalizeLocalProjectValue(value) {
|
|
@@ -7481,23 +7573,23 @@ function addLocalIdentifier(identifiers, seen, source2, value) {
|
|
|
7481
7573
|
}
|
|
7482
7574
|
function readWorkspaceCompanionProject(projectDir) {
|
|
7483
7575
|
const configPath = getConfigPath({ cwd: projectDir, scope: "workspace" });
|
|
7484
|
-
if (!
|
|
7576
|
+
if (!fs10.existsSync(configPath)) {
|
|
7485
7577
|
return null;
|
|
7486
7578
|
}
|
|
7487
7579
|
try {
|
|
7488
|
-
const parsed = JSON.parse(
|
|
7580
|
+
const parsed = JSON.parse(fs10.readFileSync(configPath, "utf8"));
|
|
7489
7581
|
return normalizeLocalProjectValue(parsed.projectId ?? parsed.project_id ?? parsed.project);
|
|
7490
7582
|
} catch {
|
|
7491
7583
|
return null;
|
|
7492
7584
|
}
|
|
7493
7585
|
}
|
|
7494
7586
|
function readProjectBinding(projectDir) {
|
|
7495
|
-
const bindingPath =
|
|
7496
|
-
if (!
|
|
7587
|
+
const bindingPath = path10.join(projectDir, ".snipara", "project");
|
|
7588
|
+
if (!fs10.existsSync(bindingPath)) {
|
|
7497
7589
|
return null;
|
|
7498
7590
|
}
|
|
7499
7591
|
try {
|
|
7500
|
-
const content =
|
|
7592
|
+
const content = fs10.readFileSync(bindingPath, "utf8").trim();
|
|
7501
7593
|
if (!content) {
|
|
7502
7594
|
return null;
|
|
7503
7595
|
}
|
|
@@ -7535,12 +7627,12 @@ function extractProjectSlugFromMcpUrl(value) {
|
|
|
7535
7627
|
return match?.[1] ? normalizeLocalProjectValue(decodeURIComponent(match[1])) : null;
|
|
7536
7628
|
}
|
|
7537
7629
|
function readProjectFromMcpJson(projectDir) {
|
|
7538
|
-
const configPath =
|
|
7539
|
-
if (!
|
|
7630
|
+
const configPath = path10.join(projectDir, ".mcp.json");
|
|
7631
|
+
if (!fs10.existsSync(configPath)) {
|
|
7540
7632
|
return null;
|
|
7541
7633
|
}
|
|
7542
7634
|
try {
|
|
7543
|
-
const parsed = JSON.parse(
|
|
7635
|
+
const parsed = JSON.parse(fs10.readFileSync(configPath, "utf8"));
|
|
7544
7636
|
for (const [serverName, serverConfig] of Object.entries(parsed.mcpServers ?? {})) {
|
|
7545
7637
|
const endpointSlug = extractProjectSlugFromMcpUrl(serverConfig?.url);
|
|
7546
7638
|
if (endpointSlug) {
|
|
@@ -7778,15 +7870,15 @@ function getNativeHookBlockReason(client) {
|
|
|
7778
7870
|
return reasons[client] ?? "This client is MCP-first; no native hook files are installed.";
|
|
7779
7871
|
}
|
|
7780
7872
|
function ensureCompanionConfigIsGitIgnored(projectDir) {
|
|
7781
|
-
const gitignorePath =
|
|
7873
|
+
const gitignorePath = path11.join(projectDir, ".gitignore");
|
|
7782
7874
|
const ignoreEntry = "/.snipara/companion/";
|
|
7783
|
-
const current =
|
|
7875
|
+
const current = fs11.existsSync(gitignorePath) ? fs11.readFileSync(gitignorePath, "utf8") : "";
|
|
7784
7876
|
const entries = current.split(/\r?\n/).map((entry) => entry.trim());
|
|
7785
7877
|
if (entries.includes(ignoreEntry)) {
|
|
7786
7878
|
return;
|
|
7787
7879
|
}
|
|
7788
7880
|
const separator = current.length === 0 || current.endsWith("\n") ? "" : "\n";
|
|
7789
|
-
|
|
7881
|
+
fs11.writeFileSync(gitignorePath, `${current}${separator}${ignoreEntry}
|
|
7790
7882
|
`, "utf8");
|
|
7791
7883
|
}
|
|
7792
7884
|
function formatClientName(client) {
|
|
@@ -7945,14 +8037,14 @@ alwaysApply: true
|
|
|
7945
8037
|
${body}`;
|
|
7946
8038
|
}
|
|
7947
8039
|
function ensureWorkflowInstructionFile(projectDir, relativePath2, generatedContent) {
|
|
7948
|
-
const filePath =
|
|
7949
|
-
const currentContent =
|
|
8040
|
+
const filePath = path11.join(projectDir, relativePath2);
|
|
8041
|
+
const currentContent = fs11.existsSync(filePath) ? fs11.readFileSync(filePath, "utf8") : void 0;
|
|
7950
8042
|
const nextContent = relativePath2 === ".cursor/rules/snipara.mdc" ? mergeCursorRuleInstructionContent(relativePath2, generatedContent, currentContent) : mergeWorkflowInstructionContent(relativePath2, generatedContent, currentContent);
|
|
7951
8043
|
if (currentContent === nextContent) {
|
|
7952
8044
|
return { relativePath: relativePath2, action: "unchanged" };
|
|
7953
8045
|
}
|
|
7954
|
-
|
|
7955
|
-
|
|
8046
|
+
fs11.mkdirSync(path11.dirname(filePath), { recursive: true });
|
|
8047
|
+
fs11.writeFileSync(filePath, nextContent);
|
|
7956
8048
|
return { relativePath: relativePath2, action: currentContent === void 0 ? "created" : "updated" };
|
|
7957
8049
|
}
|
|
7958
8050
|
function ensureWorkflowInstructions(projectDir, projectSlug, client) {
|
|
@@ -7975,10 +8067,10 @@ function prompt(question) {
|
|
|
7975
8067
|
input: process.stdin,
|
|
7976
8068
|
output: process.stdout
|
|
7977
8069
|
});
|
|
7978
|
-
return new Promise((
|
|
8070
|
+
return new Promise((resolve26) => {
|
|
7979
8071
|
rl.question(question, (answer) => {
|
|
7980
8072
|
rl.close();
|
|
7981
|
-
|
|
8073
|
+
resolve26(answer.trim());
|
|
7982
8074
|
});
|
|
7983
8075
|
});
|
|
7984
8076
|
}
|
|
@@ -8528,38 +8620,38 @@ fi
|
|
|
8528
8620
|
function installHooks(projectDir, projectId, _apiKey, client) {
|
|
8529
8621
|
try {
|
|
8530
8622
|
if (client === "cursor") {
|
|
8531
|
-
const cursorDir =
|
|
8532
|
-
const hooksDir2 =
|
|
8533
|
-
const hooksPath =
|
|
8534
|
-
if (!
|
|
8535
|
-
|
|
8536
|
-
}
|
|
8537
|
-
if (!
|
|
8538
|
-
|
|
8539
|
-
}
|
|
8540
|
-
const preCompactPath =
|
|
8541
|
-
|
|
8542
|
-
|
|
8543
|
-
const sessionStartPath =
|
|
8544
|
-
|
|
8545
|
-
|
|
8546
|
-
const beforeReadPath =
|
|
8547
|
-
|
|
8548
|
-
|
|
8549
|
-
const afterEditPath =
|
|
8550
|
-
|
|
8551
|
-
|
|
8552
|
-
|
|
8623
|
+
const cursorDir = path11.join(projectDir, ".cursor");
|
|
8624
|
+
const hooksDir2 = path11.join(cursorDir, "hooks");
|
|
8625
|
+
const hooksPath = path11.join(cursorDir, "hooks.json");
|
|
8626
|
+
if (!fs11.existsSync(cursorDir)) {
|
|
8627
|
+
fs11.mkdirSync(cursorDir, { recursive: true });
|
|
8628
|
+
}
|
|
8629
|
+
if (!fs11.existsSync(hooksDir2)) {
|
|
8630
|
+
fs11.mkdirSync(hooksDir2, { recursive: true });
|
|
8631
|
+
}
|
|
8632
|
+
const preCompactPath = path11.join(hooksDir2, "preCompact.sh");
|
|
8633
|
+
fs11.writeFileSync(preCompactPath, generateCursorPreCompactScript(projectId));
|
|
8634
|
+
fs11.chmodSync(preCompactPath, "755");
|
|
8635
|
+
const sessionStartPath = path11.join(hooksDir2, "sessionStart.sh");
|
|
8636
|
+
fs11.writeFileSync(sessionStartPath, generateCursorSessionStartScript(projectId));
|
|
8637
|
+
fs11.chmodSync(sessionStartPath, "755");
|
|
8638
|
+
const beforeReadPath = path11.join(hooksDir2, "beforeReadFile.sh");
|
|
8639
|
+
fs11.writeFileSync(beforeReadPath, generateCursorBeforeReadScript());
|
|
8640
|
+
fs11.chmodSync(beforeReadPath, "755");
|
|
8641
|
+
const afterEditPath = path11.join(hooksDir2, "afterFileEdit.sh");
|
|
8642
|
+
fs11.writeFileSync(afterEditPath, generateCursorAfterFileEditScript());
|
|
8643
|
+
fs11.chmodSync(afterEditPath, "755");
|
|
8644
|
+
fs11.writeFileSync(hooksPath, JSON.stringify(generateCursorHookConfig(), null, 2));
|
|
8553
8645
|
return { success: true };
|
|
8554
8646
|
}
|
|
8555
|
-
const claudeDir =
|
|
8556
|
-
const hooksDir =
|
|
8557
|
-
const settingsPath =
|
|
8558
|
-
if (!
|
|
8559
|
-
|
|
8647
|
+
const claudeDir = path11.join(projectDir, ".claude");
|
|
8648
|
+
const hooksDir = path11.join(claudeDir, "hooks");
|
|
8649
|
+
const settingsPath = path11.join(claudeDir, "settings.json");
|
|
8650
|
+
if (!fs11.existsSync(claudeDir)) {
|
|
8651
|
+
fs11.mkdirSync(claudeDir, { recursive: true });
|
|
8560
8652
|
}
|
|
8561
|
-
if (!
|
|
8562
|
-
|
|
8653
|
+
if (!fs11.existsSync(hooksDir)) {
|
|
8654
|
+
fs11.mkdirSync(hooksDir, { recursive: true });
|
|
8563
8655
|
}
|
|
8564
8656
|
const hookScripts = [
|
|
8565
8657
|
["snipara-stuck-guard.sh", generateClaudeStuckGuardScript()],
|
|
@@ -8568,14 +8660,14 @@ function installHooks(projectDir, projectId, _apiKey, client) {
|
|
|
8568
8660
|
["snipara-compact.sh", generateClaudeCompactScript()]
|
|
8569
8661
|
];
|
|
8570
8662
|
for (const [fileName, content] of hookScripts) {
|
|
8571
|
-
const hookPath =
|
|
8572
|
-
|
|
8573
|
-
|
|
8663
|
+
const hookPath = path11.join(hooksDir, fileName);
|
|
8664
|
+
fs11.writeFileSync(hookPath, content);
|
|
8665
|
+
fs11.chmodSync(hookPath, "755");
|
|
8574
8666
|
}
|
|
8575
8667
|
let settings = {};
|
|
8576
|
-
if (
|
|
8668
|
+
if (fs11.existsSync(settingsPath)) {
|
|
8577
8669
|
try {
|
|
8578
|
-
settings = JSON.parse(
|
|
8670
|
+
settings = JSON.parse(fs11.readFileSync(settingsPath, "utf-8"));
|
|
8579
8671
|
} catch {
|
|
8580
8672
|
}
|
|
8581
8673
|
}
|
|
@@ -8584,7 +8676,7 @@ function installHooks(projectDir, projectId, _apiKey, client) {
|
|
|
8584
8676
|
restoreOnSessionStart: true
|
|
8585
8677
|
});
|
|
8586
8678
|
settings = { ...settings, ...hookConfig };
|
|
8587
|
-
|
|
8679
|
+
fs11.writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
|
|
8588
8680
|
return { success: true };
|
|
8589
8681
|
} catch (error) {
|
|
8590
8682
|
return {
|
|
@@ -8720,7 +8812,7 @@ async function initCommand(options) {
|
|
|
8720
8812
|
existingProjectId: existingConfig.projectId,
|
|
8721
8813
|
selectedProject
|
|
8722
8814
|
});
|
|
8723
|
-
const sessionId = `sess_${Date.now()}_${(0,
|
|
8815
|
+
const sessionId = `sess_${Date.now()}_${(0, import_node_crypto2.randomBytes)(6).toString("hex")}`;
|
|
8724
8816
|
saveConfig(
|
|
8725
8817
|
{
|
|
8726
8818
|
apiKey,
|
|
@@ -8933,7 +9025,7 @@ function showConfig() {
|
|
|
8933
9025
|
|
|
8934
9026
|
// src/commands/login.ts
|
|
8935
9027
|
var import_child_process4 = require("child_process");
|
|
8936
|
-
var
|
|
9028
|
+
var import_node_crypto3 = require("crypto");
|
|
8937
9029
|
var USER_KEY_CLIENT_ID = "snipara-cli";
|
|
8938
9030
|
var CLIENT_VERSION = "1.1.20";
|
|
8939
9031
|
var GRANT_TYPE = "urn:ietf:params:oauth:grant-type:device_code";
|
|
@@ -8994,7 +9086,7 @@ async function pollForToken(apiUrl, deviceCode, intervalSeconds) {
|
|
|
8994
9086
|
throw new Error("Login timed out (15 min). Run `snipara-companion login --user-key` again.");
|
|
8995
9087
|
}
|
|
8996
9088
|
function createSessionId() {
|
|
8997
|
-
return `sess_${Date.now()}_${(0,
|
|
9089
|
+
return `sess_${Date.now()}_${(0, import_node_crypto3.randomBytes)(6).toString("hex")}`;
|
|
8998
9090
|
}
|
|
8999
9091
|
async function loginCommand(options = {}) {
|
|
9000
9092
|
const projectDir = options.dir || process.cwd();
|
|
@@ -9075,9 +9167,9 @@ async function userKeyLoginCommand(apiUrl) {
|
|
|
9075
9167
|
|
|
9076
9168
|
// src/cache/query-cache.ts
|
|
9077
9169
|
var crypto5 = __toESM(require("crypto"));
|
|
9078
|
-
var
|
|
9170
|
+
var fs12 = __toESM(require("fs"));
|
|
9079
9171
|
var os5 = __toESM(require("os"));
|
|
9080
|
-
var
|
|
9172
|
+
var path12 = __toESM(require("path"));
|
|
9081
9173
|
var CACHE_VERSION = 2;
|
|
9082
9174
|
var WARM_SNAPSHOT_VERSION = 1;
|
|
9083
9175
|
var SEARCH_MODE = "hybrid";
|
|
@@ -9169,7 +9261,7 @@ var LocalQueryCache = class {
|
|
|
9169
9261
|
}
|
|
9170
9262
|
const key = buildCacheKey(this.scope.workspaceKey, normalizedQuery, options.maxTokens);
|
|
9171
9263
|
const fileName = `${key}.json`;
|
|
9172
|
-
const filePath =
|
|
9264
|
+
const filePath = path12.join(getCacheDir(), fileName);
|
|
9173
9265
|
const now = Date.now();
|
|
9174
9266
|
const payload = {
|
|
9175
9267
|
version: CACHE_VERSION,
|
|
@@ -9179,7 +9271,7 @@ var LocalQueryCache = class {
|
|
|
9179
9271
|
const content = JSON.stringify(payload);
|
|
9180
9272
|
ensureCacheDir();
|
|
9181
9273
|
try {
|
|
9182
|
-
|
|
9274
|
+
fs12.writeFileSync(filePath, content, "utf8");
|
|
9183
9275
|
} catch {
|
|
9184
9276
|
return;
|
|
9185
9277
|
}
|
|
@@ -9209,7 +9301,7 @@ var LocalQueryCache = class {
|
|
|
9209
9301
|
const entries = extractWarmSnapshotEntries(result);
|
|
9210
9302
|
const index = this.loadIndex();
|
|
9211
9303
|
const fileName = `warm-${this.scope.workspaceKey}.json`;
|
|
9212
|
-
const filePath =
|
|
9304
|
+
const filePath = path12.join(getCacheDir(), fileName);
|
|
9213
9305
|
index.warmSnapshots = index.warmSnapshots.filter(
|
|
9214
9306
|
(snapshot2) => snapshot2.workspaceKey !== this.scope.workspaceKey
|
|
9215
9307
|
);
|
|
@@ -9232,7 +9324,7 @@ var LocalQueryCache = class {
|
|
|
9232
9324
|
const content = JSON.stringify(snapshot);
|
|
9233
9325
|
ensureCacheDir();
|
|
9234
9326
|
try {
|
|
9235
|
-
|
|
9327
|
+
fs12.writeFileSync(filePath, content, "utf8");
|
|
9236
9328
|
} catch {
|
|
9237
9329
|
return { storedEntries: 0 };
|
|
9238
9330
|
}
|
|
@@ -9252,21 +9344,21 @@ var LocalQueryCache = class {
|
|
|
9252
9344
|
}
|
|
9253
9345
|
clear() {
|
|
9254
9346
|
const cacheDir = getCacheDir();
|
|
9255
|
-
if (!
|
|
9347
|
+
if (!fs12.existsSync(cacheDir)) {
|
|
9256
9348
|
return 0;
|
|
9257
9349
|
}
|
|
9258
|
-
const files =
|
|
9259
|
-
|
|
9350
|
+
const files = fs12.readdirSync(cacheDir).filter((file) => file.endsWith(".json"));
|
|
9351
|
+
fs12.rmSync(cacheDir, { recursive: true, force: true });
|
|
9260
9352
|
return files.length;
|
|
9261
9353
|
}
|
|
9262
9354
|
loadIndex() {
|
|
9263
9355
|
ensureCacheDir();
|
|
9264
9356
|
const indexFile = getIndexFile();
|
|
9265
|
-
if (!
|
|
9357
|
+
if (!fs12.existsSync(indexFile)) {
|
|
9266
9358
|
return emptyIndex();
|
|
9267
9359
|
}
|
|
9268
9360
|
try {
|
|
9269
|
-
const content =
|
|
9361
|
+
const content = fs12.readFileSync(indexFile, "utf8");
|
|
9270
9362
|
const parsed = JSON.parse(content);
|
|
9271
9363
|
const index = {
|
|
9272
9364
|
version: parsed.version === CACHE_VERSION ? CACHE_VERSION : CACHE_VERSION,
|
|
@@ -9282,7 +9374,7 @@ var LocalQueryCache = class {
|
|
|
9282
9374
|
const pruned = this.pruneIndex(index);
|
|
9283
9375
|
ensureCacheDir();
|
|
9284
9376
|
try {
|
|
9285
|
-
|
|
9377
|
+
fs12.writeFileSync(getIndexFile(), JSON.stringify(pruned, null, 2), "utf8");
|
|
9286
9378
|
} catch {
|
|
9287
9379
|
}
|
|
9288
9380
|
}
|
|
@@ -9291,20 +9383,20 @@ var LocalQueryCache = class {
|
|
|
9291
9383
|
const cacheDir = getCacheDir();
|
|
9292
9384
|
index.entries = index.entries.filter((entry) => {
|
|
9293
9385
|
if (entry.expiresAt <= now) {
|
|
9294
|
-
tryDeleteFile(
|
|
9386
|
+
tryDeleteFile(path12.join(cacheDir, entry.fileName));
|
|
9295
9387
|
return false;
|
|
9296
9388
|
}
|
|
9297
|
-
if (!
|
|
9389
|
+
if (!fs12.existsSync(path12.join(cacheDir, entry.fileName))) {
|
|
9298
9390
|
return false;
|
|
9299
9391
|
}
|
|
9300
9392
|
return true;
|
|
9301
9393
|
});
|
|
9302
9394
|
index.warmSnapshots = index.warmSnapshots.filter((snapshot) => {
|
|
9303
9395
|
if (snapshot.expiresAt <= now) {
|
|
9304
|
-
tryDeleteFile(
|
|
9396
|
+
tryDeleteFile(path12.join(cacheDir, snapshot.fileName));
|
|
9305
9397
|
return false;
|
|
9306
9398
|
}
|
|
9307
|
-
if (!
|
|
9399
|
+
if (!fs12.existsSync(path12.join(cacheDir, snapshot.fileName))) {
|
|
9308
9400
|
return false;
|
|
9309
9401
|
}
|
|
9310
9402
|
return true;
|
|
@@ -9317,19 +9409,19 @@ var LocalQueryCache = class {
|
|
|
9317
9409
|
break;
|
|
9318
9410
|
}
|
|
9319
9411
|
totalBytes -= removed.sizeBytes;
|
|
9320
|
-
tryDeleteFile(
|
|
9412
|
+
tryDeleteFile(path12.join(cacheDir, removed.fileName));
|
|
9321
9413
|
}
|
|
9322
9414
|
return index;
|
|
9323
9415
|
}
|
|
9324
9416
|
readEntry(entry, index) {
|
|
9325
|
-
const filePath =
|
|
9326
|
-
if (!
|
|
9417
|
+
const filePath = path12.join(getCacheDir(), entry.fileName);
|
|
9418
|
+
if (!fs12.existsSync(filePath)) {
|
|
9327
9419
|
index.entries = index.entries.filter((candidate) => candidate.key !== entry.key);
|
|
9328
9420
|
this.persistIndex(index);
|
|
9329
9421
|
return null;
|
|
9330
9422
|
}
|
|
9331
9423
|
try {
|
|
9332
|
-
const content =
|
|
9424
|
+
const content = fs12.readFileSync(filePath, "utf8");
|
|
9333
9425
|
const parsed = JSON.parse(content);
|
|
9334
9426
|
if (parsed.version !== CACHE_VERSION || !isContextQueryResult(parsed.result)) {
|
|
9335
9427
|
throw new Error("invalid cache payload");
|
|
@@ -9373,8 +9465,8 @@ var LocalQueryCache = class {
|
|
|
9373
9465
|
if (!snapshotMeta) {
|
|
9374
9466
|
return null;
|
|
9375
9467
|
}
|
|
9376
|
-
const filePath =
|
|
9377
|
-
if (!
|
|
9468
|
+
const filePath = path12.join(getCacheDir(), snapshotMeta.fileName);
|
|
9469
|
+
if (!fs12.existsSync(filePath)) {
|
|
9378
9470
|
index.warmSnapshots = index.warmSnapshots.filter(
|
|
9379
9471
|
(snapshot) => snapshot.workspaceKey !== this.scope.workspaceKey
|
|
9380
9472
|
);
|
|
@@ -9382,7 +9474,7 @@ var LocalQueryCache = class {
|
|
|
9382
9474
|
return null;
|
|
9383
9475
|
}
|
|
9384
9476
|
try {
|
|
9385
|
-
const content =
|
|
9477
|
+
const content = fs12.readFileSync(filePath, "utf8");
|
|
9386
9478
|
const snapshot = JSON.parse(content);
|
|
9387
9479
|
if (snapshot.version !== WARM_SNAPSHOT_VERSION || snapshot.workspaceKey !== this.scope.workspaceKey || !Array.isArray(snapshot.entries)) {
|
|
9388
9480
|
throw new Error("invalid warm snapshot");
|
|
@@ -9431,7 +9523,7 @@ function createLocalQueryCache(scope = {}) {
|
|
|
9431
9523
|
return new LocalQueryCache(scope);
|
|
9432
9524
|
}
|
|
9433
9525
|
function resolveScope(scope) {
|
|
9434
|
-
const cwd =
|
|
9526
|
+
const cwd = path12.resolve(scope.cwd ?? process.cwd());
|
|
9435
9527
|
const workspaceRoot2 = normalizeFilePath(findWorkspaceRoot(cwd, true) ?? cwd);
|
|
9436
9528
|
const workspaceKey = hashString(
|
|
9437
9529
|
JSON.stringify({ projectId: scope.projectId ?? "", workspaceRoot: workspaceRoot2 })
|
|
@@ -9575,13 +9667,13 @@ function emptyIndex() {
|
|
|
9575
9667
|
}
|
|
9576
9668
|
function ensureCacheDir() {
|
|
9577
9669
|
const cacheDir = getCacheDir();
|
|
9578
|
-
if (!
|
|
9579
|
-
|
|
9670
|
+
if (!fs12.existsSync(cacheDir)) {
|
|
9671
|
+
fs12.mkdirSync(cacheDir, { recursive: true });
|
|
9580
9672
|
}
|
|
9581
9673
|
}
|
|
9582
9674
|
function tryDeleteFile(filePath) {
|
|
9583
9675
|
try {
|
|
9584
|
-
|
|
9676
|
+
fs12.unlinkSync(filePath);
|
|
9585
9677
|
} catch {
|
|
9586
9678
|
}
|
|
9587
9679
|
}
|
|
@@ -9611,14 +9703,14 @@ function readPositiveFloat(name, fallback) {
|
|
|
9611
9703
|
return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
|
|
9612
9704
|
}
|
|
9613
9705
|
function getCacheDir() {
|
|
9614
|
-
return
|
|
9706
|
+
return path12.join(os5.homedir(), ".snipara", "cache", "context-v2");
|
|
9615
9707
|
}
|
|
9616
9708
|
function getIndexFile() {
|
|
9617
|
-
return
|
|
9709
|
+
return path12.join(getCacheDir(), "index.json");
|
|
9618
9710
|
}
|
|
9619
9711
|
|
|
9620
9712
|
// src/commands/stuck-guard.ts
|
|
9621
|
-
var
|
|
9713
|
+
var fs13 = __toESM(require("fs"));
|
|
9622
9714
|
var SEARCH_TOOL_PATTERN = /\b(read|grep|glob|find|rg|ripgrep|search|ls)\b/i;
|
|
9623
9715
|
var SECRET_PATTERNS2 = [
|
|
9624
9716
|
[/\b(Bearer\s+)[A-Za-z0-9._~+/=-]{20,}\b/g, "$1[REDACTED]"],
|
|
@@ -9826,7 +9918,7 @@ async function stuckGuardCheckCommand(toolInput, options) {
|
|
|
9826
9918
|
}
|
|
9827
9919
|
async function stuckGuardSimulateCommand(options) {
|
|
9828
9920
|
ensureConfiguredForCommand();
|
|
9829
|
-
const fixture = JSON.parse(
|
|
9921
|
+
const fixture = JSON.parse(fs13.readFileSync(options.fixture, "utf8"));
|
|
9830
9922
|
const payload = normalizeFixture(fixture);
|
|
9831
9923
|
const client = createClient(1e4);
|
|
9832
9924
|
const result = await client.evaluateStuckGuard(payload);
|
|
@@ -10187,8 +10279,8 @@ function clearCache() {
|
|
|
10187
10279
|
var import_node_child_process5 = require("child_process");
|
|
10188
10280
|
|
|
10189
10281
|
// src/commands/memory-guard.ts
|
|
10190
|
-
var
|
|
10191
|
-
var
|
|
10282
|
+
var fs14 = __toESM(require("fs"));
|
|
10283
|
+
var path13 = __toESM(require("path"));
|
|
10192
10284
|
var import_node_child_process3 = require("child_process");
|
|
10193
10285
|
var import_chalk2 = __toESM(require("chalk"));
|
|
10194
10286
|
var MEMORY_GUARD_EXIT_CODES = {
|
|
@@ -10305,12 +10397,12 @@ function buildValidationResult(errors) {
|
|
|
10305
10397
|
};
|
|
10306
10398
|
}
|
|
10307
10399
|
function safeRelative(root, filePath) {
|
|
10308
|
-
const absolute =
|
|
10309
|
-
return
|
|
10400
|
+
const absolute = path13.isAbsolute(filePath) ? filePath : path13.join(root, filePath);
|
|
10401
|
+
return path13.relative(root, absolute).replaceAll(path13.sep, "/");
|
|
10310
10402
|
}
|
|
10311
10403
|
function readJsonFile(filePath) {
|
|
10312
10404
|
try {
|
|
10313
|
-
const parsed = JSON.parse(
|
|
10405
|
+
const parsed = JSON.parse(fs14.readFileSync(filePath, "utf8"));
|
|
10314
10406
|
return typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) ? parsed : null;
|
|
10315
10407
|
} catch {
|
|
10316
10408
|
return null;
|
|
@@ -10327,17 +10419,17 @@ function parsePyprojectProject(content) {
|
|
|
10327
10419
|
return { name, version };
|
|
10328
10420
|
}
|
|
10329
10421
|
function findManifestForFile(root, filePath, manifest) {
|
|
10330
|
-
let current =
|
|
10331
|
-
const resolvedRoot =
|
|
10422
|
+
let current = path13.dirname(path13.join(root, filePath));
|
|
10423
|
+
const resolvedRoot = path13.resolve(root);
|
|
10332
10424
|
while (current.startsWith(resolvedRoot)) {
|
|
10333
|
-
const candidate =
|
|
10334
|
-
if (
|
|
10425
|
+
const candidate = path13.join(current, manifest);
|
|
10426
|
+
if (fs14.existsSync(candidate)) {
|
|
10335
10427
|
return candidate;
|
|
10336
10428
|
}
|
|
10337
10429
|
if (current === resolvedRoot) {
|
|
10338
10430
|
break;
|
|
10339
10431
|
}
|
|
10340
|
-
current =
|
|
10432
|
+
current = path13.dirname(current);
|
|
10341
10433
|
}
|
|
10342
10434
|
return null;
|
|
10343
10435
|
}
|
|
@@ -10346,7 +10438,7 @@ function detectReleaseSurfacesFromFiles(root, files) {
|
|
|
10346
10438
|
const seen = /* @__PURE__ */ new Set();
|
|
10347
10439
|
for (const rawFile of files) {
|
|
10348
10440
|
const file = safeRelative(root, rawFile);
|
|
10349
|
-
const packageManifest = file.endsWith("package.json") &&
|
|
10441
|
+
const packageManifest = file.endsWith("package.json") && fs14.existsSync(path13.join(root, file)) ? path13.join(root, file) : findManifestForFile(root, file, "package.json");
|
|
10350
10442
|
if (packageManifest && !seen.has(packageManifest)) {
|
|
10351
10443
|
seen.add(packageManifest);
|
|
10352
10444
|
const packageJson = readJsonFile(packageManifest);
|
|
@@ -10361,10 +10453,10 @@ function detectReleaseSurfacesFromFiles(root, files) {
|
|
|
10361
10453
|
});
|
|
10362
10454
|
}
|
|
10363
10455
|
}
|
|
10364
|
-
const pyprojectManifest = file.endsWith("pyproject.toml") &&
|
|
10456
|
+
const pyprojectManifest = file.endsWith("pyproject.toml") && fs14.existsSync(path13.join(root, file)) ? path13.join(root, file) : findManifestForFile(root, file, "pyproject.toml");
|
|
10365
10457
|
if (pyprojectManifest && !seen.has(pyprojectManifest)) {
|
|
10366
10458
|
seen.add(pyprojectManifest);
|
|
10367
|
-
const project = parsePyprojectProject(
|
|
10459
|
+
const project = parsePyprojectProject(fs14.readFileSync(pyprojectManifest, "utf8"));
|
|
10368
10460
|
if (project.name) {
|
|
10369
10461
|
surfaces.push({
|
|
10370
10462
|
ecosystem: "pypi",
|
|
@@ -10851,9 +10943,9 @@ async function rememberGuardMemoryCommand(options) {
|
|
|
10851
10943
|
}
|
|
10852
10944
|
|
|
10853
10945
|
// src/commands/activity.ts
|
|
10854
|
-
var
|
|
10855
|
-
var
|
|
10856
|
-
var
|
|
10946
|
+
var fs15 = __toESM(require("fs"));
|
|
10947
|
+
var path14 = __toESM(require("path"));
|
|
10948
|
+
var import_node_crypto8 = require("crypto");
|
|
10857
10949
|
|
|
10858
10950
|
// ../project-intelligence-contracts/src/engineering-lead.ts
|
|
10859
10951
|
var PROJECT_HEALTH_COCKPIT_STATUSES = ["healthy", "watch", "risk", "unknown"];
|
|
@@ -11481,7 +11573,7 @@ function buildProjectIntentLedger(input, changedFilesOverride) {
|
|
|
11481
11573
|
}
|
|
11482
11574
|
|
|
11483
11575
|
// ../project-intelligence-contracts/src/worker-profile.ts
|
|
11484
|
-
var
|
|
11576
|
+
var import_node_crypto4 = require("crypto");
|
|
11485
11577
|
var WORKER_PROFILE_SCHEMA_VERSION = "snipara.worker_profile.v0";
|
|
11486
11578
|
var WORKER_PROFILE_RISK_CEILINGS = ["low", "medium", "high", "critical"];
|
|
11487
11579
|
var WORKER_PROFILE_PRIVACY_CLASSES = ["local", "cloud"];
|
|
@@ -11575,7 +11667,7 @@ function stableWorkerProfileJsonStringify(value) {
|
|
|
11575
11667
|
return JSON.stringify(sortJsonValue(value), null, 2);
|
|
11576
11668
|
}
|
|
11577
11669
|
function hashWorkerProfileContent(content) {
|
|
11578
|
-
return (0,
|
|
11670
|
+
return (0, import_node_crypto4.createHash)("sha256").update(content).digest("hex");
|
|
11579
11671
|
}
|
|
11580
11672
|
function normalizeWorkerProfileTransport(value) {
|
|
11581
11673
|
if (!isRecord2(value)) {
|
|
@@ -12329,10 +12421,10 @@ function renderProjectRealityCheckMarkdown(result) {
|
|
|
12329
12421
|
}
|
|
12330
12422
|
|
|
12331
12423
|
// ../project-intelligence-contracts/src/producer-loop.ts
|
|
12332
|
-
var
|
|
12424
|
+
var import_node_crypto5 = require("crypto");
|
|
12333
12425
|
|
|
12334
12426
|
// ../project-intelligence-contracts/src/decision-request.ts
|
|
12335
|
-
var
|
|
12427
|
+
var import_node_crypto6 = require("crypto");
|
|
12336
12428
|
var DECISION_REQUEST_VERSION = "snipara.decision_request.v0";
|
|
12337
12429
|
var DECISION_RESPONSE_VERSION = "snipara.decision_response.v0";
|
|
12338
12430
|
var DECISION_REQUEST_RELATIVE_DIR = ".snipara/decisions";
|
|
@@ -12340,7 +12432,7 @@ function stableDecisionJsonStringify(value) {
|
|
|
12340
12432
|
return JSON.stringify(sortJsonValue2(value), null, 2);
|
|
12341
12433
|
}
|
|
12342
12434
|
function hashDecisionContent(content) {
|
|
12343
|
-
return (0,
|
|
12435
|
+
return (0, import_node_crypto6.createHash)("sha256").update(content).digest("hex");
|
|
12344
12436
|
}
|
|
12345
12437
|
function hashDecisionJsonValue(value) {
|
|
12346
12438
|
return `sha256:${hashDecisionContent(stableDecisionJsonStringify(value))}`;
|
|
@@ -14177,7 +14269,7 @@ var WHY_CAPTURE_CONFIDENCE_VERSION = why_capture_confidence_v1_default.version;
|
|
|
14177
14269
|
var WHY_CAPTURE_CONFIDENCE_TEST_VECTORS = why_capture_confidence_v1_default.vectors;
|
|
14178
14270
|
|
|
14179
14271
|
// ../project-intelligence-contracts/src/judgment-integrity.ts
|
|
14180
|
-
var
|
|
14272
|
+
var import_node_crypto7 = require("crypto");
|
|
14181
14273
|
|
|
14182
14274
|
// ../project-intelligence-contracts/src/agent-context.ts
|
|
14183
14275
|
var AGENT_CONTEXT_MANIFEST_VERSION = "snipara.agent_context_manifest.v0";
|
|
@@ -15414,9 +15506,9 @@ function isAgentContextEvidenceReceipt(value) {
|
|
|
15414
15506
|
// src/commands/activity.ts
|
|
15415
15507
|
var ACTIVITY_TIMELINE_VERSION = "snipara.activity_timeline.v0";
|
|
15416
15508
|
var SESSION_SNAPSHOT_VERSION = "snipara.session_snapshot.v0";
|
|
15417
|
-
var ACTIVITY_RELATIVE_DIR =
|
|
15418
|
-
var ACTIVITY_TIMELINE_RELATIVE_PATH =
|
|
15419
|
-
var SESSION_SNAPSHOT_RELATIVE_PATH =
|
|
15509
|
+
var ACTIVITY_RELATIVE_DIR = path14.join(".snipara", "activity");
|
|
15510
|
+
var ACTIVITY_TIMELINE_RELATIVE_PATH = path14.join(ACTIVITY_RELATIVE_DIR, "timeline.jsonl");
|
|
15511
|
+
var SESSION_SNAPSHOT_RELATIVE_PATH = path14.join(ACTIVITY_RELATIVE_DIR, "session.json");
|
|
15420
15512
|
function uniqueStrings15(values) {
|
|
15421
15513
|
return Array.from(new Set(values.map((value) => value?.trim()).filter(Boolean)));
|
|
15422
15514
|
}
|
|
@@ -15435,11 +15527,11 @@ function sortJsonValue3(value) {
|
|
|
15435
15527
|
return value;
|
|
15436
15528
|
}
|
|
15437
15529
|
function hashEvent(input) {
|
|
15438
|
-
return (0,
|
|
15530
|
+
return (0, import_node_crypto8.createHash)("sha256").update(stableJson(input)).digest("hex").slice(0, 16);
|
|
15439
15531
|
}
|
|
15440
15532
|
function safeReadJson(filePath) {
|
|
15441
15533
|
try {
|
|
15442
|
-
const parsed = JSON.parse(
|
|
15534
|
+
const parsed = JSON.parse(fs15.readFileSync(filePath, "utf8"));
|
|
15443
15535
|
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
15444
15536
|
} catch {
|
|
15445
15537
|
return null;
|
|
@@ -15447,7 +15539,7 @@ function safeReadJson(filePath) {
|
|
|
15447
15539
|
}
|
|
15448
15540
|
function readJsonDir(dir) {
|
|
15449
15541
|
try {
|
|
15450
|
-
return
|
|
15542
|
+
return fs15.readdirSync(dir).filter((fileName) => fileName.endsWith(".json")).map((fileName) => safeReadJson(path14.join(dir, fileName))).filter((record2) => Boolean(record2));
|
|
15451
15543
|
} catch {
|
|
15452
15544
|
return [];
|
|
15453
15545
|
}
|
|
@@ -15461,10 +15553,10 @@ function countBy(items, key) {
|
|
|
15461
15553
|
return counts;
|
|
15462
15554
|
}
|
|
15463
15555
|
function getActivityTimelinePath(cwd = process.cwd()) {
|
|
15464
|
-
return
|
|
15556
|
+
return path14.join(cwd, ACTIVITY_TIMELINE_RELATIVE_PATH);
|
|
15465
15557
|
}
|
|
15466
15558
|
function getSessionSnapshotPath(cwd = process.cwd()) {
|
|
15467
|
-
return
|
|
15559
|
+
return path14.join(cwd, SESSION_SNAPSHOT_RELATIVE_PATH);
|
|
15468
15560
|
}
|
|
15469
15561
|
function appendActivityEvent(input) {
|
|
15470
15562
|
const cwd = input.cwd ?? process.cwd();
|
|
@@ -15495,8 +15587,8 @@ function appendActivityEvent(input) {
|
|
|
15495
15587
|
metadata: input.metadata ?? {}
|
|
15496
15588
|
};
|
|
15497
15589
|
const timelinePath = getActivityTimelinePath(cwd);
|
|
15498
|
-
|
|
15499
|
-
|
|
15590
|
+
fs15.mkdirSync(path14.dirname(timelinePath), { recursive: true });
|
|
15591
|
+
fs15.appendFileSync(timelinePath, `${JSON.stringify(event)}
|
|
15500
15592
|
`, "utf8");
|
|
15501
15593
|
return event;
|
|
15502
15594
|
}
|
|
@@ -15505,7 +15597,7 @@ function readActivityTimeline(options = {}) {
|
|
|
15505
15597
|
const limit = options.limit && options.limit > 0 ? options.limit : void 0;
|
|
15506
15598
|
let lines;
|
|
15507
15599
|
try {
|
|
15508
|
-
lines =
|
|
15600
|
+
lines = fs15.readFileSync(timelinePath, "utf8").split(/\r?\n/).filter(Boolean);
|
|
15509
15601
|
} catch {
|
|
15510
15602
|
return [];
|
|
15511
15603
|
}
|
|
@@ -15519,7 +15611,7 @@ function readActivityTimeline(options = {}) {
|
|
|
15519
15611
|
return limit ? events.slice(0, limit) : events;
|
|
15520
15612
|
}
|
|
15521
15613
|
function workflowSnapshot(cwd) {
|
|
15522
|
-
const state = safeReadJson(
|
|
15614
|
+
const state = safeReadJson(path14.join(cwd, ".snipara", "workflow", "current.json"));
|
|
15523
15615
|
if (!state) {
|
|
15524
15616
|
return null;
|
|
15525
15617
|
}
|
|
@@ -15541,7 +15633,7 @@ function countDecisionFingerprintRepeats(records) {
|
|
|
15541
15633
|
return Object.values(counts).filter((count2) => count2 > 1).length;
|
|
15542
15634
|
}
|
|
15543
15635
|
function producerLoopSummary(cwd) {
|
|
15544
|
-
const records = readJsonDir(
|
|
15636
|
+
const records = readJsonDir(path14.join(cwd, ".snipara", "producer-loop"));
|
|
15545
15637
|
let reviewedCount = 0;
|
|
15546
15638
|
let rejectedCount = 0;
|
|
15547
15639
|
let unreviewedCount = 0;
|
|
@@ -15562,7 +15654,7 @@ function producerLoopSummary(cwd) {
|
|
|
15562
15654
|
};
|
|
15563
15655
|
}
|
|
15564
15656
|
function teamSyncSnapshot(cwd) {
|
|
15565
|
-
const state = safeReadJson(
|
|
15657
|
+
const state = safeReadJson(path14.join(cwd, ".snipara", "team-sync", "session.json"));
|
|
15566
15658
|
const work = Array.isArray(state?.work) ? state?.work : [];
|
|
15567
15659
|
const handoffs = Array.isArray(state?.handoffs) ? state?.handoffs : [];
|
|
15568
15660
|
const latestHandoffAt = handoffs.map((handoff) => typeof handoff.createdAt === "string" ? handoff.createdAt : void 0).filter(Boolean).sort().at(-1);
|
|
@@ -15608,8 +15700,8 @@ function buildSessionSnapshot(options = {}) {
|
|
|
15608
15700
|
const cwd = options.cwd ?? process.cwd();
|
|
15609
15701
|
const events = readActivityTimeline({ cwd });
|
|
15610
15702
|
const latestEvents = events.slice(0, options.limit && options.limit > 0 ? options.limit : 20);
|
|
15611
|
-
const pendingDecisions = readJsonDir(
|
|
15612
|
-
const resolvedDecisions = readJsonDir(
|
|
15703
|
+
const pendingDecisions = readJsonDir(path14.join(cwd, ".snipara", "decisions", "pending"));
|
|
15704
|
+
const resolvedDecisions = readJsonDir(path14.join(cwd, ".snipara", "decisions", "resolved"));
|
|
15613
15705
|
const workflow2 = workflowSnapshot(cwd);
|
|
15614
15706
|
const producerLoop = producerLoopSummary(cwd);
|
|
15615
15707
|
const teamSync2 = teamSyncSnapshot(cwd);
|
|
@@ -15672,8 +15764,8 @@ function writeSessionSnapshot(options = {}) {
|
|
|
15672
15764
|
const cwd = options.cwd ?? process.cwd();
|
|
15673
15765
|
const snapshot = buildSessionSnapshot({ cwd, limit: options.limit });
|
|
15674
15766
|
const snapshotPath = getSessionSnapshotPath(cwd);
|
|
15675
|
-
|
|
15676
|
-
|
|
15767
|
+
fs15.mkdirSync(path14.dirname(snapshotPath), { recursive: true });
|
|
15768
|
+
fs15.writeFileSync(snapshotPath, `${JSON.stringify(snapshot, null, 2)}
|
|
15677
15769
|
`, "utf8");
|
|
15678
15770
|
return snapshot;
|
|
15679
15771
|
}
|
|
@@ -15687,8 +15779,8 @@ function readSessionSnapshot(cwd = process.cwd()) {
|
|
|
15687
15779
|
|
|
15688
15780
|
// src/commands/why-capture.ts
|
|
15689
15781
|
var import_node_child_process4 = require("child_process");
|
|
15690
|
-
var
|
|
15691
|
-
var
|
|
15782
|
+
var fs16 = __toESM(require("fs"));
|
|
15783
|
+
var path15 = __toESM(require("path"));
|
|
15692
15784
|
var MAX_SOURCE_TEXT_CHARS = 12e3;
|
|
15693
15785
|
var MAX_TASK_CHARS = 700;
|
|
15694
15786
|
var MAX_RECEIPT_TEXT_CHARS = 900;
|
|
@@ -15794,12 +15886,12 @@ function readCommitSha(cwd) {
|
|
|
15794
15886
|
return readGitValue(cwd, ["rev-parse", "--verify", "HEAD^{commit}"]);
|
|
15795
15887
|
}
|
|
15796
15888
|
function hasActiveManagedWorkflow(cwd) {
|
|
15797
|
-
const statePath =
|
|
15798
|
-
if (!
|
|
15889
|
+
const statePath = path15.join(cwd, ".snipara", "workflow", "current.json");
|
|
15890
|
+
if (!fs16.existsSync(statePath)) {
|
|
15799
15891
|
return false;
|
|
15800
15892
|
}
|
|
15801
15893
|
try {
|
|
15802
|
-
const parsed = JSON.parse(
|
|
15894
|
+
const parsed = JSON.parse(fs16.readFileSync(statePath, "utf8"));
|
|
15803
15895
|
return parsed.status !== "completed";
|
|
15804
15896
|
} catch {
|
|
15805
15897
|
return true;
|
|
@@ -15830,7 +15922,7 @@ function readStandaloneCommitEvidence(cwd, commitSha, additionalFiles = []) {
|
|
|
15830
15922
|
function readLatestWorkflowCommands(cwd) {
|
|
15831
15923
|
try {
|
|
15832
15924
|
const state = JSON.parse(
|
|
15833
|
-
|
|
15925
|
+
fs16.readFileSync(path15.join(cwd, ".snipara", "workflow", "current.json"), "utf8")
|
|
15834
15926
|
);
|
|
15835
15927
|
const bindings = state.runtime?.sandbox?.bindings ?? [];
|
|
15836
15928
|
for (let index = bindings.length - 1; index >= 0; index -= 1) {
|
|
@@ -16295,38 +16387,100 @@ async function postToolCommand(options) {
|
|
|
16295
16387
|
}
|
|
16296
16388
|
|
|
16297
16389
|
// src/commands/session.ts
|
|
16298
|
-
|
|
16390
|
+
var fs17 = __toESM(require("fs"));
|
|
16391
|
+
var path16 = __toESM(require("path"));
|
|
16392
|
+
var import_node_crypto9 = require("crypto");
|
|
16393
|
+
function printCloseout(report, file, json) {
|
|
16394
|
+
if (json) {
|
|
16395
|
+
console.log(JSON.stringify({ ...report, reportPath: file }, null, 2));
|
|
16396
|
+
return;
|
|
16397
|
+
}
|
|
16398
|
+
const message = report.status === "saved" ? `Session saved to journal (${report.checkpoint.files.length} files; entry ${report.entryId})` : report.status === "skipped" ? "Session checkpoint skipped: no summary or files supplied" : "Session NOT saved; local checkpoint retained for retry";
|
|
16399
|
+
console.log(`${message}
|
|
16400
|
+
Receipt: ${file}`);
|
|
16401
|
+
if (report.status === "error" || report.status === "pending") {
|
|
16402
|
+
console.error(`Retry: snipara-companion session-end --retry ${JSON.stringify(file)}`);
|
|
16403
|
+
}
|
|
16404
|
+
if (report.status === "saved" && report.eventDelivered === false) {
|
|
16405
|
+
console.error("Journal saved; automation event delivery was not confirmed.");
|
|
16406
|
+
}
|
|
16407
|
+
}
|
|
16408
|
+
async function sessionEndCommand(options = {}) {
|
|
16299
16409
|
if (!isConfigured()) {
|
|
16300
|
-
console.log(
|
|
16301
|
-
|
|
16410
|
+
console.log(
|
|
16411
|
+
options.json ? JSON.stringify({ status: "skipped", reason: "not_configured", reportPath: null }) : "Not configured. Run 'npx -y snipara-companion@latest init' first."
|
|
16412
|
+
);
|
|
16413
|
+
return;
|
|
16302
16414
|
}
|
|
16415
|
+
const cwd = path16.resolve(process.env.SNIPARA_WORKSPACE_DIR || process.cwd());
|
|
16416
|
+
const config = loadConfig();
|
|
16417
|
+
const previous = options.retry ? readSessionCloseout(path16.resolve(options.retry)) : void 0;
|
|
16418
|
+
if (options.retry && (!previous || previous.workspace !== cwd || previous.projectId !== config.projectId)) {
|
|
16419
|
+
throw new Error("Retry receipt does not belong to this workspace and project");
|
|
16420
|
+
}
|
|
16421
|
+
const checkpoint = normalizeSessionCheckpoint(
|
|
16422
|
+
previous?.checkpoint ?? {
|
|
16423
|
+
sessionId: options.sessionId ?? config.sessionId ?? `sess_${(0, import_node_crypto9.randomUUID)()}`,
|
|
16424
|
+
summary: options.summary,
|
|
16425
|
+
files: options.files
|
|
16426
|
+
}
|
|
16427
|
+
);
|
|
16428
|
+
const file = sessionCloseoutPath(cwd, config.projectId, checkpoint);
|
|
16429
|
+
const existing = readSessionCloseout(file);
|
|
16430
|
+
if (existing?.status === "saved" && existing.entryId) {
|
|
16431
|
+
printCloseout(existing, file, options.json);
|
|
16432
|
+
return;
|
|
16433
|
+
}
|
|
16434
|
+
const report = {
|
|
16435
|
+
version: "snipara.session_closeout.v1",
|
|
16436
|
+
workspace: cwd,
|
|
16437
|
+
projectId: config.projectId,
|
|
16438
|
+
checkpoint,
|
|
16439
|
+
status: "pending",
|
|
16440
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
16441
|
+
};
|
|
16442
|
+
fs17.mkdirSync(path16.dirname(file), { recursive: true, mode: 448 });
|
|
16443
|
+
const lock = lockSessionCloseout(file);
|
|
16303
16444
|
try {
|
|
16304
|
-
const
|
|
16305
|
-
|
|
16306
|
-
|
|
16307
|
-
|
|
16308
|
-
payload: {
|
|
16309
|
-
persisted: true,
|
|
16310
|
-
files_tracked: result.files_tracked
|
|
16311
|
-
}
|
|
16312
|
-
});
|
|
16313
|
-
console.log(`\u2713 Session saved (${result.files_tracked} files tracked)`);
|
|
16314
|
-
const newSessionId = `sess_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
16315
|
-
saveConfig({ sessionId: newSessionId });
|
|
16316
|
-
} catch (error) {
|
|
16317
|
-
await emitCanonicalEvent({
|
|
16318
|
-
eventType: "session_end",
|
|
16319
|
-
payload: {
|
|
16320
|
-
persisted: false,
|
|
16321
|
-
offline: true
|
|
16322
|
-
}
|
|
16323
|
-
});
|
|
16324
|
-
if (process.env.RLM_DEBUG) {
|
|
16325
|
-
console.error(
|
|
16326
|
-
`[Snipara] Session error: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
16327
|
-
);
|
|
16445
|
+
const confirmed = readSessionCloseout(file);
|
|
16446
|
+
if (confirmed?.status === "saved" && confirmed.entryId) {
|
|
16447
|
+
printCloseout(confirmed, file, options.json);
|
|
16448
|
+
return;
|
|
16328
16449
|
}
|
|
16329
|
-
|
|
16450
|
+
writeSessionCloseout(file, report);
|
|
16451
|
+
try {
|
|
16452
|
+
const result = await createClient(15e3).persistSession(checkpoint);
|
|
16453
|
+
report.status = result.status;
|
|
16454
|
+
report.entryId = result.entry_id;
|
|
16455
|
+
report.journalDate = result.date;
|
|
16456
|
+
} catch {
|
|
16457
|
+
report.status = "error";
|
|
16458
|
+
report.error = "Hosted journal persistence was not confirmed. The checkpoint is retained locally.";
|
|
16459
|
+
process.exitCode = 1;
|
|
16460
|
+
}
|
|
16461
|
+
writeSessionCloseout(file, report);
|
|
16462
|
+
report.eventDelivered = await emitCanonicalEvent(
|
|
16463
|
+
{
|
|
16464
|
+
eventType: "session_end",
|
|
16465
|
+
sessionId: checkpoint.sessionId,
|
|
16466
|
+
payload: {
|
|
16467
|
+
persisted: report.status === "saved",
|
|
16468
|
+
persistence_status: report.status,
|
|
16469
|
+
files_tracked: checkpoint.files.length,
|
|
16470
|
+
...report.entryId ? { journal_entry_id: report.entryId } : {}
|
|
16471
|
+
}
|
|
16472
|
+
},
|
|
16473
|
+
{ timeoutMs: 2e3 }
|
|
16474
|
+
);
|
|
16475
|
+
writeSessionCloseout(file, report);
|
|
16476
|
+
writeSessionCloseout(path16.join(cwd, ".snipara", "companion", "session-closeout.json"), report);
|
|
16477
|
+
if (report.status === "saved" && !options.sessionId && loadConfig().sessionId === checkpoint.sessionId) {
|
|
16478
|
+
saveConfig({ sessionId: `sess_${(0, import_node_crypto9.randomUUID)()}` });
|
|
16479
|
+
}
|
|
16480
|
+
printCloseout(report, file, options.json);
|
|
16481
|
+
} finally {
|
|
16482
|
+
fs17.closeSync(lock);
|
|
16483
|
+
fs17.unlinkSync(`${file}.lock`);
|
|
16330
16484
|
}
|
|
16331
16485
|
}
|
|
16332
16486
|
async function sessionStatusCommand() {
|
|
@@ -16337,6 +16491,17 @@ async function sessionStatusCommand() {
|
|
|
16337
16491
|
const config = loadConfig();
|
|
16338
16492
|
console.log("\n\u{1F4CA} Session Status\n");
|
|
16339
16493
|
console.log(`Session ID: ${config.sessionId || "none"}`);
|
|
16494
|
+
const reportFile = path16.join(
|
|
16495
|
+
process.env.SNIPARA_WORKSPACE_DIR || process.cwd(),
|
|
16496
|
+
".snipara",
|
|
16497
|
+
"companion",
|
|
16498
|
+
"session-closeout.json"
|
|
16499
|
+
);
|
|
16500
|
+
const report = readSessionCloseout(reportFile);
|
|
16501
|
+
if (report) {
|
|
16502
|
+
console.log(`Last checkpoint: ${report.status}${report.entryId ? ` (${report.entryId})` : ""}`);
|
|
16503
|
+
console.log(`Receipt: ${reportFile}`);
|
|
16504
|
+
}
|
|
16340
16505
|
try {
|
|
16341
16506
|
const client = createClient(5e3);
|
|
16342
16507
|
const status = await client.getSession();
|
|
@@ -16358,17 +16523,17 @@ function sessionResetCommand() {
|
|
|
16358
16523
|
var import_chalk3 = __toESM(require("chalk"));
|
|
16359
16524
|
|
|
16360
16525
|
// src/commands/decision-requests.ts
|
|
16361
|
-
var
|
|
16362
|
-
var
|
|
16526
|
+
var fs18 = __toESM(require("fs"));
|
|
16527
|
+
var path17 = __toESM(require("path"));
|
|
16363
16528
|
function decisionPendingDir(cwd = process.cwd()) {
|
|
16364
|
-
return
|
|
16529
|
+
return path17.join(cwd, DECISION_REQUEST_RELATIVE_DIR, "pending");
|
|
16365
16530
|
}
|
|
16366
16531
|
function decisionResolvedDir(cwd = process.cwd()) {
|
|
16367
|
-
return
|
|
16532
|
+
return path17.join(cwd, DECISION_REQUEST_RELATIVE_DIR, "resolved");
|
|
16368
16533
|
}
|
|
16369
16534
|
function ensureDecisionDirs(cwd = process.cwd()) {
|
|
16370
|
-
|
|
16371
|
-
|
|
16535
|
+
fs18.mkdirSync(decisionPendingDir(cwd), { recursive: true });
|
|
16536
|
+
fs18.mkdirSync(decisionResolvedDir(cwd), { recursive: true });
|
|
16372
16537
|
}
|
|
16373
16538
|
function writeDecisionRequest(request, cwd = process.cwd()) {
|
|
16374
16539
|
ensureDecisionDirs(cwd);
|
|
@@ -16393,8 +16558,8 @@ function writeDecisionRequest(request, cwd = process.cwd()) {
|
|
|
16393
16558
|
relativePath: existing.relativePath
|
|
16394
16559
|
};
|
|
16395
16560
|
}
|
|
16396
|
-
const filePath =
|
|
16397
|
-
|
|
16561
|
+
const filePath = path17.join(decisionPendingDir(cwd), `${request.requestId}.json`);
|
|
16562
|
+
fs18.writeFileSync(filePath, `${stableDecisionJsonStringify(request)}
|
|
16398
16563
|
`, "utf8");
|
|
16399
16564
|
return {
|
|
16400
16565
|
status: "written",
|
|
@@ -16409,8 +16574,8 @@ function listPendingDecisionRequests(cwd = process.cwd()) {
|
|
|
16409
16574
|
const resolved = new Set(
|
|
16410
16575
|
listResolvedDecisionRecords(cwd).map((record2) => record2.request.fingerprint)
|
|
16411
16576
|
);
|
|
16412
|
-
return
|
|
16413
|
-
const parsed = JSON.parse(
|
|
16577
|
+
return fs18.readdirSync(decisionPendingDir(cwd)).filter((fileName) => fileName.endsWith(".json")).map((fileName) => path17.join(decisionPendingDir(cwd), fileName)).sort().map((filePath) => {
|
|
16578
|
+
const parsed = JSON.parse(fs18.readFileSync(filePath, "utf8"));
|
|
16414
16579
|
if (!isDecisionRequest(parsed)) {
|
|
16415
16580
|
throw new Error(
|
|
16416
16581
|
`Invalid decision request artifact: ${toProjectRelativePath(filePath, cwd)}`
|
|
@@ -16426,8 +16591,8 @@ function listPendingDecisionRequests(cwd = process.cwd()) {
|
|
|
16426
16591
|
});
|
|
16427
16592
|
}
|
|
16428
16593
|
function listResolvedDecisionRecords(cwd = process.cwd()) {
|
|
16429
|
-
|
|
16430
|
-
return
|
|
16594
|
+
fs18.mkdirSync(decisionResolvedDir(cwd), { recursive: true });
|
|
16595
|
+
return fs18.readdirSync(decisionResolvedDir(cwd)).filter((fileName) => fileName.endsWith(".json")).map((fileName) => path17.join(decisionResolvedDir(cwd), fileName)).sort().map((filePath) => JSON.parse(fs18.readFileSync(filePath, "utf8"))).filter((record2) => record2?.schemaVersion === "snipara.decision_resolution.v0");
|
|
16431
16596
|
}
|
|
16432
16597
|
function resolveDecisionRequest(options) {
|
|
16433
16598
|
const cwd = options.cwd ?? process.cwd();
|
|
@@ -16455,18 +16620,18 @@ function resolveDecisionRequest(options) {
|
|
|
16455
16620
|
request: entry.request,
|
|
16456
16621
|
response
|
|
16457
16622
|
};
|
|
16458
|
-
const resolvedPath =
|
|
16459
|
-
|
|
16623
|
+
const resolvedPath = path17.join(decisionResolvedDir(cwd), `${entry.request.requestId}.json`);
|
|
16624
|
+
fs18.writeFileSync(resolvedPath, `${stableDecisionJsonStringify(record2)}
|
|
16460
16625
|
`, "utf8");
|
|
16461
|
-
|
|
16626
|
+
fs18.unlinkSync(entry.path);
|
|
16462
16627
|
return { request: entry.request, response, resolvedPath };
|
|
16463
16628
|
}
|
|
16464
16629
|
function decisionPendingCount(cwd = process.cwd()) {
|
|
16465
16630
|
return listPendingDecisionRequests(cwd).filter((entry) => entry.status === "pending").length;
|
|
16466
16631
|
}
|
|
16467
16632
|
function toProjectRelativePath(absolutePath, cwd) {
|
|
16468
|
-
const relative15 =
|
|
16469
|
-
return relative15.startsWith(".") ? relative15 : `.${
|
|
16633
|
+
const relative15 = path17.relative(cwd, absolutePath).replace(/\\/g, "/");
|
|
16634
|
+
return relative15.startsWith(".") ? relative15 : `.${path17.sep}${relative15}`.replace(/\\/g, "/");
|
|
16470
16635
|
}
|
|
16471
16636
|
|
|
16472
16637
|
// src/commands/memory.ts
|
|
@@ -17249,8 +17414,8 @@ async function memoryAuditCommand(options) {
|
|
|
17249
17414
|
}
|
|
17250
17415
|
|
|
17251
17416
|
// src/commands/local-stack.ts
|
|
17252
|
-
var
|
|
17253
|
-
var
|
|
17417
|
+
var fs19 = __toESM(require("fs"));
|
|
17418
|
+
var path18 = __toESM(require("path"));
|
|
17254
17419
|
var import_node_child_process6 = require("child_process");
|
|
17255
17420
|
function uniqueStrings17(values) {
|
|
17256
17421
|
return Array.from(new Set((values ?? []).map((value) => value.trim()).filter(Boolean)));
|
|
@@ -17266,13 +17431,13 @@ function keywordHints(value) {
|
|
|
17266
17431
|
}
|
|
17267
17432
|
function readJsonFile2(filePath) {
|
|
17268
17433
|
try {
|
|
17269
|
-
return JSON.parse(
|
|
17434
|
+
return JSON.parse(fs19.readFileSync(filePath, "utf8"));
|
|
17270
17435
|
} catch {
|
|
17271
17436
|
return void 0;
|
|
17272
17437
|
}
|
|
17273
17438
|
}
|
|
17274
17439
|
function maybeLocalArtifact(rootDir, relativePath2) {
|
|
17275
|
-
const absolutePath =
|
|
17440
|
+
const absolutePath = path18.join(rootDir, relativePath2);
|
|
17276
17441
|
const value = readJsonFile2(absolutePath);
|
|
17277
17442
|
if (!value) {
|
|
17278
17443
|
return null;
|
|
@@ -17305,7 +17470,7 @@ function expectedItems(section, values, files) {
|
|
|
17305
17470
|
});
|
|
17306
17471
|
}
|
|
17307
17472
|
function buildEvalCaseArtifact(options = {}) {
|
|
17308
|
-
const rootDir =
|
|
17473
|
+
const rootDir = path18.resolve(options.dir ?? process.cwd());
|
|
17309
17474
|
const files = uniqueStrings17(options.files);
|
|
17310
17475
|
const commandsRun = uniqueStrings17(options.commandRun);
|
|
17311
17476
|
const summary = options.summary?.trim() || "Snipara companion local workflow evaluation";
|
|
@@ -17324,8 +17489,8 @@ function buildEvalCaseArtifact(options = {}) {
|
|
|
17324
17489
|
}
|
|
17325
17490
|
}
|
|
17326
17491
|
const artifacts = [
|
|
17327
|
-
maybeLocalArtifact(rootDir,
|
|
17328
|
-
maybeLocalArtifact(rootDir,
|
|
17492
|
+
maybeLocalArtifact(rootDir, path18.join(".snipara", "workflow", "current.json")),
|
|
17493
|
+
maybeLocalArtifact(rootDir, path18.join(".snipara", "team-sync", "session.json"))
|
|
17329
17494
|
].filter((artifact) => artifact !== null);
|
|
17330
17495
|
return {
|
|
17331
17496
|
id,
|
|
@@ -17345,8 +17510,8 @@ function buildEvalCaseArtifact(options = {}) {
|
|
|
17345
17510
|
};
|
|
17346
17511
|
}
|
|
17347
17512
|
function writeOutput(filePath, content) {
|
|
17348
|
-
|
|
17349
|
-
|
|
17513
|
+
fs19.mkdirSync(path18.dirname(filePath), { recursive: true });
|
|
17514
|
+
fs19.writeFileSync(filePath, content, "utf8");
|
|
17350
17515
|
}
|
|
17351
17516
|
function runCommand(command, args, missingHint) {
|
|
17352
17517
|
const result = (0, import_node_child_process6.spawnSync)(command, args, {
|
|
@@ -17377,10 +17542,10 @@ async function memoryLocalCommand(options) {
|
|
|
17377
17542
|
process.exitCode = code2;
|
|
17378
17543
|
}
|
|
17379
17544
|
async function evalExportCommand(options) {
|
|
17380
|
-
const rootDir =
|
|
17381
|
-
const output =
|
|
17545
|
+
const rootDir = path18.resolve(options.dir ?? process.cwd());
|
|
17546
|
+
const output = path18.resolve(
|
|
17382
17547
|
rootDir,
|
|
17383
|
-
options.output ??
|
|
17548
|
+
options.output ?? path18.join(".snipara", "evals", "case.json")
|
|
17384
17549
|
);
|
|
17385
17550
|
const artifact = buildEvalCaseArtifact(options);
|
|
17386
17551
|
const content = `${JSON.stringify(artifact, null, 2)}
|
|
@@ -17399,7 +17564,7 @@ async function evalRunCommand(options) {
|
|
|
17399
17564
|
}
|
|
17400
17565
|
const runner = options.runner || process.env.SNIPARA_EVALS_RUNNER || "npx";
|
|
17401
17566
|
const packageSpec = options.packageSpec || "snipara-evals@latest";
|
|
17402
|
-
const args =
|
|
17567
|
+
const args = path18.basename(runner) === "snipara-evals" ? ["run", ...options.cases] : ["--yes", packageSpec, "run", ...options.cases];
|
|
17403
17568
|
if (options.json) {
|
|
17404
17569
|
args.push("--json");
|
|
17405
17570
|
}
|
|
@@ -17415,15 +17580,15 @@ async function evalRunCommand(options) {
|
|
|
17415
17580
|
}
|
|
17416
17581
|
|
|
17417
17582
|
// src/commands/doctor.ts
|
|
17418
|
-
var
|
|
17419
|
-
var
|
|
17583
|
+
var fs21 = __toESM(require("fs"));
|
|
17584
|
+
var path20 = __toESM(require("path"));
|
|
17420
17585
|
var import_node_child_process7 = require("child_process");
|
|
17421
17586
|
var import_chalk4 = __toESM(require("chalk"));
|
|
17422
17587
|
|
|
17423
17588
|
// src/runtime/detection.ts
|
|
17424
|
-
var
|
|
17589
|
+
var fs20 = __toESM(require("fs"));
|
|
17425
17590
|
var os6 = __toESM(require("os"));
|
|
17426
|
-
var
|
|
17591
|
+
var path19 = __toESM(require("path"));
|
|
17427
17592
|
var import_child_process5 = require("child_process");
|
|
17428
17593
|
var RUNTIME_INTENT_PATTERN = /\b(test|tests|validate|validation|verify|evaluate|eval|execute|execution|run|sandbox|sandboxed|isolated|isolation|simulate|script|python|csv|dataframe|notebook|generate report|lint|type-?check|build|benchmark|parse|transform|repeatable|reproducible)\b/i;
|
|
17429
17594
|
var ORCHESTRATOR_PRODUCTION_PATTERN = /\b(prod|production|deploy|deployment|release|rollout|cutover|drift|live validation|live check|live checks)\b/i;
|
|
@@ -17599,14 +17764,14 @@ function getCommandVersion(command) {
|
|
|
17599
17764
|
}
|
|
17600
17765
|
function executableExists(filePath) {
|
|
17601
17766
|
try {
|
|
17602
|
-
const stat =
|
|
17767
|
+
const stat = fs20.statSync(filePath);
|
|
17603
17768
|
if (!stat.isFile()) {
|
|
17604
17769
|
return false;
|
|
17605
17770
|
}
|
|
17606
17771
|
if (process.platform === "win32") {
|
|
17607
17772
|
return true;
|
|
17608
17773
|
}
|
|
17609
|
-
|
|
17774
|
+
fs20.accessSync(filePath, fs20.constants.X_OK);
|
|
17610
17775
|
return true;
|
|
17611
17776
|
} catch {
|
|
17612
17777
|
return false;
|
|
@@ -17652,11 +17817,11 @@ function detectOrchestratorCli(cwd, workspaceRoot2) {
|
|
|
17652
17817
|
}
|
|
17653
17818
|
function findWorkspaceOrchestratorVersion(cwd, workspaceRoot2) {
|
|
17654
17819
|
const roots = Array.from(
|
|
17655
|
-
new Set([workspaceRoot2,
|
|
17820
|
+
new Set([workspaceRoot2, path19.resolve(cwd)].filter((value) => Boolean(value)))
|
|
17656
17821
|
);
|
|
17657
17822
|
for (const root of roots) {
|
|
17658
17823
|
const version = readPyprojectVersion(
|
|
17659
|
-
|
|
17824
|
+
path19.join(root, "packages", "agentic-orchestrator", "pyproject.toml"),
|
|
17660
17825
|
"snipara-orchestrator"
|
|
17661
17826
|
);
|
|
17662
17827
|
if (version) {
|
|
@@ -17666,10 +17831,10 @@ function findWorkspaceOrchestratorVersion(cwd, workspaceRoot2) {
|
|
|
17666
17831
|
return void 0;
|
|
17667
17832
|
}
|
|
17668
17833
|
function readPyprojectVersion(filePath, packageName) {
|
|
17669
|
-
if (!
|
|
17834
|
+
if (!fs20.existsSync(filePath)) {
|
|
17670
17835
|
return void 0;
|
|
17671
17836
|
}
|
|
17672
|
-
const content =
|
|
17837
|
+
const content = fs20.readFileSync(filePath, "utf-8");
|
|
17673
17838
|
const nameMatch = content.match(/^\s*name\s*=\s*["']([^"']+)["']/m);
|
|
17674
17839
|
if (nameMatch && nameMatch[1] !== packageName) {
|
|
17675
17840
|
return void 0;
|
|
@@ -17687,13 +17852,13 @@ function parseOrchestratorVersion(version) {
|
|
|
17687
17852
|
function findWorkspaceExecutableCandidates(command, cwd, workspaceRoot2) {
|
|
17688
17853
|
const executableName = process.platform === "win32" ? `${command}.exe` : command;
|
|
17689
17854
|
const roots = Array.from(
|
|
17690
|
-
new Set([workspaceRoot2,
|
|
17855
|
+
new Set([workspaceRoot2, path19.resolve(cwd)].filter((value) => Boolean(value)))
|
|
17691
17856
|
);
|
|
17692
17857
|
return roots.flatMap((root) => [
|
|
17693
|
-
|
|
17694
|
-
|
|
17695
|
-
|
|
17696
|
-
|
|
17858
|
+
path19.join(root, ".venv", "bin", executableName),
|
|
17859
|
+
path19.join(root, "venv", "bin", executableName),
|
|
17860
|
+
path19.join(root, "packages", "agentic-orchestrator", ".venv", "bin", executableName),
|
|
17861
|
+
path19.join(root, "apps", "mcp-server", ".venv", "bin", executableName)
|
|
17697
17862
|
]);
|
|
17698
17863
|
}
|
|
17699
17864
|
function parseRuntimeVersion(version) {
|
|
@@ -17748,7 +17913,7 @@ function loadEnvFiles(cwd, workspaceRoot2) {
|
|
|
17748
17913
|
const values = {};
|
|
17749
17914
|
const files = [];
|
|
17750
17915
|
for (const envFile of findEnvFilePaths(cwd, workspaceRoot2)) {
|
|
17751
|
-
if (!
|
|
17916
|
+
if (!fs20.existsSync(envFile)) {
|
|
17752
17917
|
continue;
|
|
17753
17918
|
}
|
|
17754
17919
|
const parsed = parseEnvFile(envFile);
|
|
@@ -17759,17 +17924,17 @@ function loadEnvFiles(cwd, workspaceRoot2) {
|
|
|
17759
17924
|
}
|
|
17760
17925
|
function findEnvFilePaths(cwd, workspaceRoot2) {
|
|
17761
17926
|
const names = [".env", ".env.local", ".env.development", ".env.development.local"];
|
|
17762
|
-
const roots = [workspaceRoot2,
|
|
17927
|
+
const roots = [workspaceRoot2, path19.resolve(cwd)].filter(
|
|
17763
17928
|
(value) => Boolean(value)
|
|
17764
17929
|
);
|
|
17765
|
-
const candidates = roots.flatMap((root) => names.map((name) =>
|
|
17930
|
+
const candidates = roots.flatMap((root) => names.map((name) => path19.join(root, name)));
|
|
17766
17931
|
return Array.from(new Set(candidates));
|
|
17767
17932
|
}
|
|
17768
17933
|
function parseEnvFile(filePath) {
|
|
17769
17934
|
const values = {};
|
|
17770
17935
|
let content;
|
|
17771
17936
|
try {
|
|
17772
|
-
content =
|
|
17937
|
+
content = fs20.readFileSync(filePath, "utf-8");
|
|
17773
17938
|
} catch {
|
|
17774
17939
|
return values;
|
|
17775
17940
|
}
|
|
@@ -17813,24 +17978,24 @@ function parseEnvValue(rawValue) {
|
|
|
17813
17978
|
}
|
|
17814
17979
|
function findRuntimeMcpConfigPaths(cwd, workspaceRoot2) {
|
|
17815
17980
|
const candidatePaths = [
|
|
17816
|
-
workspaceRoot2 ?
|
|
17817
|
-
|
|
17818
|
-
|
|
17819
|
-
|
|
17820
|
-
|
|
17981
|
+
workspaceRoot2 ? path19.join(workspaceRoot2, ".mcp.json") : null,
|
|
17982
|
+
path19.join(cwd, ".mcp.json"),
|
|
17983
|
+
path19.join(os6.homedir(), ".mcp.json"),
|
|
17984
|
+
path19.join(os6.homedir(), ".claude", "claude_desktop_config.json"),
|
|
17985
|
+
path19.join(os6.homedir(), ".codex", "config.toml")
|
|
17821
17986
|
].filter((value) => Boolean(value));
|
|
17822
17987
|
const uniquePaths = Array.from(new Set(candidatePaths));
|
|
17823
17988
|
return uniquePaths.filter((configPath) => configHasRuntimeServer(configPath));
|
|
17824
17989
|
}
|
|
17825
17990
|
function configHasRuntimeServer(configPath) {
|
|
17826
|
-
if (!
|
|
17991
|
+
if (!fs20.existsSync(configPath)) {
|
|
17827
17992
|
return false;
|
|
17828
17993
|
}
|
|
17829
17994
|
if (configPath.endsWith(".toml")) {
|
|
17830
17995
|
return tomlConfigHasRuntimeServer(configPath);
|
|
17831
17996
|
}
|
|
17832
17997
|
try {
|
|
17833
|
-
const parsed = JSON.parse(
|
|
17998
|
+
const parsed = JSON.parse(fs20.readFileSync(configPath, "utf-8"));
|
|
17834
17999
|
if (!isRecord9(parsed)) {
|
|
17835
18000
|
return false;
|
|
17836
18001
|
}
|
|
@@ -17857,7 +18022,7 @@ function configHasRuntimeServer(configPath) {
|
|
|
17857
18022
|
function tomlConfigHasRuntimeServer(configPath) {
|
|
17858
18023
|
let content;
|
|
17859
18024
|
try {
|
|
17860
|
-
content =
|
|
18025
|
+
content = fs20.readFileSync(configPath, "utf-8");
|
|
17861
18026
|
} catch {
|
|
17862
18027
|
return false;
|
|
17863
18028
|
}
|
|
@@ -17910,7 +18075,7 @@ async function doctorCommand(options = {}) {
|
|
|
17910
18075
|
printDoctorReport(report, companionVersion, auth, toolCatalog);
|
|
17911
18076
|
}
|
|
17912
18077
|
function probeCompanionVersion(report) {
|
|
17913
|
-
const currentVersion = readPackageVersion(
|
|
18078
|
+
const currentVersion = readPackageVersion(path20.resolve(__dirname, "../package.json"));
|
|
17914
18079
|
const workspacePackageVersion = findWorkspaceCompanionVersion(report);
|
|
17915
18080
|
const latestNpm = probeLatestNpmVersion();
|
|
17916
18081
|
const warnings = [];
|
|
@@ -17950,7 +18115,7 @@ function probeCompanionVersion(report) {
|
|
|
17950
18115
|
}
|
|
17951
18116
|
function readPackageVersion(packageJsonPath) {
|
|
17952
18117
|
try {
|
|
17953
|
-
const raw =
|
|
18118
|
+
const raw = fs21.readFileSync(packageJsonPath, "utf8");
|
|
17954
18119
|
const parsed = JSON.parse(raw);
|
|
17955
18120
|
return typeof parsed.version === "string" && parsed.version.length > 0 ? parsed.version : void 0;
|
|
17956
18121
|
} catch {
|
|
@@ -17959,9 +18124,9 @@ function readPackageVersion(packageJsonPath) {
|
|
|
17959
18124
|
}
|
|
17960
18125
|
function findWorkspaceCompanionVersion(report) {
|
|
17961
18126
|
const candidates = [
|
|
17962
|
-
|
|
17963
|
-
report.workspaceRoot ?
|
|
17964
|
-
|
|
18127
|
+
path20.join(report.cwd, "packages", "cli", "package.json"),
|
|
18128
|
+
report.workspaceRoot ? path20.join(report.workspaceRoot, "packages", "cli", "package.json") : void 0,
|
|
18129
|
+
path20.basename(report.cwd) === "cli" ? path20.join(report.cwd, "package.json") : void 0
|
|
17965
18130
|
].filter((value) => Boolean(value));
|
|
17966
18131
|
for (const candidate of candidates) {
|
|
17967
18132
|
const version = readPackageVersion(candidate);
|
|
@@ -18304,23 +18469,23 @@ var import_path5 = __toESM(require("path"));
|
|
|
18304
18469
|
var import_chalk10 = __toESM(require("chalk"));
|
|
18305
18470
|
|
|
18306
18471
|
// src/commands/workflows.ts
|
|
18307
|
-
var
|
|
18308
|
-
var
|
|
18472
|
+
var fs32 = __toESM(require("fs"));
|
|
18473
|
+
var path31 = __toESM(require("path"));
|
|
18309
18474
|
var import_node_child_process15 = require("child_process");
|
|
18310
|
-
var
|
|
18475
|
+
var import_node_crypto15 = require("crypto");
|
|
18311
18476
|
var import_chalk9 = __toESM(require("chalk"));
|
|
18312
18477
|
|
|
18313
18478
|
// src/runtime/orchestrator-handoff.ts
|
|
18314
|
-
var
|
|
18315
|
-
var
|
|
18479
|
+
var fs22 = __toESM(require("fs"));
|
|
18480
|
+
var path21 = __toESM(require("path"));
|
|
18316
18481
|
var import_child_process6 = require("child_process");
|
|
18317
|
-
var ORCHESTRATOR_HANDOFF_RELATIVE_PATH =
|
|
18482
|
+
var ORCHESTRATOR_HANDOFF_RELATIVE_PATH = path21.join(
|
|
18318
18483
|
".snipara",
|
|
18319
18484
|
"orchestrator",
|
|
18320
18485
|
"handoff.json"
|
|
18321
18486
|
);
|
|
18322
18487
|
function buildOrchestratorHandoff(options) {
|
|
18323
|
-
const rootDir =
|
|
18488
|
+
const rootDir = path21.resolve(options.rootDir ?? process.cwd());
|
|
18324
18489
|
const workflowState = readWorkflowState(rootDir);
|
|
18325
18490
|
const changedFiles = normalizeStringList2(
|
|
18326
18491
|
options.changedFiles ?? (Array.isArray(workflowState?.currentPhase?.files) ? workflowState.currentPhase.files : [])
|
|
@@ -18672,11 +18837,11 @@ function compactObject2(value) {
|
|
|
18672
18837
|
);
|
|
18673
18838
|
}
|
|
18674
18839
|
function writeOrchestratorHandoff(options) {
|
|
18675
|
-
const rootDir =
|
|
18840
|
+
const rootDir = path21.resolve(options.rootDir ?? process.cwd());
|
|
18676
18841
|
const handoff = buildOrchestratorHandoff({ ...options, rootDir });
|
|
18677
|
-
const absolutePath =
|
|
18678
|
-
|
|
18679
|
-
|
|
18842
|
+
const absolutePath = path21.join(rootDir, ORCHESTRATOR_HANDOFF_RELATIVE_PATH);
|
|
18843
|
+
fs22.mkdirSync(path21.dirname(absolutePath), { recursive: true });
|
|
18844
|
+
fs22.writeFileSync(absolutePath, `${JSON.stringify(handoff, null, 2)}
|
|
18680
18845
|
`, "utf8");
|
|
18681
18846
|
return {
|
|
18682
18847
|
handoff,
|
|
@@ -18686,11 +18851,11 @@ function writeOrchestratorHandoff(options) {
|
|
|
18686
18851
|
};
|
|
18687
18852
|
}
|
|
18688
18853
|
function readWorkflowState(rootDir) {
|
|
18689
|
-
const workflowPath =
|
|
18690
|
-
if (!
|
|
18854
|
+
const workflowPath = path21.join(rootDir, ".snipara", "workflow", "current.json");
|
|
18855
|
+
if (!fs22.existsSync(workflowPath)) {
|
|
18691
18856
|
return null;
|
|
18692
18857
|
}
|
|
18693
|
-
const parsed = JSON.parse(
|
|
18858
|
+
const parsed = JSON.parse(fs22.readFileSync(workflowPath, "utf8"));
|
|
18694
18859
|
const phases = Array.isArray(parsed.phases) ? parsed.phases.filter(isRecord10).map((phase, index) => normalizeWorkflowPhase(phase, index)) : [];
|
|
18695
18860
|
const currentPhase = phases.find((phase) => phase.id === parsed.currentPhaseId);
|
|
18696
18861
|
const runtimeBindings = Array.isArray(parsed.runtime?.sandbox?.bindings) ? parsed.runtime?.sandbox?.bindings.filter(isRecord10) : [];
|
|
@@ -18837,9 +19002,9 @@ async function appendJournalCheckpoint(payload) {
|
|
|
18837
19002
|
}
|
|
18838
19003
|
|
|
18839
19004
|
// src/commands/coding-ledger.ts
|
|
18840
|
-
var
|
|
18841
|
-
var
|
|
18842
|
-
var
|
|
19005
|
+
var fs23 = __toESM(require("fs"));
|
|
19006
|
+
var path22 = __toESM(require("path"));
|
|
19007
|
+
var import_node_crypto10 = require("crypto");
|
|
18843
19008
|
var import_node_child_process8 = require("child_process");
|
|
18844
19009
|
var CODING_INTELLIGENCE_LEDGER_VERSION = "snipara.coding_intelligence_ledger.v0";
|
|
18845
19010
|
var MAX_SECTION_ITEMS = 24;
|
|
@@ -18883,7 +19048,7 @@ function isRecord11(value) {
|
|
|
18883
19048
|
function createRedactor2(rootDir) {
|
|
18884
19049
|
const patterns = /* @__PURE__ */ new Set();
|
|
18885
19050
|
let redactedValueCount = 0;
|
|
18886
|
-
const repoPath =
|
|
19051
|
+
const repoPath = path22.resolve(rootDir);
|
|
18887
19052
|
function redact(value) {
|
|
18888
19053
|
let result = truncateText(String(value ?? ""));
|
|
18889
19054
|
const matchedPatterns = [];
|
|
@@ -18929,7 +19094,7 @@ function createRedactor2(rootDir) {
|
|
|
18929
19094
|
};
|
|
18930
19095
|
}
|
|
18931
19096
|
function buildCodingIntelligenceLedger(options = {}) {
|
|
18932
|
-
const rootDir =
|
|
19097
|
+
const rootDir = path22.resolve(options.dir ?? process.cwd());
|
|
18933
19098
|
const input = mergeInputs(readInputFile(options.fromFile, rootDir), options.input);
|
|
18934
19099
|
const redactor = createRedactor2(rootDir);
|
|
18935
19100
|
const prompt2 = buildPrompt(input, options, redactor);
|
|
@@ -18990,9 +19155,9 @@ async function codingLedgerExportCommand(options) {
|
|
|
18990
19155
|
const ledger = buildCodingIntelligenceLedger(options);
|
|
18991
19156
|
const content = JSON.stringify(ledger, null, 2);
|
|
18992
19157
|
if (options.output) {
|
|
18993
|
-
const absolute =
|
|
18994
|
-
|
|
18995
|
-
|
|
19158
|
+
const absolute = path22.resolve(options.dir ?? process.cwd(), options.output);
|
|
19159
|
+
fs23.mkdirSync(path22.dirname(absolute), { recursive: true });
|
|
19160
|
+
fs23.writeFileSync(absolute, `${content}
|
|
18996
19161
|
`, "utf8");
|
|
18997
19162
|
if (!options.json) {
|
|
18998
19163
|
console.log(`Wrote coding intelligence ledger: ${absolute}`);
|
|
@@ -19189,8 +19354,8 @@ function readInputFile(filePath, rootDir) {
|
|
|
19189
19354
|
if (!filePath) {
|
|
19190
19355
|
return {};
|
|
19191
19356
|
}
|
|
19192
|
-
const absolute =
|
|
19193
|
-
const parsed = JSON.parse(
|
|
19357
|
+
const absolute = path22.resolve(rootDir, filePath);
|
|
19358
|
+
const parsed = JSON.parse(fs23.readFileSync(absolute, "utf8"));
|
|
19194
19359
|
if (!isRecord11(parsed)) {
|
|
19195
19360
|
throw new Error("coding ledger --from-file must contain a JSON object.");
|
|
19196
19361
|
}
|
|
@@ -19295,7 +19460,7 @@ function itemId(section, index, value) {
|
|
|
19295
19460
|
return `${section}:${stableHash([section, String(index), value]).slice(0, 16)}`;
|
|
19296
19461
|
}
|
|
19297
19462
|
function stableHash(parts) {
|
|
19298
|
-
return (0,
|
|
19463
|
+
return (0, import_node_crypto10.createHash)("sha256").update(parts.join("\0")).digest("hex");
|
|
19299
19464
|
}
|
|
19300
19465
|
function stringValue5(value) {
|
|
19301
19466
|
if (typeof value === "string") {
|
|
@@ -19389,11 +19554,11 @@ function removeUndefined(value) {
|
|
|
19389
19554
|
}
|
|
19390
19555
|
|
|
19391
19556
|
// src/commands/decision-apply.ts
|
|
19392
|
-
var
|
|
19393
|
-
var
|
|
19557
|
+
var fs24 = __toESM(require("fs"));
|
|
19558
|
+
var path23 = __toESM(require("path"));
|
|
19394
19559
|
var DECISION_APPLY_LEDGER_VERSION = "snipara.decision_apply_ledger.v0";
|
|
19395
|
-
var DECISION_APPLY_RELATIVE_DIR =
|
|
19396
|
-
var POLICY_DRAFT_RELATIVE_DIR =
|
|
19560
|
+
var DECISION_APPLY_RELATIVE_DIR = path23.join(".snipara", "policy-ledger", "applied");
|
|
19561
|
+
var POLICY_DRAFT_RELATIVE_DIR = path23.join(".snipara", "policies", "drafts");
|
|
19397
19562
|
function buildDecisionApplyReport(options = {}) {
|
|
19398
19563
|
const cwd = options.cwd ?? process.cwd();
|
|
19399
19564
|
const dryRun = options.dryRun ?? true;
|
|
@@ -19542,12 +19707,12 @@ function summarizeDecisionApplyItems(items, written) {
|
|
|
19542
19707
|
};
|
|
19543
19708
|
}
|
|
19544
19709
|
function writeAppliedDecisionRecord(item, cwd) {
|
|
19545
|
-
|
|
19710
|
+
fs24.mkdirSync(appliedDecisionDir(cwd), { recursive: true });
|
|
19546
19711
|
let policyDraftPath;
|
|
19547
19712
|
if (item.policyDraftPath) {
|
|
19548
19713
|
const absoluteDraftPath = policyDraftPathFor(cwd, item.requestId);
|
|
19549
|
-
|
|
19550
|
-
|
|
19714
|
+
fs24.mkdirSync(path23.dirname(absoluteDraftPath), { recursive: true });
|
|
19715
|
+
fs24.writeFileSync(
|
|
19551
19716
|
absoluteDraftPath,
|
|
19552
19717
|
`${stableDecisionJsonStringify({
|
|
19553
19718
|
schemaVersion: "snipara.project_policy_draft.v0",
|
|
@@ -19592,7 +19757,7 @@ function writeAppliedDecisionRecord(item, cwd) {
|
|
|
19592
19757
|
policyDraftPath,
|
|
19593
19758
|
caveats: item.caveats
|
|
19594
19759
|
};
|
|
19595
|
-
|
|
19760
|
+
fs24.writeFileSync(
|
|
19596
19761
|
appliedDecisionPath(cwd, item.requestId),
|
|
19597
19762
|
`${stableDecisionJsonStringify(record2)}
|
|
19598
19763
|
`,
|
|
@@ -19601,36 +19766,36 @@ function writeAppliedDecisionRecord(item, cwd) {
|
|
|
19601
19766
|
}
|
|
19602
19767
|
function readAppliedDecisionRecord(cwd, requestId) {
|
|
19603
19768
|
const filePath = appliedDecisionPath(cwd, requestId);
|
|
19604
|
-
if (!
|
|
19769
|
+
if (!fs24.existsSync(filePath)) {
|
|
19605
19770
|
return void 0;
|
|
19606
19771
|
}
|
|
19607
|
-
const parsed = JSON.parse(
|
|
19772
|
+
const parsed = JSON.parse(fs24.readFileSync(filePath, "utf8"));
|
|
19608
19773
|
return parsed.schemaVersion === DECISION_APPLY_LEDGER_VERSION ? parsed : void 0;
|
|
19609
19774
|
}
|
|
19610
19775
|
function appliedDecisionDir(cwd) {
|
|
19611
|
-
return
|
|
19776
|
+
return path23.join(cwd, DECISION_APPLY_RELATIVE_DIR);
|
|
19612
19777
|
}
|
|
19613
19778
|
function appliedDecisionPath(cwd, requestId) {
|
|
19614
|
-
return
|
|
19779
|
+
return path23.join(appliedDecisionDir(cwd), `${sanitizeFileStem(requestId)}.json`);
|
|
19615
19780
|
}
|
|
19616
19781
|
function policyDraftPathFor(cwd, requestId) {
|
|
19617
|
-
return
|
|
19782
|
+
return path23.join(cwd, POLICY_DRAFT_RELATIVE_DIR, `${sanitizeFileStem(requestId)}.json`);
|
|
19618
19783
|
}
|
|
19619
19784
|
function sanitizeFileStem(value) {
|
|
19620
19785
|
return value.replace(/[^a-zA-Z0-9._-]/g, "_").slice(0, 160) || "decision";
|
|
19621
19786
|
}
|
|
19622
19787
|
function toProjectRelativePath2(absolutePath, cwd) {
|
|
19623
|
-
const relative15 =
|
|
19624
|
-
return relative15.startsWith(".") ? relative15 : `.${
|
|
19788
|
+
const relative15 = path23.relative(cwd, absolutePath).replace(/\\/g, "/");
|
|
19789
|
+
return relative15.startsWith(".") ? relative15 : `.${path23.sep}${relative15}`.replace(/\\/g, "/");
|
|
19625
19790
|
}
|
|
19626
19791
|
|
|
19627
19792
|
// src/commands/collaboration.ts
|
|
19628
19793
|
var import_node_child_process9 = require("child_process");
|
|
19629
|
-
var
|
|
19630
|
-
var
|
|
19794
|
+
var import_node_crypto11 = require("crypto");
|
|
19795
|
+
var fs25 = __toESM(require("fs"));
|
|
19631
19796
|
var os7 = __toESM(require("os"));
|
|
19632
|
-
var
|
|
19633
|
-
var COLLABORATION_STATE_RELATIVE_PATH =
|
|
19797
|
+
var path24 = __toESM(require("path"));
|
|
19798
|
+
var COLLABORATION_STATE_RELATIVE_PATH = path24.join(
|
|
19634
19799
|
".snipara",
|
|
19635
19800
|
"collaboration",
|
|
19636
19801
|
"session.json"
|
|
@@ -19725,16 +19890,16 @@ function createEmptyCollaborationState(now = /* @__PURE__ */ new Date()) {
|
|
|
19725
19890
|
};
|
|
19726
19891
|
}
|
|
19727
19892
|
function getCollaborationStatePath(rootDir = process.cwd()) {
|
|
19728
|
-
return
|
|
19893
|
+
return path24.join(rootDir, COLLABORATION_STATE_RELATIVE_PATH);
|
|
19729
19894
|
}
|
|
19730
19895
|
function loadCollaborationState(rootDir = process.cwd()) {
|
|
19731
19896
|
const statePath = getCollaborationStatePath(rootDir);
|
|
19732
|
-
if (!
|
|
19897
|
+
if (!fs25.existsSync(statePath)) {
|
|
19733
19898
|
return createEmptyCollaborationState();
|
|
19734
19899
|
}
|
|
19735
19900
|
let parsed;
|
|
19736
19901
|
try {
|
|
19737
|
-
parsed = JSON.parse(
|
|
19902
|
+
parsed = JSON.parse(fs25.readFileSync(statePath, "utf8"));
|
|
19738
19903
|
} catch {
|
|
19739
19904
|
return createEmptyCollaborationState();
|
|
19740
19905
|
}
|
|
@@ -19767,15 +19932,15 @@ function saveCollaborationState(state, rootDir = process.cwd()) {
|
|
|
19767
19932
|
expireLocalLeases(state);
|
|
19768
19933
|
expireReviewOnlyAcknowledgements(state);
|
|
19769
19934
|
const statePath = getCollaborationStatePath(rootDir);
|
|
19770
|
-
|
|
19935
|
+
fs25.mkdirSync(path24.dirname(statePath), { recursive: true });
|
|
19771
19936
|
const tempPath = `${statePath}.${process.pid}.${Date.now()}.tmp`;
|
|
19772
19937
|
try {
|
|
19773
|
-
|
|
19938
|
+
fs25.writeFileSync(tempPath, `${JSON.stringify(state, null, 2)}
|
|
19774
19939
|
`, "utf8");
|
|
19775
|
-
|
|
19940
|
+
fs25.renameSync(tempPath, statePath);
|
|
19776
19941
|
} finally {
|
|
19777
|
-
if (
|
|
19778
|
-
|
|
19942
|
+
if (fs25.existsSync(tempPath)) {
|
|
19943
|
+
fs25.unlinkSync(tempPath);
|
|
19779
19944
|
}
|
|
19780
19945
|
}
|
|
19781
19946
|
}
|
|
@@ -19969,7 +20134,7 @@ async function collaborationClaimCommand(options) {
|
|
|
19969
20134
|
);
|
|
19970
20135
|
}
|
|
19971
20136
|
async function workflowCollaborationStart(options) {
|
|
19972
|
-
const rootDir =
|
|
20137
|
+
const rootDir = path24.resolve(options.rootDir ?? process.cwd());
|
|
19973
20138
|
const workSessionId = workflowWorkSessionId(options.workflowId);
|
|
19974
20139
|
const context = resolveCollaborationContext({
|
|
19975
20140
|
dir: rootDir,
|
|
@@ -20041,7 +20206,7 @@ async function workflowCollaborationStart(options) {
|
|
|
20041
20206
|
};
|
|
20042
20207
|
}
|
|
20043
20208
|
async function workflowCollaborationRelease(options) {
|
|
20044
|
-
const rootDir =
|
|
20209
|
+
const rootDir = path24.resolve(options.rootDir ?? process.cwd());
|
|
20045
20210
|
const context = resolveCollaborationContext({
|
|
20046
20211
|
dir: rootDir,
|
|
20047
20212
|
client: "snipara-companion:workflow"
|
|
@@ -20660,9 +20825,9 @@ function readGitChangedFiles(rootDir, args) {
|
|
|
20660
20825
|
return output ? normalizeFiles(output.split(/\r?\n/)) : [];
|
|
20661
20826
|
}
|
|
20662
20827
|
function resolveRepoRoot3(cwd) {
|
|
20663
|
-
const resolved =
|
|
20828
|
+
const resolved = path24.resolve(cwd);
|
|
20664
20829
|
const gitRoot = readGitValue4(resolved, ["rev-parse", "--show-toplevel"]);
|
|
20665
|
-
return gitRoot ?
|
|
20830
|
+
return gitRoot ? path24.resolve(gitRoot) : resolved;
|
|
20666
20831
|
}
|
|
20667
20832
|
function deriveGuardProfileResources(profile, files) {
|
|
20668
20833
|
const resources = [];
|
|
@@ -20939,26 +21104,26 @@ ${nextBlock}`);
|
|
|
20939
21104
|
}
|
|
20940
21105
|
function resolveGitHooksDir2(repoRoot) {
|
|
20941
21106
|
const gitHooksPath = readGitValue4(repoRoot, ["rev-parse", "--git-path", "hooks"]);
|
|
20942
|
-
const hooksDir =
|
|
20943
|
-
const huskyUserHooksDir =
|
|
20944
|
-
if (
|
|
21107
|
+
const hooksDir = path24.resolve(repoRoot, gitHooksPath ?? path24.join(".git", "hooks"));
|
|
21108
|
+
const huskyUserHooksDir = path24.dirname(hooksDir);
|
|
21109
|
+
if (path24.basename(hooksDir) === "_" && path24.basename(huskyUserHooksDir) === ".husky" && fs25.existsSync(path24.join(hooksDir, "h"))) {
|
|
20945
21110
|
return huskyUserHooksDir;
|
|
20946
21111
|
}
|
|
20947
21112
|
return hooksDir;
|
|
20948
21113
|
}
|
|
20949
21114
|
function installManagedCollaborationGitHook(repoRoot, hookName, options) {
|
|
20950
21115
|
const hooksDir = resolveGitHooksDir2(repoRoot);
|
|
20951
|
-
const hookPath =
|
|
20952
|
-
const currentContent =
|
|
21116
|
+
const hookPath = path24.join(hooksDir, hookName);
|
|
21117
|
+
const currentContent = fs25.existsSync(hookPath) ? fs25.readFileSync(hookPath, "utf8") : null;
|
|
20953
21118
|
const block = buildCollaborationGitHookBlock(hookName);
|
|
20954
21119
|
const nextContent = mergeManagedCollaborationHookBlock(hookName, currentContent, block);
|
|
20955
21120
|
const action = currentContent === null ? "created" : currentContent === nextContent ? "unchanged" : "updated";
|
|
20956
21121
|
if (!options.dryRun && action !== "unchanged") {
|
|
20957
|
-
|
|
20958
|
-
|
|
20959
|
-
|
|
20960
|
-
} else if (!options.dryRun &&
|
|
20961
|
-
|
|
21122
|
+
fs25.mkdirSync(hooksDir, { recursive: true });
|
|
21123
|
+
fs25.writeFileSync(hookPath, nextContent, "utf8");
|
|
21124
|
+
fs25.chmodSync(hookPath, 493);
|
|
21125
|
+
} else if (!options.dryRun && fs25.existsSync(hookPath)) {
|
|
21126
|
+
fs25.chmodSync(hookPath, fs25.statSync(hookPath).mode | 493);
|
|
20962
21127
|
}
|
|
20963
21128
|
return { hook: hookName, path: hookPath, action, content: nextContent };
|
|
20964
21129
|
}
|
|
@@ -21370,7 +21535,7 @@ function printGuardActionCards(cards) {
|
|
|
21370
21535
|
}
|
|
21371
21536
|
}
|
|
21372
21537
|
function buildLocalSessionId(context, task, files) {
|
|
21373
|
-
const hash = (0,
|
|
21538
|
+
const hash = (0, import_node_crypto11.createHash)("sha1").update([context.actor.actorId, context.branch ?? "", task ?? "", files.join(",")].join("\n")).digest("hex").slice(0, 12);
|
|
21374
21539
|
return `local_${hash}`;
|
|
21375
21540
|
}
|
|
21376
21541
|
function normalizeFiles(files) {
|
|
@@ -21475,7 +21640,7 @@ function fingerprintReviewOnlyGuardEvaluation(evaluation) {
|
|
|
21475
21640
|
workSessionId: conflict.workSessionId ?? null,
|
|
21476
21641
|
reason: conflict.reason
|
|
21477
21642
|
})).sort((a, b) => JSON.stringify(a).localeCompare(JSON.stringify(b)));
|
|
21478
|
-
return (0,
|
|
21643
|
+
return (0, import_node_crypto11.createHash)("sha256").update(JSON.stringify(findings)).digest("hex");
|
|
21479
21644
|
}
|
|
21480
21645
|
function persistReviewOnlyAcknowledgement(state, profile, action, findingFingerprint, now = /* @__PURE__ */ new Date()) {
|
|
21481
21646
|
invalidateReviewOnlyAcknowledgements(state, profile, action);
|
|
@@ -21554,7 +21719,7 @@ function normalizeResourceId(kind, id) {
|
|
|
21554
21719
|
return normalized;
|
|
21555
21720
|
}
|
|
21556
21721
|
function normalizeRepoPath3(value) {
|
|
21557
|
-
return value.trim().split(
|
|
21722
|
+
return value.trim().split(path24.sep).join("/").replace(/^\.?\//, "");
|
|
21558
21723
|
}
|
|
21559
21724
|
function normalizeOptionalString3(value) {
|
|
21560
21725
|
const normalized = typeof value === "string" ? value.trim() : "";
|
|
@@ -21601,15 +21766,15 @@ function ensureTrailingNewline3(value) {
|
|
|
21601
21766
|
`;
|
|
21602
21767
|
}
|
|
21603
21768
|
function sleep2(ms) {
|
|
21604
|
-
return new Promise((
|
|
21769
|
+
return new Promise((resolve26) => setTimeout(resolve26, ms));
|
|
21605
21770
|
}
|
|
21606
21771
|
|
|
21607
21772
|
// src/commands/team-sync.ts
|
|
21608
|
-
var
|
|
21609
|
-
var
|
|
21773
|
+
var fs26 = __toESM(require("fs"));
|
|
21774
|
+
var path25 = __toESM(require("path"));
|
|
21610
21775
|
var import_node_child_process10 = require("child_process");
|
|
21611
|
-
var
|
|
21612
|
-
var TEAM_SYNC_STATE_RELATIVE_PATH =
|
|
21776
|
+
var import_node_crypto12 = require("crypto");
|
|
21777
|
+
var TEAM_SYNC_STATE_RELATIVE_PATH = path25.join(".snipara", "team-sync", "session.json");
|
|
21613
21778
|
var TEAM_SYNC_STALE_WORK_MS = 48 * 60 * 60 * 1e3;
|
|
21614
21779
|
var TEAM_SYNC_AUTO_ARCHIVE_WORK_MS = 14 * 24 * 60 * 60 * 1e3;
|
|
21615
21780
|
function buildTeamSyncStartWorkRecord(input) {
|
|
@@ -21813,10 +21978,10 @@ function autoArchiveTeamSyncState(rootDir = process.cwd(), now = /* @__PURE__ */
|
|
|
21813
21978
|
}
|
|
21814
21979
|
function loadTeamSyncState(rootDir = process.cwd()) {
|
|
21815
21980
|
const statePath = getTeamSyncStatePath(rootDir);
|
|
21816
|
-
if (!
|
|
21981
|
+
if (!fs26.existsSync(statePath)) {
|
|
21817
21982
|
return createEmptyTeamSyncState();
|
|
21818
21983
|
}
|
|
21819
|
-
const parsed = JSON.parse(
|
|
21984
|
+
const parsed = JSON.parse(fs26.readFileSync(statePath, "utf8"));
|
|
21820
21985
|
return {
|
|
21821
21986
|
schemaVersion: "snipara.team-sync.v1",
|
|
21822
21987
|
updatedAt: typeof parsed.updatedAt === "string" ? parsed.updatedAt : (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -21826,12 +21991,12 @@ function loadTeamSyncState(rootDir = process.cwd()) {
|
|
|
21826
21991
|
}
|
|
21827
21992
|
function saveTeamSyncState(state, rootDir = process.cwd()) {
|
|
21828
21993
|
const statePath = getTeamSyncStatePath(rootDir);
|
|
21829
|
-
|
|
21830
|
-
|
|
21994
|
+
fs26.mkdirSync(path25.dirname(statePath), { recursive: true });
|
|
21995
|
+
fs26.writeFileSync(statePath, `${JSON.stringify(state, null, 2)}
|
|
21831
21996
|
`, "utf8");
|
|
21832
21997
|
}
|
|
21833
21998
|
function getTeamSyncStatePath(rootDir = process.cwd()) {
|
|
21834
|
-
return
|
|
21999
|
+
return path25.join(rootDir, TEAM_SYNC_STATE_RELATIVE_PATH);
|
|
21835
22000
|
}
|
|
21836
22001
|
async function createTeamSyncStartWorkPayload(rootDir, options) {
|
|
21837
22002
|
const state = loadTeamSyncState(rootDir);
|
|
@@ -22026,12 +22191,12 @@ async function createTeamSyncHandoffPayload(rootDir, options) {
|
|
|
22026
22191
|
};
|
|
22027
22192
|
}
|
|
22028
22193
|
function readWorkflowSnapshot(rootDir) {
|
|
22029
|
-
const statePath =
|
|
22030
|
-
if (!
|
|
22194
|
+
const statePath = path25.join(rootDir, ".snipara", "workflow", "current.json");
|
|
22195
|
+
if (!fs26.existsSync(statePath)) {
|
|
22031
22196
|
return void 0;
|
|
22032
22197
|
}
|
|
22033
22198
|
try {
|
|
22034
|
-
const parsed = JSON.parse(
|
|
22199
|
+
const parsed = JSON.parse(fs26.readFileSync(statePath, "utf8"));
|
|
22035
22200
|
const currentPhaseId = typeof parsed.currentPhaseId === "string" ? parsed.currentPhaseId : void 0;
|
|
22036
22201
|
const currentPhase = Array.isArray(parsed.phases) ? parsed.phases.find((phase) => phase.id === currentPhaseId) : void 0;
|
|
22037
22202
|
return {
|
|
@@ -22304,7 +22469,7 @@ function redactHandoffText(value, rootDir) {
|
|
|
22304
22469
|
let result = value;
|
|
22305
22470
|
const aliases = /* @__PURE__ */ new Set([rootDir]);
|
|
22306
22471
|
try {
|
|
22307
|
-
aliases.add(
|
|
22472
|
+
aliases.add(fs26.realpathSync(rootDir));
|
|
22308
22473
|
} catch {
|
|
22309
22474
|
}
|
|
22310
22475
|
for (const alias of aliases) {
|
|
@@ -22333,21 +22498,21 @@ function sanitizeHandoffArtifact(artifact, rootDir) {
|
|
|
22333
22498
|
return sanitizeHandoffValue(artifact, rootDir);
|
|
22334
22499
|
}
|
|
22335
22500
|
function canonicalizePathForBoundary(value) {
|
|
22336
|
-
let current =
|
|
22501
|
+
let current = path25.resolve(value);
|
|
22337
22502
|
const suffix = [];
|
|
22338
|
-
while (!
|
|
22339
|
-
const parent =
|
|
22503
|
+
while (!fs26.existsSync(current)) {
|
|
22504
|
+
const parent = path25.dirname(current);
|
|
22340
22505
|
if (parent === current) {
|
|
22341
22506
|
break;
|
|
22342
22507
|
}
|
|
22343
|
-
suffix.unshift(
|
|
22508
|
+
suffix.unshift(path25.basename(current));
|
|
22344
22509
|
current = parent;
|
|
22345
22510
|
}
|
|
22346
22511
|
try {
|
|
22347
|
-
current =
|
|
22512
|
+
current = fs26.realpathSync(current);
|
|
22348
22513
|
} catch {
|
|
22349
22514
|
}
|
|
22350
|
-
return
|
|
22515
|
+
return path25.join(current, ...suffix);
|
|
22351
22516
|
}
|
|
22352
22517
|
function markdownList(values) {
|
|
22353
22518
|
return values.map((value) => `- ${value}`).join("\n");
|
|
@@ -22420,18 +22585,18 @@ function writeAgenticHandoffArtifact(rootDir, output, artifact) {
|
|
|
22420
22585
|
if (!output) {
|
|
22421
22586
|
return void 0;
|
|
22422
22587
|
}
|
|
22423
|
-
const outputPath =
|
|
22424
|
-
const relative15 =
|
|
22588
|
+
const outputPath = path25.resolve(rootDir, output);
|
|
22589
|
+
const relative15 = path25.relative(
|
|
22425
22590
|
canonicalizePathForBoundary(rootDir),
|
|
22426
22591
|
canonicalizePathForBoundary(outputPath)
|
|
22427
22592
|
);
|
|
22428
|
-
if (!relative15 || relative15.startsWith("..") ||
|
|
22593
|
+
if (!relative15 || relative15.startsWith("..") || path25.isAbsolute(relative15) || relative15 === ".git" || relative15.startsWith(`.git${path25.sep}`)) {
|
|
22429
22594
|
throw new Error("Handoff output must stay inside the project directory and outside .git.");
|
|
22430
22595
|
}
|
|
22431
|
-
|
|
22596
|
+
fs26.mkdirSync(path25.dirname(outputPath), { recursive: true });
|
|
22432
22597
|
const content = outputPath.toLowerCase().endsWith(".json") ? `${JSON.stringify(artifact, null, 2)}
|
|
22433
22598
|
` : buildAgenticHandoffMarkdown(artifact);
|
|
22434
|
-
|
|
22599
|
+
fs26.writeFileSync(outputPath, content, "utf8");
|
|
22435
22600
|
return outputPath;
|
|
22436
22601
|
}
|
|
22437
22602
|
async function agenticHandoffCommand(options) {
|
|
@@ -23174,7 +23339,7 @@ function readHostedContext(rootDir) {
|
|
|
23174
23339
|
};
|
|
23175
23340
|
}
|
|
23176
23341
|
function resolveRootDir(dir) {
|
|
23177
|
-
return
|
|
23342
|
+
return path25.resolve(dir ?? process.cwd());
|
|
23178
23343
|
}
|
|
23179
23344
|
function matchesCompletionEvidence(item, evidence) {
|
|
23180
23345
|
if (matchesDirectCompletionEvidence(item, evidence)) {
|
|
@@ -23393,7 +23558,7 @@ function formatError2(error) {
|
|
|
23393
23558
|
return error instanceof Error ? error.message : String(error);
|
|
23394
23559
|
}
|
|
23395
23560
|
function buildRecordId(prefix, createdAt, summary, files) {
|
|
23396
|
-
const hash = (0,
|
|
23561
|
+
const hash = (0, import_node_crypto12.createHash)("sha1").update([createdAt, summary, files.join(",")].join("\n")).digest("hex").slice(0, 10);
|
|
23397
23562
|
return `${prefix}_${hash}`;
|
|
23398
23563
|
}
|
|
23399
23564
|
|
|
@@ -24298,12 +24463,12 @@ function printKeyValue(label, value) {
|
|
|
24298
24463
|
}
|
|
24299
24464
|
|
|
24300
24465
|
// src/commands/final-commit-report.ts
|
|
24301
|
-
var
|
|
24466
|
+
var import_node_crypto13 = require("crypto");
|
|
24302
24467
|
var import_node_child_process12 = require("child_process");
|
|
24303
|
-
var
|
|
24304
|
-
var
|
|
24468
|
+
var fs28 = __toESM(require("fs"));
|
|
24469
|
+
var path27 = __toESM(require("path"));
|
|
24305
24470
|
var FINAL_COMMIT_REPORT_VERSION = "snipara.final_commit_report.v1";
|
|
24306
|
-
var FINAL_COMMIT_REPORT_RELATIVE_PATH =
|
|
24471
|
+
var FINAL_COMMIT_REPORT_RELATIVE_PATH = path27.join(
|
|
24307
24472
|
".snipara",
|
|
24308
24473
|
"workflow",
|
|
24309
24474
|
"final-report.json"
|
|
@@ -24445,7 +24610,7 @@ function whyCaptureRationale(receipt) {
|
|
|
24445
24610
|
return receipt.previewCandidates.map((candidate) => candidate.rationale).find(Boolean);
|
|
24446
24611
|
}
|
|
24447
24612
|
function buildFinalCommitReport(input) {
|
|
24448
|
-
const cwd =
|
|
24613
|
+
const cwd = path27.resolve(input.cwd ?? process.cwd());
|
|
24449
24614
|
const phases = (input.state?.phases ?? []).map((phase) => ({
|
|
24450
24615
|
id: phase.id,
|
|
24451
24616
|
title: phase.title,
|
|
@@ -24568,18 +24733,18 @@ function buildFinalCommitReport(input) {
|
|
|
24568
24733
|
};
|
|
24569
24734
|
}
|
|
24570
24735
|
function writeFinalCommitReport(report, cwd = process.cwd()) {
|
|
24571
|
-
const outputPath =
|
|
24736
|
+
const outputPath = path27.join(cwd, FINAL_COMMIT_REPORT_RELATIVE_PATH);
|
|
24572
24737
|
try {
|
|
24573
|
-
|
|
24738
|
+
fs28.mkdirSync(path27.dirname(outputPath), { recursive: true });
|
|
24574
24739
|
const content = `${JSON.stringify(report, null, 2)}
|
|
24575
24740
|
`;
|
|
24576
|
-
|
|
24741
|
+
fs28.writeFileSync(outputPath, content, "utf8");
|
|
24577
24742
|
return {
|
|
24578
24743
|
status: "written",
|
|
24579
24744
|
version: FINAL_COMMIT_REPORT_VERSION,
|
|
24580
24745
|
path: outputPath,
|
|
24581
24746
|
relativePath: FINAL_COMMIT_REPORT_RELATIVE_PATH,
|
|
24582
|
-
hash: `sha256:${(0,
|
|
24747
|
+
hash: `sha256:${(0, import_node_crypto13.createHash)("sha256").update(content).digest("hex")}`
|
|
24583
24748
|
};
|
|
24584
24749
|
} catch (error) {
|
|
24585
24750
|
return {
|
|
@@ -24651,9 +24816,9 @@ function formatFinalCommitReport(report) {
|
|
|
24651
24816
|
|
|
24652
24817
|
// src/commands/run.ts
|
|
24653
24818
|
var import_node_child_process14 = require("child_process");
|
|
24654
|
-
var
|
|
24655
|
-
var
|
|
24656
|
-
var
|
|
24819
|
+
var import_node_crypto14 = require("crypto");
|
|
24820
|
+
var fs30 = __toESM(require("fs"));
|
|
24821
|
+
var path29 = __toESM(require("path"));
|
|
24657
24822
|
var import_chalk8 = __toESM(require("chalk"));
|
|
24658
24823
|
|
|
24659
24824
|
// src/commands/intelligence.ts
|
|
@@ -26751,7 +26916,7 @@ function buildProjectIntelligenceRunEnvelope(startedAt = /* @__PURE__ */ new Dat
|
|
|
26751
26916
|
const codexSessionId = stringValue10(process.env.CODEX_SESSION_ID)?.slice(0, 200);
|
|
26752
26917
|
return {
|
|
26753
26918
|
version: "project-intelligence.judgment-run-envelope.v1",
|
|
26754
|
-
runId: sniparaSessionId ?? codexSessionId ?? `judgment-run:${(0,
|
|
26919
|
+
runId: sniparaSessionId ?? codexSessionId ?? `judgment-run:${(0, import_node_crypto14.randomUUID)()}`,
|
|
26755
26920
|
identitySource: sniparaSessionId ? "snipara_session" : codexSessionId ? "codex_session" : "generated",
|
|
26756
26921
|
startedAt: startedAt.toISOString()
|
|
26757
26922
|
};
|
|
@@ -26792,8 +26957,8 @@ function packageReviewCommand3() {
|
|
|
26792
26957
|
function readOutcomeReceipts(files) {
|
|
26793
26958
|
const receipts = [];
|
|
26794
26959
|
for (const file of normalizeStringList5(files)) {
|
|
26795
|
-
const resolved =
|
|
26796
|
-
const parsed = JSON.parse(
|
|
26960
|
+
const resolved = path29.resolve(process.cwd(), file);
|
|
26961
|
+
const parsed = JSON.parse(fs30.readFileSync(resolved, "utf8"));
|
|
26797
26962
|
receipts.push(...outcomeReceiptsFromUnknown(parsed));
|
|
26798
26963
|
}
|
|
26799
26964
|
return receipts;
|
|
@@ -27693,12 +27858,12 @@ async function projectIntelligenceRunCommand(options) {
|
|
|
27693
27858
|
}
|
|
27694
27859
|
|
|
27695
27860
|
// src/commands/agent-context.ts
|
|
27696
|
-
var
|
|
27697
|
-
var
|
|
27861
|
+
var fs31 = __toESM(require("fs"));
|
|
27862
|
+
var path30 = __toESM(require("path"));
|
|
27698
27863
|
var AGENT_CONTEXT_MANIFEST_DEFAULT_PATH = "snipara.agent-context.json";
|
|
27699
27864
|
function readManifest2(manifestPath2) {
|
|
27700
27865
|
try {
|
|
27701
|
-
return JSON.parse(
|
|
27866
|
+
return JSON.parse(fs31.readFileSync(manifestPath2, "utf8"));
|
|
27702
27867
|
} catch (error) {
|
|
27703
27868
|
const message = error instanceof Error ? error.message : String(error);
|
|
27704
27869
|
throw new Error(`Unable to read Agent Context manifest ${manifestPath2}: ${message}`);
|
|
@@ -27714,15 +27879,15 @@ function localSourceFinding(sourceId, sourcePath, summary) {
|
|
|
27714
27879
|
};
|
|
27715
27880
|
}
|
|
27716
27881
|
function buildLocalAgentContextValidationReport(options) {
|
|
27717
|
-
const cwd =
|
|
27882
|
+
const cwd = path30.resolve(options.cwd ?? process.cwd());
|
|
27718
27883
|
const report = validateAgentContextManifest({
|
|
27719
27884
|
manifest: options.manifest,
|
|
27720
27885
|
generatedAt: options.generatedAt
|
|
27721
27886
|
});
|
|
27722
27887
|
if (!report.manifest) return report;
|
|
27723
27888
|
const localFindings = report.manifest.sources.flatMap((source2) => {
|
|
27724
|
-
const absolutePath =
|
|
27725
|
-
if (!
|
|
27889
|
+
const absolutePath = path30.resolve(cwd, source2.path);
|
|
27890
|
+
if (!fs31.existsSync(absolutePath)) {
|
|
27726
27891
|
return [
|
|
27727
27892
|
localSourceFinding(
|
|
27728
27893
|
source2.id,
|
|
@@ -27731,7 +27896,7 @@ function buildLocalAgentContextValidationReport(options) {
|
|
|
27731
27896
|
)
|
|
27732
27897
|
];
|
|
27733
27898
|
}
|
|
27734
|
-
if (!
|
|
27899
|
+
if (!fs31.statSync(absolutePath).isFile()) {
|
|
27735
27900
|
return [
|
|
27736
27901
|
localSourceFinding(
|
|
27737
27902
|
source2.id,
|
|
@@ -27750,10 +27915,10 @@ function buildLocalAgentContextValidationReport(options) {
|
|
|
27750
27915
|
};
|
|
27751
27916
|
}
|
|
27752
27917
|
function manifestPath(cwd, candidate) {
|
|
27753
|
-
return
|
|
27918
|
+
return path30.resolve(cwd, candidate ?? AGENT_CONTEXT_MANIFEST_DEFAULT_PATH);
|
|
27754
27919
|
}
|
|
27755
27920
|
function resolveLocalAgentContext(options) {
|
|
27756
|
-
const cwd =
|
|
27921
|
+
const cwd = path30.resolve(options.cwd ?? process.cwd());
|
|
27757
27922
|
const resolvedManifestPath = manifestPath(cwd, options.manifest);
|
|
27758
27923
|
const manifest = readManifest2(resolvedManifestPath);
|
|
27759
27924
|
const validation = buildLocalAgentContextValidationReport({ cwd, manifest });
|
|
@@ -27762,7 +27927,7 @@ function resolveLocalAgentContext(options) {
|
|
|
27762
27927
|
throw new Error(`Invalid Agent Context manifest. ${errors}`.trim());
|
|
27763
27928
|
}
|
|
27764
27929
|
return {
|
|
27765
|
-
manifestPath:
|
|
27930
|
+
manifestPath: path30.relative(cwd, resolvedManifestPath) || path30.basename(resolvedManifestPath),
|
|
27766
27931
|
resolution: resolveAgentContext({
|
|
27767
27932
|
manifest,
|
|
27768
27933
|
agent: options.agent,
|
|
@@ -27838,14 +28003,14 @@ function formatAgentContextResolution(resolution) {
|
|
|
27838
28003
|
return lines.join("\n");
|
|
27839
28004
|
}
|
|
27840
28005
|
async function agentContextValidateCommand(options = {}) {
|
|
27841
|
-
const cwd =
|
|
28006
|
+
const cwd = path30.resolve(options.cwd ?? process.cwd());
|
|
27842
28007
|
const resolvedManifestPath = manifestPath(cwd, options.manifest);
|
|
27843
28008
|
const report = buildLocalAgentContextValidationReport({
|
|
27844
28009
|
cwd,
|
|
27845
28010
|
manifest: readManifest2(resolvedManifestPath)
|
|
27846
28011
|
});
|
|
27847
28012
|
console.log(
|
|
27848
|
-
options.json ? stableDecisionJsonStringify(report) : formatValidationReport(report,
|
|
28013
|
+
options.json ? stableDecisionJsonStringify(report) : formatValidationReport(report, path30.relative(cwd, resolvedManifestPath))
|
|
27849
28014
|
);
|
|
27850
28015
|
if (report.status === "invalid") {
|
|
27851
28016
|
process.exitCode = 1;
|
|
@@ -27882,7 +28047,7 @@ var FINAL_COMMIT_SUMMARY_MAX_CHARS = 1200;
|
|
|
27882
28047
|
var FINAL_COMMIT_RETRY_SUMMARY_MAX_CHARS = 600;
|
|
27883
28048
|
var DEFAULT_ADAPTIVE_ROUTING_CATALOG_LIMIT = 20;
|
|
27884
28049
|
var DEFAULT_LOCAL_ORCHESTRATOR_TIMEOUT_MS = 8e3;
|
|
27885
|
-
var ADAPTIVE_ROUTING_POLICY_RELATIVE_PATH2 =
|
|
28050
|
+
var ADAPTIVE_ROUTING_POLICY_RELATIVE_PATH2 = path31.join(".snipara", "adaptive-routing.json");
|
|
27886
28051
|
var MEMORY_DECISION_PRODUCER_ACTIONS = /* @__PURE__ */ new Set([
|
|
27887
28052
|
"accept",
|
|
27888
28053
|
"reject",
|
|
@@ -27953,11 +28118,11 @@ var REUPLOAD_REASONS = /* @__PURE__ */ new Set([
|
|
|
27953
28118
|
"source_modified_after_upload",
|
|
27954
28119
|
"source_hash_changed"
|
|
27955
28120
|
]);
|
|
27956
|
-
var WORKFLOW_STATE_RELATIVE_PATH =
|
|
27957
|
-
var WORKFLOW_PLANS_RELATIVE_DIR =
|
|
28121
|
+
var WORKFLOW_STATE_RELATIVE_PATH = path31.join(".snipara", "workflow", "current.json");
|
|
28122
|
+
var WORKFLOW_PLANS_RELATIVE_DIR = path31.join(".snipara", "workflow", "plans");
|
|
27958
28123
|
var PRODUCER_LOOP_ARTIFACT_VERSION = "snipara.producer_loop_artifact.v0";
|
|
27959
28124
|
var PRODUCER_LOOP_REPORT_VERSION = "snipara.producer_loop_report.v0";
|
|
27960
|
-
var PRODUCER_LOOP_RELATIVE_DIR =
|
|
28125
|
+
var PRODUCER_LOOP_RELATIVE_DIR = path31.join(".snipara", "producer-loop");
|
|
27961
28126
|
var PRODUCER_LOOP_MIN_REVIEW_SAMPLE_SIZE = 5;
|
|
27962
28127
|
var WORKFLOW_PLAN_PRESET_IDS = [
|
|
27963
28128
|
"memory-backend-unification",
|
|
@@ -28049,7 +28214,7 @@ function parseJsonRecord(value, label) {
|
|
|
28049
28214
|
return parsed;
|
|
28050
28215
|
}
|
|
28051
28216
|
function readJsonRecord3(file, label) {
|
|
28052
|
-
return parseJsonRecord(
|
|
28217
|
+
return parseJsonRecord(fs32.readFileSync(file, "utf-8"), label);
|
|
28053
28218
|
}
|
|
28054
28219
|
function parseCsv(value) {
|
|
28055
28220
|
if (!value) {
|
|
@@ -28093,7 +28258,7 @@ function optionalReindexMode(value) {
|
|
|
28093
28258
|
return value === "incremental" || value === "full" ? value : void 0;
|
|
28094
28259
|
}
|
|
28095
28260
|
function inferDocumentFormat(filePath) {
|
|
28096
|
-
return DOCUMENT_SYNC_FORMATS[
|
|
28261
|
+
return DOCUMENT_SYNC_FORMATS[path31.extname(filePath).toLowerCase()];
|
|
28097
28262
|
}
|
|
28098
28263
|
function normalizeDocumentKind(value) {
|
|
28099
28264
|
const normalized = normalizeEnum(value);
|
|
@@ -28126,7 +28291,7 @@ function contentBufferForHash(content) {
|
|
|
28126
28291
|
return Buffer.from(content, "utf8");
|
|
28127
28292
|
}
|
|
28128
28293
|
function hashContent(content) {
|
|
28129
|
-
return (0,
|
|
28294
|
+
return (0, import_node_crypto15.createHash)("sha256").update(contentBufferForHash(content)).digest("hex");
|
|
28130
28295
|
}
|
|
28131
28296
|
function toPreview(value, maxLength = 160) {
|
|
28132
28297
|
if (typeof value === "string") {
|
|
@@ -28373,7 +28538,7 @@ function buildPlanRelevanceWarnings(plan, options) {
|
|
|
28373
28538
|
if (/^(?:https?:)?\/\//i.test(fileHint)) {
|
|
28374
28539
|
return false;
|
|
28375
28540
|
}
|
|
28376
|
-
return !
|
|
28541
|
+
return !fs32.existsSync(path31.resolve(options.cwd, fileHint));
|
|
28377
28542
|
});
|
|
28378
28543
|
if (missingHints.length > 0) {
|
|
28379
28544
|
warnings.push(
|
|
@@ -28934,12 +29099,12 @@ function buildGeneratedWorkflowPlanDocument(plan, fallbackGoal) {
|
|
|
28934
29099
|
}
|
|
28935
29100
|
function defaultGeneratedPlanFilePath(query) {
|
|
28936
29101
|
const filename = `${sanitizeWorkflowId(query, "snipara-plan")}-plan.json`;
|
|
28937
|
-
return
|
|
29102
|
+
return path31.join(process.cwd(), WORKFLOW_PLANS_RELATIVE_DIR, filename);
|
|
28938
29103
|
}
|
|
28939
29104
|
function writeGeneratedWorkflowPlanFile(plan, fallbackGoal, outputFile) {
|
|
28940
|
-
const outputPath =
|
|
28941
|
-
|
|
28942
|
-
|
|
29105
|
+
const outputPath = path31.resolve(outputFile ?? defaultGeneratedPlanFilePath(fallbackGoal));
|
|
29106
|
+
fs32.mkdirSync(path31.dirname(outputPath), { recursive: true });
|
|
29107
|
+
fs32.writeFileSync(
|
|
28943
29108
|
outputPath,
|
|
28944
29109
|
`${JSON.stringify(buildGeneratedWorkflowPlanDocument(plan, fallbackGoal), null, 2)}
|
|
28945
29110
|
`,
|
|
@@ -28947,7 +29112,7 @@ function writeGeneratedWorkflowPlanFile(plan, fallbackGoal, outputFile) {
|
|
|
28947
29112
|
);
|
|
28948
29113
|
return {
|
|
28949
29114
|
path: outputPath,
|
|
28950
|
-
relativePath:
|
|
29115
|
+
relativePath: path31.relative(process.cwd(), outputPath) || path31.basename(outputPath)
|
|
28951
29116
|
};
|
|
28952
29117
|
}
|
|
28953
29118
|
function booleanValue4(value) {
|
|
@@ -29364,15 +29529,15 @@ function buildWorkflowPlanPresetDocument(preset, goal) {
|
|
|
29364
29529
|
}
|
|
29365
29530
|
}
|
|
29366
29531
|
function defaultWorkflowPlanOutputPath(preset, cwd = process.cwd()) {
|
|
29367
|
-
return
|
|
29532
|
+
return path31.resolve(cwd, WORKFLOW_PLANS_RELATIVE_DIR, `${preset}-plan.json`);
|
|
29368
29533
|
}
|
|
29369
29534
|
function toProjectRelativePath3(absolutePath, cwd = process.cwd()) {
|
|
29370
|
-
const relative15 =
|
|
29535
|
+
const relative15 = path31.relative(cwd, absolutePath);
|
|
29371
29536
|
return relative15 && !relative15.startsWith("..") ? relative15 : absolutePath;
|
|
29372
29537
|
}
|
|
29373
29538
|
function buildWorkflowPlanScaffold(preset, options = {}) {
|
|
29374
|
-
const cwd =
|
|
29375
|
-
const outputPath =
|
|
29539
|
+
const cwd = path31.resolve(options.cwd ?? process.cwd());
|
|
29540
|
+
const outputPath = path31.resolve(options.outputPath ?? defaultWorkflowPlanOutputPath(preset, cwd));
|
|
29376
29541
|
const plan = buildWorkflowPlanPresetDocument(preset, options.goal);
|
|
29377
29542
|
return {
|
|
29378
29543
|
preset,
|
|
@@ -29383,18 +29548,18 @@ function buildWorkflowPlanScaffold(preset, options = {}) {
|
|
|
29383
29548
|
};
|
|
29384
29549
|
}
|
|
29385
29550
|
function readWorkflowPlanFile(planFile, fallbackGoal) {
|
|
29386
|
-
const content =
|
|
29551
|
+
const content = fs32.readFileSync(planFile, "utf-8");
|
|
29387
29552
|
if (planFile.toLowerCase().endsWith(".json")) {
|
|
29388
29553
|
return normalizeWorkflowPlanInput(JSON.parse(content), fallbackGoal);
|
|
29389
29554
|
}
|
|
29390
29555
|
return normalizeWorkflowPlanInput(content, fallbackGoal);
|
|
29391
29556
|
}
|
|
29392
29557
|
function readWorkflowPlanMode(planFile) {
|
|
29393
|
-
if (!planFile || !planFile.toLowerCase().endsWith(".json") || !
|
|
29558
|
+
if (!planFile || !planFile.toLowerCase().endsWith(".json") || !fs32.existsSync(planFile)) {
|
|
29394
29559
|
return void 0;
|
|
29395
29560
|
}
|
|
29396
29561
|
try {
|
|
29397
|
-
const parsed = JSON.parse(
|
|
29562
|
+
const parsed = JSON.parse(fs32.readFileSync(planFile, "utf-8"));
|
|
29398
29563
|
return normalizeWorkflowCoordinationMode(parsed.mode);
|
|
29399
29564
|
} catch {
|
|
29400
29565
|
return void 0;
|
|
@@ -29411,7 +29576,7 @@ function inferWorkflowCoordinationMode(options) {
|
|
|
29411
29576
|
return readWorkflowPlanMode(options.planFile) ?? (options.planFile ? "full" : "standard");
|
|
29412
29577
|
}
|
|
29413
29578
|
function getWorkflowStatePath(cwd = process.cwd()) {
|
|
29414
|
-
return
|
|
29579
|
+
return path31.join(cwd, WORKFLOW_STATE_RELATIVE_PATH);
|
|
29415
29580
|
}
|
|
29416
29581
|
function normalizeManagedWorkflowTaskState(task, phase, index, fallbackStatus) {
|
|
29417
29582
|
const status = normalizeTaskStatus(task.status ?? fallbackStatus);
|
|
@@ -29542,10 +29707,10 @@ function normalizeManagedWorkflowRuntimeState(runtime) {
|
|
|
29542
29707
|
}
|
|
29543
29708
|
function readWorkflowState2(cwd = process.cwd()) {
|
|
29544
29709
|
const statePath = getWorkflowStatePath(cwd);
|
|
29545
|
-
if (!
|
|
29710
|
+
if (!fs32.existsSync(statePath)) {
|
|
29546
29711
|
return void 0;
|
|
29547
29712
|
}
|
|
29548
|
-
const parsed = JSON.parse(
|
|
29713
|
+
const parsed = JSON.parse(fs32.readFileSync(statePath, "utf-8"));
|
|
29549
29714
|
if (!Array.isArray(parsed.phases)) {
|
|
29550
29715
|
throw new Error(`${WORKFLOW_STATE_RELATIVE_PATH} is not a valid Snipara workflow state file`);
|
|
29551
29716
|
}
|
|
@@ -29562,14 +29727,14 @@ function readRequiredWorkflowState() {
|
|
|
29562
29727
|
}
|
|
29563
29728
|
function writeWorkflowState(state) {
|
|
29564
29729
|
const statePath = getWorkflowStatePath();
|
|
29565
|
-
|
|
29730
|
+
fs32.mkdirSync(path31.dirname(statePath), { recursive: true });
|
|
29566
29731
|
const normalizedState = normalizeManagedWorkflowState(state);
|
|
29567
29732
|
const normalized = {
|
|
29568
29733
|
...normalizedState,
|
|
29569
29734
|
schemaVersion: "snipara.workflow.v2",
|
|
29570
29735
|
runtime: normalizeManagedWorkflowRuntimeState(normalizedState.runtime)
|
|
29571
29736
|
};
|
|
29572
|
-
|
|
29737
|
+
fs32.writeFileSync(statePath, `${JSON.stringify(normalized, null, 2)}
|
|
29573
29738
|
`, "utf-8");
|
|
29574
29739
|
}
|
|
29575
29740
|
function sortJsonValue4(value) {
|
|
@@ -29592,7 +29757,7 @@ function hashJsonValue(value) {
|
|
|
29592
29757
|
return `sha256:${hashContent(stableJsonStringify(value))}`;
|
|
29593
29758
|
}
|
|
29594
29759
|
function getProducerLoopDir(cwd = process.cwd()) {
|
|
29595
|
-
return
|
|
29760
|
+
return path31.join(cwd, PRODUCER_LOOP_RELATIVE_DIR);
|
|
29596
29761
|
}
|
|
29597
29762
|
function buildProducerLoopArtifactId(options) {
|
|
29598
29763
|
const source2 = [
|
|
@@ -29705,9 +29870,9 @@ function writeProducerLoopArtifact(options) {
|
|
|
29705
29870
|
const artifact = buildProducerLoopArtifact(options);
|
|
29706
29871
|
const artifactHash = hashJsonValue(artifact);
|
|
29707
29872
|
const fileName = `${artifact.generatedAt.replace(/[:.]/g, "-")}-${artifact.artifactId}.json`;
|
|
29708
|
-
const outputPath =
|
|
29709
|
-
|
|
29710
|
-
|
|
29873
|
+
const outputPath = path31.join(getProducerLoopDir(), fileName);
|
|
29874
|
+
fs32.mkdirSync(path31.dirname(outputPath), { recursive: true });
|
|
29875
|
+
fs32.writeFileSync(outputPath, stableJsonStringify(artifact), "utf-8");
|
|
29711
29876
|
return {
|
|
29712
29877
|
status: "written",
|
|
29713
29878
|
schemaVersion: PRODUCER_LOOP_ARTIFACT_VERSION,
|
|
@@ -29760,7 +29925,7 @@ function stringArrayValue(value) {
|
|
|
29760
29925
|
function summarizeProducerLoopArtifactFile(filePath, cwd) {
|
|
29761
29926
|
const relativePath2 = toProjectRelativePath3(filePath, cwd);
|
|
29762
29927
|
try {
|
|
29763
|
-
const content =
|
|
29928
|
+
const content = fs32.readFileSync(filePath, "utf-8");
|
|
29764
29929
|
const parsed = JSON.parse(content);
|
|
29765
29930
|
if (!isRecord19(parsed)) {
|
|
29766
29931
|
throw new Error("artifact must be a JSON object");
|
|
@@ -29826,10 +29991,10 @@ function summarizeProducerLoopArtifactFile(filePath, cwd) {
|
|
|
29826
29991
|
}
|
|
29827
29992
|
function listProducerLoopArtifactFiles(cwd) {
|
|
29828
29993
|
const dir = getProducerLoopDir(cwd);
|
|
29829
|
-
if (!
|
|
29994
|
+
if (!fs32.existsSync(dir)) {
|
|
29830
29995
|
return [];
|
|
29831
29996
|
}
|
|
29832
|
-
return
|
|
29997
|
+
return fs32.readdirSync(dir).filter((fileName) => fileName.endsWith(".json")).map((fileName) => path31.join(dir, fileName)).sort();
|
|
29833
29998
|
}
|
|
29834
29999
|
function producerLoopCalibrationStatus(sampleSize, reviewedSampleSize, minReviewSampleSize) {
|
|
29835
30000
|
if (sampleSize === 0) {
|
|
@@ -29840,8 +30005,8 @@ function producerLoopCalibrationStatus(sampleSize, reviewedSampleSize, minReview
|
|
|
29840
30005
|
}
|
|
29841
30006
|
return "reviewable_sample_set";
|
|
29842
30007
|
}
|
|
29843
|
-
var WORKER_RECEIPT_RELATIVE_DIR =
|
|
29844
|
-
var WORKER_REVIEW_RELATIVE_DIR =
|
|
30008
|
+
var WORKER_RECEIPT_RELATIVE_DIR = path31.join(".snipara", "orchestrator", "executions");
|
|
30009
|
+
var WORKER_REVIEW_RELATIVE_DIR = path31.join(".snipara", "orchestrator", "reviews");
|
|
29845
30010
|
var REQUIRED_WORKER_RECEIPT_FAMILIES = [
|
|
29846
30011
|
"handoffReceiptId",
|
|
29847
30012
|
"claimId",
|
|
@@ -29850,18 +30015,18 @@ var REQUIRED_WORKER_RECEIPT_FAMILIES = [
|
|
|
29850
30015
|
"brainUpdateReceiptId"
|
|
29851
30016
|
];
|
|
29852
30017
|
function listJsonFiles(relativeDir, cwd) {
|
|
29853
|
-
const directory =
|
|
29854
|
-
if (!
|
|
30018
|
+
const directory = path31.join(cwd, relativeDir);
|
|
30019
|
+
if (!fs32.existsSync(directory)) {
|
|
29855
30020
|
return [];
|
|
29856
30021
|
}
|
|
29857
|
-
return
|
|
30022
|
+
return fs32.readdirSync(directory, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => path31.join(directory, entry.name)).sort();
|
|
29858
30023
|
}
|
|
29859
30024
|
function readWorkerReviewFiles(cwd) {
|
|
29860
30025
|
const reviews = /* @__PURE__ */ new Map();
|
|
29861
30026
|
const invalid = [];
|
|
29862
30027
|
for (const filePath of listJsonFiles(WORKER_REVIEW_RELATIVE_DIR, cwd)) {
|
|
29863
30028
|
try {
|
|
29864
|
-
const parsed = JSON.parse(
|
|
30029
|
+
const parsed = JSON.parse(fs32.readFileSync(filePath, "utf-8"));
|
|
29865
30030
|
if (!isRecord19(parsed)) {
|
|
29866
30031
|
throw new Error("review must be a JSON object");
|
|
29867
30032
|
}
|
|
@@ -29893,7 +30058,7 @@ function summarizeWorkerExecutionReceipts(cwd) {
|
|
|
29893
30058
|
const samples = [];
|
|
29894
30059
|
for (const filePath of listJsonFiles(WORKER_RECEIPT_RELATIVE_DIR, cwd)) {
|
|
29895
30060
|
try {
|
|
29896
|
-
const parsed = JSON.parse(
|
|
30061
|
+
const parsed = JSON.parse(fs32.readFileSync(filePath, "utf-8"));
|
|
29897
30062
|
if (!isRecord19(parsed)) {
|
|
29898
30063
|
throw new Error("receipt must be a JSON object");
|
|
29899
30064
|
}
|
|
@@ -29989,7 +30154,7 @@ function buildWorkerTrustRows(samples, minReviewSampleSize) {
|
|
|
29989
30154
|
);
|
|
29990
30155
|
}
|
|
29991
30156
|
function buildProducerLoopReport(options = {}) {
|
|
29992
|
-
const cwd =
|
|
30157
|
+
const cwd = path31.resolve(options.cwd ?? process.cwd());
|
|
29993
30158
|
const minReviewSampleSize = Math.max(
|
|
29994
30159
|
1,
|
|
29995
30160
|
Math.floor(options.minReviewSampleSize ?? PRODUCER_LOOP_MIN_REVIEW_SAMPLE_SIZE)
|
|
@@ -30110,22 +30275,22 @@ function resolveProducerLoopReviewTarget(cwd, selector, latest) {
|
|
|
30110
30275
|
return latestArtifact.path;
|
|
30111
30276
|
}
|
|
30112
30277
|
const directCandidates = [
|
|
30113
|
-
|
|
30114
|
-
|
|
30278
|
+
path31.resolve(cwd, normalizedSelector),
|
|
30279
|
+
path31.resolve(cwd, PRODUCER_LOOP_RELATIVE_DIR, normalizedSelector)
|
|
30115
30280
|
];
|
|
30116
|
-
const directMatch = directCandidates.find((candidate) =>
|
|
30281
|
+
const directMatch = directCandidates.find((candidate) => fs32.existsSync(candidate));
|
|
30117
30282
|
if (directMatch) {
|
|
30118
30283
|
return directMatch;
|
|
30119
30284
|
}
|
|
30120
30285
|
const normalizedPathSelector = normalizedSelector.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
30121
30286
|
const matches = files.filter((filePath) => {
|
|
30122
30287
|
const relativePath2 = toProjectRelativePath3(filePath, cwd).replace(/\\/g, "/");
|
|
30123
|
-
const basename12 =
|
|
30288
|
+
const basename12 = path31.basename(filePath);
|
|
30124
30289
|
if (basename12 === normalizedSelector || relativePath2 === normalizedPathSelector || relativePath2.replace(/^\.\//, "") === normalizedPathSelector) {
|
|
30125
30290
|
return true;
|
|
30126
30291
|
}
|
|
30127
30292
|
try {
|
|
30128
|
-
const parsed = JSON.parse(
|
|
30293
|
+
const parsed = JSON.parse(fs32.readFileSync(filePath, "utf-8"));
|
|
30129
30294
|
return isRecord19(parsed) && stringValue11(parsed.artifactId) === normalizedSelector;
|
|
30130
30295
|
} catch {
|
|
30131
30296
|
return false;
|
|
@@ -30142,7 +30307,7 @@ function resolveProducerLoopReviewTarget(cwd, selector, latest) {
|
|
|
30142
30307
|
return matches[0];
|
|
30143
30308
|
}
|
|
30144
30309
|
function readProducerLoopArtifactForReview(filePath) {
|
|
30145
|
-
const parsed = JSON.parse(
|
|
30310
|
+
const parsed = JSON.parse(fs32.readFileSync(filePath, "utf-8"));
|
|
30146
30311
|
if (!isRecord19(parsed)) {
|
|
30147
30312
|
throw new Error("artifact must be a JSON object");
|
|
30148
30313
|
}
|
|
@@ -30197,7 +30362,7 @@ function applyProducerLoopArtifactReview(artifact, options) {
|
|
|
30197
30362
|
};
|
|
30198
30363
|
}
|
|
30199
30364
|
function reviewProducerLoopArtifact(options) {
|
|
30200
|
-
const cwd =
|
|
30365
|
+
const cwd = path31.resolve(options.cwd ?? process.cwd());
|
|
30201
30366
|
const targetPath = resolveProducerLoopReviewTarget(cwd, options.artifact, options.latest);
|
|
30202
30367
|
const artifact = readProducerLoopArtifactForReview(targetPath);
|
|
30203
30368
|
const rawOutcome = stringValue11(options.outcome);
|
|
@@ -30217,8 +30382,8 @@ function reviewProducerLoopArtifact(options) {
|
|
|
30217
30382
|
...outcome ? { outcome } : {},
|
|
30218
30383
|
notes: options.notes ?? []
|
|
30219
30384
|
});
|
|
30220
|
-
|
|
30221
|
-
const content =
|
|
30385
|
+
fs32.writeFileSync(targetPath, stableJsonStringify(reviewed), "utf-8");
|
|
30386
|
+
const content = fs32.readFileSync(targetPath, "utf-8");
|
|
30222
30387
|
return {
|
|
30223
30388
|
status: "reviewed",
|
|
30224
30389
|
schemaVersion: PRODUCER_LOOP_ARTIFACT_VERSION,
|
|
@@ -30967,8 +31132,8 @@ async function workflowScaffoldCommand(options) {
|
|
|
30967
31132
|
goal: options.goal,
|
|
30968
31133
|
outputPath: options.output
|
|
30969
31134
|
});
|
|
30970
|
-
|
|
30971
|
-
|
|
31135
|
+
fs32.mkdirSync(path31.dirname(scaffold.outputPath), { recursive: true });
|
|
31136
|
+
fs32.writeFileSync(`${scaffold.outputPath}`, `${JSON.stringify(scaffold.plan, null, 2)}
|
|
30972
31137
|
`, "utf8");
|
|
30973
31138
|
if (options.json) {
|
|
30974
31139
|
printJson2({
|
|
@@ -31062,17 +31227,17 @@ function nextEligibleWorkflowTask(state, phase) {
|
|
|
31062
31227
|
}
|
|
31063
31228
|
var DEFAULT_AGENT_CONTEXT_AGENT = "snipara-code";
|
|
31064
31229
|
function agentContextManifestConfig(cwd = process.cwd()) {
|
|
31065
|
-
const manifestPath2 =
|
|
31066
|
-
if (!
|
|
31230
|
+
const manifestPath2 = path31.resolve(cwd, "snipara.agent-context.json");
|
|
31231
|
+
if (!fs32.existsSync(manifestPath2)) return void 0;
|
|
31067
31232
|
try {
|
|
31068
|
-
const parsed = JSON.parse(
|
|
31233
|
+
const parsed = JSON.parse(fs32.readFileSync(manifestPath2, "utf8"));
|
|
31069
31234
|
const agentId = process.env.SNIPARA_AGENT_ID?.trim() || DEFAULT_AGENT_CONTEXT_AGENT;
|
|
31070
31235
|
if (!parsed.agents || !Object.prototype.hasOwnProperty.call(parsed.agents, agentId)) {
|
|
31071
31236
|
return void 0;
|
|
31072
31237
|
}
|
|
31073
31238
|
return {
|
|
31074
31239
|
agentId,
|
|
31075
|
-
manifest:
|
|
31240
|
+
manifest: path31.relative(cwd, manifestPath2) || path31.basename(manifestPath2)
|
|
31076
31241
|
};
|
|
31077
31242
|
} catch {
|
|
31078
31243
|
return void 0;
|
|
@@ -31245,7 +31410,7 @@ function findSandboxRuntimeBinding(state, phaseId) {
|
|
|
31245
31410
|
function defaultSandboxSessionId(state, phase) {
|
|
31246
31411
|
const workflowSlug = sanitizeWorkflowId(state.workflowId, "workflow").slice(0, 24);
|
|
31247
31412
|
const phaseSlug = sanitizeWorkflowId(phase.id, "phase").slice(0, 24);
|
|
31248
|
-
const digest = (0,
|
|
31413
|
+
const digest = (0, import_node_crypto15.createHash)("sha1").update(`${state.workflowId}:${phase.id}`).digest("hex").slice(0, 10);
|
|
31249
31414
|
return `sandbox-${workflowSlug}-${phaseSlug}-${digest}`.slice(0, 96);
|
|
31250
31415
|
}
|
|
31251
31416
|
function ensureSandboxRuntimeBinding(state, phase, now) {
|
|
@@ -31806,10 +31971,10 @@ function readGitNulList(args, cwd) {
|
|
|
31806
31971
|
return output.split("\0").map((item) => item.trim()).filter(Boolean);
|
|
31807
31972
|
}
|
|
31808
31973
|
function readGitRepoRoot(cwd = process.cwd()) {
|
|
31809
|
-
return
|
|
31974
|
+
return path31.resolve(runGitText(["rev-parse", "--show-toplevel"], cwd) ?? cwd);
|
|
31810
31975
|
}
|
|
31811
31976
|
function normalizeRepoFilePath(value) {
|
|
31812
|
-
return value.split(
|
|
31977
|
+
return value.split(path31.sep).join("/").replace(/^\/+/, "");
|
|
31813
31978
|
}
|
|
31814
31979
|
function resolveWorkflowImpactBaseRef(repoRoot, base) {
|
|
31815
31980
|
const explicitBase = base?.trim();
|
|
@@ -31868,7 +32033,7 @@ function parseDirtyFileFromStatusLine(line) {
|
|
|
31868
32033
|
return renamedPath ? normalizeRepoFilePath(renamedPath.replace(/^"|"$/g, "")) : void 0;
|
|
31869
32034
|
}
|
|
31870
32035
|
function isLocalImpactCodeFile(filePath) {
|
|
31871
|
-
return [".ts", ".tsx", ".mts", ".cts", ".py", ".pyi", ".go"].includes(
|
|
32036
|
+
return [".ts", ".tsx", ".mts", ".cts", ".py", ".pyi", ".go"].includes(path31.extname(filePath));
|
|
31872
32037
|
}
|
|
31873
32038
|
function completedWorkflowPhasesForImpact(state, changedFiles) {
|
|
31874
32039
|
const changedFileSet = new Set(changedFiles);
|
|
@@ -32787,12 +32952,12 @@ function readLocalAdaptiveRoutingProjectPolicy() {
|
|
|
32787
32952
|
if (!workspaceRoot2) {
|
|
32788
32953
|
return null;
|
|
32789
32954
|
}
|
|
32790
|
-
const policyPath =
|
|
32791
|
-
if (!
|
|
32955
|
+
const policyPath = path31.join(workspaceRoot2, ADAPTIVE_ROUTING_POLICY_RELATIVE_PATH2);
|
|
32956
|
+
if (!fs32.existsSync(policyPath)) {
|
|
32792
32957
|
return null;
|
|
32793
32958
|
}
|
|
32794
32959
|
try {
|
|
32795
|
-
const parsed = JSON.parse(
|
|
32960
|
+
const parsed = JSON.parse(fs32.readFileSync(policyPath, "utf8"));
|
|
32796
32961
|
if (!isRecord19(parsed)) {
|
|
32797
32962
|
return null;
|
|
32798
32963
|
}
|
|
@@ -33261,8 +33426,8 @@ function enrichAdaptiveRoutingWithLocalOrchestrator(routing, options, cwd = proc
|
|
|
33261
33426
|
};
|
|
33262
33427
|
}
|
|
33263
33428
|
}
|
|
33264
|
-
function printUploadResult(
|
|
33265
|
-
printKeyValue2("Uploaded:",
|
|
33429
|
+
function printUploadResult(path46, result) {
|
|
33430
|
+
printKeyValue2("Uploaded:", path46);
|
|
33266
33431
|
printCompactObject(result, ["message", "document_id", "documentId", "version", "status"]);
|
|
33267
33432
|
console.log("");
|
|
33268
33433
|
printJson2(result);
|
|
@@ -33607,9 +33772,9 @@ function printOrchestrateResult(result) {
|
|
|
33607
33772
|
}
|
|
33608
33773
|
printJson2(result);
|
|
33609
33774
|
}
|
|
33610
|
-
function printLoadDocumentResult(
|
|
33775
|
+
function printLoadDocumentResult(path46, result) {
|
|
33611
33776
|
printKeyValue2("Tool:", "snipara_load_document");
|
|
33612
|
-
printKeyValue2("Path:",
|
|
33777
|
+
printKeyValue2("Path:", path46);
|
|
33613
33778
|
console.log("");
|
|
33614
33779
|
if (typeof result === "string") {
|
|
33615
33780
|
console.log(result.trim());
|
|
@@ -33749,7 +33914,7 @@ async function uploadCommand(options) {
|
|
|
33749
33914
|
const inferred = inferDocumentFormat(options.path) ?? (options.file ? inferDocumentFormat(options.file) : void 0);
|
|
33750
33915
|
const kind = normalizeDocumentKind(options.kind) ?? inferred?.kind;
|
|
33751
33916
|
const format = normalizeDocumentFormat(options.format) ?? inferred?.format;
|
|
33752
|
-
const content = options.content ?? (options.file ? kind === "BINARY" ? `base64:${
|
|
33917
|
+
const content = options.content ?? (options.file ? kind === "BINARY" ? `base64:${fs32.readFileSync(options.file).toString("base64")}` : fs32.readFileSync(options.file, "utf-8") : void 0);
|
|
33753
33918
|
if (!content) {
|
|
33754
33919
|
throw new Error("Provide either --content or --file");
|
|
33755
33920
|
}
|
|
@@ -33825,7 +33990,7 @@ async function businessCollectionEnsureCommand(options) {
|
|
|
33825
33990
|
}
|
|
33826
33991
|
async function businessCollectionUploadCommand(options) {
|
|
33827
33992
|
ensureConfigured();
|
|
33828
|
-
const content = options.content ?? (options.file ?
|
|
33993
|
+
const content = options.content ?? (options.file ? fs32.readFileSync(options.file, "utf-8") : void 0);
|
|
33829
33994
|
if (!content) {
|
|
33830
33995
|
throw new Error("Provide either --content or --file");
|
|
33831
33996
|
}
|
|
@@ -33937,30 +34102,30 @@ function normalizeSyncDocumentsPayload(payload) {
|
|
|
33937
34102
|
};
|
|
33938
34103
|
}
|
|
33939
34104
|
function toUploadPath(filePath, rootDir, prefix) {
|
|
33940
|
-
const relative15 =
|
|
34105
|
+
const relative15 = path31.relative(rootDir, filePath).split(path31.sep).join("/");
|
|
33941
34106
|
const trimmedPrefix = prefix?.replace(/^\/+|\/+$/g, "");
|
|
33942
34107
|
return trimmedPrefix ? `${trimmedPrefix}/${relative15}` : relative15;
|
|
33943
34108
|
}
|
|
33944
34109
|
function collectDirectoryDocuments(options) {
|
|
33945
|
-
const rootDir =
|
|
34110
|
+
const rootDir = path31.resolve(options.dir);
|
|
33946
34111
|
const documents = [];
|
|
33947
34112
|
function visit(directory) {
|
|
33948
|
-
for (const entry of
|
|
33949
|
-
const entryPath =
|
|
34113
|
+
for (const entry of fs32.readdirSync(directory, { withFileTypes: true })) {
|
|
34114
|
+
const entryPath = path31.join(directory, entry.name);
|
|
33950
34115
|
if (entry.isDirectory()) {
|
|
33951
34116
|
if (options.recursive) {
|
|
33952
34117
|
visit(entryPath);
|
|
33953
34118
|
}
|
|
33954
34119
|
continue;
|
|
33955
34120
|
}
|
|
33956
|
-
if (!entry.isFile() || !DEFAULT_SYNC_EXTENSIONS.has(
|
|
34121
|
+
if (!entry.isFile() || !DEFAULT_SYNC_EXTENSIONS.has(path31.extname(entry.name).toLowerCase())) {
|
|
33957
34122
|
continue;
|
|
33958
34123
|
}
|
|
33959
34124
|
const documentFormat = inferDocumentFormat(entry.name);
|
|
33960
34125
|
if (!documentFormat) {
|
|
33961
34126
|
continue;
|
|
33962
34127
|
}
|
|
33963
|
-
const rawContent =
|
|
34128
|
+
const rawContent = fs32.readFileSync(entryPath);
|
|
33964
34129
|
const content = documentFormat.kind === "BINARY" ? `base64:${rawContent.toString("base64")}` : rawContent.toString("utf-8");
|
|
33965
34130
|
documents.push({
|
|
33966
34131
|
path: toUploadPath(entryPath, rootDir, options.prefix),
|
|
@@ -33985,7 +34150,7 @@ function collectSyncDocumentsInput(options) {
|
|
|
33985
34150
|
throw new Error("Provide either --file or --dir");
|
|
33986
34151
|
}
|
|
33987
34152
|
if (options.file) {
|
|
33988
|
-
const payload = JSON.parse(
|
|
34153
|
+
const payload = JSON.parse(fs32.readFileSync(options.file, "utf-8"));
|
|
33989
34154
|
return normalizeSyncDocumentsPayload(payload);
|
|
33990
34155
|
}
|
|
33991
34156
|
return {
|
|
@@ -34128,7 +34293,7 @@ function normalizeOnboardFolderMode(value) {
|
|
|
34128
34293
|
throw new Error("Onboard mode must be one of: auto, business_context, code_project, mixed");
|
|
34129
34294
|
}
|
|
34130
34295
|
function toPosixPath(filePath) {
|
|
34131
|
-
return filePath.split(
|
|
34296
|
+
return filePath.split(path31.sep).join("/");
|
|
34132
34297
|
}
|
|
34133
34298
|
function firstPathSegment(filePath) {
|
|
34134
34299
|
return filePath.split("/")[0]?.toLowerCase() ?? "";
|
|
@@ -34138,31 +34303,31 @@ function hasBusinessKeyword(filePath) {
|
|
|
34138
34303
|
return BUSINESS_PATH_KEYWORDS.some((keyword) => lower.includes(keyword));
|
|
34139
34304
|
}
|
|
34140
34305
|
function isBusinessLookingFile(file) {
|
|
34141
|
-
return BUSINESS_MARKER_EXTENSIONS.has(
|
|
34306
|
+
return BUSINESS_MARKER_EXTENSIONS.has(path31.extname(file.path).toLowerCase()) || hasBusinessKeyword(file.path);
|
|
34142
34307
|
}
|
|
34143
34308
|
function scanOnboardFolder(options) {
|
|
34144
|
-
const rootDir =
|
|
34145
|
-
if (!
|
|
34309
|
+
const rootDir = path31.resolve(options.dir);
|
|
34310
|
+
if (!fs32.existsSync(rootDir)) {
|
|
34146
34311
|
throw new Error(`Directory does not exist: ${options.dir}`);
|
|
34147
34312
|
}
|
|
34148
|
-
if (!
|
|
34313
|
+
if (!fs32.statSync(rootDir).isDirectory()) {
|
|
34149
34314
|
throw new Error(`Expected a directory: ${options.dir}`);
|
|
34150
34315
|
}
|
|
34151
34316
|
const files = [];
|
|
34152
34317
|
function visit(directory) {
|
|
34153
|
-
for (const entry of
|
|
34318
|
+
for (const entry of fs32.readdirSync(directory, { withFileTypes: true })) {
|
|
34154
34319
|
if (entry.isDirectory()) {
|
|
34155
34320
|
if (options.recursive && !ONBOARD_IGNORED_DIRS.has(entry.name)) {
|
|
34156
|
-
visit(
|
|
34321
|
+
visit(path31.join(directory, entry.name));
|
|
34157
34322
|
}
|
|
34158
34323
|
continue;
|
|
34159
34324
|
}
|
|
34160
34325
|
if (!entry.isFile()) {
|
|
34161
34326
|
continue;
|
|
34162
34327
|
}
|
|
34163
|
-
const absolutePath =
|
|
34164
|
-
const stat =
|
|
34165
|
-
const relativePath2 = toPosixPath(
|
|
34328
|
+
const absolutePath = path31.join(directory, entry.name);
|
|
34329
|
+
const stat = fs32.statSync(absolutePath);
|
|
34330
|
+
const relativePath2 = toPosixPath(path31.relative(rootDir, absolutePath));
|
|
34166
34331
|
const format = inferDocumentFormat(entry.name);
|
|
34167
34332
|
files.push({
|
|
34168
34333
|
absolutePath,
|
|
@@ -34190,13 +34355,13 @@ function classifyOnboardFolder(rootDir, files, overrideMode = "auto") {
|
|
|
34190
34355
|
let businessScore = 0;
|
|
34191
34356
|
let codeSourceFiles = 0;
|
|
34192
34357
|
let supportedPlainDocuments = 0;
|
|
34193
|
-
if (
|
|
34358
|
+
if (fs32.existsSync(path31.join(rootDir, ".git"))) {
|
|
34194
34359
|
codeScore += 4;
|
|
34195
34360
|
addSignal2(codeSignals, ".git directory");
|
|
34196
34361
|
}
|
|
34197
34362
|
for (const file of files) {
|
|
34198
|
-
const base =
|
|
34199
|
-
const ext =
|
|
34363
|
+
const base = path31.basename(file.path);
|
|
34364
|
+
const ext = path31.extname(file.path).toLowerCase();
|
|
34200
34365
|
const firstSegment = firstPathSegment(file.path);
|
|
34201
34366
|
if (CODE_MARKER_FILES.has(base)) {
|
|
34202
34367
|
codeScore += 3;
|
|
@@ -34273,10 +34438,10 @@ function inferOnboardContextLane(file, mode) {
|
|
|
34273
34438
|
if (hasBusinessKeyword(file.path)) {
|
|
34274
34439
|
return "business_context";
|
|
34275
34440
|
}
|
|
34276
|
-
if (REPO_DOC_FILES.has(
|
|
34441
|
+
if (REPO_DOC_FILES.has(path31.basename(file.path))) {
|
|
34277
34442
|
return "repo_docs";
|
|
34278
34443
|
}
|
|
34279
|
-
const ext =
|
|
34444
|
+
const ext = path31.extname(file.path).toLowerCase();
|
|
34280
34445
|
if ([".docx", ".pdf", ".pptx", ".vsdx"].includes(ext)) {
|
|
34281
34446
|
return "business_context";
|
|
34282
34447
|
}
|
|
@@ -34304,7 +34469,7 @@ function buildOnboardSyncManifestPayload(result) {
|
|
|
34304
34469
|
};
|
|
34305
34470
|
}
|
|
34306
34471
|
function buildOnboardFolderManifest(options) {
|
|
34307
|
-
const rootDir =
|
|
34472
|
+
const rootDir = path31.resolve(options.dir);
|
|
34308
34473
|
const recursive = options.recursive ?? true;
|
|
34309
34474
|
const files = scanOnboardFolder({ dir: rootDir, recursive });
|
|
34310
34475
|
const modeOverride = normalizeOnboardFolderMode(options.mode);
|
|
@@ -34335,7 +34500,7 @@ function buildOnboardFolderManifest(options) {
|
|
|
34335
34500
|
options.clientId ? { clientId: options.clientId } : void 0
|
|
34336
34501
|
);
|
|
34337
34502
|
const documents = supportedFiles.map((file) => {
|
|
34338
|
-
const rawContent =
|
|
34503
|
+
const rawContent = fs32.readFileSync(file.absolutePath);
|
|
34339
34504
|
const content = file.kind === "BINARY" ? `base64:${rawContent.toString("base64")}` : rawContent.toString("utf-8");
|
|
34340
34505
|
const lane = inferOnboardContextLane(file, classification.mode);
|
|
34341
34506
|
const metadata = mergeRecords(metadataDefaults, {
|
|
@@ -34633,7 +34798,7 @@ async function syncDocumentsCommand(options) {
|
|
|
34633
34798
|
async function onboardFolderCommand(options) {
|
|
34634
34799
|
const manifest = buildOnboardFolderManifest(options);
|
|
34635
34800
|
if (options.writeManifest) {
|
|
34636
|
-
|
|
34801
|
+
fs32.writeFileSync(
|
|
34637
34802
|
options.writeManifest,
|
|
34638
34803
|
`${JSON.stringify(buildOnboardSyncManifestPayload(manifest), null, 2)}
|
|
34639
34804
|
`,
|
|
@@ -35228,7 +35393,7 @@ function startManagedWorkflowState(options) {
|
|
|
35228
35393
|
`Active workflow '${existing.workflowId}' already exists. Use --force to replace ${WORKFLOW_STATE_RELATIVE_PATH}.`
|
|
35229
35394
|
);
|
|
35230
35395
|
}
|
|
35231
|
-
const goal = options.goal ?? (options.planFile ? `Workflow from ${
|
|
35396
|
+
const goal = options.goal ?? (options.planFile ? `Workflow from ${path31.basename(options.planFile)}` : void 0);
|
|
35232
35397
|
if (!goal) {
|
|
35233
35398
|
throw new Error("Provide --goal or --plan-file");
|
|
35234
35399
|
}
|
|
@@ -35246,7 +35411,7 @@ function startManagedWorkflowState(options) {
|
|
|
35246
35411
|
status: "active",
|
|
35247
35412
|
currentPhaseId: phases[0]?.id,
|
|
35248
35413
|
planSource: options.planFile ? "file" : "inline",
|
|
35249
|
-
...options.planFile ? { planFile:
|
|
35414
|
+
...options.planFile ? { planFile: path31.resolve(options.planFile) } : {},
|
|
35250
35415
|
createdAt: now,
|
|
35251
35416
|
updatedAt: now,
|
|
35252
35417
|
phases,
|
|
@@ -36380,7 +36545,7 @@ function localWorkspacePathAliases() {
|
|
|
36380
36545
|
const cwd = process.cwd();
|
|
36381
36546
|
const aliases = /* @__PURE__ */ new Set([cwd]);
|
|
36382
36547
|
try {
|
|
36383
|
-
aliases.add(
|
|
36548
|
+
aliases.add(fs32.realpathSync(cwd));
|
|
36384
36549
|
} catch {
|
|
36385
36550
|
}
|
|
36386
36551
|
for (const alias of [...aliases]) {
|
|
@@ -36398,9 +36563,9 @@ function redactTimelineText(value, maxLength = 180) {
|
|
|
36398
36563
|
}
|
|
36399
36564
|
function redactTimelineFile(file) {
|
|
36400
36565
|
const workspaceAlias = localWorkspacePathAliases().find(
|
|
36401
|
-
(alias) =>
|
|
36566
|
+
(alias) => path31.isAbsolute(file) && file.startsWith(alias)
|
|
36402
36567
|
);
|
|
36403
|
-
const relative15 = workspaceAlias ?
|
|
36568
|
+
const relative15 = workspaceAlias ? path31.relative(workspaceAlias, file) : file;
|
|
36404
36569
|
if (relative15.startsWith(".snipara/") || relative15 === ".snipara") {
|
|
36405
36570
|
return "[local-state]";
|
|
36406
36571
|
}
|
|
@@ -37806,12 +37971,12 @@ function emptySessionMemoriesResult() {
|
|
|
37806
37971
|
};
|
|
37807
37972
|
}
|
|
37808
37973
|
function readLocalJsonFile(relativePath2) {
|
|
37809
|
-
const absolutePath =
|
|
37810
|
-
if (!
|
|
37974
|
+
const absolutePath = path31.join(process.cwd(), relativePath2);
|
|
37975
|
+
if (!fs32.existsSync(absolutePath)) {
|
|
37811
37976
|
return null;
|
|
37812
37977
|
}
|
|
37813
37978
|
try {
|
|
37814
|
-
const parsed = JSON.parse(
|
|
37979
|
+
const parsed = JSON.parse(fs32.readFileSync(absolutePath, "utf-8"));
|
|
37815
37980
|
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
37816
37981
|
} catch {
|
|
37817
37982
|
return null;
|
|
@@ -37821,14 +37986,14 @@ function summarizeSourceSnapshot(snapshot) {
|
|
|
37821
37986
|
if (!snapshot) {
|
|
37822
37987
|
return {
|
|
37823
37988
|
status: "missing",
|
|
37824
|
-
snapshotPath:
|
|
37989
|
+
snapshotPath: path31.join(".snipara", "source", "latest.json"),
|
|
37825
37990
|
nextAction: "Run snipara-companion source sync --json after meaningful local code or docs movement."
|
|
37826
37991
|
};
|
|
37827
37992
|
}
|
|
37828
37993
|
const summary = snapshot.summary && typeof snapshot.summary === "object" && !Array.isArray(snapshot.summary) ? snapshot.summary : {};
|
|
37829
37994
|
return {
|
|
37830
37995
|
status: "present",
|
|
37831
|
-
snapshotPath:
|
|
37996
|
+
snapshotPath: path31.join(".snipara", "source", "latest.json"),
|
|
37832
37997
|
generatedAt: snapshot.generatedAt,
|
|
37833
37998
|
revision: snapshot.revision,
|
|
37834
37999
|
totalFiles: summary.totalFiles,
|
|
@@ -37862,7 +38027,7 @@ function summarizeTeamSyncForContinuity() {
|
|
|
37862
38027
|
const summary = buildTeamSyncSummary(state);
|
|
37863
38028
|
const latestHandoff = state.handoffs.at(-1);
|
|
37864
38029
|
return {
|
|
37865
|
-
statePath:
|
|
38030
|
+
statePath: path31.relative(process.cwd(), getTeamSyncStatePath()),
|
|
37866
38031
|
activeWorkCount: summary.activeWorkCount,
|
|
37867
38032
|
staleWorkCount: summary.staleWorkCount,
|
|
37868
38033
|
completedWorkCount: summary.completedWorkCount,
|
|
@@ -37880,7 +38045,7 @@ function buildCompanionContinuityPayload(args) {
|
|
|
37880
38045
|
const config = args.configured ? loadConfig() : null;
|
|
37881
38046
|
const workflow2 = readWorkflowState2();
|
|
37882
38047
|
const sessionSnapshot = readSessionSnapshot();
|
|
37883
|
-
const sourceSnapshot = readLocalJsonFile(
|
|
38048
|
+
const sourceSnapshot = readLocalJsonFile(path31.join(".snipara", "source", "latest.json"));
|
|
37884
38049
|
return {
|
|
37885
38050
|
version: COMPANION_CONTINUITY_CONTRACT_VERSION,
|
|
37886
38051
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -37892,9 +38057,9 @@ function buildCompanionContinuityPayload(args) {
|
|
|
37892
38057
|
} : null,
|
|
37893
38058
|
artifacts: {
|
|
37894
38059
|
workflowStatePath: WORKFLOW_STATE_RELATIVE_PATH,
|
|
37895
|
-
teamSyncStatePath:
|
|
37896
|
-
sessionSnapshotPath:
|
|
37897
|
-
sourceSnapshotPath:
|
|
38060
|
+
teamSyncStatePath: path31.relative(process.cwd(), getTeamSyncStatePath()),
|
|
38061
|
+
sessionSnapshotPath: path31.join(".snipara", "activity", "session.json"),
|
|
38062
|
+
sourceSnapshotPath: path31.join(".snipara", "source", "latest.json")
|
|
37898
38063
|
},
|
|
37899
38064
|
bootstrap: args.bootstrap,
|
|
37900
38065
|
bootstrapQuality: args.bootstrapQuality,
|
|
@@ -38632,12 +38797,12 @@ async function sourceWatchCommand(options = {}) {
|
|
|
38632
38797
|
if (stopping) {
|
|
38633
38798
|
break;
|
|
38634
38799
|
}
|
|
38635
|
-
await new Promise((
|
|
38636
|
-
resolveWait =
|
|
38800
|
+
await new Promise((resolve26) => {
|
|
38801
|
+
resolveWait = resolve26;
|
|
38637
38802
|
activeTimer = setTimeout(() => {
|
|
38638
38803
|
activeTimer = null;
|
|
38639
38804
|
resolveWait = null;
|
|
38640
|
-
|
|
38805
|
+
resolve26();
|
|
38641
38806
|
}, intervalMs);
|
|
38642
38807
|
});
|
|
38643
38808
|
}
|
|
@@ -38903,7 +39068,7 @@ async function docsBootstrapCommand(options = {}) {
|
|
|
38903
39068
|
var import_fs7 = __toESM(require("fs"));
|
|
38904
39069
|
var import_path7 = __toESM(require("path"));
|
|
38905
39070
|
var import_node_child_process16 = require("child_process");
|
|
38906
|
-
var
|
|
39071
|
+
var import_node_crypto16 = require("crypto");
|
|
38907
39072
|
var import_chalk12 = __toESM(require("chalk"));
|
|
38908
39073
|
var CONTROLLED_WORKER_EXECUTIONS_DIR = import_path7.default.join(".snipara", "worker-executions");
|
|
38909
39074
|
var UNIFIED_RECEIPTS_DIR = import_path7.default.join(".snipara", "unified-receipts");
|
|
@@ -39171,7 +39336,7 @@ function pathFingerprint(workspaceRoot2, relativePath2) {
|
|
|
39171
39336
|
const stat = import_fs7.default.lstatSync(candidate);
|
|
39172
39337
|
if (stat.isSymbolicLink()) return `symlink:${import_fs7.default.readlinkSync(candidate)}`;
|
|
39173
39338
|
if (!stat.isFile()) return `mode:${stat.mode}:size:${stat.size}`;
|
|
39174
|
-
return `file:${stat.mode}:${(0,
|
|
39339
|
+
return `file:${stat.mode}:${(0, import_node_crypto16.createHash)("sha256").update(import_fs7.default.readFileSync(candidate)).digest("hex")}`;
|
|
39175
39340
|
} catch {
|
|
39176
39341
|
return "missing";
|
|
39177
39342
|
}
|
|
@@ -39546,8 +39711,8 @@ function printJson5(value) {
|
|
|
39546
39711
|
}
|
|
39547
39712
|
|
|
39548
39713
|
// src/commands/agent-readiness.ts
|
|
39549
|
-
var
|
|
39550
|
-
var
|
|
39714
|
+
var fs37 = __toESM(require("fs"));
|
|
39715
|
+
var path36 = __toESM(require("path"));
|
|
39551
39716
|
var TARGETS = {
|
|
39552
39717
|
codex: {
|
|
39553
39718
|
label: "Codex",
|
|
@@ -39602,18 +39767,18 @@ function recordList2(value) {
|
|
|
39602
39767
|
}
|
|
39603
39768
|
function safeReadJson2(filePath) {
|
|
39604
39769
|
try {
|
|
39605
|
-
const parsed = JSON.parse(
|
|
39770
|
+
const parsed = JSON.parse(fs37.readFileSync(filePath, "utf8"));
|
|
39606
39771
|
return isRecord21(parsed) ? parsed : void 0;
|
|
39607
39772
|
} catch {
|
|
39608
39773
|
return void 0;
|
|
39609
39774
|
}
|
|
39610
39775
|
}
|
|
39611
39776
|
function relativePath(rootDir, filePath) {
|
|
39612
|
-
const relative15 =
|
|
39777
|
+
const relative15 = path36.relative(rootDir, filePath);
|
|
39613
39778
|
return relative15 && !relative15.startsWith("..") ? relative15 : filePath;
|
|
39614
39779
|
}
|
|
39615
39780
|
function collectAgentReadinessLocalSignals(rootDir = process.cwd()) {
|
|
39616
|
-
const workflowPath =
|
|
39781
|
+
const workflowPath = path36.join(rootDir, ".snipara", "workflow", "current.json");
|
|
39617
39782
|
const workflowJson = safeReadJson2(workflowPath);
|
|
39618
39783
|
const phases = recordList2(workflowJson?.phases);
|
|
39619
39784
|
const workflow2 = {
|
|
@@ -39625,7 +39790,7 @@ function collectAgentReadinessLocalSignals(rootDir = process.cwd()) {
|
|
|
39625
39790
|
completedPhases: phases.filter((phase) => phase.status === "completed").length,
|
|
39626
39791
|
pendingPhases: phases.filter((phase) => phase.status === "pending").length
|
|
39627
39792
|
};
|
|
39628
|
-
const teamSyncPath =
|
|
39793
|
+
const teamSyncPath = path36.join(rootDir, ".snipara", "team-sync", "session.json");
|
|
39629
39794
|
const teamSyncJson = safeReadJson2(teamSyncPath);
|
|
39630
39795
|
const work = recordList2(teamSyncJson?.work);
|
|
39631
39796
|
const handoffs = recordList2(teamSyncJson?.handoffs);
|
|
@@ -39640,9 +39805,9 @@ function collectAgentReadinessLocalSignals(rootDir = process.cwd()) {
|
|
|
39640
39805
|
latestActiveSummary: stringValue14(latestActive?.summary),
|
|
39641
39806
|
latestHandoffSummary: stringValue14(latestHandoff?.summary)
|
|
39642
39807
|
};
|
|
39643
|
-
const agentsPath =
|
|
39808
|
+
const agentsPath = path36.join(rootDir, "AGENTS.md");
|
|
39644
39809
|
const projectInstructions = {
|
|
39645
|
-
present:
|
|
39810
|
+
present: fs37.existsSync(agentsPath),
|
|
39646
39811
|
path: relativePath(rootDir, agentsPath)
|
|
39647
39812
|
};
|
|
39648
39813
|
return { workflow: workflow2, teamSync: teamSync2, projectInstructions };
|
|
@@ -39963,15 +40128,15 @@ function formatAgentReadinessAuditReport(report) {
|
|
|
39963
40128
|
return lines.join("\n");
|
|
39964
40129
|
}
|
|
39965
40130
|
function writeReport(outputPath, report) {
|
|
39966
|
-
const absolute =
|
|
39967
|
-
|
|
40131
|
+
const absolute = path36.resolve(outputPath);
|
|
40132
|
+
fs37.mkdirSync(path36.dirname(absolute), { recursive: true });
|
|
39968
40133
|
const content = outputPath.endsWith(".json") ? `${JSON.stringify(report, null, 2)}
|
|
39969
40134
|
` : `${formatAgentReadinessAuditReport(report)}
|
|
39970
40135
|
`;
|
|
39971
|
-
|
|
40136
|
+
fs37.writeFileSync(absolute, content, "utf8");
|
|
39972
40137
|
}
|
|
39973
40138
|
async function agentReadinessAuditCommand(options) {
|
|
39974
|
-
const cwd =
|
|
40139
|
+
const cwd = path36.resolve(options.dir ?? process.cwd());
|
|
39975
40140
|
const report = buildAgentReadinessAuditReport({
|
|
39976
40141
|
...options,
|
|
39977
40142
|
cwd,
|
|
@@ -39988,8 +40153,8 @@ async function agentReadinessAuditCommand(options) {
|
|
|
39988
40153
|
}
|
|
39989
40154
|
|
|
39990
40155
|
// src/commands/lead-plan.ts
|
|
39991
|
-
var
|
|
39992
|
-
var
|
|
40156
|
+
var fs38 = __toESM(require("fs"));
|
|
40157
|
+
var path37 = __toESM(require("path"));
|
|
39993
40158
|
|
|
39994
40159
|
// src/commands/execution-receipts.ts
|
|
39995
40160
|
var ENGINEERING_LEAD_PROOF_VERIFICATION_MAX_AGE_MS = 14 * 24 * 60 * 60 * 1e3;
|
|
@@ -41233,7 +41398,7 @@ function applyReconciliationToPlan(plan, reconciliation) {
|
|
|
41233
41398
|
};
|
|
41234
41399
|
}
|
|
41235
41400
|
function readJsonFile3(filePath) {
|
|
41236
|
-
const parsed = JSON.parse(
|
|
41401
|
+
const parsed = JSON.parse(fs38.readFileSync(path37.resolve(filePath), "utf8"));
|
|
41237
41402
|
if (!isRecord22(parsed)) {
|
|
41238
41403
|
throw new Error(`${filePath} must contain a JSON object`);
|
|
41239
41404
|
}
|
|
@@ -41419,16 +41584,16 @@ function formatCompanionEngineeringLeadPlanReport(report) {
|
|
|
41419
41584
|
return lines.join("\n");
|
|
41420
41585
|
}
|
|
41421
41586
|
function writeReport2(outputPath, report) {
|
|
41422
|
-
const absolute =
|
|
41423
|
-
|
|
41587
|
+
const absolute = path37.resolve(outputPath);
|
|
41588
|
+
fs38.mkdirSync(path37.dirname(absolute), { recursive: true });
|
|
41424
41589
|
const content = outputPath.endsWith(".json") ? `${JSON.stringify(report, null, 2)}
|
|
41425
41590
|
` : `${formatCompanionEngineeringLeadPlanReport(report)}
|
|
41426
41591
|
`;
|
|
41427
|
-
|
|
41592
|
+
fs38.writeFileSync(absolute, content, "utf8");
|
|
41428
41593
|
}
|
|
41429
41594
|
function defaultJsonOutputPath(cwd, report) {
|
|
41430
41595
|
const timestamp = report.generatedAt.replace(/[:.]/g, "-");
|
|
41431
|
-
return
|
|
41596
|
+
return path37.join(
|
|
41432
41597
|
cwd,
|
|
41433
41598
|
".snipara",
|
|
41434
41599
|
"lead-plans",
|
|
@@ -41436,7 +41601,7 @@ function defaultJsonOutputPath(cwd, report) {
|
|
|
41436
41601
|
);
|
|
41437
41602
|
}
|
|
41438
41603
|
async function leadPlanCommand(options) {
|
|
41439
|
-
const cwd =
|
|
41604
|
+
const cwd = path37.resolve(options.dir ?? process.cwd());
|
|
41440
41605
|
const report = buildCompanionEngineeringLeadPlanReport({
|
|
41441
41606
|
...options,
|
|
41442
41607
|
cwd,
|
|
@@ -41451,11 +41616,11 @@ async function leadPlanCommand(options) {
|
|
|
41451
41616
|
JSON.stringify(
|
|
41452
41617
|
{
|
|
41453
41618
|
...report,
|
|
41454
|
-
outputPath: writtenOutput ?
|
|
41455
|
-
relativeOutputPath: writtenOutput ?
|
|
41456
|
-
nextCommand: writtenOutput ? `snipara-orchestrator team-sync gate --plan ${
|
|
41619
|
+
outputPath: writtenOutput ? path37.resolve(writtenOutput) : void 0,
|
|
41620
|
+
relativeOutputPath: writtenOutput ? path37.relative(cwd, path37.resolve(writtenOutput)) : void 0,
|
|
41621
|
+
nextCommand: writtenOutput ? `snipara-orchestrator team-sync gate --plan ${path37.relative(
|
|
41457
41622
|
cwd,
|
|
41458
|
-
|
|
41623
|
+
path37.resolve(writtenOutput)
|
|
41459
41624
|
)} --json` : void 0
|
|
41460
41625
|
},
|
|
41461
41626
|
null,
|
|
@@ -41468,11 +41633,11 @@ async function leadPlanCommand(options) {
|
|
|
41468
41633
|
}
|
|
41469
41634
|
|
|
41470
41635
|
// src/commands/feature.ts
|
|
41471
|
-
var
|
|
41472
|
-
var
|
|
41636
|
+
var fs39 = __toESM(require("fs"));
|
|
41637
|
+
var path38 = __toESM(require("path"));
|
|
41473
41638
|
var import_chalk14 = __toESM(require("chalk"));
|
|
41474
41639
|
var FEATURE_WORK_ITEM_VERSION = "snipara.feature_work_item.v1";
|
|
41475
|
-
var FEATURE_DEFAULT_OUTPUT_DIR =
|
|
41640
|
+
var FEATURE_DEFAULT_OUTPUT_DIR = path38.join("docs", "specs");
|
|
41476
41641
|
function compact(value) {
|
|
41477
41642
|
return (value ?? "").trim().replace(/\s+/g, " ");
|
|
41478
41643
|
}
|
|
@@ -41491,34 +41656,34 @@ function normalizeFeatureSlug(value) {
|
|
|
41491
41656
|
}
|
|
41492
41657
|
function resolveFeatureArtifactPaths(slug2, options = {}) {
|
|
41493
41658
|
const normalizedSlug = normalizeFeatureSlug(slug2);
|
|
41494
|
-
const cwd =
|
|
41659
|
+
const cwd = path38.resolve(options.cwd ?? process.cwd());
|
|
41495
41660
|
const workspaceRoot2 = findWorkspaceRoot(cwd, true) ?? cwd;
|
|
41496
41661
|
const outputDir = options.outputDir ?? FEATURE_DEFAULT_OUTPUT_DIR;
|
|
41497
|
-
const root =
|
|
41662
|
+
const root = path38.resolve(workspaceRoot2, outputDir, normalizedSlug);
|
|
41498
41663
|
return {
|
|
41499
41664
|
root,
|
|
41500
|
-
manifest:
|
|
41501
|
-
spec:
|
|
41502
|
-
plan:
|
|
41503
|
-
tasks:
|
|
41504
|
-
workflowPlan:
|
|
41665
|
+
manifest: path38.join(root, "feature.json"),
|
|
41666
|
+
spec: path38.join(root, "spec.md"),
|
|
41667
|
+
plan: path38.join(root, "plan.md"),
|
|
41668
|
+
tasks: path38.join(root, "tasks.md"),
|
|
41669
|
+
workflowPlan: path38.join(root, "workflow-plan.json")
|
|
41505
41670
|
};
|
|
41506
41671
|
}
|
|
41507
41672
|
function readJsonFile4(filePath) {
|
|
41508
|
-
return JSON.parse(
|
|
41673
|
+
return JSON.parse(fs39.readFileSync(filePath, "utf8"));
|
|
41509
41674
|
}
|
|
41510
41675
|
function writeJsonFile4(filePath, value) {
|
|
41511
|
-
|
|
41676
|
+
fs39.writeFileSync(filePath, `${JSON.stringify(value, null, 2)}
|
|
41512
41677
|
`, "utf8");
|
|
41513
41678
|
}
|
|
41514
41679
|
function ensureParent(filePath) {
|
|
41515
|
-
|
|
41680
|
+
fs39.mkdirSync(path38.dirname(filePath), { recursive: true });
|
|
41516
41681
|
}
|
|
41517
41682
|
function assertWritable(filePath, force, allowGeneratedPlaceholder = false) {
|
|
41518
|
-
if (!
|
|
41683
|
+
if (!fs39.existsSync(filePath) || force) {
|
|
41519
41684
|
return;
|
|
41520
41685
|
}
|
|
41521
|
-
if (allowGeneratedPlaceholder && isGeneratedPlaceholder(
|
|
41686
|
+
if (allowGeneratedPlaceholder && isGeneratedPlaceholder(fs39.readFileSync(filePath, "utf8"))) {
|
|
41522
41687
|
return;
|
|
41523
41688
|
}
|
|
41524
41689
|
throw new Error(
|
|
@@ -41528,7 +41693,7 @@ function assertWritable(filePath, force, allowGeneratedPlaceholder = false) {
|
|
|
41528
41693
|
function writeArtifact(filePath, content, force, allowGeneratedPlaceholder = false) {
|
|
41529
41694
|
assertWritable(filePath, force, allowGeneratedPlaceholder);
|
|
41530
41695
|
ensureParent(filePath);
|
|
41531
|
-
|
|
41696
|
+
fs39.writeFileSync(filePath, content.endsWith("\n") ? content : `${content}
|
|
41532
41697
|
`, "utf8");
|
|
41533
41698
|
}
|
|
41534
41699
|
function isGeneratedPlaceholder(content) {
|
|
@@ -41556,14 +41721,14 @@ function createManifest(options, paths) {
|
|
|
41556
41721
|
},
|
|
41557
41722
|
status: {
|
|
41558
41723
|
spec: compact(options.goal).length > 0 ? "ready" : "draft",
|
|
41559
|
-
plan:
|
|
41560
|
-
tasks:
|
|
41724
|
+
plan: fs39.existsSync(paths.plan) && !isGeneratedPlaceholder(fs39.readFileSync(paths.plan, "utf8")) ? "ready" : "missing",
|
|
41725
|
+
tasks: fs39.existsSync(paths.tasks) && !isGeneratedPlaceholder(fs39.readFileSync(paths.tasks, "utf8")) ? "ready" : "missing"
|
|
41561
41726
|
}
|
|
41562
41727
|
};
|
|
41563
41728
|
}
|
|
41564
41729
|
function readManifest3(paths) {
|
|
41565
|
-
if (!
|
|
41566
|
-
throw new Error(`Feature '${
|
|
41730
|
+
if (!fs39.existsSync(paths.manifest)) {
|
|
41731
|
+
throw new Error(`Feature '${path38.basename(paths.root)}' is not initialized at ${paths.root}.`);
|
|
41567
41732
|
}
|
|
41568
41733
|
const manifest = readJsonFile4(paths.manifest);
|
|
41569
41734
|
if (manifest.schemaVersion !== FEATURE_WORK_ITEM_VERSION) {
|
|
@@ -41783,11 +41948,11 @@ function featureInitCommand(options) {
|
|
|
41783
41948
|
if (!normalizedGoal) {
|
|
41784
41949
|
throw new Error("Feature initialization requires --goal.");
|
|
41785
41950
|
}
|
|
41786
|
-
if (
|
|
41951
|
+
if (fs39.existsSync(paths.manifest) && !options.force) {
|
|
41787
41952
|
throw new Error(`Feature already exists at ${paths.root}. Use --force to reinitialize it.`);
|
|
41788
41953
|
}
|
|
41789
41954
|
const manifest = createManifest(options, paths);
|
|
41790
|
-
|
|
41955
|
+
fs39.mkdirSync(paths.root, { recursive: true });
|
|
41791
41956
|
writeManifest(paths, manifest);
|
|
41792
41957
|
writeArtifact(paths.spec, buildFeatureSpecMarkdown(manifest), Boolean(options.force));
|
|
41793
41958
|
writeArtifact(paths.plan, renderPlanPlaceholder(manifest), Boolean(options.force));
|
|
@@ -41803,7 +41968,7 @@ function featureInitCommand(options) {
|
|
|
41803
41968
|
}
|
|
41804
41969
|
function featureSpecifyCommand(options) {
|
|
41805
41970
|
const paths = resolveFeatureArtifactPaths(options.slug, options);
|
|
41806
|
-
const existing =
|
|
41971
|
+
const existing = fs39.existsSync(paths.manifest) ? readManifest3(paths) : void 0;
|
|
41807
41972
|
const manifest = createManifest(
|
|
41808
41973
|
{
|
|
41809
41974
|
...options,
|
|
@@ -41819,10 +41984,10 @@ function featureSpecifyCommand(options) {
|
|
|
41819
41984
|
if (!manifest.goal) {
|
|
41820
41985
|
throw new Error("Feature specification requires --goal when no existing manifest is present.");
|
|
41821
41986
|
}
|
|
41822
|
-
if (
|
|
41987
|
+
if (fs39.existsSync(paths.spec) && !options.force && !isGeneratedPlaceholder(fs39.readFileSync(paths.spec, "utf8"))) {
|
|
41823
41988
|
throw new Error(`Refusing to overwrite existing specification: ${paths.spec}. Use --force.`);
|
|
41824
41989
|
}
|
|
41825
|
-
|
|
41990
|
+
fs39.mkdirSync(paths.root, { recursive: true });
|
|
41826
41991
|
writeArtifact(paths.spec, buildFeatureSpecMarkdown(manifest), Boolean(options.force), true);
|
|
41827
41992
|
manifest.updatedAt = nowIso2();
|
|
41828
41993
|
writeManifest(paths, manifest);
|
|
@@ -41837,7 +42002,7 @@ function featureSpecifyCommand(options) {
|
|
|
41837
42002
|
async function featurePlanCommand(options) {
|
|
41838
42003
|
const paths = resolveFeatureArtifactPaths(options.slug, options);
|
|
41839
42004
|
const manifest = readManifest3(paths);
|
|
41840
|
-
if (!
|
|
42005
|
+
if (!fs39.existsSync(paths.spec)) {
|
|
41841
42006
|
throw new Error(`Missing specification: ${paths.spec}`);
|
|
41842
42007
|
}
|
|
41843
42008
|
if (!isConfigured({ cwd: options.cwd })) {
|
|
@@ -41845,7 +42010,7 @@ async function featurePlanCommand(options) {
|
|
|
41845
42010
|
"Hosted planning requires Companion configuration. Run 'snipara-companion init' first."
|
|
41846
42011
|
);
|
|
41847
42012
|
}
|
|
41848
|
-
const spec =
|
|
42013
|
+
const spec = fs39.readFileSync(paths.spec, "utf8");
|
|
41849
42014
|
const query = buildPlanQuery(manifest, spec);
|
|
41850
42015
|
const result = await createClient(3e4, { cwd: options.cwd }).plan(query, options.maxTokens);
|
|
41851
42016
|
const quality = validatePlanResult(result, { query, cwd: options.cwd ?? process.cwd() });
|
|
@@ -41879,11 +42044,11 @@ async function featurePlanCommand(options) {
|
|
|
41879
42044
|
function featureTasksCommand(options) {
|
|
41880
42045
|
const paths = resolveFeatureArtifactPaths(options.slug, options);
|
|
41881
42046
|
const manifest = readManifest3(paths);
|
|
41882
|
-
const useLocalPlan = Boolean(options.fromPlan) || !
|
|
41883
|
-
if (useLocalPlan && (!
|
|
42047
|
+
const useLocalPlan = Boolean(options.fromPlan) || !fs39.existsSync(paths.workflowPlan);
|
|
42048
|
+
if (useLocalPlan && (!fs39.existsSync(paths.plan) || isGeneratedPlaceholder(fs39.readFileSync(paths.plan, "utf8")))) {
|
|
41884
42049
|
throw new Error(`Missing workflow plan: ${paths.workflowPlan}. Run feature plan first.`);
|
|
41885
42050
|
}
|
|
41886
|
-
const plan = useLocalPlan ? buildLocalWorkflowPlan(manifest,
|
|
42051
|
+
const plan = useLocalPlan ? buildLocalWorkflowPlan(manifest, fs39.readFileSync(paths.plan, "utf8")) : readJsonFile4(paths.workflowPlan);
|
|
41887
42052
|
if (!Array.isArray(plan.steps) || plan.steps.length === 0) {
|
|
41888
42053
|
throw new Error(`Workflow plan has no executable phases: ${paths.workflowPlan}`);
|
|
41889
42054
|
}
|
|
@@ -41921,7 +42086,7 @@ async function featureStartCommand(options) {
|
|
|
41921
42086
|
outputDir: options.outputDir
|
|
41922
42087
|
});
|
|
41923
42088
|
const manifest = readManifest3(paths);
|
|
41924
|
-
if (manifest.status.tasks !== "ready" || !
|
|
42089
|
+
if (manifest.status.tasks !== "ready" || !fs39.existsSync(paths.tasks)) {
|
|
41925
42090
|
throw new Error(
|
|
41926
42091
|
`Tasks are not ready. Run 'snipara-companion feature tasks ${manifest.slug}' first.`
|
|
41927
42092
|
);
|
|
@@ -41958,9 +42123,9 @@ function featureStatusCommand(options) {
|
|
|
41958
42123
|
}
|
|
41959
42124
|
|
|
41960
42125
|
// src/commands/outcome-capture.ts
|
|
41961
|
-
var
|
|
41962
|
-
var
|
|
41963
|
-
var
|
|
42126
|
+
var fs40 = __toESM(require("fs"));
|
|
42127
|
+
var path39 = __toESM(require("path"));
|
|
42128
|
+
var import_node_crypto17 = require("crypto");
|
|
41964
42129
|
var WHY_OUTCOME_CAPTURE_VERSION = "snipara.why_outcome_capture.v1";
|
|
41965
42130
|
var DEFAULT_MAX_CANDIDATES = 20;
|
|
41966
42131
|
var MAX_EVENTS = 50;
|
|
@@ -42040,7 +42205,7 @@ function buildWhyOutcomeCaptureReport(options) {
|
|
|
42040
42205
|
};
|
|
42041
42206
|
}
|
|
42042
42207
|
async function outcomeCapturePreviewCommand(options) {
|
|
42043
|
-
const rootDir =
|
|
42208
|
+
const rootDir = path39.resolve(options.dir ?? process.cwd());
|
|
42044
42209
|
const workflowFile = typeof options.fromWorkflow === "string" ? options.fromWorkflow : options.fromWorkflow ? ".snipara/workflow/current.json" : void 0;
|
|
42045
42210
|
const workflow2 = workflowFile ? readWorkflowSnapshot2(rootDir, workflowFile) : void 0;
|
|
42046
42211
|
const workflowEvents = workflow2 ? buildWorkflowOutcomeEvents(workflow2, rootDir) : [];
|
|
@@ -42477,8 +42642,8 @@ function normalizeStringList6(value) {
|
|
|
42477
42642
|
return values.flatMap((item) => String(item).split("\n")).map((item) => item.trim()).filter(Boolean).slice(0, MAX_LIST_ITEMS4);
|
|
42478
42643
|
}
|
|
42479
42644
|
function readEventsFromFile(filePath, cwd = process.cwd()) {
|
|
42480
|
-
const resolved =
|
|
42481
|
-
const parsed = JSON.parse(
|
|
42645
|
+
const resolved = path39.resolve(cwd, filePath);
|
|
42646
|
+
const parsed = JSON.parse(fs40.readFileSync(resolved, "utf8"));
|
|
42482
42647
|
if (Array.isArray(parsed)) {
|
|
42483
42648
|
return parsed;
|
|
42484
42649
|
}
|
|
@@ -42495,8 +42660,8 @@ function readEventsFromFile(filePath, cwd = process.cwd()) {
|
|
|
42495
42660
|
return [];
|
|
42496
42661
|
}
|
|
42497
42662
|
function readWorkflowSnapshot2(rootDir, filePath) {
|
|
42498
|
-
const resolved =
|
|
42499
|
-
const parsed = JSON.parse(
|
|
42663
|
+
const resolved = path39.resolve(rootDir, filePath);
|
|
42664
|
+
const parsed = JSON.parse(fs40.readFileSync(resolved, "utf8"));
|
|
42500
42665
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
42501
42666
|
throw new Error("Workflow snapshot must be a JSON object.");
|
|
42502
42667
|
}
|
|
@@ -42539,12 +42704,12 @@ function buildWorkflowOutcomeEvents(workflow2, rootDir) {
|
|
|
42539
42704
|
});
|
|
42540
42705
|
}
|
|
42541
42706
|
function projectRelativeWorkflowFile(value, rootDir) {
|
|
42542
|
-
const absolute =
|
|
42543
|
-
const relative15 =
|
|
42544
|
-
if (!relative15 || relative15.startsWith("..") ||
|
|
42707
|
+
const absolute = path39.resolve(rootDir, value);
|
|
42708
|
+
const relative15 = path39.relative(rootDir, absolute);
|
|
42709
|
+
if (!relative15 || relative15.startsWith("..") || path39.isAbsolute(relative15)) {
|
|
42545
42710
|
return null;
|
|
42546
42711
|
}
|
|
42547
|
-
return relative15.split(
|
|
42712
|
+
return relative15.split(path39.sep).join("/");
|
|
42548
42713
|
}
|
|
42549
42714
|
function boundedWorkflowValue(value, fallback) {
|
|
42550
42715
|
if (typeof value !== "string" || !value.trim()) return fallback;
|
|
@@ -42554,7 +42719,7 @@ function isRecord23(value) {
|
|
|
42554
42719
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
42555
42720
|
}
|
|
42556
42721
|
function stableHash2(parts) {
|
|
42557
|
-
return (0,
|
|
42722
|
+
return (0, import_node_crypto17.createHash)("sha256").update(parts.join("\0")).digest("hex");
|
|
42558
42723
|
}
|
|
42559
42724
|
function uniqueStrings24(values) {
|
|
42560
42725
|
return Array.from(new Set(values.filter(Boolean)));
|
|
@@ -42998,17 +43163,17 @@ async function realityCheckCommand(options) {
|
|
|
42998
43163
|
}
|
|
42999
43164
|
|
|
43000
43165
|
// src/commands/context-control.ts
|
|
43001
|
-
var
|
|
43002
|
-
var
|
|
43166
|
+
var fs42 = __toESM(require("fs"));
|
|
43167
|
+
var path41 = __toESM(require("path"));
|
|
43003
43168
|
var import_node_child_process18 = require("child_process");
|
|
43004
43169
|
var import_chalk16 = __toESM(require("chalk"));
|
|
43005
|
-
var CONTEXT_CONTROL_RELATIVE_DIR =
|
|
43006
|
-
var CONTEXT_CONTROL_PLANS_RELATIVE_DIR =
|
|
43007
|
-
var CONTEXT_CONTROL_APPLIED_RELATIVE_DIR =
|
|
43170
|
+
var CONTEXT_CONTROL_RELATIVE_DIR = path41.join(".snipara", "context-control");
|
|
43171
|
+
var CONTEXT_CONTROL_PLANS_RELATIVE_DIR = path41.join(CONTEXT_CONTROL_RELATIVE_DIR, "plans");
|
|
43172
|
+
var CONTEXT_CONTROL_APPLIED_RELATIVE_DIR = path41.join(
|
|
43008
43173
|
CONTEXT_CONTROL_RELATIVE_DIR,
|
|
43009
43174
|
"applied"
|
|
43010
43175
|
);
|
|
43011
|
-
var CONTEXT_CONTROL_STATE_RELATIVE_DIR =
|
|
43176
|
+
var CONTEXT_CONTROL_STATE_RELATIVE_DIR = path41.join(CONTEXT_CONTROL_RELATIVE_DIR, "state");
|
|
43012
43177
|
var PROJECT_CONTEXT_MANIFEST_DEFAULT_PATH = "snipara.project-context.json";
|
|
43013
43178
|
var DEFAULT_PLAN_SUMMARY = "Record local context-control state";
|
|
43014
43179
|
function runGit4(args, cwd, options = {}) {
|
|
@@ -43046,10 +43211,10 @@ function resolveGitDriftScopePaths(cwd) {
|
|
|
43046
43211
|
const scopePaths = [
|
|
43047
43212
|
PROJECT_CONTEXT_MANIFEST_DEFAULT_PATH,
|
|
43048
43213
|
CONTEXT_CONTROL_RELATIVE_DIR,
|
|
43049
|
-
|
|
43214
|
+
path41.join(".snipara", "decisions")
|
|
43050
43215
|
];
|
|
43051
43216
|
const manifestPath2 = resolveManifestPath(cwd);
|
|
43052
|
-
if (!
|
|
43217
|
+
if (!fs42.existsSync(manifestPath2)) {
|
|
43053
43218
|
return normalizeScopePaths(scopePaths, cwd);
|
|
43054
43219
|
}
|
|
43055
43220
|
const manifestRead = readJsonFileSafe(manifestPath2);
|
|
@@ -43076,16 +43241,16 @@ function slugify2(value) {
|
|
|
43076
43241
|
return slug2 || "context-control-state";
|
|
43077
43242
|
}
|
|
43078
43243
|
function toProjectRelativePath4(absolutePath, cwd) {
|
|
43079
|
-
const relative15 =
|
|
43244
|
+
const relative15 = path41.relative(cwd, absolutePath);
|
|
43080
43245
|
return relative15 && !relative15.startsWith("..") ? relative15 : absolutePath;
|
|
43081
43246
|
}
|
|
43082
43247
|
function normalizeProjectRelativePath(filePath, cwd) {
|
|
43083
|
-
const absolute =
|
|
43084
|
-
return toProjectRelativePath4(absolute, cwd).split(
|
|
43248
|
+
const absolute = path41.isAbsolute(filePath) ? filePath : path41.resolve(cwd, filePath);
|
|
43249
|
+
return toProjectRelativePath4(absolute, cwd).split(path41.sep).join("/");
|
|
43085
43250
|
}
|
|
43086
43251
|
function assertContextControlTarget(target, cwd) {
|
|
43087
43252
|
const relative15 = normalizeProjectRelativePath(target, cwd);
|
|
43088
|
-
if (
|
|
43253
|
+
if (path41.isAbsolute(relative15) || relative15.startsWith("../") || relative15 === ".." || !relative15.startsWith(".snipara/context-control/")) {
|
|
43089
43254
|
throw new Error(
|
|
43090
43255
|
`Context-control apply can only write under ${CONTEXT_CONTROL_RELATIVE_DIR}; got ${target}`
|
|
43091
43256
|
);
|
|
@@ -43093,18 +43258,18 @@ function assertContextControlTarget(target, cwd) {
|
|
|
43093
43258
|
return relative15;
|
|
43094
43259
|
}
|
|
43095
43260
|
function defaultTargetPath(summary) {
|
|
43096
|
-
return
|
|
43261
|
+
return path41.join(CONTEXT_CONTROL_STATE_RELATIVE_DIR, `${slugify2(summary)}.json`);
|
|
43097
43262
|
}
|
|
43098
43263
|
function receiptPathFor(receipt, cwd) {
|
|
43099
|
-
return
|
|
43264
|
+
return path41.resolve(cwd, CONTEXT_CONTROL_APPLIED_RELATIVE_DIR, `${receipt.receiptId}.json`);
|
|
43100
43265
|
}
|
|
43101
43266
|
function writeStableJsonFile(filePath, value) {
|
|
43102
|
-
|
|
43103
|
-
|
|
43267
|
+
fs42.mkdirSync(path41.dirname(filePath), { recursive: true });
|
|
43268
|
+
fs42.writeFileSync(filePath, `${stableDecisionJsonStringify(value)}
|
|
43104
43269
|
`, "utf8");
|
|
43105
43270
|
}
|
|
43106
43271
|
function readJsonFile5(filePath) {
|
|
43107
|
-
return JSON.parse(
|
|
43272
|
+
return JSON.parse(fs42.readFileSync(filePath, "utf8"));
|
|
43108
43273
|
}
|
|
43109
43274
|
function buildStateOperation(options) {
|
|
43110
43275
|
const target = assertContextControlTarget(
|
|
@@ -43128,10 +43293,10 @@ function buildStateOperation(options) {
|
|
|
43128
43293
|
};
|
|
43129
43294
|
}
|
|
43130
43295
|
function resolveManifestPath(cwd, manifest) {
|
|
43131
|
-
return
|
|
43296
|
+
return path41.resolve(cwd, manifest ?? PROJECT_CONTEXT_MANIFEST_DEFAULT_PATH);
|
|
43132
43297
|
}
|
|
43133
43298
|
function buildLocalProjectContextValidationReport(options = {}) {
|
|
43134
|
-
const cwd =
|
|
43299
|
+
const cwd = path41.resolve(options.cwd ?? process.cwd());
|
|
43135
43300
|
const manifestPath2 = resolveManifestPath(cwd, options.manifest);
|
|
43136
43301
|
const manifest = readJsonFile5(manifestPath2);
|
|
43137
43302
|
return validateProjectContextManifest({
|
|
@@ -43142,7 +43307,7 @@ function buildLocalProjectContextValidationReport(options = {}) {
|
|
|
43142
43307
|
function buildManifestOperation(options) {
|
|
43143
43308
|
const relativeManifestPath = toProjectRelativePath4(options.manifestPath, options.cwd);
|
|
43144
43309
|
const target = assertContextControlTarget(
|
|
43145
|
-
options.target ??
|
|
43310
|
+
options.target ?? path41.join(CONTEXT_CONTROL_STATE_RELATIVE_DIR, "project-context-manifest.json"),
|
|
43146
43311
|
options.cwd
|
|
43147
43312
|
);
|
|
43148
43313
|
return {
|
|
@@ -43161,7 +43326,7 @@ function buildManifestOperation(options) {
|
|
|
43161
43326
|
};
|
|
43162
43327
|
}
|
|
43163
43328
|
function buildLocalContextMutationPlan(options = {}) {
|
|
43164
|
-
const cwd =
|
|
43329
|
+
const cwd = path41.resolve(options.cwd ?? process.cwd());
|
|
43165
43330
|
const now = options.now ?? /* @__PURE__ */ new Date();
|
|
43166
43331
|
const manifestPath2 = options.manifest ? resolveManifestPath(cwd, options.manifest) : void 0;
|
|
43167
43332
|
const validation = manifestPath2 ? buildLocalProjectContextValidationReport({ cwd, manifest: manifestPath2, now }) : void 0;
|
|
@@ -43208,15 +43373,15 @@ function buildLocalContextMutationPlan(options = {}) {
|
|
|
43208
43373
|
approvalRequired: options.approvalRequired ?? true,
|
|
43209
43374
|
expiresAt: options.expiresAt
|
|
43210
43375
|
});
|
|
43211
|
-
const planPath = options.output ?
|
|
43376
|
+
const planPath = options.output ? path41.resolve(cwd, options.output) : void 0;
|
|
43212
43377
|
if (planPath) {
|
|
43213
43378
|
writeStableJsonFile(planPath, plan);
|
|
43214
43379
|
}
|
|
43215
43380
|
return { plan, ...planPath ? { planPath } : {} };
|
|
43216
43381
|
}
|
|
43217
43382
|
function applyLocalContextMutationPlan(options) {
|
|
43218
|
-
const cwd =
|
|
43219
|
-
const planPath =
|
|
43383
|
+
const cwd = path41.resolve(options.cwd ?? process.cwd());
|
|
43384
|
+
const planPath = path41.resolve(cwd, options.plan);
|
|
43220
43385
|
const rawPlan = readJsonFile5(planPath);
|
|
43221
43386
|
if (!isContextMutationPlan(rawPlan)) {
|
|
43222
43387
|
throw new Error(`Invalid context mutation plan: ${options.plan}`);
|
|
@@ -43296,7 +43461,7 @@ function applyLocalContextMutationPlan(options) {
|
|
|
43296
43461
|
baseRevisionAtApply: currentRevision
|
|
43297
43462
|
});
|
|
43298
43463
|
const receiptPath = receiptPathFor(pendingReceipt, cwd);
|
|
43299
|
-
if (
|
|
43464
|
+
if (fs42.existsSync(receiptPath)) {
|
|
43300
43465
|
const receipt2 = buildContextMutationApplyReceipt({
|
|
43301
43466
|
plan,
|
|
43302
43467
|
appliedAt: options.now,
|
|
@@ -43333,8 +43498,8 @@ function applyLocalContextMutationPlan(options) {
|
|
|
43333
43498
|
});
|
|
43334
43499
|
continue;
|
|
43335
43500
|
}
|
|
43336
|
-
const absoluteTarget =
|
|
43337
|
-
if (operation.mode === "create" &&
|
|
43501
|
+
const absoluteTarget = path41.resolve(cwd, target);
|
|
43502
|
+
if (operation.mode === "create" && fs42.existsSync(absoluteTarget)) {
|
|
43338
43503
|
throw new Error(`Refusing to overwrite existing context-control file: ${target}`);
|
|
43339
43504
|
}
|
|
43340
43505
|
writeStableJsonFile(absoluteTarget, operation.content ?? {});
|
|
@@ -43368,8 +43533,8 @@ function applyLocalContextMutationPlan(options) {
|
|
|
43368
43533
|
};
|
|
43369
43534
|
}
|
|
43370
43535
|
function listJsonFiles2(dir) {
|
|
43371
|
-
if (!
|
|
43372
|
-
return
|
|
43536
|
+
if (!fs42.existsSync(dir)) return [];
|
|
43537
|
+
return fs42.readdirSync(dir).filter((name) => name.endsWith(".json")).map((name) => path41.join(dir, name)).sort((left, right) => left.localeCompare(right));
|
|
43373
43538
|
}
|
|
43374
43539
|
function readJsonFileSafe(filePath) {
|
|
43375
43540
|
try {
|
|
@@ -43447,8 +43612,8 @@ function collectGitDriftSignals(cwd) {
|
|
|
43447
43612
|
return [dirtySignal, upstreamSignal];
|
|
43448
43613
|
}
|
|
43449
43614
|
function collectWorkflowDriftSignals(cwd) {
|
|
43450
|
-
const workflowPath =
|
|
43451
|
-
if (!
|
|
43615
|
+
const workflowPath = path41.join(cwd, ".snipara", "workflow", "current.json");
|
|
43616
|
+
if (!fs42.existsSync(workflowPath)) {
|
|
43452
43617
|
return [
|
|
43453
43618
|
{
|
|
43454
43619
|
id: "workflow-state-missing",
|
|
@@ -43493,7 +43658,7 @@ function collectWorkflowDriftSignals(cwd) {
|
|
|
43493
43658
|
];
|
|
43494
43659
|
}
|
|
43495
43660
|
function collectDecisionDriftSignals(cwd) {
|
|
43496
|
-
const pendingDir =
|
|
43661
|
+
const pendingDir = path41.join(cwd, ".snipara", "decisions", "pending");
|
|
43497
43662
|
const pending = listJsonFiles2(pendingDir).map((file) => toProjectRelativePath4(file, cwd));
|
|
43498
43663
|
return [
|
|
43499
43664
|
pending.length > 0 ? {
|
|
@@ -43518,8 +43683,8 @@ function collectDecisionDriftSignals(cwd) {
|
|
|
43518
43683
|
];
|
|
43519
43684
|
}
|
|
43520
43685
|
function collectContextControlDriftSignals(cwd) {
|
|
43521
|
-
const planFiles = listJsonFiles2(
|
|
43522
|
-
const receiptFiles = listJsonFiles2(
|
|
43686
|
+
const planFiles = listJsonFiles2(path41.join(cwd, CONTEXT_CONTROL_PLANS_RELATIVE_DIR));
|
|
43687
|
+
const receiptFiles = listJsonFiles2(path41.join(cwd, CONTEXT_CONTROL_APPLIED_RELATIVE_DIR));
|
|
43523
43688
|
const receiptPlanHashes = new Set(
|
|
43524
43689
|
receiptFiles.map((file) => readJsonFileSafe(file).value).filter(isContextMutationApplyReceipt).map((receipt) => receipt.planHash)
|
|
43525
43690
|
);
|
|
@@ -43542,7 +43707,7 @@ function collectContextControlDriftSignals(cwd) {
|
|
|
43542
43707
|
const read = readJsonFileSafe(file);
|
|
43543
43708
|
if (!read.value || !isContextMutationPlan(read.value)) {
|
|
43544
43709
|
return {
|
|
43545
|
-
id: `context-control-plan-invalid-${
|
|
43710
|
+
id: `context-control-plan-invalid-${path41.basename(file, ".json")}`,
|
|
43546
43711
|
surface: "context_control",
|
|
43547
43712
|
state: "UNKNOWN",
|
|
43548
43713
|
summary: "A saved context mutation plan is invalid or unreadable.",
|
|
@@ -43591,7 +43756,7 @@ function collectContextControlDriftSignals(cwd) {
|
|
|
43591
43756
|
function collectProjectContextManifestDriftSignals(cwd) {
|
|
43592
43757
|
const manifestPath2 = resolveManifestPath(cwd);
|
|
43593
43758
|
const relative15 = toProjectRelativePath4(manifestPath2, cwd);
|
|
43594
|
-
if (!
|
|
43759
|
+
if (!fs42.existsSync(manifestPath2)) {
|
|
43595
43760
|
return [
|
|
43596
43761
|
{
|
|
43597
43762
|
id: "project-context-manifest-missing",
|
|
@@ -43647,7 +43812,7 @@ function collectProjectContextManifestDriftSignals(cwd) {
|
|
|
43647
43812
|
];
|
|
43648
43813
|
}
|
|
43649
43814
|
function buildLocalProjectDriftReport(options = {}) {
|
|
43650
|
-
const cwd =
|
|
43815
|
+
const cwd = path41.resolve(options.cwd ?? process.cwd());
|
|
43651
43816
|
return buildProjectDriftReport({
|
|
43652
43817
|
generatedAt: options.now,
|
|
43653
43818
|
signals: [
|
|
@@ -43794,23 +43959,23 @@ function resolveHostedContextSources(cwd, manifestPath2, report) {
|
|
|
43794
43959
|
if (!report.manifest || report.status === "invalid") {
|
|
43795
43960
|
throw new Error("ProjectContext manifest is invalid; run context-control validate first.");
|
|
43796
43961
|
}
|
|
43797
|
-
const workspaceRoot2 =
|
|
43962
|
+
const workspaceRoot2 = fs42.realpathSync(cwd);
|
|
43798
43963
|
return report.manifest.sources.map((source2) => {
|
|
43799
|
-
const candidate =
|
|
43800
|
-
if (!
|
|
43964
|
+
const candidate = path41.resolve(cwd, source2.path);
|
|
43965
|
+
if (!fs42.existsSync(candidate)) {
|
|
43801
43966
|
throw new Error(`ProjectContext source is missing: ${source2.path}`);
|
|
43802
43967
|
}
|
|
43803
|
-
if (
|
|
43968
|
+
if (fs42.lstatSync(candidate).isSymbolicLink()) {
|
|
43804
43969
|
throw new Error(`ProjectContext source symlinks are not allowed: ${source2.path}`);
|
|
43805
43970
|
}
|
|
43806
|
-
const canonical =
|
|
43807
|
-
if (canonical !== workspaceRoot2 && !canonical.startsWith(`${workspaceRoot2}${
|
|
43971
|
+
const canonical = fs42.realpathSync(candidate);
|
|
43972
|
+
if (canonical !== workspaceRoot2 && !canonical.startsWith(`${workspaceRoot2}${path41.sep}`)) {
|
|
43808
43973
|
throw new Error(`ProjectContext source escapes the workspace: ${source2.path}`);
|
|
43809
43974
|
}
|
|
43810
|
-
if (!
|
|
43975
|
+
if (!fs42.statSync(canonical).isFile()) {
|
|
43811
43976
|
throw new Error(`ProjectContext source must be a file: ${source2.path}`);
|
|
43812
43977
|
}
|
|
43813
|
-
const content =
|
|
43978
|
+
const content = fs42.readFileSync(canonical, "utf8");
|
|
43814
43979
|
if (Buffer.byteLength(content, "utf8") > 1e6) {
|
|
43815
43980
|
throw new Error(`ProjectContext source exceeds 1 MB: ${source2.path}`);
|
|
43816
43981
|
}
|
|
@@ -43831,7 +43996,7 @@ async function contextControlHostedDiffCommand(options) {
|
|
|
43831
43996
|
plan: response.plan
|
|
43832
43997
|
};
|
|
43833
43998
|
if (options.output) {
|
|
43834
|
-
const planPath =
|
|
43999
|
+
const planPath = path41.resolve(cwd, options.output);
|
|
43835
44000
|
writeStableJsonFile(planPath, response.plan);
|
|
43836
44001
|
result.planPath = toProjectRelativePath4(planPath, cwd);
|
|
43837
44002
|
}
|
|
@@ -43903,11 +44068,11 @@ async function contextControlHostedDiffCommand(options) {
|
|
|
43903
44068
|
}
|
|
43904
44069
|
async function contextControlHostedApplyCommand(options) {
|
|
43905
44070
|
const cwd = process.cwd();
|
|
43906
|
-
const rawPlan = readJsonFile5(
|
|
44071
|
+
const rawPlan = readJsonFile5(path41.resolve(cwd, options.plan));
|
|
43907
44072
|
if (!isHostedContextControlPlan(rawPlan)) {
|
|
43908
44073
|
throw new Error(`Invalid hosted Context Control plan: ${options.plan}`);
|
|
43909
44074
|
}
|
|
43910
|
-
const approval = options.approval ? readJsonFile5(
|
|
44075
|
+
const approval = options.approval ? readJsonFile5(path41.resolve(cwd, options.approval)) : void 0;
|
|
43911
44076
|
const response = await createClient(12e4, { cwd }).applyHostedContextControl({
|
|
43912
44077
|
plan: rawPlan,
|
|
43913
44078
|
approval
|
|
@@ -43920,7 +44085,7 @@ async function contextControlHostedApplyCommand(options) {
|
|
|
43920
44085
|
receipt: response.receipt
|
|
43921
44086
|
};
|
|
43922
44087
|
if (options.output) {
|
|
43923
|
-
const receiptPath =
|
|
44088
|
+
const receiptPath = path41.resolve(cwd, options.output);
|
|
43924
44089
|
writeStableJsonFile(receiptPath, response.receipt);
|
|
43925
44090
|
result.receiptPath = toProjectRelativePath4(receiptPath, cwd);
|
|
43926
44091
|
}
|
|
@@ -43944,16 +44109,16 @@ function uniqueStrings25(values) {
|
|
|
43944
44109
|
}
|
|
43945
44110
|
|
|
43946
44111
|
// src/commands/agent-context-evidence.ts
|
|
43947
|
-
var
|
|
43948
|
-
var
|
|
43949
|
-
var AGENT_CONTEXT_EVIDENCE_DEFAULT_LEDGER =
|
|
44112
|
+
var fs43 = __toESM(require("fs"));
|
|
44113
|
+
var path42 = __toESM(require("path"));
|
|
44114
|
+
var AGENT_CONTEXT_EVIDENCE_DEFAULT_LEDGER = path42.join(
|
|
43950
44115
|
".snipara",
|
|
43951
44116
|
"agent-context",
|
|
43952
44117
|
"evidence.jsonl"
|
|
43953
44118
|
);
|
|
43954
44119
|
function readJson(filePath, label) {
|
|
43955
44120
|
try {
|
|
43956
|
-
return JSON.parse(
|
|
44121
|
+
return JSON.parse(fs43.readFileSync(filePath, "utf8"));
|
|
43957
44122
|
} catch (error) {
|
|
43958
44123
|
const message = error instanceof Error ? error.message : String(error);
|
|
43959
44124
|
throw new Error(`Unable to read ${label} ${filePath}: ${message}`);
|
|
@@ -43961,7 +44126,7 @@ function readJson(filePath, label) {
|
|
|
43961
44126
|
}
|
|
43962
44127
|
function readManifest4(cwd, candidate) {
|
|
43963
44128
|
return readJson(
|
|
43964
|
-
|
|
44129
|
+
path42.resolve(cwd, candidate ?? AGENT_CONTEXT_MANIFEST_DEFAULT_PATH),
|
|
43965
44130
|
"Agent Context manifest"
|
|
43966
44131
|
);
|
|
43967
44132
|
}
|
|
@@ -43979,8 +44144,8 @@ function receiptHash(receipt) {
|
|
|
43979
44144
|
return hashDecisionJsonValue(base);
|
|
43980
44145
|
}
|
|
43981
44146
|
function readAgentContextEvidenceLedger(ledgerPath) {
|
|
43982
|
-
if (!
|
|
43983
|
-
const content =
|
|
44147
|
+
if (!fs43.existsSync(ledgerPath)) return [];
|
|
44148
|
+
const content = fs43.readFileSync(ledgerPath, "utf8").trim();
|
|
43984
44149
|
if (!content) return [];
|
|
43985
44150
|
return content.split("\n").map((line, index) => {
|
|
43986
44151
|
let candidate;
|
|
@@ -44006,23 +44171,23 @@ function writeJsonOutput(value, outputPath, force = false) {
|
|
|
44006
44171
|
console.log(content.trimEnd());
|
|
44007
44172
|
return void 0;
|
|
44008
44173
|
}
|
|
44009
|
-
if (
|
|
44174
|
+
if (fs43.existsSync(outputPath) && !force) {
|
|
44010
44175
|
throw new Error(
|
|
44011
44176
|
`Refusing to overwrite existing file ${outputPath}; pass --force to replace it.`
|
|
44012
44177
|
);
|
|
44013
44178
|
}
|
|
44014
|
-
|
|
44015
|
-
|
|
44179
|
+
fs43.mkdirSync(path42.dirname(outputPath), { recursive: true });
|
|
44180
|
+
fs43.writeFileSync(outputPath, content, "utf8");
|
|
44016
44181
|
return outputPath;
|
|
44017
44182
|
}
|
|
44018
44183
|
function safeWorkflowReference(value, cwd) {
|
|
44019
44184
|
if (typeof value !== "string" || !value.trim()) return void 0;
|
|
44020
44185
|
const candidate = value.trim();
|
|
44021
44186
|
if (/^[a-z][a-z0-9+.-]*:\/\//i.test(candidate)) return candidate;
|
|
44022
|
-
const absolute =
|
|
44023
|
-
const relative15 =
|
|
44024
|
-
if (!relative15 || relative15.startsWith("..") ||
|
|
44025
|
-
return relative15.replaceAll(
|
|
44187
|
+
const absolute = path42.isAbsolute(candidate) ? candidate : path42.resolve(cwd, candidate);
|
|
44188
|
+
const relative15 = path42.relative(cwd, absolute);
|
|
44189
|
+
if (!relative15 || relative15.startsWith("..") || path42.isAbsolute(relative15)) return void 0;
|
|
44190
|
+
return relative15.replaceAll(path42.sep, "/");
|
|
44026
44191
|
}
|
|
44027
44192
|
function collectWorkflowProofRefs(workflow2, cwd) {
|
|
44028
44193
|
if (!workflow2 || typeof workflow2 !== "object" || Array.isArray(workflow2)) {
|
|
@@ -44115,7 +44280,7 @@ function formatStatus(report, ledgerPath) {
|
|
|
44115
44280
|
return lines.join("\n");
|
|
44116
44281
|
}
|
|
44117
44282
|
async function agentContextEvidenceTemplateCommand(options) {
|
|
44118
|
-
const cwd =
|
|
44283
|
+
const cwd = path42.resolve(options.cwd ?? process.cwd());
|
|
44119
44284
|
const manifest = validatedManifest(cwd, options.manifest);
|
|
44120
44285
|
const resolution = resolveAgentContext({
|
|
44121
44286
|
manifest,
|
|
@@ -44123,19 +44288,19 @@ async function agentContextEvidenceTemplateCommand(options) {
|
|
|
44123
44288
|
task: options.task
|
|
44124
44289
|
});
|
|
44125
44290
|
const template = buildAgentContextEvidenceTemplate(resolution);
|
|
44126
|
-
const outputPath = options.output ?
|
|
44291
|
+
const outputPath = options.output ? path42.resolve(cwd, options.output) : void 0;
|
|
44127
44292
|
const written = writeJsonOutput(template, outputPath, Boolean(options.force));
|
|
44128
44293
|
if (written && !options.json) {
|
|
44129
|
-
console.log(`Wrote AC-1 evidence template: ${
|
|
44294
|
+
console.log(`Wrote AC-1 evidence template: ${path42.relative(cwd, written)}`);
|
|
44130
44295
|
console.log("Complete the task evidence and proofRefs before recording it.");
|
|
44131
44296
|
}
|
|
44132
44297
|
}
|
|
44133
44298
|
async function agentContextEvidenceCollectCommand(options) {
|
|
44134
|
-
const cwd =
|
|
44299
|
+
const cwd = path42.resolve(options.cwd ?? process.cwd());
|
|
44135
44300
|
const manifest = validatedManifest(cwd, options.manifest);
|
|
44136
|
-
const workflowPath =
|
|
44301
|
+
const workflowPath = path42.resolve(
|
|
44137
44302
|
cwd,
|
|
44138
|
-
options.workflow ??
|
|
44303
|
+
options.workflow ?? path42.join(".snipara", "workflow", "current.json")
|
|
44139
44304
|
);
|
|
44140
44305
|
const workflow2 = readJson(workflowPath, "workflow state");
|
|
44141
44306
|
const workflowGoal = workflow2 && typeof workflow2 === "object" && !Array.isArray(workflow2) ? workflow2.goal : void 0;
|
|
@@ -44145,19 +44310,19 @@ async function agentContextEvidenceCollectCommand(options) {
|
|
|
44145
44310
|
}
|
|
44146
44311
|
const resolution = resolveAgentContext({ manifest, agent: options.agent, task });
|
|
44147
44312
|
const draft = workflowDraftEvidence(buildAgentContextEvidenceTemplate(resolution), workflow2, cwd);
|
|
44148
|
-
const outputPath = options.output ?
|
|
44313
|
+
const outputPath = options.output ? path42.resolve(cwd, options.output) : void 0;
|
|
44149
44314
|
const written = writeJsonOutput(draft, outputPath, Boolean(options.force));
|
|
44150
44315
|
if (written && !options.json) {
|
|
44151
|
-
console.log(`Wrote AC-1 evidence draft from workflow: ${
|
|
44316
|
+
console.log(`Wrote AC-1 evidence draft from workflow: ${path42.relative(cwd, written)}`);
|
|
44152
44317
|
console.log(
|
|
44153
44318
|
"Review usedSourceIds, executedRecallKeys, contextEffect, and capabilityAssessment before recording it."
|
|
44154
44319
|
);
|
|
44155
44320
|
}
|
|
44156
44321
|
}
|
|
44157
44322
|
async function agentContextEvidenceRecordCommand(options) {
|
|
44158
|
-
const cwd =
|
|
44323
|
+
const cwd = path42.resolve(options.cwd ?? process.cwd());
|
|
44159
44324
|
const manifest = validatedManifest(cwd, options.manifest);
|
|
44160
|
-
const evidencePath =
|
|
44325
|
+
const evidencePath = path42.resolve(cwd, options.from);
|
|
44161
44326
|
const evidence = readJson(evidencePath, "AC-1 evidence input");
|
|
44162
44327
|
if (!evidence || typeof evidence !== "object" || Array.isArray(evidence)) {
|
|
44163
44328
|
throw new Error("AC-1 evidence input must be a JSON object.");
|
|
@@ -44169,25 +44334,25 @@ async function agentContextEvidenceRecordCommand(options) {
|
|
|
44169
44334
|
}
|
|
44170
44335
|
const resolution = resolveAgentContext({ manifest, agent, task });
|
|
44171
44336
|
const receipt = buildAgentContextEvidenceReceipt({ resolution, evidence });
|
|
44172
|
-
const ledgerPath =
|
|
44337
|
+
const ledgerPath = path42.resolve(cwd, options.ledger ?? AGENT_CONTEXT_EVIDENCE_DEFAULT_LEDGER);
|
|
44173
44338
|
const existing = readAgentContextEvidenceLedger(ledgerPath);
|
|
44174
44339
|
if (existing.some((candidate) => candidate.taskId === receipt.taskId)) {
|
|
44175
44340
|
throw new Error(`Evidence taskId already exists in the ledger: ${receipt.taskId}.`);
|
|
44176
44341
|
}
|
|
44177
|
-
|
|
44178
|
-
|
|
44342
|
+
fs43.mkdirSync(path42.dirname(ledgerPath), { recursive: true });
|
|
44343
|
+
fs43.appendFileSync(ledgerPath, `${JSON.stringify(receipt)}
|
|
44179
44344
|
`, "utf8");
|
|
44180
44345
|
if (options.json) {
|
|
44181
44346
|
console.log(JSON.stringify(receipt, null, 2));
|
|
44182
44347
|
} else {
|
|
44183
44348
|
console.log(`Recorded AC-1 evidence: ${receipt.taskId}`);
|
|
44184
|
-
console.log(`Ledger: ${
|
|
44349
|
+
console.log(`Ledger: ${path42.relative(cwd, ledgerPath)}`);
|
|
44185
44350
|
console.log(`Receipt: ${receipt.receiptHash}`);
|
|
44186
44351
|
}
|
|
44187
44352
|
return receipt;
|
|
44188
44353
|
}
|
|
44189
44354
|
async function agentContextEvidenceStatusCommand(options = {}) {
|
|
44190
|
-
const cwd =
|
|
44355
|
+
const cwd = path42.resolve(options.cwd ?? process.cwd());
|
|
44191
44356
|
const validation = buildLocalAgentContextValidationReport({
|
|
44192
44357
|
cwd,
|
|
44193
44358
|
manifest: readManifest4(cwd, options.manifest)
|
|
@@ -44197,7 +44362,7 @@ async function agentContextEvidenceStatusCommand(options = {}) {
|
|
|
44197
44362
|
throw new Error(`Invalid Agent Context manifest. ${errors}`.trim());
|
|
44198
44363
|
}
|
|
44199
44364
|
const manifest = validation.manifest;
|
|
44200
|
-
const ledgerPath =
|
|
44365
|
+
const ledgerPath = path42.resolve(cwd, options.ledger ?? AGENT_CONTEXT_EVIDENCE_DEFAULT_LEDGER);
|
|
44201
44366
|
const receipts = readAgentContextEvidenceLedger(ledgerPath);
|
|
44202
44367
|
const report = buildAgentContextEvidenceReport({
|
|
44203
44368
|
receipts,
|
|
@@ -44205,7 +44370,7 @@ async function agentContextEvidenceStatusCommand(options = {}) {
|
|
|
44205
44370
|
manifestHash: validation.manifestHash
|
|
44206
44371
|
});
|
|
44207
44372
|
console.log(
|
|
44208
|
-
options.json ? JSON.stringify(report, null, 2) : formatStatus(report,
|
|
44373
|
+
options.json ? JSON.stringify(report, null, 2) : formatStatus(report, path42.relative(cwd, ledgerPath))
|
|
44209
44374
|
);
|
|
44210
44375
|
if (options.enforce && report.status !== "ready") process.exitCode = 1;
|
|
44211
44376
|
return report;
|
|
@@ -44213,12 +44378,12 @@ async function agentContextEvidenceStatusCommand(options = {}) {
|
|
|
44213
44378
|
|
|
44214
44379
|
// src/commands/references.ts
|
|
44215
44380
|
var crypto7 = __toESM(require("crypto"));
|
|
44216
|
-
var
|
|
44217
|
-
var
|
|
44381
|
+
var fs44 = __toESM(require("fs"));
|
|
44382
|
+
var path43 = __toESM(require("path"));
|
|
44218
44383
|
var import_chalk17 = __toESM(require("chalk"));
|
|
44219
44384
|
var MANIFEST_VERSION2 = "snipara.references.v1";
|
|
44220
|
-
var DEFAULT_MANIFEST_PATH =
|
|
44221
|
-
var DEFAULT_SNAPSHOT_DIR =
|
|
44385
|
+
var DEFAULT_MANIFEST_PATH = path43.join(".snipara", "references", "manifest.json");
|
|
44386
|
+
var DEFAULT_SNAPSHOT_DIR = path43.join(".snipara", "references", "snapshots");
|
|
44222
44387
|
var DEFAULT_DESTINATION_PREFIX = "external-references";
|
|
44223
44388
|
var DEFAULT_SCAN_EXTENSIONS = /* @__PURE__ */ new Set([".md", ".mdx", ".txt", ".rst"]);
|
|
44224
44389
|
var DEFAULT_IGNORE_DIRS = /* @__PURE__ */ new Set([
|
|
@@ -44294,27 +44459,27 @@ function sanitizeSegment(value, fallback) {
|
|
|
44294
44459
|
return sanitized || fallback;
|
|
44295
44460
|
}
|
|
44296
44461
|
function toRelative(root, file) {
|
|
44297
|
-
return
|
|
44462
|
+
return path43.relative(root, file).split(path43.sep).join("/");
|
|
44298
44463
|
}
|
|
44299
44464
|
function ensureParentDir(file) {
|
|
44300
|
-
|
|
44465
|
+
fs44.mkdirSync(path43.dirname(file), { recursive: true });
|
|
44301
44466
|
}
|
|
44302
44467
|
function walkFiles(root, extensions, maxFiles, files = []) {
|
|
44303
44468
|
if (files.length >= maxFiles) {
|
|
44304
44469
|
return files;
|
|
44305
44470
|
}
|
|
44306
|
-
for (const entry of
|
|
44471
|
+
for (const entry of fs44.readdirSync(root, { withFileTypes: true })) {
|
|
44307
44472
|
if (files.length >= maxFiles) {
|
|
44308
44473
|
break;
|
|
44309
44474
|
}
|
|
44310
|
-
const fullPath =
|
|
44475
|
+
const fullPath = path43.join(root, entry.name);
|
|
44311
44476
|
if (entry.isDirectory()) {
|
|
44312
44477
|
if (!DEFAULT_IGNORE_DIRS.has(entry.name)) {
|
|
44313
44478
|
walkFiles(fullPath, extensions, maxFiles, files);
|
|
44314
44479
|
}
|
|
44315
44480
|
continue;
|
|
44316
44481
|
}
|
|
44317
|
-
if (entry.isFile() && extensions.has(
|
|
44482
|
+
if (entry.isFile() && extensions.has(path43.extname(entry.name).toLowerCase())) {
|
|
44318
44483
|
files.push(fullPath);
|
|
44319
44484
|
}
|
|
44320
44485
|
}
|
|
@@ -44324,7 +44489,7 @@ function collectReferenceItems(root, files, allowDomains, denyDomains) {
|
|
|
44324
44489
|
const byUrl = /* @__PURE__ */ new Map();
|
|
44325
44490
|
const discoveredAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
44326
44491
|
for (const file of files) {
|
|
44327
|
-
const content =
|
|
44492
|
+
const content = fs44.readFileSync(file, "utf-8");
|
|
44328
44493
|
const lines = content.split(/\r?\n/);
|
|
44329
44494
|
const markdownLink = /\[([^\]]+)\]\((https?:\/\/[^)\s]+)\)/g;
|
|
44330
44495
|
const bareUrl = /https?:\/\/[^\s<>"'`]+/g;
|
|
@@ -44369,8 +44534,8 @@ function collectReferenceItems(root, files, allowDomains, denyDomains) {
|
|
|
44369
44534
|
return Array.from(byUrl.values()).sort((a, b) => a.normalizedUrl.localeCompare(b.normalizedUrl));
|
|
44370
44535
|
}
|
|
44371
44536
|
function scanReferences(options = {}) {
|
|
44372
|
-
const root =
|
|
44373
|
-
const outputPath =
|
|
44537
|
+
const root = path43.resolve(options.root ?? process.cwd());
|
|
44538
|
+
const outputPath = path43.resolve(root, options.output ?? DEFAULT_MANIFEST_PATH);
|
|
44374
44539
|
const allowDomains = normalizeList(options.allowDomain);
|
|
44375
44540
|
const denyDomains = normalizeList(options.denyDomain);
|
|
44376
44541
|
const extensions = new Set(
|
|
@@ -44390,7 +44555,7 @@ function scanReferences(options = {}) {
|
|
|
44390
44555
|
items
|
|
44391
44556
|
};
|
|
44392
44557
|
ensureParentDir(outputPath);
|
|
44393
|
-
|
|
44558
|
+
fs44.writeFileSync(outputPath, `${JSON.stringify(manifest, null, 2)}
|
|
44394
44559
|
`, "utf-8");
|
|
44395
44560
|
return {
|
|
44396
44561
|
manifest,
|
|
@@ -44404,7 +44569,7 @@ function scanReferences(options = {}) {
|
|
|
44404
44569
|
};
|
|
44405
44570
|
}
|
|
44406
44571
|
function readManifest5(file) {
|
|
44407
|
-
const manifest = JSON.parse(
|
|
44572
|
+
const manifest = JSON.parse(fs44.readFileSync(file, "utf-8"));
|
|
44408
44573
|
if (manifest.version !== MANIFEST_VERSION2 || !Array.isArray(manifest.items)) {
|
|
44409
44574
|
throw new Error(`${file} is not a ${MANIFEST_VERSION2} manifest`);
|
|
44410
44575
|
}
|
|
@@ -44472,8 +44637,8 @@ async function fetchReference(item, outputDir, destinationPrefix, timeoutMs, max
|
|
|
44472
44637
|
slugSource,
|
|
44473
44638
|
item.id
|
|
44474
44639
|
)}-${item.id}.md`;
|
|
44475
|
-
const snapshotPath =
|
|
44476
|
-
const destinationPath =
|
|
44640
|
+
const snapshotPath = path43.resolve(outputDir, fileName);
|
|
44641
|
+
const destinationPath = path43.posix.join(
|
|
44477
44642
|
destinationPrefix.replace(/^\/+|\/+$/g, "") || DEFAULT_DESTINATION_PREFIX,
|
|
44478
44643
|
fileName
|
|
44479
44644
|
);
|
|
@@ -44489,7 +44654,7 @@ async function fetchReference(item, outputDir, destinationPrefix, timeoutMs, max
|
|
|
44489
44654
|
bodyHash: hash
|
|
44490
44655
|
});
|
|
44491
44656
|
ensureParentDir(snapshotPath);
|
|
44492
|
-
|
|
44657
|
+
fs44.writeFileSync(snapshotPath, markdown, "utf-8");
|
|
44493
44658
|
return {
|
|
44494
44659
|
item,
|
|
44495
44660
|
fetchedAt,
|
|
@@ -44518,14 +44683,14 @@ function selectItems(manifest, options, allowDomains) {
|
|
|
44518
44683
|
return typeof options.max === "number" && options.max > 0 ? selected.slice(0, options.max) : selected;
|
|
44519
44684
|
}
|
|
44520
44685
|
async function ingestReferences(options = {}) {
|
|
44521
|
-
const manifestPath2 =
|
|
44686
|
+
const manifestPath2 = path43.resolve(options.manifest ?? DEFAULT_MANIFEST_PATH);
|
|
44522
44687
|
const manifest = readManifest5(manifestPath2);
|
|
44523
|
-
const root = manifest.root ?
|
|
44688
|
+
const root = manifest.root ? path43.resolve(manifest.root) : process.cwd();
|
|
44524
44689
|
const allowDomains = normalizeList([
|
|
44525
44690
|
...manifest.allowDomains ?? [],
|
|
44526
44691
|
...options.allowDomain ?? []
|
|
44527
44692
|
]);
|
|
44528
|
-
const outputDir =
|
|
44693
|
+
const outputDir = path43.resolve(root, options.outputDir ?? DEFAULT_SNAPSHOT_DIR);
|
|
44529
44694
|
const destinationPrefix = options.destinationPrefix ?? DEFAULT_DESTINATION_PREFIX;
|
|
44530
44695
|
const items = selectItems(manifest, options, allowDomains);
|
|
44531
44696
|
const summary = {
|
|
@@ -44552,7 +44717,7 @@ async function ingestReferences(options = {}) {
|
|
|
44552
44717
|
options.maxBytes ?? 512 * 1024
|
|
44553
44718
|
);
|
|
44554
44719
|
summary.fetched += 1;
|
|
44555
|
-
item.latestSnapshotPath =
|
|
44720
|
+
item.latestSnapshotPath = path43.relative(root, snapshot.snapshotPath).split(path43.sep).join("/");
|
|
44556
44721
|
item.latestFetchStatus = snapshot.status;
|
|
44557
44722
|
item.latestFetchAt = snapshot.fetchedAt;
|
|
44558
44723
|
item.latestContentHash = snapshot.contentHash;
|
|
@@ -44599,7 +44764,7 @@ async function ingestReferences(options = {}) {
|
|
|
44599
44764
|
});
|
|
44600
44765
|
}
|
|
44601
44766
|
}
|
|
44602
|
-
|
|
44767
|
+
fs44.writeFileSync(manifestPath2, `${JSON.stringify(manifest, null, 2)}
|
|
44603
44768
|
`, "utf-8");
|
|
44604
44769
|
if (options.reindex && client) {
|
|
44605
44770
|
await client.reindex({ kind: "doc", mode: "incremental" });
|
|
@@ -44651,8 +44816,8 @@ async function referencesIngestCommand(options) {
|
|
|
44651
44816
|
}
|
|
44652
44817
|
|
|
44653
44818
|
// src/commands/policy-ledger-sync.ts
|
|
44654
|
-
var
|
|
44655
|
-
var
|
|
44819
|
+
var fs45 = __toESM(require("fs"));
|
|
44820
|
+
var path44 = __toESM(require("path"));
|
|
44656
44821
|
var POLICY_LEDGER_SYNC_REPORT_VERSION = "snipara.workflow_policy_ledger_sync.v0";
|
|
44657
44822
|
function buildPolicyLedgerSyncReport(options = {}) {
|
|
44658
44823
|
const cwd = options.cwd ?? process.cwd();
|
|
@@ -44719,7 +44884,7 @@ function collectPolicyLedgerSyncArtifacts(cwd = process.cwd()) {
|
|
|
44719
44884
|
applyState: applyItem?.state ?? "manual_follow_up_required",
|
|
44720
44885
|
humanChoice: record2.response.choice,
|
|
44721
44886
|
summary: record2.request.evidence.summary,
|
|
44722
|
-
sourcePath:
|
|
44887
|
+
sourcePath: path44.join(
|
|
44723
44888
|
".snipara",
|
|
44724
44889
|
"decisions",
|
|
44725
44890
|
"resolved",
|
|
@@ -44729,10 +44894,10 @@ function collectPolicyLedgerSyncArtifacts(cwd = process.cwd()) {
|
|
|
44729
44894
|
payload: record2
|
|
44730
44895
|
};
|
|
44731
44896
|
});
|
|
44732
|
-
const applyArtifacts = readJsonFiles(
|
|
44897
|
+
const applyArtifacts = readJsonFiles(path44.join(cwd, DECISION_APPLY_RELATIVE_DIR), cwd).map(
|
|
44733
44898
|
({ parsed, relativePath: relativePath2 }) => ({
|
|
44734
44899
|
kind: "apply_receipt",
|
|
44735
|
-
requestId: stringField(parsed, "requestId") ??
|
|
44900
|
+
requestId: stringField(parsed, "requestId") ?? path44.basename(relativePath2, ".json"),
|
|
44736
44901
|
fingerprint: stringField(parsed, "fingerprint"),
|
|
44737
44902
|
title: stringField(parsed, "question") ?? stringField(parsed, "decision") ?? "Applied decision",
|
|
44738
44903
|
status: statusForChoiceClass(stringField(parsed, "choiceClass")),
|
|
@@ -44744,10 +44909,10 @@ function collectPolicyLedgerSyncArtifacts(cwd = process.cwd()) {
|
|
|
44744
44909
|
payload: parsed
|
|
44745
44910
|
})
|
|
44746
44911
|
);
|
|
44747
|
-
const draftArtifacts = readJsonFiles(
|
|
44912
|
+
const draftArtifacts = readJsonFiles(path44.join(cwd, POLICY_DRAFT_RELATIVE_DIR), cwd).map(
|
|
44748
44913
|
({ parsed, relativePath: relativePath2 }) => ({
|
|
44749
44914
|
kind: "policy_draft",
|
|
44750
|
-
requestId: stringField(parsed, "requestId") ??
|
|
44915
|
+
requestId: stringField(parsed, "requestId") ?? path44.basename(relativePath2, ".json"),
|
|
44751
44916
|
fingerprint: stringField(parsed, "fingerprint"),
|
|
44752
44917
|
title: stringField(parsed, "title") ?? "Policy draft",
|
|
44753
44918
|
status: "modified",
|
|
@@ -44799,12 +44964,12 @@ function statusForChoiceClass(choiceClass) {
|
|
|
44799
44964
|
return "modified";
|
|
44800
44965
|
}
|
|
44801
44966
|
function readJsonFiles(directory, cwd) {
|
|
44802
|
-
if (!
|
|
44967
|
+
if (!fs45.existsSync(directory)) {
|
|
44803
44968
|
return [];
|
|
44804
44969
|
}
|
|
44805
|
-
return
|
|
44806
|
-
const filePath =
|
|
44807
|
-
const parsed = JSON.parse(
|
|
44970
|
+
return fs45.readdirSync(directory).filter((fileName) => fileName.endsWith(".json")).sort().map((fileName) => {
|
|
44971
|
+
const filePath = path44.join(directory, fileName);
|
|
44972
|
+
const parsed = JSON.parse(fs45.readFileSync(filePath, "utf8"));
|
|
44808
44973
|
return { parsed, relativePath: toProjectRelativePath5(filePath, cwd) };
|
|
44809
44974
|
});
|
|
44810
44975
|
}
|
|
@@ -44813,8 +44978,8 @@ function stringField(value, key) {
|
|
|
44813
44978
|
return typeof field === "string" && field.trim() ? field : void 0;
|
|
44814
44979
|
}
|
|
44815
44980
|
function toProjectRelativePath5(absolutePath, cwd) {
|
|
44816
|
-
const relative15 =
|
|
44817
|
-
return relative15.startsWith(".") ? relative15 : `.${
|
|
44981
|
+
const relative15 = path44.relative(cwd, absolutePath).replace(/\\/g, "/");
|
|
44982
|
+
return relative15.startsWith(".") ? relative15 : `.${path44.sep}${relative15}`.replace(/\\/g, "/");
|
|
44818
44983
|
}
|
|
44819
44984
|
|
|
44820
44985
|
// src/commands/htask.ts
|
|
@@ -45399,8 +45564,24 @@ program.command("post-tool").description("Track file access (PostToolUse hook)")
|
|
|
45399
45564
|
packResult: Boolean(options.packResult)
|
|
45400
45565
|
});
|
|
45401
45566
|
});
|
|
45402
|
-
program.command("session-end").description("Persist session
|
|
45403
|
-
|
|
45567
|
+
program.command("session-end").description("Persist a session checkpoint with a verifiable journal receipt (Stop hook)").option("--summary <summary>", "Bounded session summary to preserve").option("--summary-stdin", "Read the session summary from stdin").option("--files <files...>", "Files represented by this checkpoint").option("--session-id <sessionId>", "Host session id; do not rotate the workspace session").option("--retry <receipt>", "Retry a retained local checkpoint receipt").option("--json", "Print the persistence receipt as JSON").action(async (options) => {
|
|
45568
|
+
if (options.retry && (options.summary || options.summaryStdin || options.files)) {
|
|
45569
|
+
throw new Error("--retry cannot be combined with new checkpoint content");
|
|
45570
|
+
}
|
|
45571
|
+
let summary = options.summary;
|
|
45572
|
+
if (options.summaryStdin) {
|
|
45573
|
+
if (summary !== void 0) throw new Error("Choose --summary or --summary-stdin");
|
|
45574
|
+
const chunks = [];
|
|
45575
|
+
let bytes = 0;
|
|
45576
|
+
for await (const chunk of process.stdin) {
|
|
45577
|
+
const buffer = Buffer.from(chunk);
|
|
45578
|
+
bytes += buffer.length;
|
|
45579
|
+
if (bytes > 128e3) throw new Error("Session summary exceeds 128000 bytes");
|
|
45580
|
+
chunks.push(buffer);
|
|
45581
|
+
}
|
|
45582
|
+
summary = Buffer.concat(chunks).toString("utf8");
|
|
45583
|
+
}
|
|
45584
|
+
await sessionEndCommand({ ...options, summary });
|
|
45404
45585
|
});
|
|
45405
45586
|
program.command("session").description("Session management").addCommand(
|
|
45406
45587
|
new import_commander.Command("status").description("Show session status").action(async () => {
|