@outerlayer/cli 0.1.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +134 -0
- package/README.md +238 -77
- package/dist/agent-setup-IFH3FB5X.js +197 -0
- package/dist/build-TZUUTRGH.js +9 -0
- package/dist/build-info.json +1 -1
- package/dist/check-WQP2CZDW.js +94 -0
- package/dist/chunk-2E54Z3P5.js +232 -0
- package/dist/chunk-3TT7RQYB.js +55 -0
- package/dist/chunk-3YPKXE5L.js +1683 -0
- package/dist/{chunk-HNCCD2IX.js → chunk-5DLBAXY5.js} +209 -61
- package/dist/{chunk-R5KBGVII.js → chunk-5QRP3MVS.js} +30 -14
- package/dist/chunk-5Y3QQRUH.js +300 -0
- package/dist/chunk-6Y63SXFO.js +383 -0
- package/dist/chunk-774HEQL6.js +178 -0
- package/dist/chunk-7A6RVXPZ.js +2233 -0
- package/dist/chunk-7YIOOFVJ.js +71 -0
- package/dist/chunk-ABIWDUMS.js +104 -0
- package/dist/chunk-AUFG23AA.js +534 -0
- package/dist/chunk-B2G7JHHB.js +42 -0
- package/dist/chunk-BCJNHMZT.js +34 -0
- package/dist/chunk-BCLJSQCV.js +56 -0
- package/dist/chunk-BFESLKPP.js +61 -0
- package/dist/chunk-BJ3KTMDH.js +63 -0
- package/dist/chunk-BKO6JEZI.js +47 -0
- package/dist/chunk-BOLTI6LR.js +37 -0
- package/dist/chunk-CBPPJSAR.js +89 -0
- package/dist/chunk-CBZB6XY6.js +102 -0
- package/dist/{chunk-RCQXYLMO.js → chunk-DVDEBNQJ.js} +18 -18
- package/dist/{work-pr-cmd-GOYSPEN2.js → chunk-DVYHCMB2.js} +10 -25
- package/dist/{chunk-TFUIDMOB.js → chunk-EABW6AJQ.js} +12 -1
- package/dist/{chunk-KFYJV2ZG.js → chunk-EMY4I27X.js} +1 -1
- package/dist/{chunk-NTTPJV35.js → chunk-F47JBIAW.js} +3 -1
- package/dist/chunk-F6GFZXZ3.js +60 -0
- package/dist/{chunk-YOOSBOKS.js → chunk-F7CU5ABH.js} +1 -1
- package/dist/chunk-FAJSS2WN.js +1357 -0
- package/dist/chunk-FS2VYGZT.js +1764 -0
- package/dist/chunk-FV2CCGXK.js +9 -0
- package/dist/{chunk-BQB3U2VD.js → chunk-G7FSV7JX.js} +5113 -3729
- package/dist/{emit-cmd-TWSYYEZI.js → chunk-H5NCNVDA.js} +68 -17
- package/dist/chunk-HE2D4EY5.js +83 -0
- package/dist/chunk-L2DBRKRA.js +94 -0
- package/dist/chunk-LF6MLJCY.js +38 -0
- package/dist/chunk-M5POMKKW.js +1051 -0
- package/dist/{mcp-install-cmd-FDQH6SEN.js → chunk-MQ3IPHIZ.js} +35 -18
- package/dist/{chunk-D77LS3UI.js → chunk-N5FOE5PS.js} +33 -4
- package/dist/chunk-N6LURUEF.js +64 -0
- package/dist/chunk-NYC54VBD.js +1084 -0
- package/dist/chunk-OGFGZQA3.js +23 -0
- package/dist/chunk-QOZKPLVJ.js +226 -0
- package/dist/chunk-RA3O54FC.js +30 -0
- package/dist/chunk-TBT347UY.js +41 -0
- package/dist/{chunk-3VQ4XXQA.js → chunk-UFFXNXLQ.js} +115 -71
- package/dist/chunk-USO2DKBD.js +421 -0
- package/dist/chunk-W4SQCOZU.js +206 -0
- package/dist/{chunk-A3WLZX2F.js → chunk-WIOZAJ2W.js} +15 -2
- package/dist/chunk-WO2BXCTQ.js +83 -0
- package/dist/chunk-WZBHBH3J.js +20 -0
- package/dist/{chunk-IWIUYLDR.js → chunk-XCCLFVXM.js} +118 -189
- package/dist/{context-materialize-J6CRQ7O7.js → chunk-XDDW4FRS.js} +134 -26
- package/dist/chunk-YYYXRJUW.js +101 -0
- package/dist/chunk-ZM2IMMYN.js +76 -0
- package/dist/chunk-ZMYPLFG3.js +71 -0
- package/dist/chunk-ZNA27WEV.js +470 -0
- package/dist/{cli-EFJIG2VT.js → cli-NHUXABYH.js} +597 -965
- package/dist/{paths-D2VGWWFI.js → cli-build-K56DK4DS.js} +1 -1
- package/dist/config-XVJYZ4IQ.js +9 -0
- package/dist/connect-cmd-OOG4TPU7.js +16 -0
- package/dist/context-adopt-UMA4O5NY.js +105 -0
- package/dist/context-materialize-G2FUFC72.js +19 -0
- package/dist/dist-RW4UPPC2.js +6 -0
- package/dist/docker-NEGDLU6D.js +7 -0
- package/dist/doctor-53F2PYY7.js +43 -0
- package/dist/doctor-UFVL4PZY.js +426 -0
- package/dist/{emit-artifact-cmd-KPPD3YLO.js → emit-artifact-cmd-KTYW2TN2.js} +25 -19
- package/dist/emit-cmd-DCERAU27.js +9 -0
- package/dist/emit-criteria-cmd-VAUUSAYD.js +166 -0
- package/dist/{emit-finding-cmd-VR5VEGXJ.js → emit-finding-cmd-UR4ID45Z.js} +35 -30
- package/dist/{emit-result-cmd-YOA5BJKL.js → emit-result-cmd-FDTUKGKE.js} +35 -61
- package/dist/exec-client-4XGXV3XN.js +8 -0
- package/dist/guest-init-GENRHNP7.js +8 -0
- package/dist/hook-fast-EYENPK6F.js +9 -0
- package/dist/{hook-wrap-fast-KXYNX3AD.js → hook-wrap-fast-NPLHJXFK.js} +2 -2
- package/dist/host-key-KDYZ5ECC.js +7 -0
- package/dist/import-capture-cmd-AVZ4VIVJ.js +68 -0
- package/dist/{import-ruler-cmd-7LH2QOMG.js → import-ruler-cmd-GUHL6IY5.js} +1 -1
- package/dist/index.js +4 -4
- package/dist/init-DXBCOAJK.js +36 -0
- package/dist/init-YEXK35CF.js +221 -0
- package/dist/init-cmd-NHR7PRSQ.js +135 -0
- package/dist/install-cmd-7WXOIFDO.js +55 -0
- package/dist/lima-XN65D7GN.js +55 -0
- package/dist/login-browser-7XGSV7MA.js +10 -0
- package/dist/{config-POF7DEQW.js → logout-cmd-QAUFDJ6J.js} +3 -1
- package/dist/{logs-TRNPQM42.js → logs-7RYUH5A6.js} +1 -1
- package/dist/loop-VZOLL4WQ.js +43 -0
- package/dist/machine-WSG52J75.js +35 -0
- package/dist/mcp-install-cmd-RLK4SO3N.js +9 -0
- package/dist/{mcp-serve-cmd-57EZZOTL.js → mcp-serve-cmd-JPTP5FMS.js} +20 -9
- package/dist/paths-OYKMVYJP.js +6 -0
- package/dist/{pidfile-PTW76F56.js → pidfile-UZRH774M.js} +2 -3
- package/dist/real-deps-SU24ZA2K.js +21 -0
- package/dist/relay-L76HDX72.js +46 -0
- package/dist/settings-J2652U5N.js +7 -0
- package/dist/starter-pack-LIZYMKYQ.js +10 -0
- package/dist/{status-JHVSZYC5.js → status-2UZKKNB7.js} +31 -12
- package/dist/{statusline-fast-3C5OXHDD.js → statusline-fast-SVTMBMD7.js} +3 -2
- package/dist/sync-cmd-VPPYCNNM.js +28 -0
- package/dist/version-BWM6VLDI.js +6 -0
- package/dist/{watch-NRLXJUST.js → watch-5C4ZBBGO.js} +20 -7
- package/dist/{work-claim-cmd-HXB7K27H.js → work-claim-cmd-LSO2B2EX.js} +34 -19
- package/dist/work-cmd-UOQO2AD4.js +17 -0
- package/dist/work-comment-cmd-WF3EOLAE.js +106 -0
- package/dist/{work-launch-YNNCKIH3.js → work-launch-YI4CJDAP.js} +2 -1
- package/dist/work-open-pr-cmd-4SSQZMYG.js +156 -0
- package/dist/work-pr-cmd-6AN6RRQJ.js +16 -0
- package/package.json +13 -3
- package/skill-pack/maintained/amend/SKILL.md +104 -0
- package/skill-pack/maintained/emitting-evidence/SKILL.md +99 -0
- package/skill-pack/maintained/emitting-evidence/references/agents-snippet.md +20 -0
- package/skill-pack/maintained/outerlayer/SKILL.md +55 -0
- package/skill-pack/maintained/reporting-findings/SKILL.md +148 -0
- package/skill-pack/template/build/SKILL.md +193 -0
- package/skill-pack/template/build/references/agent-briefs.md +243 -0
- package/skill-pack/template/build/references/criteria-judge.md +91 -0
- package/skill-pack/template/build/references/evidence.md +42 -0
- package/skill-pack/template/build/references/release.md +74 -0
- package/skill-pack/template/build/references/review-briefs.md +275 -0
- package/skill-pack/template/build/references/review-loop.md +158 -0
- package/skill-pack/template/build/scripts/record-criteria.mjs +235 -0
- package/skill-pack/template/spec/SKILL.md +84 -0
- package/skill-pack/template/writing-specs/SKILL.md +134 -0
- package/dist/chunk-JJP7YLMN.js +0 -25
- package/dist/chunk-KKEU6FFR.js +0 -589
- package/dist/chunk-OZ7C3XUE.js +0 -34
- package/dist/chunk-WQ6VGRGZ.js +0 -150
- package/dist/emit-commit-credit-cmd-656BRAQ4.js +0 -121
- package/dist/hook-fast-I2XTHDE6.js +0 -8
- package/dist/import-capture-cmd-EUMBGIV3.js +0 -176
- package/dist/init-PTBITAUO.js +0 -103
- package/dist/login-cmd-IRX6LZT7.js +0 -62
- package/dist/loop-BWE2BS6J.js +0 -646
- package/dist/sync-cmd-S7Q6DWU3.js +0 -15
- package/dist/work-cmd-ABP6XDBP.js +0 -16
|
@@ -1,14 +1,27 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import { staleBuildRefusal, staleBuildWarning
|
|
3
|
+
import { staleBuildRefusal, staleBuildWarning } from './chunk-3YPKXE5L.js';
|
|
4
|
+
import { detectCi } from './chunk-HE2D4EY5.js';
|
|
5
|
+
import { launchRefusalForSession } from './chunk-BCJNHMZT.js';
|
|
6
|
+
import './chunk-TBT347UY.js';
|
|
7
|
+
import './chunk-F7CU5ABH.js';
|
|
8
|
+
import './chunk-BKO6JEZI.js';
|
|
9
|
+
import { detectActiveSession } from './chunk-BFESLKPP.js';
|
|
10
|
+
import { readEffectiveArtifactSpoolState, localArtifactIds, isArtifactTombstoned, artifactBlobsDir, appendArtifactRecord, artifactsSpoolPath, findPendingArtifactRecord, appendArtifactTombstone } from './chunk-6Y63SXFO.js';
|
|
11
|
+
import { ARTIFACT_MAX_CAPTION_LENGTH, ArtifactCriterionIdSchema, ARTIFACT_MAX_FILENAME_LENGTH, mediaTypeForArtifactPath, inferArtifactKind, resolveRepoIdentity, ARTIFACT_MAX_REPLACES_TARGETS } from './chunk-G7FSV7JX.js';
|
|
4
12
|
import './chunk-YRYMNBGQ.js';
|
|
5
|
-
import
|
|
13
|
+
import './chunk-DVDEBNQJ.js';
|
|
14
|
+
import { parseTrackerNumber, trackerNumberError } from './chunk-WZBHBH3J.js';
|
|
15
|
+
import './chunk-5QRP3MVS.js';
|
|
6
16
|
import './chunk-ZJSNLVCE.js';
|
|
7
|
-
import './chunk-
|
|
8
|
-
import './chunk-
|
|
9
|
-
import './chunk-
|
|
10
|
-
import './chunk-
|
|
11
|
-
import
|
|
17
|
+
import { defaultFetch } from './chunk-BCLJSQCV.js';
|
|
18
|
+
import { resolveGatewayCredentials, unauthorizedMessage } from './chunk-BOLTI6LR.js';
|
|
19
|
+
import './chunk-EABW6AJQ.js';
|
|
20
|
+
import './chunk-M5POMKKW.js';
|
|
21
|
+
import './chunk-ZM2IMMYN.js';
|
|
22
|
+
import './chunk-UFFXNXLQ.js';
|
|
23
|
+
import './chunk-XCCLFVXM.js';
|
|
24
|
+
import './chunk-BJ3KTMDH.js';
|
|
12
25
|
import { homeFromEnv } from './chunk-VNVZDWO3.js';
|
|
13
26
|
import './chunk-Z5GEFMRW.js';
|
|
14
27
|
import { createHash, randomUUID } from 'crypto';
|
|
@@ -249,16 +262,9 @@ async function runEmitArtifact(opts) {
|
|
|
249
262
|
"nothing to attach this to \u2014 no recorded session, no PR, and no git repo. Run inside a recorded Claude Code session, from a git checkout, in CI with PR context, or pass --pr <number>."
|
|
250
263
|
);
|
|
251
264
|
}
|
|
252
|
-
const
|
|
253
|
-
|
|
254
|
-
const
|
|
255
|
-
const appId = opts.appId ?? env.OUTERLAYER_APP_ID ?? fileConfig.appId;
|
|
256
|
-
if (!url || !apiKey || !appId) {
|
|
257
|
-
const missing = [!url && "--url", !apiKey && "--api-key", !appId && "--app-id"].filter(Boolean).join(", ");
|
|
258
|
-
throw new EmitArtifactError(
|
|
259
|
-
`missing ${missing}. Run \`outerlayer login --url <your gateway>\` and paste the key at the prompt, or set OUTERLAYER_URL / OUTERLAYER_API_KEY / OUTERLAYER_APP_ID. Mint a key in the dashboard: Settings \u2192 API keys.`
|
|
260
|
-
);
|
|
261
|
-
}
|
|
265
|
+
const resolved = resolveGatewayCredentials({ ...opts, home, env });
|
|
266
|
+
if (!resolved.ok) throw new EmitArtifactError(resolved.message);
|
|
267
|
+
const { url, credential: apiKey, appId } = resolved;
|
|
262
268
|
const clientArtifactId = randomUUID();
|
|
263
269
|
const singleTarget = replacesTargets !== void 0 && replacesTargets.length === 1 ? replacesTargets[0] : void 0;
|
|
264
270
|
const targetPendingLocally = singleTarget !== void 0 && findPendingArtifactRecord(singleTarget, home) !== void 0;
|
|
@@ -285,7 +291,7 @@ async function runEmitArtifact(opts) {
|
|
|
285
291
|
},
|
|
286
292
|
blob: { data: bytes.toString("base64") }
|
|
287
293
|
};
|
|
288
|
-
const fetchImpl = opts.fetchImpl ??
|
|
294
|
+
const fetchImpl = opts.fetchImpl ?? defaultFetch;
|
|
289
295
|
const endpoint = new URL("/v1/artifacts", url).toString();
|
|
290
296
|
let response;
|
|
291
297
|
try {
|
|
@@ -303,7 +309,7 @@ async function runEmitArtifact(opts) {
|
|
|
303
309
|
}
|
|
304
310
|
if (response.status === 401) {
|
|
305
311
|
throw new EmitArtifactError(
|
|
306
|
-
|
|
312
|
+
unauthorizedMessage(apiKey)
|
|
307
313
|
);
|
|
308
314
|
}
|
|
309
315
|
if (!response.ok) {
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
export { EmitError, runEmit } from './chunk-H5NCNVDA.js';
|
|
4
|
+
import './chunk-WO2BXCTQ.js';
|
|
5
|
+
import './chunk-EMY4I27X.js';
|
|
6
|
+
import './chunk-RA3O54FC.js';
|
|
7
|
+
import './chunk-Z5GEFMRW.js';
|
|
8
|
+
|
|
9
|
+
createRequire(import.meta.url);
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
import { launchRefusalForSession } from './chunk-BCJNHMZT.js';
|
|
4
|
+
import { detectActiveSession } from './chunk-BFESLKPP.js';
|
|
5
|
+
import { resolveRepoIdentity, CriteriaListSchema } from './chunk-G7FSV7JX.js';
|
|
6
|
+
import { launchedItemForSession } from './chunk-DVDEBNQJ.js';
|
|
7
|
+
import { parseTrackerNumber, trackerNumberError } from './chunk-WZBHBH3J.js';
|
|
8
|
+
import { defaultFetch } from './chunk-BCLJSQCV.js';
|
|
9
|
+
import { resolveGatewayCredentials, unauthorizedMessage } from './chunk-BOLTI6LR.js';
|
|
10
|
+
import './chunk-EABW6AJQ.js';
|
|
11
|
+
import './chunk-M5POMKKW.js';
|
|
12
|
+
import './chunk-ZM2IMMYN.js';
|
|
13
|
+
import './chunk-BJ3KTMDH.js';
|
|
14
|
+
import { homeFromEnv } from './chunk-VNVZDWO3.js';
|
|
15
|
+
import './chunk-Z5GEFMRW.js';
|
|
16
|
+
import { readFileSync } from 'fs';
|
|
17
|
+
|
|
18
|
+
createRequire(import.meta.url);
|
|
19
|
+
var GREEN = "\x1B[32m";
|
|
20
|
+
var DIM = "\x1B[2m";
|
|
21
|
+
var RESET = "\x1B[0m";
|
|
22
|
+
var EmitCriteriaError = class extends Error {
|
|
23
|
+
};
|
|
24
|
+
var REPLACE_REFUSED_MESSAGE = "this item already has a recorded list, and a person must replace it. Run the command yourself, outside the session, with your own login. A repository's .outerlayer/policy.yaml can let sessions replace it with `criteria: { replace: anyone }`.";
|
|
25
|
+
async function readAllStdin() {
|
|
26
|
+
const chunks = [];
|
|
27
|
+
for await (const chunk of process.stdin) chunks.push(Buffer.from(chunk));
|
|
28
|
+
return Buffer.concat(chunks).toString("utf8");
|
|
29
|
+
}
|
|
30
|
+
function valueAt(raw, path) {
|
|
31
|
+
let current = raw;
|
|
32
|
+
for (const key of path) current = current?.[key];
|
|
33
|
+
return current;
|
|
34
|
+
}
|
|
35
|
+
function describeIssue(raw, issue) {
|
|
36
|
+
const where = issue.path.join(".");
|
|
37
|
+
if (issue.code === "custom") return `${where}: ${issue.message}`;
|
|
38
|
+
const value = valueAt(raw, issue.path);
|
|
39
|
+
const leaf = issue.path[issue.path.length - 1];
|
|
40
|
+
if ((leaf === "id" || leaf === "proof") && value !== void 0) {
|
|
41
|
+
return `${where}: ${JSON.stringify(value)} is not accepted (${issue.message})`;
|
|
42
|
+
}
|
|
43
|
+
return `${where}: ${issue.message}`;
|
|
44
|
+
}
|
|
45
|
+
function parseFile(raw) {
|
|
46
|
+
const parsed = CriteriaListSchema.safeParse(raw);
|
|
47
|
+
if (parsed.success) return parsed.data;
|
|
48
|
+
const issue = parsed.error.issues[0];
|
|
49
|
+
throw new EmitCriteriaError(
|
|
50
|
+
`invalid criteria list \u2014 ${issue ? describeIssue(raw, issue) : "malformed"}`
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
function resolveTarget(opts) {
|
|
54
|
+
let item;
|
|
55
|
+
if (opts.item !== void 0) {
|
|
56
|
+
const number = parseTrackerNumber(opts.item);
|
|
57
|
+
if (number === void 0) throw new EmitCriteriaError(trackerNumberError("--item", opts.item));
|
|
58
|
+
item = { number };
|
|
59
|
+
}
|
|
60
|
+
const { sessionId } = opts;
|
|
61
|
+
if (sessionId !== void 0) {
|
|
62
|
+
const refusal = launchRefusalForSession(sessionId, opts.home);
|
|
63
|
+
if (refusal !== void 0) throw new EmitCriteriaError(refusal);
|
|
64
|
+
}
|
|
65
|
+
if (item !== void 0) return sessionId !== void 0 ? { item, sessionId } : { item };
|
|
66
|
+
if (sessionId === void 0) {
|
|
67
|
+
throw new EmitCriteriaError(
|
|
68
|
+
"nothing to record this on \u2014 no work item. Pass --item <number>, or run inside a recorded session launched with OUTERLAYER_WORK \u2014 its own launch record names the item automatically."
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
const launched = launchedItemForSession(sessionId, opts.home);
|
|
72
|
+
if (launched === void 0) {
|
|
73
|
+
throw new EmitCriteriaError(
|
|
74
|
+
"nothing to record this on \u2014 no work item. Pass --item <number>; this recorded session's own launch record names no item either."
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
return { item: { number: launched }, sessionId };
|
|
78
|
+
}
|
|
79
|
+
async function errorCode(response) {
|
|
80
|
+
let text = "";
|
|
81
|
+
try {
|
|
82
|
+
text = await response.text();
|
|
83
|
+
} catch {
|
|
84
|
+
}
|
|
85
|
+
let code = null;
|
|
86
|
+
try {
|
|
87
|
+
const parsed = JSON.parse(text);
|
|
88
|
+
if (typeof parsed.error?.code === "string") code = parsed.error.code;
|
|
89
|
+
} catch {
|
|
90
|
+
}
|
|
91
|
+
return { code, detail: text.replace(/\s+/g, " ").trim().slice(0, 160) };
|
|
92
|
+
}
|
|
93
|
+
async function runEmitCriteria(opts) {
|
|
94
|
+
const cwd = opts.cwd ?? process.cwd();
|
|
95
|
+
const home = opts.home ?? homeFromEnv();
|
|
96
|
+
const env = opts.env ?? process.env;
|
|
97
|
+
const now = opts.now ?? (() => /* @__PURE__ */ new Date());
|
|
98
|
+
let text;
|
|
99
|
+
if (opts.file === "-") {
|
|
100
|
+
text = await (opts.readStdin ?? readAllStdin)();
|
|
101
|
+
} else {
|
|
102
|
+
try {
|
|
103
|
+
text = readFileSync(opts.file, "utf8");
|
|
104
|
+
} catch (err) {
|
|
105
|
+
throw new EmitCriteriaError(`cannot read "${opts.file}": ${String(err)}`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
let raw;
|
|
109
|
+
try {
|
|
110
|
+
raw = JSON.parse(text);
|
|
111
|
+
} catch (err) {
|
|
112
|
+
throw new EmitCriteriaError(`"${opts.file}" is not valid JSON: ${String(err)}`);
|
|
113
|
+
}
|
|
114
|
+
const list = parseFile(raw);
|
|
115
|
+
const identity = resolveRepoIdentity(cwd);
|
|
116
|
+
const sessionId = detectActiveSession({
|
|
117
|
+
env,
|
|
118
|
+
home,
|
|
119
|
+
cwds: identity.repoRoot !== void 0 ? [identity.repoRoot, cwd] : [cwd],
|
|
120
|
+
nowMs: now().getTime()
|
|
121
|
+
});
|
|
122
|
+
const target = resolveTarget({ item: opts.item, sessionId, home });
|
|
123
|
+
const resolved = resolveGatewayCredentials({ url: opts.url, apiKey: opts.apiKey, appId: opts.appId, cwd, home, env });
|
|
124
|
+
if (!resolved.ok) throw new EmitCriteriaError(resolved.message);
|
|
125
|
+
const { url, credential: apiKey, appId } = resolved;
|
|
126
|
+
const request = {
|
|
127
|
+
...list,
|
|
128
|
+
item: target.item,
|
|
129
|
+
...target.sessionId !== void 0 ? { sessionId: target.sessionId } : {}
|
|
130
|
+
};
|
|
131
|
+
const endpoint = new URL("/v1/criteria", url).toString();
|
|
132
|
+
const fetchImpl = opts.fetchImpl ?? defaultFetch;
|
|
133
|
+
let response;
|
|
134
|
+
try {
|
|
135
|
+
response = await fetchImpl(endpoint, {
|
|
136
|
+
method: "POST",
|
|
137
|
+
headers: {
|
|
138
|
+
"content-type": "application/json",
|
|
139
|
+
authorization: `Bearer ${apiKey}`,
|
|
140
|
+
"x-outerlayer-app-id": appId
|
|
141
|
+
},
|
|
142
|
+
body: JSON.stringify(request)
|
|
143
|
+
});
|
|
144
|
+
} catch (err) {
|
|
145
|
+
throw new EmitCriteriaError(`network error reaching ${endpoint}: ${String(err)}`);
|
|
146
|
+
}
|
|
147
|
+
if (response.status === 401) throw new EmitCriteriaError(unauthorizedMessage(apiKey));
|
|
148
|
+
if (!response.ok) {
|
|
149
|
+
const { code, detail } = await errorCode(response);
|
|
150
|
+
if (response.status === 409 && code === "criteria_replace_refused") {
|
|
151
|
+
throw new EmitCriteriaError(`refused (409): ${REPLACE_REFUSED_MESSAGE}`);
|
|
152
|
+
}
|
|
153
|
+
throw new EmitCriteriaError(`emit failed (${response.status})${detail ? `: ${detail}` : ""}`);
|
|
154
|
+
}
|
|
155
|
+
let data = {};
|
|
156
|
+
try {
|
|
157
|
+
data = (await response.json()).data ?? {};
|
|
158
|
+
} catch {
|
|
159
|
+
}
|
|
160
|
+
const count = typeof data.count === "number" ? data.count : list.criteria.length;
|
|
161
|
+
const output = opts.json ? JSON.stringify(data) : `${GREEN}\u2713${RESET} recorded ${count} ${count === 1 ? "criterion" : "criteria"} ${DIM}\xB7${RESET} item #${target.item.number}`;
|
|
162
|
+
if (!opts.quiet) process.stdout.write(output + "\n");
|
|
163
|
+
return { data, output, exitCode: 0 };
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export { EmitCriteriaError, runEmitCriteria };
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import {
|
|
4
|
-
import './chunk-
|
|
5
|
-
import {
|
|
3
|
+
import { launchRefusalForSession } from './chunk-BCJNHMZT.js';
|
|
4
|
+
import { detectActiveSession } from './chunk-BFESLKPP.js';
|
|
5
|
+
import { FindingBatchSchema, resolveRepoIdentity } from './chunk-G7FSV7JX.js';
|
|
6
|
+
import { launchedItemForSession } from './chunk-DVDEBNQJ.js';
|
|
7
|
+
import { parseTrackerNumber, trackerNumberError } from './chunk-WZBHBH3J.js';
|
|
6
8
|
import { readLatestProvenanceForSession } from './chunk-ZJSNLVCE.js';
|
|
7
|
-
import './chunk-
|
|
8
|
-
import './chunk-
|
|
9
|
-
import './chunk-
|
|
10
|
-
import './chunk-
|
|
11
|
-
import
|
|
9
|
+
import { defaultFetch } from './chunk-BCLJSQCV.js';
|
|
10
|
+
import { resolveGatewayCredentials, unauthorizedMessage } from './chunk-BOLTI6LR.js';
|
|
11
|
+
import './chunk-EABW6AJQ.js';
|
|
12
|
+
import './chunk-M5POMKKW.js';
|
|
13
|
+
import './chunk-ZM2IMMYN.js';
|
|
14
|
+
import './chunk-BJ3KTMDH.js';
|
|
12
15
|
import { homeFromEnv } from './chunk-VNVZDWO3.js';
|
|
13
16
|
import './chunk-Z5GEFMRW.js';
|
|
14
17
|
import { readFileSync } from 'fs';
|
|
@@ -19,6 +22,14 @@ var DIM = "\x1B[2m";
|
|
|
19
22
|
var RESET = "\x1B[0m";
|
|
20
23
|
var EmitFindingError = class extends Error {
|
|
21
24
|
};
|
|
25
|
+
var REMOVED_FINDING_FLAGS = ["subject", "kind", "severity", "verdict", "fixed", "source"];
|
|
26
|
+
function refuseRemovedFindingFlags(opts) {
|
|
27
|
+
const used = REMOVED_FINDING_FLAGS.find((flag) => opts[flag] !== void 0);
|
|
28
|
+
if (used === void 0) return;
|
|
29
|
+
throw new EmitFindingError(
|
|
30
|
+
`--${used} is no longer accepted: findings record problems in the factory, not review verdicts. Pass --category <context|flaky-test|tooling|environment|defect|other> instead.`
|
|
31
|
+
);
|
|
32
|
+
}
|
|
22
33
|
function parseItemFlag(raw) {
|
|
23
34
|
if (raw === void 0) return void 0;
|
|
24
35
|
const number = parseTrackerNumber(raw);
|
|
@@ -48,23 +59,19 @@ function recordFromFlags(opts) {
|
|
|
48
59
|
const ruleLine = parseIntFlag(opts.ruleLine, "--rule-line", { min: 1 });
|
|
49
60
|
const turnIndex = parseIntFlag(opts.turn, "--turn", { min: 0 });
|
|
50
61
|
const round = parseIntFlag(opts.round, "--round", { min: 0 });
|
|
62
|
+
const hasRule = opts.rulePath !== void 0 || opts.ruleQuote !== void 0 || opts.ruleRelation !== void 0 || ruleLine !== void 0;
|
|
51
63
|
return {
|
|
52
64
|
id: opts.id,
|
|
53
|
-
|
|
65
|
+
category: opts.category,
|
|
54
66
|
title: opts.title,
|
|
55
67
|
file: opts.file,
|
|
56
68
|
line: line ?? null,
|
|
57
|
-
|
|
58
|
-
kind: opts.kind,
|
|
59
|
-
verdict: opts.verdict,
|
|
60
|
-
fixed: opts.fixed ?? false,
|
|
61
|
-
rule: opts.rulePath !== void 0 ? {
|
|
69
|
+
rule: hasRule ? {
|
|
62
70
|
path: opts.rulePath,
|
|
63
71
|
line: ruleLine ?? null,
|
|
64
|
-
quote: opts.ruleQuote
|
|
72
|
+
...opts.ruleQuote !== void 0 ? { quote: opts.ruleQuote } : {},
|
|
65
73
|
relation: opts.ruleRelation
|
|
66
74
|
} : null,
|
|
67
|
-
source: opts.source,
|
|
68
75
|
where: {
|
|
69
76
|
label: opts.where,
|
|
70
77
|
...opts.traceId !== void 0 ? { traceId: opts.traceId } : {},
|
|
@@ -110,22 +117,15 @@ function resolveUploadTarget(opts) {
|
|
|
110
117
|
return { item: { number: launchedNumber }, sessionId };
|
|
111
118
|
}
|
|
112
119
|
async function upload(batch, target, opts) {
|
|
113
|
-
const
|
|
114
|
-
|
|
115
|
-
const
|
|
116
|
-
const appId = opts.appId ?? opts.env.OUTERLAYER_APP_ID ?? fileConfig.appId;
|
|
117
|
-
if (!url || !apiKey || !appId) {
|
|
118
|
-
const missing = [!url && "--url", !apiKey && "--api-key", !appId && "--app-id"].filter(Boolean).join(", ");
|
|
119
|
-
throw new EmitFindingError(
|
|
120
|
-
`missing ${missing}. Run \`outerlayer login --url <your gateway>\` and paste the key at the prompt, or set OUTERLAYER_URL / OUTERLAYER_API_KEY / OUTERLAYER_APP_ID. Mint a key in the dashboard: Settings \u2192 API keys.`
|
|
121
|
-
);
|
|
122
|
-
}
|
|
120
|
+
const resolved = resolveGatewayCredentials(opts);
|
|
121
|
+
if (!resolved.ok) throw new EmitFindingError(resolved.message);
|
|
122
|
+
const { url, credential: apiKey, appId } = resolved;
|
|
123
123
|
const request = {
|
|
124
124
|
...batch,
|
|
125
125
|
item: target.item,
|
|
126
126
|
...target.sessionId !== void 0 ? { sessionId: target.sessionId } : {}
|
|
127
127
|
};
|
|
128
|
-
const fetchImpl = opts.fetchImpl ??
|
|
128
|
+
const fetchImpl = opts.fetchImpl ?? defaultFetch;
|
|
129
129
|
const endpoint = new URL("/v1/findings", url).toString();
|
|
130
130
|
let response;
|
|
131
131
|
try {
|
|
@@ -143,7 +143,7 @@ async function upload(batch, target, opts) {
|
|
|
143
143
|
}
|
|
144
144
|
if (response.status === 401) {
|
|
145
145
|
throw new EmitFindingError(
|
|
146
|
-
|
|
146
|
+
unauthorizedMessage(apiKey)
|
|
147
147
|
);
|
|
148
148
|
}
|
|
149
149
|
if (!response.ok) {
|
|
@@ -172,7 +172,7 @@ async function runEmitFinding(opts) {
|
|
|
172
172
|
const sessionId = detectUploadSessionId({ cwd, home, env, now });
|
|
173
173
|
const contextSourceSha = opts.contextSourceSha ?? (sessionId !== void 0 ? readLatestProvenanceForSession(sessionId, home)?.sha ?? void 0 : void 0);
|
|
174
174
|
const rawBatch = {
|
|
175
|
-
schemaVersion:
|
|
175
|
+
schemaVersion: 2,
|
|
176
176
|
...opts.headSha !== void 0 ? { headSha: opts.headSha } : {},
|
|
177
177
|
...contextSourceSha !== void 0 ? { contextSourceSha } : {},
|
|
178
178
|
findings: [recordFromFlags(opts)]
|
|
@@ -214,6 +214,11 @@ async function runEmitFindings(opts) {
|
|
|
214
214
|
} catch (err) {
|
|
215
215
|
throw new EmitFindingError(`"${opts.file}" is not valid JSON: ${String(err)}`);
|
|
216
216
|
}
|
|
217
|
+
if (typeof raw === "object" && raw !== null && raw.schemaVersion === 1) {
|
|
218
|
+
throw new EmitFindingError(
|
|
219
|
+
`"${opts.file}" uses schemaVersion 1, which is no longer accepted. Use schemaVersion 2: each finding takes a category (context, flaky-test, tooling, environment, defect or other) in place of subject, kind, severity, verdict, fixed and source.`
|
|
220
|
+
);
|
|
221
|
+
}
|
|
217
222
|
const parsed = FindingBatchSchema.safeParse(raw);
|
|
218
223
|
if (!parsed.success) {
|
|
219
224
|
throw new EmitFindingError(`invalid finding batch \u2014 ${firstIssueMessage(parsed)}`);
|
|
@@ -232,4 +237,4 @@ async function runEmitFindings(opts) {
|
|
|
232
237
|
});
|
|
233
238
|
}
|
|
234
239
|
|
|
235
|
-
export { EmitFindingError, runEmitFinding, runEmitFindings };
|
|
240
|
+
export { EmitFindingError, refuseRemovedFindingFlags, runEmitFinding, runEmitFindings };
|
|
@@ -1,14 +1,27 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import
|
|
3
|
+
import './chunk-3YPKXE5L.js';
|
|
4
|
+
import { detectCi } from './chunk-HE2D4EY5.js';
|
|
5
|
+
import { launchRefusalForSession } from './chunk-BCJNHMZT.js';
|
|
6
|
+
import './chunk-TBT347UY.js';
|
|
7
|
+
import './chunk-F7CU5ABH.js';
|
|
8
|
+
import './chunk-BKO6JEZI.js';
|
|
9
|
+
import { detectActiveSession } from './chunk-BFESLKPP.js';
|
|
10
|
+
import './chunk-6Y63SXFO.js';
|
|
11
|
+
import { EmittedNameSchema, EMITTED_RESULT_MAX_LINK_LENGTH, EMITTED_RESULTS, EMITTED_RESULT_MAX_BODY_LENGTH, resolveRepoIdentity } from './chunk-G7FSV7JX.js';
|
|
4
12
|
import './chunk-YRYMNBGQ.js';
|
|
5
|
-
import
|
|
13
|
+
import './chunk-DVDEBNQJ.js';
|
|
14
|
+
import { parseTrackerNumber, trackerNumberError } from './chunk-WZBHBH3J.js';
|
|
15
|
+
import './chunk-5QRP3MVS.js';
|
|
6
16
|
import './chunk-ZJSNLVCE.js';
|
|
7
|
-
import './chunk-
|
|
8
|
-
import './chunk-
|
|
9
|
-
import './chunk-
|
|
10
|
-
import './chunk-
|
|
11
|
-
import
|
|
17
|
+
import { defaultFetch } from './chunk-BCLJSQCV.js';
|
|
18
|
+
import { resolveGatewayCredentials, unauthorizedMessage } from './chunk-BOLTI6LR.js';
|
|
19
|
+
import './chunk-EABW6AJQ.js';
|
|
20
|
+
import './chunk-M5POMKKW.js';
|
|
21
|
+
import './chunk-ZM2IMMYN.js';
|
|
22
|
+
import './chunk-UFFXNXLQ.js';
|
|
23
|
+
import './chunk-XCCLFVXM.js';
|
|
24
|
+
import './chunk-BJ3KTMDH.js';
|
|
12
25
|
import { homeFromEnv } from './chunk-VNVZDWO3.js';
|
|
13
26
|
import './chunk-Z5GEFMRW.js';
|
|
14
27
|
import { randomUUID } from 'crypto';
|
|
@@ -51,23 +64,7 @@ async function runEmitResult(opts) {
|
|
|
51
64
|
`invalid name "${opts.name}" \u2014 an emit name is 1-64 characters: a lowercase letter followed by lowercase letters, digits, ".", "_" or "-" (e.g. smoke.pass)`
|
|
52
65
|
);
|
|
53
66
|
}
|
|
54
|
-
const isArtifactReview = opts.name === ARTIFACT_REVIEW_CHECK_NAME;
|
|
55
|
-
const artifactId = opts.artifact === "" ? void 0 : opts.artifact;
|
|
56
|
-
if (isArtifactReview) {
|
|
57
|
-
if (artifactId === void 0) {
|
|
58
|
-
throw new EmitResultError(
|
|
59
|
-
`--artifact <id> is required for ${ARTIFACT_REVIEW_CHECK_NAME} \u2014 it names which artifact this verdict is on`
|
|
60
|
-
);
|
|
61
|
-
}
|
|
62
|
-
} else if (artifactId !== void 0) {
|
|
63
|
-
throw new EmitResultError(`--artifact is only accepted with ${ARTIFACT_REVIEW_CHECK_NAME}`);
|
|
64
|
-
}
|
|
65
67
|
const link = opts.link === "" ? void 0 : opts.link;
|
|
66
|
-
if (isArtifactReview && link !== void 0) {
|
|
67
|
-
throw new EmitResultError(
|
|
68
|
-
`--link is refused for ${ARTIFACT_REVIEW_CHECK_NAME} \u2014 an artifact verdict is a judgment on evidence already on file, never a run to point at; pass --body / --body-file instead`
|
|
69
|
-
);
|
|
70
|
-
}
|
|
71
68
|
if (link !== void 0) {
|
|
72
69
|
if (!link.startsWith("http://") && !link.startsWith("https://")) {
|
|
73
70
|
throw new EmitResultError(`invalid --link "${link}" \u2014 expected an http:// or https:// URL`);
|
|
@@ -98,8 +95,6 @@ async function runEmitResult(opts) {
|
|
|
98
95
|
body = opts.body;
|
|
99
96
|
} else if (opts.bodyFile !== void 0) {
|
|
100
97
|
body = await readBodyFile(opts.bodyFile, opts.readStdin);
|
|
101
|
-
} else if (isArtifactReview && result === "fail") {
|
|
102
|
-
body = await (opts.readStdin ?? readAllStdin)();
|
|
103
98
|
}
|
|
104
99
|
if (body !== void 0) {
|
|
105
100
|
body = body.trim();
|
|
@@ -114,13 +109,7 @@ async function runEmitResult(opts) {
|
|
|
114
109
|
);
|
|
115
110
|
}
|
|
116
111
|
}
|
|
117
|
-
if (
|
|
118
|
-
if (result === "fail" && body === void 0) {
|
|
119
|
-
throw new EmitResultError(
|
|
120
|
-
`a failing artifact verdict needs a sentence \u2014 pass --body or --body-file with one sentence saying what is wrong`
|
|
121
|
-
);
|
|
122
|
-
}
|
|
123
|
-
} else if (result === "fail" && link === void 0 && body === void 0) {
|
|
112
|
+
if (result === "fail" && link === void 0 && body === void 0) {
|
|
124
113
|
throw new EmitResultError(
|
|
125
114
|
`a failing check needs something to act on \u2014 pass --link with the run URL, or --body / --body-file with one sentence saying what is wrong`
|
|
126
115
|
);
|
|
@@ -133,37 +122,23 @@ async function runEmitResult(opts) {
|
|
|
133
122
|
cwds: identity.repoRoot !== void 0 ? [identity.repoRoot, cwd] : [cwd],
|
|
134
123
|
nowMs: now().getTime()
|
|
135
124
|
});
|
|
136
|
-
if (
|
|
125
|
+
if (item === void 0 && sessionId === void 0) {
|
|
137
126
|
throw new EmitResultError(
|
|
138
|
-
"
|
|
127
|
+
"nothing to attach this to \u2014 no work item. Pass --item <number>; a recorded session alone does not name one."
|
|
139
128
|
);
|
|
140
129
|
}
|
|
141
|
-
if (
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
"nothing to attach this to \u2014 no work item. Pass --item <number>; a recorded session alone does not name one, and a session with no --item is always refused as self-judgment."
|
|
145
|
-
);
|
|
146
|
-
}
|
|
147
|
-
if (sessionId !== void 0) {
|
|
148
|
-
const refusal = launchRefusalForSession(sessionId, home);
|
|
149
|
-
if (refusal !== void 0) throw new EmitResultError(refusal);
|
|
150
|
-
}
|
|
151
|
-
if (item === void 0 && sessionId !== void 0) {
|
|
152
|
-
throw new EmitResultError(
|
|
153
|
-
"a session records a check only on a work item it was not launched for, named with --item \u2014 the item this session was launched for needs a machine key (an API key run outside the recorded session) or CI."
|
|
154
|
-
);
|
|
155
|
-
}
|
|
130
|
+
if (sessionId !== void 0) {
|
|
131
|
+
const refusal = launchRefusalForSession(sessionId, home);
|
|
132
|
+
if (refusal !== void 0) throw new EmitResultError(refusal);
|
|
156
133
|
}
|
|
157
|
-
|
|
158
|
-
const url = opts.url ?? env.OUTERLAYER_URL ?? fileConfig.url;
|
|
159
|
-
const apiKey = opts.apiKey ?? env.OUTERLAYER_API_KEY ?? fileConfig.apiKey;
|
|
160
|
-
const appId = opts.appId ?? env.OUTERLAYER_APP_ID ?? fileConfig.appId;
|
|
161
|
-
if (!url || !apiKey || !appId) {
|
|
162
|
-
const missing = [!url && "--url", !apiKey && "--api-key", !appId && "--app-id"].filter(Boolean).join(", ");
|
|
134
|
+
if (item === void 0) {
|
|
163
135
|
throw new EmitResultError(
|
|
164
|
-
|
|
136
|
+
"nothing to attach this to \u2014 no work item. Pass --item <number>; a recorded session alone does not name one."
|
|
165
137
|
);
|
|
166
138
|
}
|
|
139
|
+
const resolved = resolveGatewayCredentials({ ...opts, home, env });
|
|
140
|
+
if (!resolved.ok) throw new EmitResultError(resolved.message);
|
|
141
|
+
const { url, credential: apiKey, appId } = resolved;
|
|
167
142
|
const ci = detectCi(env);
|
|
168
143
|
const request = {
|
|
169
144
|
schemaVersion: 1,
|
|
@@ -176,11 +151,10 @@ async function runEmitResult(opts) {
|
|
|
176
151
|
emittedAt: now().toISOString(),
|
|
177
152
|
...ci ? { ci: true } : {},
|
|
178
153
|
...sessionId !== void 0 ? { sessionId } : {},
|
|
179
|
-
...item !== void 0 ? { item } : {}
|
|
180
|
-
...isArtifactReview ? { artifactId } : {}
|
|
154
|
+
...item !== void 0 ? { item } : {}
|
|
181
155
|
}
|
|
182
156
|
};
|
|
183
|
-
const fetchImpl = opts.fetchImpl ??
|
|
157
|
+
const fetchImpl = opts.fetchImpl ?? defaultFetch;
|
|
184
158
|
const endpoint = new URL("/v1/emitted-results", url).toString();
|
|
185
159
|
let response;
|
|
186
160
|
try {
|
|
@@ -198,7 +172,7 @@ async function runEmitResult(opts) {
|
|
|
198
172
|
}
|
|
199
173
|
if (response.status === 401) {
|
|
200
174
|
throw new EmitResultError(
|
|
201
|
-
|
|
175
|
+
unauthorizedMessage(apiKey)
|
|
202
176
|
);
|
|
203
177
|
}
|
|
204
178
|
if (!response.ok) {
|
|
@@ -214,7 +188,7 @@ async function runEmitResult(opts) {
|
|
|
214
188
|
data = (await response.json()).data ?? {};
|
|
215
189
|
} catch {
|
|
216
190
|
}
|
|
217
|
-
const anchorLabel =
|
|
191
|
+
const anchorLabel = `item #${item.number}`;
|
|
218
192
|
const recordedId = typeof data.id === "string" ? data.id : "";
|
|
219
193
|
const idSuffix = recordedId ? ` ${DIM}\xB7${RESET} ${recordedId}` : "";
|
|
220
194
|
const output = opts.json ? JSON.stringify(data) : `${GREEN}\u2713${RESET} emitted ${opts.name} (${result}) ${DIM}\xB7${RESET} ${anchorLabel}${idSuffix}`;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
export { CAPTURE_LIMIT_BYTES, ExecConnectionError, HANDSHAKE_TIMEOUT_MS, execCapture, runExec, runVmExec, vmExecArgs, waitForAgent } from './chunk-W4SQCOZU.js';
|
|
4
|
+
import './chunk-B2G7JHHB.js';
|
|
5
|
+
import './chunk-AUFG23AA.js';
|
|
6
|
+
import './chunk-Z5GEFMRW.js';
|
|
7
|
+
|
|
8
|
+
createRequire(import.meta.url);
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
export { DOCKERD_LOG, HELPER_PATH, realGuestHost, relayPortsFrom, runGuestInit } from './chunk-CBPPJSAR.js';
|
|
4
|
+
import './chunk-B2G7JHHB.js';
|
|
5
|
+
import './chunk-AUFG23AA.js';
|
|
6
|
+
import './chunk-Z5GEFMRW.js';
|
|
7
|
+
|
|
8
|
+
createRequire(import.meta.url);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
export { AUTO_SYNC_DEBOUNCE_MS, WORK_LEASE_RENEW_DEBOUNCE_MS, WORK_LINK_RETRIES, contextPossiblyGoverned, handleWorkLaunch, handleWorkSessionEnd, hookFiredMarkerPath, maybeAutoSync, maybeRenewWorkLease, runHookFast, spoolDir } from './chunk-UFFXNXLQ.js';
|
|
4
|
+
import './chunk-XCCLFVXM.js';
|
|
5
|
+
import './chunk-BJ3KTMDH.js';
|
|
6
|
+
import './chunk-VNVZDWO3.js';
|
|
7
|
+
import './chunk-Z5GEFMRW.js';
|
|
8
|
+
|
|
9
|
+
createRequire(import.meta.url);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
export { hookExecSpoolPath, hookWrapStdio, installAbortForwarding, makeTailCollector, parseHookWrapArgs, runHookWrapFast, spoolDir } from './chunk-
|
|
4
|
-
import './chunk-
|
|
3
|
+
export { hookExecSpoolPath, hookWrapStdio, installAbortForwarding, makeTailCollector, parseHookWrapArgs, runHookWrapFast, spoolDir } from './chunk-F7CU5ABH.js';
|
|
4
|
+
import './chunk-5QRP3MVS.js';
|
|
5
5
|
import './chunk-VNVZDWO3.js';
|
|
6
6
|
import './chunk-Z5GEFMRW.js';
|
|
7
7
|
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
import { loadMaintainedFiles, writeMaintainedFiles } from './chunk-WO2BXCTQ.js';
|
|
4
|
+
import './chunk-EMY4I27X.js';
|
|
5
|
+
import './chunk-RA3O54FC.js';
|
|
6
|
+
import './chunk-Z5GEFMRW.js';
|
|
7
|
+
import { statSync, existsSync, readFileSync, writeFileSync } from 'fs';
|
|
8
|
+
import { join } from 'path';
|
|
9
|
+
|
|
10
|
+
createRequire(import.meta.url);
|
|
11
|
+
var GREEN = "\x1B[32m";
|
|
12
|
+
var DIM = "\x1B[2m";
|
|
13
|
+
var YELLOW = "\x1B[33m";
|
|
14
|
+
var RESET = "\x1B[0m";
|
|
15
|
+
var ImportCaptureError = class extends Error {
|
|
16
|
+
};
|
|
17
|
+
var SNIPPET_PATH = ".outerlayer/skills/emitting-evidence/references/agents-snippet.md";
|
|
18
|
+
var AGENTS_MD_PATH = ".outerlayer/AGENTS.md";
|
|
19
|
+
var AGENTS_MD_MARKER = "<!-- outerlayer:capture-pack -->";
|
|
20
|
+
function runImportCapture(opts = {}) {
|
|
21
|
+
const cwd = opts.cwd ?? process.cwd();
|
|
22
|
+
let cwdStat;
|
|
23
|
+
try {
|
|
24
|
+
cwdStat = statSync(cwd);
|
|
25
|
+
} catch {
|
|
26
|
+
throw new ImportCaptureError(`no such directory: ${cwd}`);
|
|
27
|
+
}
|
|
28
|
+
if (!cwdStat.isDirectory()) throw new ImportCaptureError(`not a directory: ${cwd}`);
|
|
29
|
+
const bundle = loadMaintainedFiles();
|
|
30
|
+
const { created: files, rewritten } = writeMaintainedFiles(cwd, bundle);
|
|
31
|
+
const snippet = bundle.find((f) => f.path === SNIPPET_PATH)?.content ?? "";
|
|
32
|
+
let appendedAgentsMd = false;
|
|
33
|
+
const agentsMdAbs = join(cwd, AGENTS_MD_PATH);
|
|
34
|
+
if (existsSync(agentsMdAbs)) {
|
|
35
|
+
const existing = readFileSync(agentsMdAbs, "utf8");
|
|
36
|
+
if (!existing.includes(AGENTS_MD_MARKER)) {
|
|
37
|
+
writeFileSync(agentsMdAbs, existing + "\n" + snippet);
|
|
38
|
+
appendedAgentsMd = true;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
let output;
|
|
42
|
+
if (opts.json) {
|
|
43
|
+
output = JSON.stringify({ files, rewritten, appendedAgentsMd });
|
|
44
|
+
} else {
|
|
45
|
+
const lines = [
|
|
46
|
+
...files.map((f) => `${GREEN}\u2713${RESET} wrote ${f}`),
|
|
47
|
+
...rewritten.map((f) => `${YELLOW}!${RESET} rewrote ${f} to match this CLI's bundle (local edits were overwritten)`)
|
|
48
|
+
];
|
|
49
|
+
if (appendedAgentsMd) lines.push(`${GREEN}\u2713${RESET} appended the evidence snippet to ${AGENTS_MD_PATH}`);
|
|
50
|
+
if (files.length === 0 && rewritten.length === 0 && !appendedAgentsMd) {
|
|
51
|
+
lines.push(`${DIM}capture pack already installed \u2014 nothing to write${RESET}`);
|
|
52
|
+
}
|
|
53
|
+
lines.push(`Run ${YELLOW}\`outerlayer emit\`${RESET} to compile the pack into your agent's native files.`);
|
|
54
|
+
output = lines.join("\n");
|
|
55
|
+
}
|
|
56
|
+
if (!opts.quiet) {
|
|
57
|
+
process.stdout.write(output + "\n");
|
|
58
|
+
if (!opts.json && !appendedAgentsMd && !existsSync(agentsMdAbs)) {
|
|
59
|
+
process.stdout.write(
|
|
60
|
+
`${DIM} no ${AGENTS_MD_PATH} to append to \u2014 paste ${SNIPPET_PATH} into your instructions file if your harness reads no skills${RESET}
|
|
61
|
+
`
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return { files, rewritten, appendedAgentsMd, output };
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export { ImportCaptureError, runImportCapture };
|