@outerlayer/cli 0.17.0 → 0.18.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 +47 -0
- package/README.md +15 -0
- package/dist/agent-setup-RBTEACYU.js +28 -0
- package/dist/{artifact-link-cmd-2F47LT7F.js → artifact-link-cmd-AVM2EKTV.js} +4 -3
- package/dist/{build-BG2YENGK.js → build-TQ6X5PYN.js} +5 -4
- package/dist/build-info.json +1 -1
- package/dist/{builder-2D3WSOOY.js → builder-DUI2ZH2H.js} +5 -6
- package/dist/{check-5XE7XMC4.js → check-5C4YDZYV.js} +53 -50
- package/dist/{chunk-R7PF5OOU.js → chunk-3CWUOFV6.js} +21 -14
- package/dist/{chunk-G5NPRL2K.js → chunk-3OFZM4X6.js} +548 -68
- package/dist/{chunk-2MNPHL23.js → chunk-47TTLEDX.js} +6 -5
- package/dist/{chunk-PLMTLGYH.js → chunk-52NC2FIU.js} +4 -3
- package/dist/chunk-6CHIYEZZ.js +564 -0
- package/dist/{chunk-TI7B7UEO.js → chunk-AMFWYESY.js} +1 -1
- package/dist/{chunk-YRYMNBGQ.js → chunk-ANPNT6PM.js} +2 -1
- package/dist/{chunk-YU3VKZ5F.js → chunk-B3UKB46N.js} +6 -6
- package/dist/{chunk-JXYVA45C.js → chunk-BMYGAGBJ.js} +1050 -304
- package/dist/{chunk-4Q7OMKAT.js → chunk-BQXFBI7T.js} +81 -5
- package/dist/chunk-CRB3POP4.js +34 -0
- package/dist/{chunk-F47JBIAW.js → chunk-DSF2FWAZ.js} +2 -1
- package/dist/{chunk-N5FOE5PS.js → chunk-ECODQ7II.js} +4 -33
- package/dist/{chunk-NBGDBTO2.js → chunk-ESC6UR76.js} +6 -5
- package/dist/{chunk-HHJDN6AU.js → chunk-ESVW4MJY.js} +1 -1
- package/dist/{chunk-42ZI52JW.js → chunk-F4XSVQJ4.js} +4 -3
- package/dist/{chunk-LWSJQJC6.js → chunk-FUB7LRUE.js} +7 -7
- package/dist/chunk-G2YNJIGF.js +44 -0
- package/dist/{chunk-QKFB4K7X.js → chunk-GGOMT6KF.js} +1 -1
- package/dist/{chunk-VQYBXPI7.js → chunk-GOBOJMOJ.js} +5 -5
- package/dist/{chunk-N6LURUEF.js → chunk-GOSFARMS.js} +1 -1
- package/dist/chunk-JBJTC3UU.js +35 -0
- package/dist/{chunk-NWQTTSBB.js → chunk-JF42URPU.js} +16 -15
- package/dist/{chunk-ADJRGVZC.js → chunk-KDVIU23F.js} +1 -1
- package/dist/{chunk-S3NYLI2P.js → chunk-KK4VBOH6.js} +93 -37
- package/dist/{chunk-KMDLFI4P.js → chunk-L2USZT6T.js} +1 -1
- package/dist/{chunk-WTE3MQML.js → chunk-LXAY4A2G.js} +3 -12
- package/dist/{chunk-V7NIVOFD.js → chunk-M2ZWWTWZ.js} +1 -1
- package/dist/{chunk-ERI5GBNI.js → chunk-MLAAT4S6.js} +3 -3
- package/dist/{chunk-POJMEEJJ.js → chunk-MNTSH4CL.js} +1 -1
- package/dist/{chunk-WUYTWNMA.js → chunk-MQJSXHV7.js} +1 -1
- package/dist/{chunk-O765JR4W.js → chunk-MTP2QEVO.js} +1 -1
- package/dist/{chunk-ZM2IMMYN.js → chunk-N2PXGQRL.js} +9 -1
- package/dist/{chunk-J5M7BSJQ.js → chunk-N3CUDFCW.js} +9 -3
- package/dist/{chunk-4KSQKQXE.js → chunk-NACDBXUG.js} +19 -15
- package/dist/{chunk-ONKJUM6R.js → chunk-NL4XPC7W.js} +1 -1
- package/dist/{chunk-WVUIRTWA.js → chunk-QQM2UJ6T.js} +31 -26
- package/dist/{chunk-KG5ECZGJ.js → chunk-RAZTWYZN.js} +10 -9
- package/dist/{chunk-4NPZVMJU.js → chunk-S26M3YBJ.js} +60 -4
- package/dist/{chunk-UGP76IZ5.js → chunk-S5PCA3SN.js} +1 -1
- package/dist/{chunk-3NSNIIBE.js → chunk-S76AYB4M.js} +17 -16
- package/dist/{chunk-RMWLBUCJ.js → chunk-SADUQSO4.js} +1 -1
- package/dist/{chunk-OZGHL5Y5.js → chunk-SWCTGCSC.js} +2 -2
- package/dist/{chunk-GQD22KKN.js → chunk-T2Q7ISPE.js} +2 -1
- package/dist/{chunk-C5Y5ZJJZ.js → chunk-T4Y6SCG3.js} +5 -4
- package/dist/{chunk-BWQ66M6N.js → chunk-ULSIJGLS.js} +45 -13
- package/dist/{chunk-NNRTPG7X.js → chunk-UYOYTKE2.js} +4 -4
- package/dist/{chunk-PTW6W5NR.js → chunk-VYAL7PUE.js} +1 -1
- package/dist/{chunk-YZ5F4PIS.js → chunk-W5VPCONO.js} +146 -247
- package/dist/{chunk-6Y5RUTHO.js → chunk-WBT5X3NH.js} +5 -4
- package/dist/{chunk-RLYZLUQ7.js → chunk-WGAUY5LE.js} +2 -2
- package/dist/{chunk-RSNSZ2LJ.js → chunk-X5H2WYMB.js} +1 -1
- package/dist/{chunk-OHVJA253.js → chunk-X5N6KC6V.js} +47 -29
- package/dist/{chunk-22RMZBGW.js → chunk-XGP3VYOG.js} +1 -1
- package/dist/{chunk-HYZRY4KZ.js → chunk-XNGMQ27R.js} +16 -6
- package/dist/{chunk-HGECYFEI.js → chunk-Y5GE76XC.js} +131 -54
- package/dist/{chunk-MAK5LYRF.js → chunk-Y5MXET4M.js} +277 -535
- package/dist/{chunk-XCK2YAY5.js → chunk-YVZJ6GKF.js} +3 -2
- package/dist/{chunk-YO4PSLVB.js → chunk-ZRL6HKBY.js} +1 -1
- package/dist/claude-launcher-YVXI76NX.js +102 -0
- package/dist/{cli-A76AXELQ.js → cli-C77H54BV.js} +468 -161
- package/dist/{command-R2QCVX55.js → command-H5CILO4S.js} +40 -37
- package/dist/{config-N3C6DFQA.js → config-FXDG4NPJ.js} +2 -3
- package/dist/{connect-cmd-JBKAQNSF.js → connect-cmd-ZW5FV3ZW.js} +9 -8
- package/dist/{context-adopt-NFHCLVUB.js → context-adopt-O5OFXMKI.js} +13 -12
- package/dist/context-materialize-Y5IJ4MQT.js +23 -0
- package/dist/{dist-LKDWQWZ7.js → dist-QTX4RSCL.js} +2 -2
- package/dist/{docker-4J77Q2BF.js → docker-RC3PRX3Q.js} +7 -8
- package/dist/{doctor-4TAIARIG.js → doctor-2NQQML6P.js} +46 -39
- package/dist/{emit-artifact-cmd-MPZVR56N.js → emit-artifact-cmd-7MP63KXU.js} +25 -22
- package/dist/emit-cmd-PPN4QQF2.js +14 -0
- package/dist/{emit-criteria-cmd-EFGYI23V.js → emit-criteria-cmd-3RXPDLNK.js} +16 -14
- package/dist/{emit-finding-cmd-5GF3V4LR.js → emit-finding-cmd-OL7JB6H3.js} +18 -16
- package/dist/{emit-result-cmd-I4OADKMD.js → emit-result-cmd-UZVMOCF4.js} +20 -17
- package/dist/{exec-client-CQV746UF.js → exec-client-7UMESIE2.js} +3 -4
- package/dist/governing-source-BUU4IABS.js +35 -0
- package/dist/guest-init-KPBQOFE5.js +9 -0
- package/dist/{hook-fast-R4FVSZ2H.js → hook-fast-W5MKHMJT.js} +4 -1
- package/dist/host-key-U4B5QETR.js +8 -0
- package/dist/{import-capture-cmd-EQ35EARA.js → import-capture-cmd-ZO6KGHI2.js} +7 -5
- package/dist/{import-ruler-cmd-BGAZXCQM.js → import-ruler-cmd-KJMWL5V6.js} +5 -3
- package/dist/index.js +8 -4
- package/dist/init-VWXIZEAN.js +54 -0
- package/dist/{init-PWU5YVL7.js → init-WNXXYMO7.js} +38 -35
- package/dist/{init-cmd-XAVO7HYZ.js → init-cmd-WS6TIRYT.js} +28 -24
- package/dist/{init-update-CVCWD6VS.js → init-update-E3J6TVIN.js} +27 -26
- package/dist/{install-HDBIPHTX.js → install-CBWIEF3R.js} +4 -5
- package/dist/{install-cmd-5HYMXLEW.js → install-cmd-QDOTR4OM.js} +5 -4
- package/dist/{login-browser-QZCS3WW6.js → login-browser-O63QZN7D.js} +4 -3
- package/dist/{logout-cmd-QAUFDJ6J.js → logout-cmd-5V5MMBSY.js} +3 -2
- package/dist/{logs-H55NWW4H.js → logs-AMLKC3VP.js} +3 -1
- package/dist/loop-UGI2BJOT.js +76 -0
- package/dist/machine-JOW4RNZ7.js +49 -0
- package/dist/{mcp-install-cmd-FDTPQQS6.js → mcp-install-cmd-GGWB3JJ2.js} +3 -2
- package/dist/{mcp-serve-cmd-3KVYEUXG.js → mcp-serve-cmd-DOTY5FKY.js} +10 -8
- package/dist/paths-7XP63OAX.js +7 -0
- package/dist/pending-532ABZYC.js +8 -0
- package/dist/{pidfile-UZRH774M.js → pidfile-3DM4OBKO.js} +4 -2
- package/dist/{record-C43U4PKS.js → record-3WP6V2K5.js} +3 -2
- package/dist/{runner-env-EN7YE7QX.js → runner-env-4NB2GA7O.js} +5 -6
- package/dist/{runner-key-6SLBI7PP.js → runner-key-TC3NFWFV.js} +38 -35
- package/dist/{session-sender-FO3LCREV.js → session-sender-NNVPSPY7.js} +17 -14
- package/dist/spec-cmd-OWVTBB4J.js +116 -0
- package/dist/{starter-pack-KF66HGZR.js → starter-pack-OPWUDOWX.js} +7 -5
- package/dist/{status-7VNQN5PW.js → status-TKCLLKFG.js} +42 -39
- package/dist/{statusline-fast-SVTMBMD7.js → statusline-fast-KN3BX67H.js} +2 -1
- package/dist/{sync-cmd-GVPPFZ3G.js → sync-cmd-Q6VYNPWG.js} +16 -13
- package/dist/{watch-23HSAEI6.js → watch-ARAGADTF.js} +16 -13
- package/dist/{work-claim-cmd-LKL3GHFQ.js → work-claim-cmd-34FERLYX.js} +25 -27
- package/dist/work-cmd-7S5B2H2P.js +25 -0
- package/dist/{work-comment-cmd-AWHP56M2.js → work-comment-cmd-SZJSPM5S.js} +15 -13
- package/dist/{work-launch-R5HTAP6X.js → work-launch-LEQ2MPM3.js} +3 -1
- package/dist/{work-open-pr-cmd-IOM4AVQQ.js → work-open-pr-cmd-RPXKCBWS.js} +17 -15
- package/dist/work-pr-cmd-5LGANL32.js +26 -0
- package/package.json +3 -2
- package/skill-pack/maintained/outerlayer-amend/SKILL.md +4 -2
- package/skill-pack/shipped.json +17 -2
- package/skill-pack/template/build/SKILL.md +23 -10
- package/skill-pack/template/build/references/agent-briefs.md +3 -1
- package/skill-pack/template/build/references/criteria-judge.md +27 -0
- package/skill-pack/template/build/references/release.md +19 -28
- package/skill-pack/template/spec/SKILL.md +35 -10
- package/skill-pack/validators/acceptance-criteria.yaml +25 -26
- package/dist/agent-setup-T624CWPD.js +0 -27
- package/dist/chunk-BYT5O5RV.js +0 -61
- package/dist/context-materialize-IV2TUUFO.js +0 -22
- package/dist/emit-cmd-IJ3GVRFD.js +0 -12
- package/dist/guest-init-LJP5GPZF.js +0 -9
- package/dist/host-key-YMLXY6QB.js +0 -7
- package/dist/init-6XPDRDTC.js +0 -51
- package/dist/loop-FK3LPMMZ.js +0 -73
- package/dist/machine-SQXEBAM2.js +0 -46
- package/dist/paths-OYKMVYJP.js +0 -6
- package/dist/pending-MXLSRYMO.js +0 -7
- package/dist/work-cmd-Z2WXLZPH.js +0 -23
- package/dist/work-pr-cmd-HNEUIEN7.js +0 -24
|
@@ -1,36 +1,40 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import { gatherDoctorChecks, doctorExitCode, summarizeChecks, renderDoctorText, recordWrapped, recordUnwrapped, recordRemoval, readManifest, recordInstall, recordStatusline } from './chunk-
|
|
4
|
-
import './chunk-
|
|
5
|
-
import './chunk-
|
|
6
|
-
import './chunk-
|
|
3
|
+
import { gatherDoctorChecks, doctorExitCode, summarizeChecks, renderDoctorText, recordWrapped, recordUnwrapped, recordRemoval, readManifest, recordInstall, recordStatusline } from './chunk-Y5GE76XC.js';
|
|
4
|
+
import './chunk-ESC6UR76.js';
|
|
5
|
+
import { verifiedTrackerNames, TRACKERS } from './chunk-KK4VBOH6.js';
|
|
6
|
+
import './chunk-WBT5X3NH.js';
|
|
7
7
|
import './chunk-IP7BIBXJ.js';
|
|
8
|
-
import './chunk-
|
|
8
|
+
import './chunk-S76AYB4M.js';
|
|
9
|
+
import './chunk-MQJSXHV7.js';
|
|
10
|
+
import './chunk-DSF2FWAZ.js';
|
|
9
11
|
import './chunk-BKO6JEZI.js';
|
|
10
|
-
import './chunk-
|
|
11
|
-
import './chunk-
|
|
12
|
-
import './chunk-
|
|
13
|
-
import './chunk-
|
|
14
|
-
import './chunk-
|
|
15
|
-
import './chunk-
|
|
16
|
-
import './chunk-N6LURUEF.js';
|
|
17
|
-
import { C, NO_COLOR_FLAG, warnDeprecated, stripNoColor, API_KEY_FLAG_DEPRECATION } from './chunk-YRYMNBGQ.js';
|
|
12
|
+
import './chunk-BMYGAGBJ.js';
|
|
13
|
+
import './chunk-YVZJ6GKF.js';
|
|
14
|
+
import './chunk-F4XSVQJ4.js';
|
|
15
|
+
import './chunk-NACDBXUG.js';
|
|
16
|
+
import './chunk-GOSFARMS.js';
|
|
17
|
+
import { C, NO_COLOR_FLAG, warnDeprecated, stripNoColor, API_KEY_FLAG_DEPRECATION } from './chunk-ANPNT6PM.js';
|
|
18
18
|
import { parseTrackerNumber, trackerNumberError } from './chunk-WZBHBH3J.js';
|
|
19
19
|
import { settingsPath, readSettings, SettingsParseError, listHookCandidates, wrapHooks, writeSettings, unwrapHooks, REGISTERED_EVENTS, cliCommand, removeHooks, removeStatusline, cliBinResolvable, mergeHooks, repointWrappedHooks, AUTO_WRAP_EVENTS, mergeStatusline } from './chunk-5QRP3MVS.js';
|
|
20
|
-
import { pinExists } from './chunk-
|
|
21
|
-
import './chunk-
|
|
22
|
-
import './chunk-
|
|
23
|
-
import './chunk-
|
|
24
|
-
import './chunk-
|
|
25
|
-
import './chunk-
|
|
26
|
-
import './chunk-
|
|
20
|
+
import { pinExists } from './chunk-LXAY4A2G.js';
|
|
21
|
+
import './chunk-T4Y6SCG3.js';
|
|
22
|
+
import './chunk-ZRL6HKBY.js';
|
|
23
|
+
import './chunk-52NC2FIU.js';
|
|
24
|
+
import './chunk-MNTSH4CL.js';
|
|
25
|
+
import './chunk-X5N6KC6V.js';
|
|
26
|
+
import './chunk-N3CUDFCW.js';
|
|
27
27
|
import './chunk-EABW6AJQ.js';
|
|
28
28
|
import { resolveVersion } from './chunk-RA3O54FC.js';
|
|
29
|
-
import './chunk-
|
|
30
|
-
import './chunk-
|
|
31
|
-
import
|
|
29
|
+
import './chunk-M2ZWWTWZ.js';
|
|
30
|
+
import './chunk-N2PXGQRL.js';
|
|
31
|
+
import './chunk-BQXFBI7T.js';
|
|
32
|
+
import { hookFiredMarkerPath, installedCliDistDir } from './chunk-ULSIJGLS.js';
|
|
33
|
+
import './chunk-G2YNJIGF.js';
|
|
32
34
|
import { managedHookScripts, removeJournalHooks, installPreCommitGuardHook, removePreCommitGuardHook } from './chunk-XCCLFVXM.js';
|
|
35
|
+
import './chunk-ZJSNLVCE.js';
|
|
33
36
|
import './chunk-BJ3KTMDH.js';
|
|
37
|
+
import { cliInvocation, packageRunnerOf } from './chunk-CRB3POP4.js';
|
|
34
38
|
import { homeFromEnv } from './chunk-VNVZDWO3.js';
|
|
35
39
|
import './chunk-Z5GEFMRW.js';
|
|
36
40
|
import { EventEmitter } from 'events';
|
|
@@ -3400,7 +3404,7 @@ function useColor() {
|
|
|
3400
3404
|
// ../../node_modules/commander/index.js
|
|
3401
3405
|
new Command();
|
|
3402
3406
|
function isEphemeralBin(bin) {
|
|
3403
|
-
return bin
|
|
3407
|
+
return packageRunnerOf(bin) !== void 0;
|
|
3404
3408
|
}
|
|
3405
3409
|
function initHookBin(opts) {
|
|
3406
3410
|
const { runningBin } = opts;
|
|
@@ -3610,11 +3614,12 @@ function orgRolloutSnippet(cliBin) {
|
|
|
3610
3614
|
"managed-settings.json:",
|
|
3611
3615
|
managed,
|
|
3612
3616
|
"",
|
|
3613
|
-
|
|
3617
|
+
`Each developer still runs \`${cliInvocation()} login\` once to attribute sessions.`
|
|
3614
3618
|
].join("\n");
|
|
3615
3619
|
}
|
|
3616
3620
|
|
|
3617
3621
|
// src/cli.ts
|
|
3622
|
+
var TRACKER_OPTION_FLAG = `--tracker <${verifiedTrackerNames(TRACKERS).join("|")}>`;
|
|
3618
3623
|
function resolveCliBin() {
|
|
3619
3624
|
try {
|
|
3620
3625
|
return fileURLToPath(new URL("./index.js", import.meta.url));
|
|
@@ -3640,13 +3645,13 @@ function writeJson(value) {
|
|
|
3640
3645
|
`);
|
|
3641
3646
|
}
|
|
3642
3647
|
function apiKeyOption() {
|
|
3643
|
-
return new Option("--api-key <key>",
|
|
3648
|
+
return new Option("--api-key <key>", `deprecated: use \`${cliInvocation()} login\` or OUTERLAYER_API_KEY`).hideHelp();
|
|
3644
3649
|
}
|
|
3645
3650
|
function warnIfApiKeyFlag(opts) {
|
|
3646
3651
|
if (opts.apiKey !== void 0) warnDeprecated(API_KEY_FLAG_DEPRECATION);
|
|
3647
3652
|
}
|
|
3648
3653
|
async function installStarterPackInRepo() {
|
|
3649
|
-
const { installStarterPack, formatStarterPackOutput } = await import('./starter-pack-
|
|
3654
|
+
const { installStarterPack, formatStarterPackOutput } = await import('./starter-pack-OPWUDOWX.js');
|
|
3650
3655
|
const cwd = process.cwd();
|
|
3651
3656
|
let repoRoot = cwd;
|
|
3652
3657
|
try {
|
|
@@ -3687,7 +3692,7 @@ ${C.dim} backup: ${result.backupPath}${C.reset}` : ""}
|
|
|
3687
3692
|
}
|
|
3688
3693
|
if (result.wrapped.length > 0) {
|
|
3689
3694
|
lines.push(
|
|
3690
|
-
`${C.green}\u2713${C.reset} Auto-wrapped ${result.wrapped.length} hook(s) for execution evidence (adds one spawn per firing \u2014 see ${C.yellow}
|
|
3695
|
+
`${C.green}\u2713${C.reset} Auto-wrapped ${result.wrapped.length} hook(s) for execution evidence (adds one spawn per firing \u2014 see ${C.yellow}${cliInvocation()} hooks unwrap${C.reset} to undo):
|
|
3691
3696
|
`
|
|
3692
3697
|
);
|
|
3693
3698
|
for (const w of result.wrapped) {
|
|
@@ -3729,9 +3734,12 @@ cannot be disabled.
|
|
|
3729
3734
|
(opts.next === false ? "\n" : `
|
|
3730
3735
|
Next: launch a session naming its work item, then sync it:
|
|
3731
3736
|
${C.yellow}OUTERLAYER_WORK=42 claude${C.reset}
|
|
3732
|
-
${C.yellow}
|
|
3737
|
+
${C.yellow}${cliInvocation()} sync${C.reset}
|
|
3733
3738
|
|
|
3734
|
-
`) + (opts.connected ? "This repository is connected to a factory, so launched sessions sync\nautomatically in the background after each agent turn and at the end\nof the session, at most once every five minutes.\n" :
|
|
3739
|
+
`) + (opts.connected ? "This repository is connected to a factory, so launched sessions sync\nautomatically in the background after each agent turn and at the end\nof the session, at most once every five minutes.\n" : `Once you have run ${cliInvocation()} login and ${cliInvocation()} init in this repository,
|
|
3740
|
+
launched sessions sync automatically in the background after each agent
|
|
3741
|
+
turn and at the end of the session, at most once every five minutes.
|
|
3742
|
+
`)
|
|
3735
3743
|
);
|
|
3736
3744
|
return lines.join("");
|
|
3737
3745
|
}
|
|
@@ -3748,7 +3756,7 @@ function formatGuardInstallOutput(guard) {
|
|
|
3748
3756
|
return {
|
|
3749
3757
|
lines: [
|
|
3750
3758
|
`${C.yellow}!${C.reset} a pre-commit hook we did not write already exists (${guard.path}) \u2014 left untouched.`,
|
|
3751
|
-
` Append the guard script yourself: ${C.yellow}
|
|
3759
|
+
` Append the guard script yourself: ${C.yellow}${cliInvocation()} hooks install-git --print${C.reset}`,
|
|
3752
3760
|
` Place it before any exit in the existing hook \u2014 code after an early exit never runs.`
|
|
3753
3761
|
],
|
|
3754
3762
|
exitCode: 1
|
|
@@ -3760,7 +3768,7 @@ function formatGuardInstallOutput(guard) {
|
|
|
3760
3768
|
return {
|
|
3761
3769
|
lines: [
|
|
3762
3770
|
`${C.yellow}!${C.reset} this repo manages hooks in its working tree (core.hooksPath) \u2014 nothing written.`,
|
|
3763
|
-
` Add the script to your hook manager instead: ${C.yellow}
|
|
3771
|
+
` Add the script to your hook manager instead: ${C.yellow}${cliInvocation()} hooks install-git --print${C.reset}`
|
|
3764
3772
|
],
|
|
3765
3773
|
exitCode: 1
|
|
3766
3774
|
};
|
|
@@ -3775,7 +3783,7 @@ async function installHooks(opts, resolvedBin, connected, starterTemplate, withN
|
|
|
3775
3783
|
cliBin = initHookBin({ home: homeFromEnv(), runningBin: resolvedBin, remove: opts.remove === true });
|
|
3776
3784
|
} catch (err) {
|
|
3777
3785
|
const text = `could not copy the CLI to ~/.outerlayer/cli: ${err instanceof Error ? err.message : String(err)}
|
|
3778
|
-
Hooks were not changed. Fix the permissions on ~/.outerlayer, then re-run ${C.yellow}
|
|
3786
|
+
Hooks were not changed. Fix the permissions on ~/.outerlayer, then re-run ${C.yellow}${cliInvocation()} init${C.reset}.`;
|
|
3779
3787
|
return { ok: false, text, detail: "could not copy the CLI to ~/.outerlayer/cli" };
|
|
3780
3788
|
}
|
|
3781
3789
|
try {
|
|
@@ -3789,7 +3797,7 @@ async function installHooks(opts, resolvedBin, connected, starterTemplate, withN
|
|
|
3789
3797
|
});
|
|
3790
3798
|
if (result.cliBinUnresolved) {
|
|
3791
3799
|
const text = `the resolved CLI path (${cliBin}) does not exist \u2014 refusing to write hook entries pointing at it.
|
|
3792
|
-
Reinstall OuterLayer, then re-run ${C.yellow}
|
|
3800
|
+
Reinstall OuterLayer, then re-run ${C.yellow}${cliInvocation()} init${C.reset}.`;
|
|
3793
3801
|
return { ok: false, text, detail: "the CLI path does not exist" };
|
|
3794
3802
|
}
|
|
3795
3803
|
const starter = starterTemplate === void 0 ? null : await installStarterPackInRepo();
|
|
@@ -3806,8 +3814,8 @@ ${starter.output}`),
|
|
|
3806
3814
|
}
|
|
3807
3815
|
}
|
|
3808
3816
|
async function realConnectDepsForCwd() {
|
|
3809
|
-
const { realConnectDeps } = await import('./connect-cmd-
|
|
3810
|
-
const { resolveRepoIdentity } = await import('./dist-
|
|
3817
|
+
const { realConnectDeps } = await import('./connect-cmd-ZW5FV3ZW.js');
|
|
3818
|
+
const { resolveRepoIdentity } = await import('./dist-QTX4RSCL.js');
|
|
3811
3819
|
return {
|
|
3812
3820
|
...realConnectDeps(),
|
|
3813
3821
|
home: homeFromEnv(),
|
|
@@ -3822,13 +3830,53 @@ function invokedCommandToken(argv) {
|
|
|
3822
3830
|
}
|
|
3823
3831
|
function buildProgram(argv = process.argv) {
|
|
3824
3832
|
const program2 = new Command();
|
|
3825
|
-
program2.name(
|
|
3826
|
-
program2.command("init").description("Connect this repository, install hooks and agent skills, run doctor").option("--user", "install into user settings [default]").option("--project", "install into project settings (./.claude/settings.json)").option("--org", "print a managed-settings.json snippet for MDM/GPO rollout").option("--remove", "uninstall OuterLayer hooks").option("--local", "install the hooks only: no connect step and no network call").option("--factory <org/factory>",
|
|
3833
|
+
program2.name(cliInvocation()).description("OuterLayer \u2014 see what your coding agents actually do").enablePositionalOptions().version(resolveVersion()).option(NO_COLOR_FLAG, "disable color (NO_COLOR=1 does the same)").addHelpText("after", SUPPORT_TEXT);
|
|
3834
|
+
program2.command("init").description("Connect this repository, install hooks and agent skills, run doctor").option("--user", "install into user settings [default]").option("--project", "install into project settings (./.claude/settings.json)").option("--org", "print a managed-settings.json snippet for MDM/GPO rollout").option("--remove", "uninstall OuterLayer hooks").option("--local", "install the hooks only: no connect step and no network call").option("--factory <org/factory>", `the factory to connect this repository to (see \`${cliInvocation()} connect\`)`).option("--gitignore", "also add .outerlayer/ to .gitignore (project scope)").option("--template <name>", "install the starter skills and a policy file (only: default)").option("--update", "update the files init wrote that you have not edited, and write missing ones").option("--dry-run", "with --update: print the plan and write nothing").option("--no-wrap-hooks", "leave PreToolUse/PostToolUse hooks unwrapped").option("--statusline", "install the status-line segment [default]").option("--no-statusline", "leave the statusLine slot untouched").option("--json", "machine-readable JSON output").addHelpText(
|
|
3827
3835
|
"after",
|
|
3828
|
-
|
|
3836
|
+
`
|
|
3837
|
+
In a repository, init runs four steps: connect the repository to a
|
|
3838
|
+
factory (\`${cliInvocation()} connect\`), install the hooks, set up the coding agent,
|
|
3839
|
+
and run \`${cliInvocation()} doctor\`. It never signs in and asks nothing. With no
|
|
3840
|
+
login it skips the connect step and says to run \`${cliInvocation()} login\`. With
|
|
3841
|
+
--json it prints one document naming the outcome of each step: done,
|
|
3842
|
+
skipped or failed. The exit code is 1 when a step failed.
|
|
3843
|
+
|
|
3844
|
+
The agent setup step installs the starter skills and the \`outerlayer\` skill
|
|
3845
|
+
into .outerlayer/skills/, writes .outerlayer/config.json for Claude Code when
|
|
3846
|
+
there is none, runs \`${cliInvocation()} context emit\` so the skills appear in
|
|
3847
|
+
.claude/skills/, and adds the outerlayer and outerlayer-docs MCP servers to
|
|
3848
|
+
.mcp.json. Nothing you wrote is changed: an existing config, policy, edited
|
|
3849
|
+
skill, MCP entry or root CLAUDE.md and AGENTS.md is left as it is, and a
|
|
3850
|
+
hand-written file the emit would replace is kept and listed. The files are
|
|
3851
|
+
left uncommitted.
|
|
3852
|
+
The step is skipped outside a git repository and in a repository whose
|
|
3853
|
+
context comes from a control plane, where it arrives at session start.
|
|
3854
|
+
|
|
3855
|
+
--local installs only the hooks: no connect step, no agent setup and no
|
|
3856
|
+
network call. Add \`--template default\` to also write the starter skills and
|
|
3857
|
+
a policy file into .outerlayer/ without compiling them; \`${cliInvocation()} context
|
|
3858
|
+
emit\` does that.
|
|
3859
|
+
|
|
3860
|
+
Idempotent: settings are backed up before any write, and a second run
|
|
3861
|
+
changes nothing. Wrapping adds one spawn per hook firing; undo it with
|
|
3862
|
+
\`${cliInvocation()} hooks unwrap\`. An occupied status-line slot is wrapped, never
|
|
3863
|
+
replaced.
|
|
3864
|
+
|
|
3865
|
+
Three of the starter skills are copied once and are yours to edit. The
|
|
3866
|
+
others are rewritten from this CLI on every \`context emit\`.
|
|
3867
|
+
|
|
3868
|
+
--update brings the files init wrote once up to this CLI's version: the
|
|
3869
|
+
template skills, the policy, the two starter checks and the two MCP
|
|
3870
|
+
entries. A file still equal to a version an earlier release wrote is
|
|
3871
|
+
replaced, and a missing one is written. A file you edited is never
|
|
3872
|
+
touched. It then runs \`${cliInvocation()} context emit\` and leaves the changes
|
|
3873
|
+
uncommitted. --dry-run prints the plan, with a command to compare each
|
|
3874
|
+
edited file, and writes nothing. \`${cliInvocation()} doctor\` reports the same
|
|
3875
|
+
states under Starter files.
|
|
3876
|
+
`
|
|
3829
3877
|
).action(async (opts) => {
|
|
3830
3878
|
if (opts.update || opts.dryRun) {
|
|
3831
|
-
const { runInitUpdate, formatInitUpdate, updateFlagProblem } = await import('./init-update-
|
|
3879
|
+
const { runInitUpdate, formatInitUpdate, updateFlagProblem } = await import('./init-update-E3J6TVIN.js');
|
|
3832
3880
|
const problem = updateFlagProblem(opts);
|
|
3833
3881
|
if (problem !== void 0) {
|
|
3834
3882
|
fail(problem);
|
|
@@ -3842,7 +3890,7 @@ function buildProgram(argv = process.argv) {
|
|
|
3842
3890
|
}
|
|
3843
3891
|
let starterTemplate;
|
|
3844
3892
|
if (opts.template !== void 0) {
|
|
3845
|
-
const { assertKnownTemplate, StarterPackError } = await import('./starter-pack-
|
|
3893
|
+
const { assertKnownTemplate, StarterPackError } = await import('./starter-pack-OPWUDOWX.js');
|
|
3846
3894
|
try {
|
|
3847
3895
|
assertKnownTemplate(opts.template);
|
|
3848
3896
|
} catch (err) {
|
|
@@ -3873,7 +3921,7 @@ function buildProgram(argv = process.argv) {
|
|
|
3873
3921
|
else process.stdout.write(outcome.text);
|
|
3874
3922
|
return;
|
|
3875
3923
|
}
|
|
3876
|
-
const { runInitCommand } = await import('./init-cmd-
|
|
3924
|
+
const { runInitCommand } = await import('./init-cmd-WS6TIRYT.js');
|
|
3877
3925
|
const code = await runInitCommand(
|
|
3878
3926
|
{ json: opts.json, factory: opts.factory },
|
|
3879
3927
|
{
|
|
@@ -3885,7 +3933,7 @@ function buildProgram(argv = process.argv) {
|
|
|
3885
3933
|
return { ok, text, detail };
|
|
3886
3934
|
},
|
|
3887
3935
|
runAgentSetup: async () => {
|
|
3888
|
-
const { runAgentSetup } = await import('./agent-setup-
|
|
3936
|
+
const { runAgentSetup } = await import('./agent-setup-RBTEACYU.js');
|
|
3889
3937
|
return runAgentSetup({ cwd: process.cwd() });
|
|
3890
3938
|
},
|
|
3891
3939
|
runDoctorChecks: gatherDoctorChecks
|
|
@@ -3895,9 +3943,29 @@ function buildProgram(argv = process.argv) {
|
|
|
3895
3943
|
});
|
|
3896
3944
|
program2.command("connect").description("Choose the factory this repository's work goes to").option("--factory <org/factory>", "the factory to use: <org>/<factory> as in its dashboard address, or a factory id").option("--json", "write one JSON document to stdout; the text goes to stderr").addHelpText(
|
|
3897
3945
|
"after",
|
|
3898
|
-
|
|
3946
|
+
`
|
|
3947
|
+
Run it in a repository, after \`${cliInvocation()} login\`. With a login, connect lists
|
|
3948
|
+
the factories you can use and takes the first rule that leaves one answer:
|
|
3949
|
+
1. --factory <org>/<factory>, or a factory id
|
|
3950
|
+
2. the factory this repository is already connected to
|
|
3951
|
+
3. the one factory this repository is linked to
|
|
3952
|
+
4. the one factory you can use
|
|
3953
|
+
5. on a terminal, ask; with no terminal, exit 1 and list each --factory value
|
|
3954
|
+
|
|
3955
|
+
It says what it chose and why. The choice is saved in this repository's git
|
|
3956
|
+
directory (outerlayer/connection.json), shared by every worktree of the
|
|
3957
|
+
clone and never committed. A factory key already belongs to one factory, so
|
|
3958
|
+
connect changes nothing for it. Connect never links a repository.
|
|
3959
|
+
|
|
3960
|
+
After it saves the choice, connect checks that this repository is linked to
|
|
3961
|
+
the factory. If it is not, connect says so, prints the factory's Work page
|
|
3962
|
+
link where you link it, and exits 2. The choice is saved either way. Run
|
|
3963
|
+
connect again once the repository is linked. With --json, the document has
|
|
3964
|
+
linked (true, false, or null when it could not be checked) and, when false,
|
|
3965
|
+
linkUrl.
|
|
3966
|
+
`
|
|
3899
3967
|
).action(async (opts) => {
|
|
3900
|
-
const { runConnectCommand } = await import('./connect-cmd-
|
|
3968
|
+
const { runConnectCommand } = await import('./connect-cmd-ZW5FV3ZW.js');
|
|
3901
3969
|
const code = await runConnectCommand({ factory: opts.factory, json: opts.json }, await realConnectDepsForCwd(), {
|
|
3902
3970
|
stdout: process.stdout,
|
|
3903
3971
|
stderr: process.stderr
|
|
@@ -3915,9 +3983,28 @@ function buildProgram(argv = process.argv) {
|
|
|
3915
3983
|
});
|
|
3916
3984
|
program2.command("login").description("Sign in to your account by browser approval, or save a piped factory key").option("--dashboard <address>", "the dashboard to sign in on (default: https://app.outerlayer.ai)").option("--no-browser", "print the approve link without opening a browser").option("--check <id>", "check a login that is still waiting for approval, once").option("--url <url>", "gateway base URL for a piped key (browser login gets it from the dashboard)").option("--app-id <id>", "factory id a piped key is bound to (Settings \u2192 General)").option("--no-input", "never wait on a person; fail if the key is not on stdin").option("--json", "machine-readable JSON output").addHelpText(
|
|
3917
3985
|
"after",
|
|
3918
|
-
|
|
3986
|
+
`
|
|
3987
|
+
With no key on stdin, login prints an approve link and a code. A signed-in
|
|
3988
|
+
person approves it on the dashboard. The login is a token for that person's
|
|
3989
|
+
account, made for this machine, saved here and never printed. It picks no
|
|
3990
|
+
factory: run \`${cliInvocation()} connect\` for that. \`${cliInvocation()} logout\` revokes it.
|
|
3991
|
+
|
|
3992
|
+
When stdout is not a terminal, login does not wait. It prints one JSON
|
|
3993
|
+
document with the link, the code and a \`login --check <id>\` command, and
|
|
3994
|
+
exits 75. Run the check until it stops exiting 75: 0 is signed in, 1 is
|
|
3995
|
+
denied or expired. A dropped connection or a 5xx also exits 75.
|
|
3996
|
+
|
|
3997
|
+
A factory key piped on stdin is saved as it always was, never as a flag and
|
|
3998
|
+
never printed back. A factory key always wins over the login, so CI and
|
|
3999
|
+
runners keep acting as their key.
|
|
4000
|
+
|
|
4001
|
+
echo "$OUTERLAYER_KEY" | ${cliInvocation()} login --url <gateway url> --app-id <factory id>
|
|
4002
|
+
|
|
4003
|
+
Every later command reads the saved file, so none of them needs a key on
|
|
4004
|
+
its command line. A saved key is checked for real on the first \`sync\`.
|
|
4005
|
+
`
|
|
3919
4006
|
).action(async (opts) => {
|
|
3920
|
-
const { runLoginCommand, realLoginDeps } = await import('./login-browser-
|
|
4007
|
+
const { runLoginCommand, realLoginDeps } = await import('./login-browser-O63QZN7D.js');
|
|
3921
4008
|
const code = await runLoginCommand(
|
|
3922
4009
|
{
|
|
3923
4010
|
browser: opts.browser !== false,
|
|
@@ -3934,9 +4021,14 @@ function buildProgram(argv = process.argv) {
|
|
|
3934
4021
|
});
|
|
3935
4022
|
program2.command("logout").description("Revoke this machine's login and remove it").addHelpText(
|
|
3936
4023
|
"after",
|
|
3937
|
-
|
|
4024
|
+
`
|
|
4025
|
+
Revokes the token \`${cliInvocation()} login\` saved, then deletes it from the config
|
|
4026
|
+
file. A factory key and the chosen factory are left alone. When the
|
|
4027
|
+
dashboard cannot be reached the local copy is still deleted and the exit
|
|
4028
|
+
code is 1: revoke the token on /profile/security.
|
|
4029
|
+
`
|
|
3938
4030
|
).action(async () => {
|
|
3939
|
-
const { runLogoutCommand, realLogoutDeps } = await import('./logout-cmd-
|
|
4031
|
+
const { runLogoutCommand, realLogoutDeps } = await import('./logout-cmd-5V5MMBSY.js');
|
|
3940
4032
|
const code = await runLogoutCommand(realLogoutDeps());
|
|
3941
4033
|
if (code !== 0) process.exitCode = code;
|
|
3942
4034
|
});
|
|
@@ -3946,13 +4038,13 @@ function buildProgram(argv = process.argv) {
|
|
|
3946
4038
|
).action(async (opts) => {
|
|
3947
4039
|
warnIfApiKeyFlag(opts);
|
|
3948
4040
|
if (opts.link !== void 0) {
|
|
3949
|
-
const { lookupArtifactLink } = await import('./artifact-link-cmd-
|
|
4041
|
+
const { lookupArtifactLink } = await import('./artifact-link-cmd-AVM2EKTV.js');
|
|
3950
4042
|
const found = lookupArtifactLink(opts.link);
|
|
3951
4043
|
if (found.ok) process.stdout.write(found.url + "\n");
|
|
3952
4044
|
else fail(found.reason);
|
|
3953
4045
|
return;
|
|
3954
4046
|
}
|
|
3955
|
-
const { runSync, SyncConfigError, SyncTransportError } = await import('./sync-cmd-
|
|
4047
|
+
const { runSync, SyncConfigError, SyncTransportError } = await import('./sync-cmd-Q6VYNPWG.js');
|
|
3956
4048
|
try {
|
|
3957
4049
|
const result = await runSync({
|
|
3958
4050
|
url: opts.url,
|
|
@@ -3977,11 +4069,13 @@ function buildProgram(argv = process.argv) {
|
|
|
3977
4069
|
throw err;
|
|
3978
4070
|
}
|
|
3979
4071
|
});
|
|
3980
|
-
program2.command("daemon").alias("watch").description("Run the copy-out daemon that mirrors transcripts before they are deleted").option("--once", "do a single mirror sweep and exit").addHelpText("after",
|
|
4072
|
+
program2.command("daemon").alias("watch").description("Run the copy-out daemon that mirrors transcripts before they are deleted").option("--once", "do a single mirror sweep and exit").addHelpText("after", `
|
|
4073
|
+
\`${cliInvocation()} watch\` is the former name and still works, with a warning.
|
|
4074
|
+
`).action(async (opts) => {
|
|
3981
4075
|
if (invokedCommandToken(argv) === "watch") {
|
|
3982
|
-
warnDeprecated(
|
|
4076
|
+
warnDeprecated(`\`${cliInvocation()} watch\` is now \`${cliInvocation()} daemon\`; the old name will be removed in a future release.`);
|
|
3983
4077
|
}
|
|
3984
|
-
const { runWatch } = await import('./watch-
|
|
4078
|
+
const { runWatch } = await import('./watch-ARAGADTF.js');
|
|
3985
4079
|
await runWatch({ once: opts.once });
|
|
3986
4080
|
});
|
|
3987
4081
|
program2.command("hook <event>", { hidden: true }).description("capture-hook fast path, installed by `init`").action(() => {
|
|
@@ -3990,6 +4084,8 @@ function buildProgram(argv = process.argv) {
|
|
|
3990
4084
|
});
|
|
3991
4085
|
program2.command("hook-wrap", { hidden: true }).description("runs a hook wrapped by `hooks wrap`, recording exec evidence").option("--id <base64>", "the original hook command, base64-encoded").option("--capture-output", "tee stdout/stderr into a bounded tail").action(() => {
|
|
3992
4086
|
});
|
|
4087
|
+
program2.command("claude [args...]", { hidden: true }).description("start Claude Code with the repository's control plane attached").allowUnknownOption().helpOption(false).action(() => {
|
|
4088
|
+
});
|
|
3993
4089
|
program2.command("broker-relay", { hidden: true }).description("relay a build's loopback connections to the runner's tunnel and destinations").requiredOption("--port <port>", "the loopback port to listen on").requiredOption("--socket <path>", "the runner's tunnel socket").option("--forward <port=socket>", "also relay a loopback port to a destination's socket; repeatable", (value, previous) => [...previous, value], []).action(async (opts) => {
|
|
3994
4090
|
const { startRelay } = await import('./relay-L76HDX72.js');
|
|
3995
4091
|
const port = Number(opts.port);
|
|
@@ -4010,7 +4106,7 @@ function buildProgram(argv = process.argv) {
|
|
|
4010
4106
|
await startRelay({ port, socketPath: opts.socket, forwards });
|
|
4011
4107
|
});
|
|
4012
4108
|
program2.command("vm-exec", { hidden: true }).description("run a command in a microVM build's guest through its exec agent").requiredOption("--socket <path>", "the Unix socket Firecracker serves the build's vsock device on").option("--user <user>", "the user to run as", "").option("--cwd <dir>", "the working directory", "/").option("--env <NAME=value>", "an environment value the command line carries; repeatable", (value, previous) => [...previous, value], []).option("--pass <NAME>", "an environment variable whose value is read from this process; repeatable", (value, previous) => [...previous, value], []).argument("<argv...>", "the command and its arguments").action(async (argv2, opts) => {
|
|
4013
|
-
const { runVmExec } = await import('./exec-client-
|
|
4109
|
+
const { runVmExec } = await import('./exec-client-7UMESIE2.js');
|
|
4014
4110
|
const env = {};
|
|
4015
4111
|
for (const entry of opts.env) {
|
|
4016
4112
|
const eq = entry.indexOf("=");
|
|
@@ -4035,7 +4131,7 @@ function buildProgram(argv = process.argv) {
|
|
|
4035
4131
|
}
|
|
4036
4132
|
});
|
|
4037
4133
|
program2.command("session-sender", { hidden: true }).description("stream a runner build's sessions to its work item while the build runs").action(async () => {
|
|
4038
|
-
const { runSessionSender } = await import('./session-sender-
|
|
4134
|
+
const { runSessionSender } = await import('./session-sender-NNVPSPY7.js');
|
|
4039
4135
|
try {
|
|
4040
4136
|
await runSessionSender();
|
|
4041
4137
|
} catch (err) {
|
|
@@ -4043,7 +4139,7 @@ function buildProgram(argv = process.argv) {
|
|
|
4043
4139
|
}
|
|
4044
4140
|
});
|
|
4045
4141
|
program2.command("vm-init", { hidden: true }).description("lay out a microVM build's guest; the guest helper runs it").action(async () => {
|
|
4046
|
-
const { realGuestHost, runGuestInit } = await import('./guest-init-
|
|
4142
|
+
const { realGuestHost, runGuestInit } = await import('./guest-init-KPBQOFE5.js');
|
|
4047
4143
|
const { readFileSync: readFileSync3 } = await import('fs');
|
|
4048
4144
|
try {
|
|
4049
4145
|
runGuestInit(realGuestHost(), readFileSync3("/proc/cmdline", "utf8"));
|
|
@@ -4057,6 +4153,7 @@ function buildProgram(argv = process.argv) {
|
|
|
4057
4153
|
registerMcpCommands(program2);
|
|
4058
4154
|
registerContextCommands(program2);
|
|
4059
4155
|
registerWorkCommands(program2);
|
|
4156
|
+
registerSpecCommands(program2);
|
|
4060
4157
|
registerRunnerCommands(program2);
|
|
4061
4158
|
return program2;
|
|
4062
4159
|
}
|
|
@@ -4070,7 +4167,7 @@ async function runCli(processArgv) {
|
|
|
4070
4167
|
await buildProgram(argv).parseAsync(argv);
|
|
4071
4168
|
}
|
|
4072
4169
|
async function compileContext(opts) {
|
|
4073
|
-
const { runEmit, EmitError } = await import('./emit-cmd-
|
|
4170
|
+
const { runEmit, EmitError } = await import('./emit-cmd-PPN4QQF2.js');
|
|
4074
4171
|
try {
|
|
4075
4172
|
const result = runEmit({ cwd: opts.dir, check: opts.check, json: opts.json });
|
|
4076
4173
|
if (result.exitCode !== 0) process.exitCode = result.exitCode;
|
|
@@ -4085,15 +4182,39 @@ async function compileContext(opts) {
|
|
|
4085
4182
|
function registerEmitCommands(program2) {
|
|
4086
4183
|
const emitCmd = program2.command("emit").enablePositionalOptions().description("Record evidence for a work item: a named check result").argument("[name]", "the check name a validator declares (e.g. smoke.pass)").option("--link <url>", "proof link, usually the CI run URL").option("--body <text>", "one sentence recording your judgment").option("--body-file <path>", "read the sentence from a file; - reads standard input").option("--result <pass|fail>", "check outcome (default: pass)").option("--item <number>", "work item to record on directly, by its number in this factory").option("--json", "machine-readable JSON output").option("--url <url>", "cloud base URL (or OUTERLAYER_URL / config)").addOption(apiKeyOption()).option("--app-id <id>", "factory id the key is bound to (or OUTERLAYER_APP_ID / config)").addOption(new Option("--check", "deprecated: use `context emit --check`").hideHelp()).addOption(new Option("--dir <path>", "deprecated: use `context emit --dir`").hideHelp()).addHelpText(
|
|
4087
4184
|
"after",
|
|
4088
|
-
|
|
4185
|
+
`
|
|
4186
|
+
${cliInvocation()} emit smoke.pass --item 412 --link https://ci.example.com/run/42
|
|
4187
|
+
${cliInvocation()} emit code-review --result fail --item 412 --body "The button should be red."
|
|
4188
|
+
|
|
4189
|
+
Records that a named check passed or failed, anchored to a work item.
|
|
4190
|
+
--item is always required, in or out of a recorded session \u2014 there is no
|
|
4191
|
+
session fallback. A check that ran carries the run URL as proof (--link);
|
|
4192
|
+
a judgment you are making yourself carries one sentence (--body, or
|
|
4193
|
+
--body-file to read it from a file or standard input). A fail needs at
|
|
4194
|
+
least one of the two. Run from inside a session, the check is stored as
|
|
4195
|
+
the session's; a session cannot record over a person's fail. With
|
|
4196
|
+
nothing to attach it to, the command refuses.
|
|
4197
|
+
|
|
4198
|
+
Who recorded a check is decided by your API key, never by what you send:
|
|
4199
|
+
a key bound to your membership records it as yours, and nothing automated
|
|
4200
|
+
can then clear it.
|
|
4201
|
+
|
|
4202
|
+
A person's pass or fail on one criterion's proof is recorded on that
|
|
4203
|
+
criterion's thread instead \u2014 see \`${cliInvocation()} work comment\`.
|
|
4204
|
+
|
|
4205
|
+
Subcommands: \`emit artifact <file>\` for screenshots, recordings, reports and
|
|
4206
|
+
logs; \`emit finding\` / \`emit findings <file>\` to record a problem in the factory;
|
|
4207
|
+
\`emit criteria <file>\` to record a work item's acceptance criteria.
|
|
4208
|
+
Compiling .outerlayer/ moved to \`${cliInvocation()} context emit\`.
|
|
4209
|
+
`
|
|
4089
4210
|
).action(async (name, opts) => {
|
|
4090
4211
|
if (name === void 0) {
|
|
4091
|
-
warnDeprecated(
|
|
4212
|
+
warnDeprecated(`\`${cliInvocation()} emit\` with no name now lives at \`${cliInvocation()} context emit\`; the bare form will be removed in a future release.`);
|
|
4092
4213
|
await compileContext({ dir: opts.dir, check: opts.check, json: opts.json });
|
|
4093
4214
|
return;
|
|
4094
4215
|
}
|
|
4095
4216
|
warnIfApiKeyFlag(opts);
|
|
4096
|
-
const { runEmitResult, EmitResultError } = await import('./emit-result-cmd-
|
|
4217
|
+
const { runEmitResult, EmitResultError } = await import('./emit-result-cmd-UZVMOCF4.js');
|
|
4097
4218
|
try {
|
|
4098
4219
|
const result = await runEmitResult({
|
|
4099
4220
|
name,
|
|
@@ -4123,10 +4244,10 @@ function registerEmitCommands(program2) {
|
|
|
4123
4244
|
).option("--replaces <ids>", "artifact id(s) this one corrects; comma-separate 2-20 to retire them all").option("--pr <number>", "pull request number to anchor to").option("--json", "machine-readable JSON output").option("--url <url>", "cloud base URL (or OUTERLAYER_URL / config)").addOption(apiKeyOption()).option("--app-id <id>", "factory id the key is bound to (or OUTERLAYER_APP_ID / config)").addHelpText(
|
|
4124
4245
|
"after",
|
|
4125
4246
|
`
|
|
4126
|
-
|
|
4247
|
+
${cliInvocation()} emit artifact shot.png --caption "the dot row, current dot marked" --for LOGIN-01
|
|
4127
4248
|
|
|
4128
4249
|
Inside a recorded Claude Code session the artifact spools locally and ships,
|
|
4129
|
-
bound to that session, on the next
|
|
4250
|
+
bound to that session, on the next \`${cliInvocation()} sync\` \u2014 but only if that
|
|
4130
4251
|
session was launched with OUTERLAYER_WORK; without it nothing the session
|
|
4131
4252
|
produces may leave the machine, and the command refuses rather than queue an
|
|
4132
4253
|
artifact that can never ship. Otherwise it uploads immediately, anchored to a
|
|
@@ -4144,7 +4265,7 @@ locally so it never uploads. One correction can retire several duplicates.
|
|
|
4144
4265
|
`
|
|
4145
4266
|
).action(async (file, opts) => {
|
|
4146
4267
|
warnIfApiKeyFlag(opts);
|
|
4147
|
-
const { runEmitArtifact, EmitArtifactError } = await import('./emit-artifact-cmd-
|
|
4268
|
+
const { runEmitArtifact, EmitArtifactError } = await import('./emit-artifact-cmd-7MP63KXU.js');
|
|
4148
4269
|
let pr;
|
|
4149
4270
|
if (opts.pr !== void 0) {
|
|
4150
4271
|
pr = parseTrackerNumber(opts.pr);
|
|
@@ -4176,10 +4297,35 @@ locally so it never uploads. One correction can retire several duplicates.
|
|
|
4176
4297
|
});
|
|
4177
4298
|
emitCmd.command("finding").description("Record one finding: a problem you hit in the factory").requiredOption("--id <id>", "client id \u2014 re-emitting the same id replaces it").option("--category <context|flaky-test|tooling|environment|defect|other>", "what kind of problem this is").requiredOption("--title <text>", "one sentence").requiredOption("--file <path>", "the file the problem is in, or the instruction's own path").option("--line <number>", "line number in --file").option("--rule-path <path>", "the instruction's own path \u2014 required for a context finding").option("--rule-line <number>", "line number in --rule-path").option("--rule-quote <text>", "the instruction's quoted sentence \u2014 required unless --rule-relation is missing").option("--rule-relation <wrong|broken|missing>", "how the instruction fails \u2014 required for a context finding").requiredOption("--where <label>", 'where this was recorded, e.g. "build session"').option("--detail <text>", "what happened, a few paragraphs").option("--cause <text>", 'what is actually wrong, or "unknown"').option("--suggestion <text>", "what would help").option("--command <text>", "the command that misbehaved").option("--error <text>", "the first error line").option("--test <name>", "the test name, for a flaky test").option("--symbol <name>", "the function the problem is in, for a defect").option("--started-at <event>", "event id where you hit the problem (default: first output showing --error)").option("--ended-at <event>", "event id where you got past it (default: the newest event)").option("--untimed", "record no time, only when the problem cost none in this session").option("--find <text>", "list this session's events that contain the text, and record nothing").option("--problem <id>", "a problem this finding reports; repeat for each one (needs --link-reason)", (value, previous = []) => [...previous, value]).option("--link-reason <text>", "why the finding reports each --problem").option("--new", "record a new problem instead of linking an existing one").option("--trace-id <id>", "the session's trace id, when there is one").option("--turn <number>", "turn index within the session").option("--round <number>", "round number, when there is one").addOption(new Option("--subject <value>").hideHelp()).addOption(new Option("--kind <value>").hideHelp()).addOption(new Option("--severity <value>").hideHelp()).addOption(new Option("--verdict <value>").hideHelp()).addOption(new Option("--fixed").hideHelp()).addOption(new Option("--source <value>").hideHelp()).option("--head-sha <sha>", "the commit this batch was recorded against").option("--context-source-sha <sha>", "the context-source commit this batch was recorded against").option("--item <number>", "work item to record on directly, by its number in this factory").option("--json", "machine-readable JSON output").option("--url <url>", "cloud base URL (or OUTERLAYER_URL / config)").addOption(apiKeyOption()).option("--app-id <id>", "factory id the key is bound to (or OUTERLAYER_APP_ID / config)").addHelpText(
|
|
4178
4299
|
"after",
|
|
4179
|
-
|
|
4300
|
+
`
|
|
4301
|
+
${cliInvocation()} emit finding --id gate-skip --category tooling \\
|
|
4302
|
+
--title "The pre-push gate prints green when a step was skipped" \\
|
|
4303
|
+
--file scripts/git/pre-push-checks.mjs --where "build session"
|
|
4304
|
+
|
|
4305
|
+
Records one problem you hit in the factory: an instruction that is wrong or
|
|
4306
|
+
missing (context), a flaky test, a misbehaving script (tooling), a local
|
|
4307
|
+
setup trap (environment), a bug outside your own change (defect), or
|
|
4308
|
+
anything else. A problem in your own change is fixed, not recorded.
|
|
4309
|
+
A context finding needs --rule-path and --rule-relation, and --rule-quote
|
|
4310
|
+
unless the relation is missing. Add --cause, --detail and --suggestion, and
|
|
4311
|
+
--command, --error (first error line), --test or --symbol when there is one.
|
|
4312
|
+
|
|
4313
|
+
Every finding joins a factory-level problem. When one of its keys matches a
|
|
4314
|
+
known problem it joins that problem. Otherwise nothing is stored: the command
|
|
4315
|
+
prints the closest problems and exits with code 3. Run it again with
|
|
4316
|
+
--problem <id> --link-reason <why> (repeat --problem for each problem the
|
|
4317
|
+
finding reports), or with --new if none of them is the same problem.
|
|
4318
|
+
A finding records the time it cost, read from two events of your session or
|
|
4319
|
+
its subagents. The start is --started-at, else the first tool output that
|
|
4320
|
+
shows --error. The end is --ended-at, else the newest event. When the session
|
|
4321
|
+
has events and no start is found, nothing is stored: the command lists the
|
|
4322
|
+
recent events with their ids. --find <text> searches all of them.
|
|
4323
|
+
--item names the work item; without it, inside a recorded session, the
|
|
4324
|
+
item that session was launched for is used automatically.
|
|
4325
|
+
`
|
|
4180
4326
|
).action(async (opts) => {
|
|
4181
4327
|
warnIfApiKeyFlag(opts);
|
|
4182
|
-
const { runEmitFinding, refuseRemovedFindingFlags, EmitFindingError } = await import('./emit-finding-cmd-
|
|
4328
|
+
const { runEmitFinding, refuseRemovedFindingFlags, EmitFindingError } = await import('./emit-finding-cmd-OL7JB6H3.js');
|
|
4183
4329
|
try {
|
|
4184
4330
|
refuseRemovedFindingFlags(opts);
|
|
4185
4331
|
const result = await runEmitFinding({
|
|
@@ -4229,10 +4375,25 @@ locally so it never uploads. One correction can retire several duplicates.
|
|
|
4229
4375
|
});
|
|
4230
4376
|
emitCmd.command("findings <file>").description("Record a batch of findings from a FindingBatch JSON file (- for standard input)").option("--item <number>", "work item to record on directly, by its number in this factory").option("--json", "machine-readable JSON output").option("--url <url>", "cloud base URL (or OUTERLAYER_URL / config)").addOption(apiKeyOption()).option("--app-id <id>", "factory id the key is bound to (or OUTERLAYER_APP_ID / config)").addHelpText(
|
|
4231
4377
|
"after",
|
|
4232
|
-
|
|
4378
|
+
`
|
|
4379
|
+
${cliInvocation()} emit findings review.json --item 412
|
|
4380
|
+
|
|
4381
|
+
Records a whole batch at once \u2014 a FindingBatch JSON file (schemaVersion 3,
|
|
4382
|
+
optional headSha / contextSourceSha, and 1-500 findings), validated against
|
|
4383
|
+
the same contract \`emit finding\` uses before anything is sent. Re-emitting
|
|
4384
|
+
an id already on the item replaces that row rather than adding a second one.
|
|
4385
|
+
Findings that need a choice between candidate problems are listed and not
|
|
4386
|
+
stored; the rest are stored, and the exit code is 3.
|
|
4387
|
+
Each finding records its time as \`emit finding\` does: "startedAt" is an event
|
|
4388
|
+
id, else the first tool output that shows its "error"; "endedAt" defaults to
|
|
4389
|
+
the newest event. A finding with neither, in a session that has events, stops
|
|
4390
|
+
the whole batch. "untimed": true records one with no time on purpose.
|
|
4391
|
+
--item names the work item; without it, inside a recorded session, the item
|
|
4392
|
+
that session was launched for is used automatically.
|
|
4393
|
+
`
|
|
4233
4394
|
).action(async (file, opts) => {
|
|
4234
4395
|
warnIfApiKeyFlag(opts);
|
|
4235
|
-
const { runEmitFindings, EmitFindingError } = await import('./emit-finding-cmd-
|
|
4396
|
+
const { runEmitFindings, EmitFindingError } = await import('./emit-finding-cmd-OL7JB6H3.js');
|
|
4236
4397
|
try {
|
|
4237
4398
|
const result = await runEmitFindings({
|
|
4238
4399
|
file,
|
|
@@ -4254,7 +4415,7 @@ locally so it never uploads. One correction can retire several duplicates.
|
|
|
4254
4415
|
emitCmd.command("criteria <file>").description("Record a work item's acceptance criteria from a JSON file (- for stdin)").option("--item <number>", "work item to record on directly, by its number in this factory").option("--json", "machine-readable JSON output").option("--url <url>", "cloud base URL (or OUTERLAYER_URL / config)").addOption(apiKeyOption()).option("--app-id <id>", "factory id the key is bound to (or OUTERLAYER_APP_ID / config)").addHelpText(
|
|
4255
4416
|
"after",
|
|
4256
4417
|
`
|
|
4257
|
-
|
|
4418
|
+
${cliInvocation()} emit criteria criteria.json --item 412
|
|
4258
4419
|
|
|
4259
4420
|
Records the item's acceptance criteria as one list. The file is JSON:
|
|
4260
4421
|
{ "criteria": [ { "id": "AC-1", "text": "Given ...", "proof": null },
|
|
@@ -4272,7 +4433,7 @@ session was launched for is used automatically.
|
|
|
4272
4433
|
`
|
|
4273
4434
|
).action(async (file, opts) => {
|
|
4274
4435
|
warnIfApiKeyFlag(opts);
|
|
4275
|
-
const { runEmitCriteria, EmitCriteriaError } = await import('./emit-criteria-cmd-
|
|
4436
|
+
const { runEmitCriteria, EmitCriteriaError } = await import('./emit-criteria-cmd-3RXPDLNK.js');
|
|
4276
4437
|
try {
|
|
4277
4438
|
const result = await runEmitCriteria({
|
|
4278
4439
|
file,
|
|
@@ -4292,14 +4453,56 @@ session was launched for is used automatically.
|
|
|
4292
4453
|
}
|
|
4293
4454
|
});
|
|
4294
4455
|
}
|
|
4456
|
+
function registerSpecCommands(program2) {
|
|
4457
|
+
const specCmd = program2.command("spec").description("Find, file and edit the issue a spec lives in, in your factory's tracker");
|
|
4458
|
+
const credentialOptions = (command) => command.option("--json", "machine-readable JSON output").option("--url <url>", "cloud base URL (or OUTERLAYER_URL / config)").addOption(apiKeyOption()).option("--app-id <id>", "factory id the key is bound to (or OUTERLAYER_APP_ID / config)");
|
|
4459
|
+
const run = async (opts, action) => {
|
|
4460
|
+
warnIfApiKeyFlag(opts);
|
|
4461
|
+
const { WorkCommandError } = await import('./work-cmd-7S5B2H2P.js');
|
|
4462
|
+
try {
|
|
4463
|
+
await action(await import('./spec-cmd-OWVTBB4J.js'));
|
|
4464
|
+
} catch (err) {
|
|
4465
|
+
if (err instanceof WorkCommandError) {
|
|
4466
|
+
fail(err.message);
|
|
4467
|
+
return;
|
|
4468
|
+
}
|
|
4469
|
+
throw err;
|
|
4470
|
+
}
|
|
4471
|
+
};
|
|
4472
|
+
credentialOptions(
|
|
4473
|
+
specCmd.command("target").description("Say where a spec would be filed, and whether this factory can file there").option("--tracker <name>", "one connected tracker, when the factory has more than one")
|
|
4474
|
+
).action((opts) => run(opts, (spec) => spec.runSpecTarget(opts)));
|
|
4475
|
+
credentialOptions(
|
|
4476
|
+
specCmd.command("search").description("Find open and closed issues that match a query, before filing a duplicate").argument("<query>", "words from the title or body").option("--tracker <name>", "one connected tracker, when the factory has more than one")
|
|
4477
|
+
).action((query, opts) => run(opts, (spec) => spec.runSpecSearch({ ...opts, query })));
|
|
4478
|
+
credentialOptions(
|
|
4479
|
+
specCmd.command("file").description("File a spec as an issue and print its key, URL and the command that builds it").requiredOption("--title <text>", "the issue title").option("--body-file <path>", "the spec as Markdown; - reads standard input").option("--repo <owner/name>", "the repository to file in (GitHub), or the one the work lands in").option("--tracker <name>", "the tracker, when the factory files in more than one").option("--scope <key>", "the Linear team or Jira project, when the connection covers several")
|
|
4480
|
+
).action((opts) => run(opts, (spec) => spec.runSpecFile(opts)));
|
|
4481
|
+
credentialOptions(
|
|
4482
|
+
specCmd.command("edit").description("Replace the body of an issue that holds a spec").argument("<key>", "the issue key, such as acme/api#12 or ENG-142").option("--body-file <path>", "the new body as Markdown; - reads standard input").option("--updated-at <timestamp>", "the updatedAt you read; the edit is refused if the issue has changed since")
|
|
4483
|
+
).action((key, opts) => run(opts, (spec) => spec.runSpecEdit({ ...opts, key })));
|
|
4484
|
+
}
|
|
4295
4485
|
function registerWorkCommands(program2) {
|
|
4296
4486
|
const workCmd = program2.command("work").description("Start, remove, or read what the factory is working on (the Work page)");
|
|
4297
|
-
workCmd.command("build").description("Start work on an item: a host builds it, or with --local you do").option("--issue <number>", "issue number, or a Linear/Jira key like ENG-123 (adds it to Work first)").option(
|
|
4487
|
+
workCmd.command("build").description("Start work on an item: a host builds it, or with --local you do").option("--issue <number>", "issue number, or a Linear/Jira key like ENG-123 (adds it to Work first)").option(TRACKER_OPTION_FLAG, "tracker for a keyed --issue \u2014 required if more than one is connected").option("--item <number>", "the item's own number inside this factory \u2014 must already exist").option("--local", "you build it in a session you start; no host takes it").option("--repo <owner/name>", "repository \u2014 the checkout's remote for a number, never guessed for a key").option("--note <text>", "a short note stored with the request").option("--session-id <id>", "session id to record as-is, skipping detection").option("--retry <count>", "retries after a gateway answer worth trying again").option("--json", "machine-readable JSON output").option("--url <url>", "cloud base URL (or OUTERLAYER_URL / config)").addOption(apiKeyOption()).option("--app-id <id>", "factory id the key is bound to (or OUTERLAYER_APP_ID / config)").addHelpText(
|
|
4298
4488
|
"after",
|
|
4299
|
-
|
|
4489
|
+
`
|
|
4490
|
+
${cliInvocation()} work build --issue 42 # a host builds it
|
|
4491
|
+
${cliInvocation()} work build --item 7 # retry an item already on Work
|
|
4492
|
+
${cliInvocation()} work build --issue 42 --local # you build it
|
|
4493
|
+
${cliInvocation()} work build --issue ENG-123 --tracker linear # a Linear issue
|
|
4494
|
+
|
|
4495
|
+
Without --local, records a build request: a host takes the item when it
|
|
4496
|
+
has a free slot. It never links the calling session and never takes a
|
|
4497
|
+
lease, even run from inside one.
|
|
4498
|
+
|
|
4499
|
+
With --local, puts the item on Work with no build request, so no host
|
|
4500
|
+
takes it, and prints the line that starts your session on it. That
|
|
4501
|
+
session links itself and holds the item's lease while it works.
|
|
4502
|
+
`
|
|
4300
4503
|
).action(async (opts) => {
|
|
4301
4504
|
warnIfApiKeyFlag(opts);
|
|
4302
|
-
const { runWorkBuild, WorkCommandError } = await import('./work-cmd-
|
|
4505
|
+
const { runWorkBuild, WorkCommandError } = await import('./work-cmd-7S5B2H2P.js');
|
|
4303
4506
|
try {
|
|
4304
4507
|
await runWorkBuild(opts);
|
|
4305
4508
|
} catch (err) {
|
|
@@ -4312,10 +4515,18 @@ function registerWorkCommands(program2) {
|
|
|
4312
4515
|
});
|
|
4313
4516
|
workCmd.command("link-session").description("Link the calling session to a work item that already exists").argument("<number>", "the item's number inside this factory").option("--session-id <id>", "session id to record as-is, skipping detection (used by the SessionStart hook)").option("--retry <count>", "resend after a failure that may pass, with backoff").option("--no-lease", "link only \u2014 ask for no session lease (used by a host's own job)").option("--ended", "release this session's lease instead of taking or renewing one").addOption(new Option("--log-failures", "append a failure to the hook error log (used by hooks)").hideHelp()).option("--json", "machine-readable JSON output").option("--url <url>", "cloud base URL (or OUTERLAYER_URL / config)").addOption(apiKeyOption()).option("--app-id <id>", "factory id the key is bound to (or OUTERLAYER_APP_ID / config)").addHelpText(
|
|
4314
4517
|
"after",
|
|
4315
|
-
|
|
4518
|
+
`
|
|
4519
|
+
${cliInvocation()} work link-session 42
|
|
4520
|
+
|
|
4521
|
+
Names an item that already exists on the calling session \u2014 it never
|
|
4522
|
+
creates one. Create one with \`${cliInvocation()} work build --local\`. Linking
|
|
4523
|
+
the same session to the same item twice is a no-op. Also takes or
|
|
4524
|
+
renews that session's own 20-minute lease, unless --no-lease or
|
|
4525
|
+
--ended is given, or another worker already holds a live one.
|
|
4526
|
+
`
|
|
4316
4527
|
).action(async (number, opts) => {
|
|
4317
4528
|
warnIfApiKeyFlag(opts);
|
|
4318
|
-
const { runWorkLinkSession, WorkCommandError } = await import('./work-cmd-
|
|
4529
|
+
const { runWorkLinkSession, WorkCommandError } = await import('./work-cmd-7S5B2H2P.js');
|
|
4319
4530
|
try {
|
|
4320
4531
|
await runWorkLinkSession({ ...opts, number, noLease: opts.lease === false, logFailures: opts.logFailures === true });
|
|
4321
4532
|
} catch (err) {
|
|
@@ -4329,7 +4540,7 @@ function registerWorkCommands(program2) {
|
|
|
4329
4540
|
workCmd.command("comment").description("Post a comment on a work item's general thread or one of its criterion threads").requiredOption("--item <number>", "the item's number inside this factory").option("--criterion <id>", "the criterion thread to post on (default: the general thread)").option("--body <text>", "the comment's text").option("--artifact <id>", "artifact id \u2014 required with --attach, naming the criterion's new proof").option("--pass", "record a pass (a person's verdict; refused from an agent session or a key)").option("--fail", "record a fail (a person's verdict; refused from an agent session or a key)").option("--attach", "make --artifact the named criterion's proof").option("--ready", "hand the thread back to a person (refused from a person)").option("--session-id <id>", "session id to record as-is, skipping detection (used by the SessionStart hook)").option("--json", "machine-readable JSON output").option("--url <url>", "cloud base URL (or OUTERLAYER_URL / config)").addOption(apiKeyOption()).option("--app-id <id>", "factory id the key is bound to (or OUTERLAYER_APP_ID / config)").addHelpText(
|
|
4330
4541
|
"after",
|
|
4331
4542
|
`
|
|
4332
|
-
|
|
4543
|
+
${cliInvocation()} work comment --item 7 --criterion AC-9-01 --body "fixed" --artifact 3f2a1c9d --attach
|
|
4333
4544
|
|
|
4334
4545
|
Posts one comment. Omitting --criterion posts on the general thread;
|
|
4335
4546
|
naming one posts on that criterion's own thread. --pass/--fail are a
|
|
@@ -4340,8 +4551,8 @@ most one action flag may be given.
|
|
|
4340
4551
|
`
|
|
4341
4552
|
).action(async (opts) => {
|
|
4342
4553
|
warnIfApiKeyFlag(opts);
|
|
4343
|
-
const { runWorkComment, WorkCommentCommandError } = await import('./work-comment-cmd-
|
|
4344
|
-
const { WorkCommandError } = await import('./work-cmd-
|
|
4554
|
+
const { runWorkComment, WorkCommentCommandError } = await import('./work-comment-cmd-SZJSPM5S.js');
|
|
4555
|
+
const { WorkCommandError } = await import('./work-cmd-7S5B2H2P.js');
|
|
4345
4556
|
try {
|
|
4346
4557
|
await runWorkComment(opts);
|
|
4347
4558
|
} catch (err) {
|
|
@@ -4354,11 +4565,17 @@ most one action flag may be given.
|
|
|
4354
4565
|
});
|
|
4355
4566
|
workCmd.command("threads").description("Read a work item's general thread and its criterion threads").requiredOption("--item <number>", "the item's number inside this factory").option("--json", "machine-readable JSON output").option("--url <url>", "cloud base URL (or OUTERLAYER_URL / config)").addOption(apiKeyOption()).option("--app-id <id>", "factory id the key is bound to (or OUTERLAYER_APP_ID / config)").addHelpText(
|
|
4356
4567
|
"after",
|
|
4357
|
-
|
|
4568
|
+
`
|
|
4569
|
+
${cliInvocation()} work threads --item 7
|
|
4570
|
+
|
|
4571
|
+
Prints the item's general thread, then one thread per acceptance
|
|
4572
|
+
criterion that carries proof or a comment, each with who is waiting
|
|
4573
|
+
on whom next.
|
|
4574
|
+
`
|
|
4358
4575
|
).action(async (opts) => {
|
|
4359
4576
|
warnIfApiKeyFlag(opts);
|
|
4360
|
-
const { runWorkThreads, WorkCommentCommandError } = await import('./work-comment-cmd-
|
|
4361
|
-
const { WorkCommandError } = await import('./work-cmd-
|
|
4577
|
+
const { runWorkThreads, WorkCommentCommandError } = await import('./work-comment-cmd-SZJSPM5S.js');
|
|
4578
|
+
const { WorkCommandError } = await import('./work-cmd-7S5B2H2P.js');
|
|
4362
4579
|
try {
|
|
4363
4580
|
await runWorkThreads(opts);
|
|
4364
4581
|
} catch (err) {
|
|
@@ -4369,10 +4586,10 @@ most one action flag may be given.
|
|
|
4369
4586
|
throw err;
|
|
4370
4587
|
}
|
|
4371
4588
|
});
|
|
4372
|
-
workCmd.command("remove").description("Withdraw a source's addition \u2014 never deletes the item").option("--item <number>", "the item's number inside this factory").option("--issue <number>", "issue number (default: named by --item instead)").option("--repo <owner/name>", "repository (default: the
|
|
4589
|
+
workCmd.command("remove").description("Withdraw a source's addition \u2014 never deletes the item").option("--item <number>", "the item's number inside this factory").option("--issue <number>", "issue number or Linear/Jira key (default: named by --item instead)").option(TRACKER_OPTION_FLAG, "tracker for a keyed --issue, when both hold the key").option("--repo <owner/name>", "repository for an issue number (default: the checkout's remote)").requiredOption("--reason <text>", "why this source is no longer working on it").option("--json", "machine-readable JSON output").option("--url <url>", "cloud base URL (or OUTERLAYER_URL / config)").addOption(apiKeyOption()).option("--app-id <id>", "factory id the key is bound to (or OUTERLAYER_APP_ID / config)").addHelpText(
|
|
4373
4590
|
"after",
|
|
4374
4591
|
`
|
|
4375
|
-
|
|
4592
|
+
${cliInvocation()} work remove --item 42 --reason "done"
|
|
4376
4593
|
|
|
4377
4594
|
Withdraws the caller's own addition, recording the reason. Never
|
|
4378
4595
|
deletes anything \u2014 the item is removed from Work only once no
|
|
@@ -4380,7 +4597,7 @@ live addition remains on it.
|
|
|
4380
4597
|
`
|
|
4381
4598
|
).action(async (opts) => {
|
|
4382
4599
|
warnIfApiKeyFlag(opts);
|
|
4383
|
-
const { runWorkRemove, WorkCommandError } = await import('./work-cmd-
|
|
4600
|
+
const { runWorkRemove, WorkCommandError } = await import('./work-cmd-7S5B2H2P.js');
|
|
4384
4601
|
try {
|
|
4385
4602
|
await runWorkRemove(opts);
|
|
4386
4603
|
} catch (err) {
|
|
@@ -4391,9 +4608,9 @@ live addition remains on it.
|
|
|
4391
4608
|
throw err;
|
|
4392
4609
|
}
|
|
4393
4610
|
});
|
|
4394
|
-
workCmd.command("status").description("Show one item's stage, gate ledger, and additions").option("--item <number>", "the item's number inside this factory").option("--issue <number>", "issue number").option("--repo <owner/name>", "repository (default: the
|
|
4611
|
+
workCmd.command("status").description("Show one item's stage, gate ledger, and additions").option("--item <number>", "the item's number inside this factory").option("--issue <number>", "issue number, or a Linear/Jira key like ENG-123").option(TRACKER_OPTION_FLAG, "tracker for a keyed --issue, when both hold the key").option("--repo <owner/name>", "repository for an issue number (default: the checkout's remote)").option("--json", "machine-readable JSON output").option("--url <url>", "cloud base URL (or OUTERLAYER_URL / config)").addOption(apiKeyOption()).option("--app-id <id>", "factory id the key is bound to (or OUTERLAYER_APP_ID / config)").action(async (opts) => {
|
|
4395
4612
|
warnIfApiKeyFlag(opts);
|
|
4396
|
-
const { runWorkStatus, WorkCommandError } = await import('./work-cmd-
|
|
4613
|
+
const { runWorkStatus, WorkCommandError } = await import('./work-cmd-7S5B2H2P.js');
|
|
4397
4614
|
try {
|
|
4398
4615
|
await runWorkStatus(opts);
|
|
4399
4616
|
} catch (err) {
|
|
@@ -4406,7 +4623,7 @@ live addition remains on it.
|
|
|
4406
4623
|
});
|
|
4407
4624
|
workCmd.command("list").description("List live work items for this factory").option("--stage <spec|build|review>", "filter by stage").option("--section <attention|waiting|flowing>", "filter by Queue section").option("--repo <owner/name>", "repository (default: the current checkout's remote)").option("--unclaimed", "only items with no live lease").option("--claimed", "only items with a live lease, held by a host or a local session").option("--startable", "only items a host can start: a build request, no open PR, no live lease").option("--needs <amend>", "only items with a thread waiting on an agent").option("--json", "machine-readable JSON output").option("--url <url>", "cloud base URL (or OUTERLAYER_URL / config)").addOption(apiKeyOption()).option("--app-id <id>", "factory id the key is bound to (or OUTERLAYER_APP_ID / config)").action(async (opts) => {
|
|
4408
4625
|
warnIfApiKeyFlag(opts);
|
|
4409
|
-
const { runWorkList, WorkCommandError } = await import('./work-cmd-
|
|
4626
|
+
const { runWorkList, WorkCommandError } = await import('./work-cmd-7S5B2H2P.js');
|
|
4410
4627
|
try {
|
|
4411
4628
|
await runWorkList(opts);
|
|
4412
4629
|
} catch (err) {
|
|
@@ -4417,12 +4634,18 @@ live addition remains on it.
|
|
|
4417
4634
|
throw err;
|
|
4418
4635
|
}
|
|
4419
4636
|
});
|
|
4420
|
-
workCmd.command("claim").description("Claim a work item under a lease this API key holds before working on it").option("--item <number>", "the item's number inside this factory").option("--issue <number>", "issue number (default: named by --item instead)").option("--repo <owner/name>", "repository (default: the
|
|
4637
|
+
workCmd.command("claim").description("Claim a work item under a lease this API key holds before working on it").option("--item <number>", "the item's number inside this factory").option("--issue <number>", "issue number or Linear/Jira key (default: named by --item instead)").option(TRACKER_OPTION_FLAG, "tracker for a keyed --issue, when both hold the key").option("--repo <owner/name>", "repository for an issue number (default: the checkout's remote)").requiredOption("--kind <implement|amend>", "what this host is doing with the item").option("--host <name>", "the claiming host (default: this machine's hostname)").option("--seconds <n>", "lease length in seconds, clamped to 900 (default: 900)").option("--json", "machine-readable JSON output").option("--url <url>", "cloud base URL (or OUTERLAYER_URL / config)").addOption(apiKeyOption()).option("--app-id <id>", "factory id the key is bound to (or OUTERLAYER_APP_ID / config)").addHelpText(
|
|
4421
4638
|
"after",
|
|
4422
|
-
|
|
4639
|
+
`
|
|
4640
|
+
${cliInvocation()} work claim --item 42 --kind implement
|
|
4641
|
+
|
|
4642
|
+
Records a lease held by the API key that sends it. A live lease held
|
|
4643
|
+
by a different key is refused; claiming again with the same key extends
|
|
4644
|
+
it. --host is a label only.
|
|
4645
|
+
`
|
|
4423
4646
|
).action(async (opts) => {
|
|
4424
4647
|
warnIfApiKeyFlag(opts);
|
|
4425
|
-
const { runWorkClaim, WorkCommandError } = await import('./work-claim-cmd-
|
|
4648
|
+
const { runWorkClaim, WorkCommandError } = await import('./work-claim-cmd-34FERLYX.js');
|
|
4426
4649
|
try {
|
|
4427
4650
|
await runWorkClaim(opts);
|
|
4428
4651
|
} catch (err) {
|
|
@@ -4433,12 +4656,17 @@ live addition remains on it.
|
|
|
4433
4656
|
throw err;
|
|
4434
4657
|
}
|
|
4435
4658
|
});
|
|
4436
|
-
workCmd.command("renew").description("Extend the lease this API key holds on a work item").option("--item <number>", "the item's number inside this factory").option("--issue <number>", "issue number (default: named by --item instead)").option("--repo <owner/name>", "repository (default: the
|
|
4659
|
+
workCmd.command("renew").description("Extend the lease this API key holds on a work item").option("--item <number>", "the item's number inside this factory").option("--issue <number>", "issue number or Linear/Jira key (default: named by --item instead)").option(TRACKER_OPTION_FLAG, "tracker for a keyed --issue, when both hold the key").option("--repo <owner/name>", "repository for an issue number (default: the checkout's remote)").option("--host <name>", "the claiming host (default: this machine's hostname)").option("--seconds <n>", "lease length in seconds, clamped to 900 (default: 900)").option("--json", "machine-readable JSON output").option("--url <url>", "cloud base URL (or OUTERLAYER_URL / config)").addOption(apiKeyOption()).option("--app-id <id>", "factory id the key is bound to (or OUTERLAYER_APP_ID / config)").addHelpText(
|
|
4437
4660
|
"after",
|
|
4438
|
-
|
|
4661
|
+
`
|
|
4662
|
+
${cliInvocation()} work renew --item 42
|
|
4663
|
+
|
|
4664
|
+
Extends the live lease this API key holds. Refused with a 410 if the
|
|
4665
|
+
lease has expired, or a 403 if a different key holds it.
|
|
4666
|
+
`
|
|
4439
4667
|
).action(async (opts) => {
|
|
4440
4668
|
warnIfApiKeyFlag(opts);
|
|
4441
|
-
const { runWorkRenew, WorkCommandError } = await import('./work-claim-cmd-
|
|
4669
|
+
const { runWorkRenew, WorkCommandError } = await import('./work-claim-cmd-34FERLYX.js');
|
|
4442
4670
|
try {
|
|
4443
4671
|
await runWorkRenew(opts);
|
|
4444
4672
|
} catch (err) {
|
|
@@ -4449,15 +4677,29 @@ live addition remains on it.
|
|
|
4449
4677
|
throw err;
|
|
4450
4678
|
}
|
|
4451
4679
|
});
|
|
4452
|
-
workCmd.command("release").description("Release the lease this API key holds on a work item, or this session's own lease").option("--item <number>", "the item's number inside this factory").option("--issue <number>", "issue number (default: named by --item instead)").option("--repo <owner/name>", "repository (default: the
|
|
4680
|
+
workCmd.command("release").description("Release the lease this API key holds on a work item, or this session's own lease").option("--item <number>", "the item's number inside this factory").option("--issue <number>", "issue number or Linear/Jira key (default: named by --item instead)").option(TRACKER_OPTION_FLAG, "tracker for a keyed --issue, when both hold the key").option("--repo <owner/name>", "repository for an issue number (default: the checkout's remote)").option("--host <name>", "the claiming host (default: this machine's hostname); releases a host's lease").option("--session-id <id>", "the session whose lease to release, skipping detection").option(
|
|
4453
4681
|
"--outcome <ok|incomplete|failed|timed_out|idle|lease_lost|interrupted|stopped>",
|
|
4454
4682
|
"how a host's attempt ended (default: none)"
|
|
4455
4683
|
).option("--json", "machine-readable JSON output").option("--url <url>", "cloud base URL (or OUTERLAYER_URL / config)").addOption(apiKeyOption()).option("--app-id <id>", "factory id the key is bound to (or OUTERLAYER_APP_ID / config)").addHelpText(
|
|
4456
4684
|
"after",
|
|
4457
|
-
|
|
4685
|
+
`
|
|
4686
|
+
${cliInvocation()} work release --item 42 --outcome ok
|
|
4687
|
+
${cliInvocation()} work release --item 42
|
|
4688
|
+
|
|
4689
|
+
Marks the lease this API key holds released, optionally with an
|
|
4690
|
+
outcome. A lease held by a different key is refused. Releasing an
|
|
4691
|
+
already-released lease is a no-op that returns the recorded release
|
|
4692
|
+
time and outcome.
|
|
4693
|
+
|
|
4694
|
+
Run inside a session with no --host, it releases that session's own
|
|
4695
|
+
lease instead, so the item's review opens without ending the
|
|
4696
|
+
session. It never releases another session's lease. --outcome
|
|
4697
|
+
applies to a host's lease only. A later tool call in the session
|
|
4698
|
+
takes the lease again.
|
|
4699
|
+
`
|
|
4458
4700
|
).action(async (opts) => {
|
|
4459
4701
|
warnIfApiKeyFlag(opts);
|
|
4460
|
-
const { runWorkRelease, WorkCommandError } = await import('./work-claim-cmd-
|
|
4702
|
+
const { runWorkRelease, WorkCommandError } = await import('./work-claim-cmd-34FERLYX.js');
|
|
4461
4703
|
try {
|
|
4462
4704
|
await runWorkRelease(opts);
|
|
4463
4705
|
} catch (err) {
|
|
@@ -4470,10 +4712,22 @@ live addition remains on it.
|
|
|
4470
4712
|
});
|
|
4471
4713
|
workCmd.command("pr <number>").description("Declare a pull request onto the launched work item, or withdraw it").option("--repo <owner/name>", "repository (default: the current checkout's remote)").option("--session-id <id>", "session id to record as-is, skipping detection").option("--withdraw", "remove the declaration instead of making one (needs --item)").option("--item <number>", "with --withdraw, the item to remove the declaration from").option("--json", "machine-readable JSON output").option("--url <url>", "cloud base URL (or OUTERLAYER_URL / config)").addOption(apiKeyOption()).option("--app-id <id>", "factory id the key is bound to (or OUTERLAYER_APP_ID / config)").addHelpText(
|
|
4472
4714
|
"after",
|
|
4473
|
-
|
|
4715
|
+
`
|
|
4716
|
+
${cliInvocation()} work pr 481
|
|
4717
|
+
${cliInvocation()} work pr 481 --withdraw --item 250
|
|
4718
|
+
|
|
4719
|
+
Run inside a session already on a work item. Records that pull
|
|
4720
|
+
request 481 in the checkout's repository belongs to the item named by
|
|
4721
|
+
OUTERLAYER_WORK, or refuses when the session is not on it. The same
|
|
4722
|
+
fact a \`pr-link\` in the session's own transcript records on sync.
|
|
4723
|
+
Idempotent: declaring the same pull request twice is a no-op.
|
|
4724
|
+
|
|
4725
|
+
--withdraw removes one item's declaration of the pull request. It
|
|
4726
|
+
needs your own login; an agent session or a factory key is refused.
|
|
4727
|
+
`
|
|
4474
4728
|
).action(async (number, opts) => {
|
|
4475
4729
|
warnIfApiKeyFlag(opts);
|
|
4476
|
-
const { runWorkPr, WorkPrCommandError } = await import('./work-pr-cmd-
|
|
4730
|
+
const { runWorkPr, WorkPrCommandError } = await import('./work-pr-cmd-5LGANL32.js');
|
|
4477
4731
|
try {
|
|
4478
4732
|
await runWorkPr({ ...opts, number });
|
|
4479
4733
|
} catch (err) {
|
|
@@ -4486,11 +4740,21 @@ live addition remains on it.
|
|
|
4486
4740
|
});
|
|
4487
4741
|
workCmd.command("open-pr").description("Open, or edit, the pull request for the work item this session is on").requiredOption("--title <title>", "the pull request's title").requiredOption("--body-file <path>", "a file holding the pull request's description").option("--repository <owner/name>", "repository to open the pull request in (default: the primary)").option("--repo <owner/name>", "same as --repository, on the gh path").option("--session-id <id>", "session id to record as-is, on the gh path, skipping detection").option("--json", "machine-readable JSON output").option("--url <url>", "cloud base URL (or OUTERLAYER_URL / config)").addOption(apiKeyOption()).option("--app-id <id>", "factory id the key is bound to (or OUTERLAYER_APP_ID / config)").addHelpText(
|
|
4488
4742
|
"after",
|
|
4489
|
-
|
|
4743
|
+
`
|
|
4744
|
+
${cliInvocation()} work open-pr --title "Add the thing" --body-file pr.md
|
|
4745
|
+
${cliInvocation()} work open-pr --repository acme/web --title "Add the thing" --body-file pr.md
|
|
4746
|
+
|
|
4747
|
+
In a host build, which holds an item key, the gateway opens the pull
|
|
4748
|
+
request as the factory's GitHub App, from the branch the claim named,
|
|
4749
|
+
or edits the one already open on that branch. No gh command runs.
|
|
4750
|
+
In your own session it runs \`gh pr create\` (or \`gh pr edit\`) under your
|
|
4751
|
+
login, then declares the pull request on the item, as \`work pr\` does.
|
|
4752
|
+
Run it again after a change to the title or description.
|
|
4753
|
+
`
|
|
4490
4754
|
).action(async (opts) => {
|
|
4491
4755
|
warnIfApiKeyFlag(opts);
|
|
4492
|
-
const { runWorkOpenPr, WorkOpenPrCommandError } = await import('./work-open-pr-cmd-
|
|
4493
|
-
const { WorkCommandError } = await import('./work-cmd-
|
|
4756
|
+
const { runWorkOpenPr, WorkOpenPrCommandError } = await import('./work-open-pr-cmd-RPXKCBWS.js');
|
|
4757
|
+
const { WorkCommandError } = await import('./work-cmd-7S5B2H2P.js');
|
|
4494
4758
|
try {
|
|
4495
4759
|
await runWorkOpenPr(opts);
|
|
4496
4760
|
} catch (err) {
|
|
@@ -4506,9 +4770,9 @@ function registerRunnerCommands(program2) {
|
|
|
4506
4770
|
const runnerCmd = program2.command("runner").description("Take work from the implement and amend queues on this machine");
|
|
4507
4771
|
const configOption = "the cloud config file to run against (default: ~/.outerlayer/config.json)";
|
|
4508
4772
|
runnerCmd.command("start").description("Run the loop: claim work, run it, report, clean up, repeat").option("--config <path>", configOption).action(async (opts) => {
|
|
4509
|
-
const { defaultRunnerConfigPath, RunnerConfigError } = await import('./config-
|
|
4510
|
-
const { start, RunnerStartError } = await import('./loop-
|
|
4511
|
-
const { RunnerAlreadyRunningError } = await import('./pidfile-
|
|
4773
|
+
const { defaultRunnerConfigPath, RunnerConfigError } = await import('./config-FXDG4NPJ.js');
|
|
4774
|
+
const { start, RunnerStartError } = await import('./loop-UGI2BJOT.js');
|
|
4775
|
+
const { RunnerAlreadyRunningError } = await import('./pidfile-3DM4OBKO.js');
|
|
4512
4776
|
const configPath = opts.config ?? defaultRunnerConfigPath();
|
|
4513
4777
|
try {
|
|
4514
4778
|
const { realUpdateDeps } = await import('./real-deps-KNNBQC75.js');
|
|
@@ -4522,8 +4786,8 @@ function registerRunnerCommands(program2) {
|
|
|
4522
4786
|
}
|
|
4523
4787
|
});
|
|
4524
4788
|
runnerCmd.command("check").description("Validate the config, the hooks and the key, and print the effective settings").option("--config <path>", configOption).action(async (opts) => {
|
|
4525
|
-
const { defaultRunnerConfigPath } = await import('./config-
|
|
4526
|
-
const { runRunnerCheck } = await import('./check-
|
|
4789
|
+
const { defaultRunnerConfigPath } = await import('./config-FXDG4NPJ.js');
|
|
4790
|
+
const { runRunnerCheck } = await import('./check-5C4YDZYV.js');
|
|
4527
4791
|
const configPath = opts.config ?? defaultRunnerConfigPath();
|
|
4528
4792
|
const result = await runRunnerCheck(configPath);
|
|
4529
4793
|
if (!result.ok) {
|
|
@@ -4539,8 +4803,8 @@ function registerRunnerCommands(program2) {
|
|
|
4539
4803
|
`);
|
|
4540
4804
|
});
|
|
4541
4805
|
runnerCmd.command("install").description("Put this CLI in the runner's install layout; --service adds its service").option("--config <path>", configOption).option("--service", "set up the service that keeps the runner running").option("--print", "with --service, print the unit and set up nothing").option("--user <account>", "with --service, the account the service runs as").option("--replace", "replace a unit or launcher file this command did not write").option("--allow-downgrade", "install this CLI even when it is older than the version the runner runs").option("--unit-name <name>", "with --service, the unit's name, to run a second runner beside the first").action(async (opts) => {
|
|
4542
|
-
const { defaultRunnerConfigPath, RunnerConfigError } = await import('./config-
|
|
4543
|
-
const { runRunnerInstall, RunnerInstallError, launcherSummary, restartNote } = await import('./install-cmd-
|
|
4806
|
+
const { defaultRunnerConfigPath, RunnerConfigError } = await import('./config-FXDG4NPJ.js');
|
|
4807
|
+
const { runRunnerInstall, RunnerInstallError, launcherSummary, restartNote } = await import('./install-cmd-QDOTR4OM.js');
|
|
4544
4808
|
const configPath = opts.config ?? defaultRunnerConfigPath();
|
|
4545
4809
|
if (opts.service !== true) {
|
|
4546
4810
|
for (const flag of ["print", "user", "unitName"]) {
|
|
@@ -4552,7 +4816,7 @@ function registerRunnerCommands(program2) {
|
|
|
4552
4816
|
}
|
|
4553
4817
|
try {
|
|
4554
4818
|
if (opts.service === true) {
|
|
4555
|
-
const { installServiceCommand } = await import('./command-
|
|
4819
|
+
const { installServiceCommand } = await import('./command-H5CILO4S.js');
|
|
4556
4820
|
const result2 = await installServiceCommand({
|
|
4557
4821
|
configPath,
|
|
4558
4822
|
print: opts.print,
|
|
@@ -4590,7 +4854,7 @@ function registerRunnerCommands(program2) {
|
|
|
4590
4854
|
printLauncher(result, launcherSummary);
|
|
4591
4855
|
process.stdout.write(
|
|
4592
4856
|
`
|
|
4593
|
-
To keep it running, run ${C.yellow}
|
|
4857
|
+
To keep it running, run ${C.yellow}${cliInvocation()} runner install --service${C.reset}. To start the runner from the install layout yourself, use this line, then restart the service:
|
|
4594
4858
|
${C.yellow}${result.execStart}${C.reset}
|
|
4595
4859
|
`
|
|
4596
4860
|
);
|
|
@@ -4604,11 +4868,11 @@ To keep it running, run ${C.yellow}outerlayer runner install --service${C.reset}
|
|
|
4604
4868
|
});
|
|
4605
4869
|
runnerCmd.command("uninstall").description("Stop the runner's service and remove it (needs --service)").option("--config <path>", configOption).option("--service", "remove the service, and the launch agent or scheduled task").option("--unit-name <name>", "the unit's name, when it is not the default").action(async (opts) => {
|
|
4606
4870
|
if (opts.service !== true) {
|
|
4607
|
-
fail(
|
|
4871
|
+
fail(`pass --service: \`${cliInvocation()} runner uninstall --service\` removes the runner's service.`);
|
|
4608
4872
|
return;
|
|
4609
4873
|
}
|
|
4610
|
-
const { defaultRunnerConfigPath } = await import('./config-
|
|
4611
|
-
const { uninstallServiceCommand } = await import('./command-
|
|
4874
|
+
const { defaultRunnerConfigPath } = await import('./config-FXDG4NPJ.js');
|
|
4875
|
+
const { uninstallServiceCommand } = await import('./command-H5CILO4S.js');
|
|
4612
4876
|
const result = await uninstallServiceCommand({ configPath: opts.config ?? defaultRunnerConfigPath(), unitName: opts.unitName, home: homeFromEnv() });
|
|
4613
4877
|
if (result.ok) for (const line of result.lines) process.stdout.write(`${C.green}\u2713${C.reset} ${line}
|
|
4614
4878
|
`);
|
|
@@ -4616,14 +4880,31 @@ To keep it running, run ${C.yellow}outerlayer runner install --service${C.reset}
|
|
|
4616
4880
|
});
|
|
4617
4881
|
runnerCmd.command("init").description("Write a runner block that fits this machine; on macOS, offers a Linux VM").option("--config <path>", configOption).option("--vm", "on macOS, run the runner in a Linux VM (Lima), with container builds").option("--no-vm", "on macOS, skip the VM and run builds as unisolated processes").option("--allow-process-builds", "where builds cannot be isolated, run them as processes anyway").addOption(new Option("--config-stdin", "the VM-side hand-off: read the whole config as JSON on stdin").hideHelp()).option("--vm-cli-package <path>", "with --vm, install this packed CLI tarball in the VM").option("--unit-name <name>", "the service unit's name, to run a second runner beside the first").option("--agent <name>", "write commands that start this agent (claude); its credential comes on stdin").option("--factory <org/factory>", "factory to create the runner key on, as <org>/<factory>").option("--app-id <id>", "factory id, instead of --factory (Settings \u2192 General)").addHelpText(
|
|
4618
4882
|
"after",
|
|
4619
|
-
|
|
4883
|
+
`
|
|
4884
|
+
With no apiKey in the config file, and a login saved by \`${cliInvocation()} login\`,
|
|
4885
|
+
runner init names the factory the runner is for: --factory, then --app-id,
|
|
4886
|
+
OUTERLAYER_APP_ID, or this repository's connection. With none of those, a
|
|
4887
|
+
login that can use one factory uses it, and one that can use several lists
|
|
4888
|
+
them. It then prints the factory's API keys page, where you create a key with
|
|
4889
|
+
the Runner preset, and asks you to paste it. Nothing is shown as you paste.
|
|
4890
|
+
With no terminal to ask on, it stops and says what to put in the config file.
|
|
4891
|
+
|
|
4892
|
+
With --agent claude, the queue commands start Claude Code instead of the
|
|
4893
|
+
placeholder, and Claude's credential is read from stdin: a token from
|
|
4894
|
+
\`claude setup-token\` (sk-ant-oat...) or an API key (sk-ant-api...). It is
|
|
4895
|
+
never printed, and is stored in the runner.env beside the config with mode
|
|
4896
|
+
600. Other lines in the file are kept. With nothing piped, a credential
|
|
4897
|
+
already in runner.env is used.
|
|
4898
|
+
|
|
4899
|
+
printf '%s' "$CLAUDE_CODE_OAUTH_TOKEN" | ${cliInvocation()} runner init --agent claude --factory <org>/<factory>
|
|
4900
|
+
`
|
|
4620
4901
|
).action(async (opts) => {
|
|
4621
|
-
const { defaultRunnerConfigPath, RunnerConfigError } = await import('./config-
|
|
4622
|
-
const { prepareRunnerInit, runRunnerInit, RunnerInitError, writeRunnerInit } = await import('./init-
|
|
4623
|
-
const { obtainRunnerKey, runnerKeyLogin } = await import('./runner-key-
|
|
4624
|
-
const { detectMachine } = await import('./machine-
|
|
4625
|
-
const { chooseVm, runVmInit, VmInitError } = await import('./init-
|
|
4626
|
-
const { AGENT_COMMANDS, credentialFromStdin, isAgentName, restartForCredential, RunnerEnvError } = await import('./runner-env-
|
|
4902
|
+
const { defaultRunnerConfigPath, RunnerConfigError } = await import('./config-FXDG4NPJ.js');
|
|
4903
|
+
const { prepareRunnerInit, runRunnerInit, RunnerInitError, writeRunnerInit } = await import('./init-VWXIZEAN.js');
|
|
4904
|
+
const { obtainRunnerKey, runnerKeyLogin } = await import('./runner-key-TC3NFWFV.js');
|
|
4905
|
+
const { detectMachine } = await import('./machine-JOW4RNZ7.js');
|
|
4906
|
+
const { chooseVm, runVmInit, VmInitError } = await import('./init-WNXXYMO7.js');
|
|
4907
|
+
const { AGENT_COMMANDS, credentialFromStdin, isAgentName, restartForCredential, RunnerEnvError } = await import('./runner-env-4NB2GA7O.js');
|
|
4627
4908
|
const configPath = opts.config ?? defaultRunnerConfigPath();
|
|
4628
4909
|
if (opts.agent !== void 0 && !isAgentName(opts.agent)) {
|
|
4629
4910
|
fail(`--agent ${opts.agent}: runner init writes commands for ${Object.keys(AGENT_COMMANDS).join(", ")}. For another agent, leave --agent out and edit runner.commands.`);
|
|
@@ -4637,7 +4918,7 @@ To keep it running, run ${C.yellow}outerlayer runner install --service${C.reset}
|
|
|
4637
4918
|
try {
|
|
4638
4919
|
let credential;
|
|
4639
4920
|
if (agent !== void 0) {
|
|
4640
|
-
const { readPipedKey } = await import('./login-browser-
|
|
4921
|
+
const { readPipedKey } = await import('./login-browser-O63QZN7D.js');
|
|
4641
4922
|
credential = credentialFromStdin(
|
|
4642
4923
|
await readPipedKey(process.stdin, {
|
|
4643
4924
|
onWaiting: () => process.stderr.write(`runner init is waiting for Claude's credential on stdin; close stdin to use the one already in runner.env
|
|
@@ -4654,7 +4935,7 @@ To keep it running, run ${C.yellow}outerlayer runner install --service${C.reset}
|
|
|
4654
4935
|
const chunks = [];
|
|
4655
4936
|
for await (const chunk of process.stdin) chunks.push(Buffer.from(chunk));
|
|
4656
4937
|
const result2 = runRunnerInit(configPath, { machine, configFromStdin: Buffer.concat(chunks).toString("utf8"), requireContainer: true });
|
|
4657
|
-
const { ensureHostKey: ensureHostKey2 } = await import('./host-key-
|
|
4938
|
+
const { ensureHostKey: ensureHostKey2 } = await import('./host-key-U4B5QETR.js');
|
|
4658
4939
|
const hostKey2 = await ensureHostKey2(configPath);
|
|
4659
4940
|
process.stdout.write(`host key ${hostKey2.fingerprint}
|
|
4660
4941
|
hooks: ${result2.hooks}
|
|
@@ -4713,7 +4994,7 @@ hooks: ${result2.hooks}
|
|
|
4713
4994
|
const prepared = prepareRunnerInit(configPath, { machine, allowProcess, agent, credential, keyFromLogin: makeKey !== void 0 });
|
|
4714
4995
|
const created = makeKey === void 0 ? void 0 : await makeKey();
|
|
4715
4996
|
const result = writeRunnerInit(prepared, created);
|
|
4716
|
-
const { ensureHostKey } = await import('./host-key-
|
|
4997
|
+
const { ensureHostKey } = await import('./host-key-U4B5QETR.js');
|
|
4717
4998
|
const hostKey = await ensureHostKey(configPath);
|
|
4718
4999
|
if (created !== void 0) {
|
|
4719
5000
|
process.stdout.write(`${C.green}\u2713${C.reset} saved the runner key in ${result.configPath}
|
|
@@ -4738,10 +5019,10 @@ ${C.yellow}${result.note}${C.reset}
|
|
|
4738
5019
|
`);
|
|
4739
5020
|
if (machine.platform === "darwin" && opts.vm === void 0) {
|
|
4740
5021
|
process.stdout.write(`
|
|
4741
|
-
To isolate builds in containers instead, run ${C.yellow}
|
|
5022
|
+
To isolate builds in containers instead, run ${C.yellow}${cliInvocation()} runner init --vm${C.reset}.
|
|
4742
5023
|
`);
|
|
4743
5024
|
}
|
|
4744
|
-
const { runRunnerInstall, RunnerInstallError, RunnerDowngradeError, launcherSummary } = await import('./install-cmd-
|
|
5025
|
+
const { runRunnerInstall, RunnerInstallError, RunnerDowngradeError, launcherSummary } = await import('./install-cmd-QDOTR4OM.js');
|
|
4745
5026
|
let installedLayout = false;
|
|
4746
5027
|
let noService = "it starts the runner from the install layout, which needs a CLI installed with npm";
|
|
4747
5028
|
try {
|
|
@@ -4773,7 +5054,7 @@ ${C.yellow}The runner will not update itself: ${installErr.message}${C.reset}
|
|
|
4773
5054
|
let serviceUp = false;
|
|
4774
5055
|
let restart;
|
|
4775
5056
|
if (installedLayout) {
|
|
4776
|
-
const { installServiceCommand } = await import('./command-
|
|
5057
|
+
const { installServiceCommand } = await import('./command-H5CILO4S.js');
|
|
4777
5058
|
const service = await installServiceCommand({
|
|
4778
5059
|
configPath,
|
|
4779
5060
|
entryPath: process.argv[1] ?? "",
|
|
@@ -4795,14 +5076,14 @@ ${C.yellow}The runner will not update itself: ${installErr.message}${C.reset}
|
|
|
4795
5076
|
if (restart !== void 0) process.stdout.write(`
|
|
4796
5077
|
${C.yellow}${restart}${C.reset}
|
|
4797
5078
|
`);
|
|
4798
|
-
const steps = agent === void 0 ? [`Edit the command lines in ${result.configPath} to start your agent.`, `${C.yellow}
|
|
4799
|
-
if (!serviceUp) steps.push(`${C.yellow}
|
|
5079
|
+
const steps = agent === void 0 ? [`Edit the command lines in ${result.configPath} to start your agent.`, `${C.yellow}${cliInvocation()} runner check${C.reset}`] : [`${C.yellow}${cliInvocation()} runner check${C.reset}`];
|
|
5080
|
+
if (!serviceUp) steps.push(`${C.yellow}${cliInvocation()} runner start${C.reset}, or ${C.yellow}${cliInvocation()} runner install --service${C.reset} to keep it running.`);
|
|
4800
5081
|
process.stdout.write(
|
|
4801
5082
|
`
|
|
4802
5083
|
Next:
|
|
4803
5084
|
` + steps.map((step, i) => ` ${i + 1}. ${step}
|
|
4804
|
-
`).join("") + (serviceUp && agent === void 0 ? ` The runner service claims nothing until step 1 is done and a Claude credential is in ${join(dirname(configPath), "runner.env")}; ${C.yellow}
|
|
4805
|
-
` : serviceUp ? ` The runner service is running; ${C.yellow}
|
|
5085
|
+
`).join("") + (serviceUp && agent === void 0 ? ` The runner service claims nothing until step 1 is done and a Claude credential is in ${join(dirname(configPath), "runner.env")}; ${C.yellow}${cliInvocation()} runner status${C.reset} shows what it is doing.
|
|
5086
|
+
` : serviceUp ? ` The runner service is running; ${C.yellow}${cliInvocation()} runner status${C.reset} shows what it is doing.
|
|
4806
5087
|
` : "")
|
|
4807
5088
|
);
|
|
4808
5089
|
} catch (err) {
|
|
@@ -4813,29 +5094,42 @@ Next:
|
|
|
4813
5094
|
throw err;
|
|
4814
5095
|
}
|
|
4815
5096
|
});
|
|
4816
|
-
runnerCmd.command("image").description("Build a repository's image from its
|
|
5097
|
+
runnerCmd.command("image").description("Build a repository's image from its governing repository's devcontainer").requiredOption("--repository <owner/name>", "the repository to build the image for").option("--remote <url>", "where to fetch from (default: the repository's GitHub URL)").option("--config <path>", configOption).option("--json", "machine-readable JSON output").addHelpText(
|
|
4817
5098
|
"after",
|
|
4818
|
-
"\
|
|
5099
|
+
"\nA repository governed by a control plane builds the control plane's image, at the commit\nthe gateway has stored for it. A repository that governs itself fetches the head of its\ndefault branch into the runner's cache. Either way it reads .devcontainer/devcontainer.json\nand builds the image with the devcontainer CLI. Settings\nthat reach the host or widen the container's privileges are ignored and listed. The\nimage holds this CLI and a pinned Claude Code. Nothing runs inside the image.\n"
|
|
4819
5100
|
).action(async (opts) => {
|
|
4820
|
-
const { defaultRunnerConfigPath } = await import('./config-
|
|
4821
|
-
const { buildRepositoryImage, RecipeError } = await import('./build-
|
|
5101
|
+
const { defaultRunnerConfigPath } = await import('./config-FXDG4NPJ.js');
|
|
5102
|
+
const { buildRepositoryImage, RecipeError } = await import('./build-TQ6X5PYN.js');
|
|
4822
5103
|
const { currentCliBuild } = await import('./cli-build-K56DK4DS.js');
|
|
4823
|
-
const { createDockerHost } = await import('./docker-
|
|
4824
|
-
const { builderSpec } = await import('./builder-
|
|
4825
|
-
const { loadRunnerConfig } = await import('./config-
|
|
5104
|
+
const { createDockerHost } = await import('./docker-RC3PRX3Q.js');
|
|
5105
|
+
const { builderSpec } = await import('./builder-DUI2ZH2H.js');
|
|
5106
|
+
const { loadRunnerConfig } = await import('./config-FXDG4NPJ.js');
|
|
4826
5107
|
const configPath = opts.config ?? defaultRunnerConfigPath();
|
|
4827
|
-
const
|
|
5108
|
+
const loaded = (() => {
|
|
4828
5109
|
try {
|
|
4829
|
-
return loadRunnerConfig(configPath)
|
|
5110
|
+
return loadRunnerConfig(configPath);
|
|
4830
5111
|
} catch {
|
|
4831
|
-
return
|
|
5112
|
+
return void 0;
|
|
4832
5113
|
}
|
|
4833
5114
|
})();
|
|
5115
|
+
const memory = loaded?.build?.memory ?? "8g";
|
|
4834
5116
|
try {
|
|
5117
|
+
const { imageTargetFor } = await import('./governing-source-BUU4IABS.js');
|
|
5118
|
+
const target = await imageTargetFor({ config: loaded, repository: opts.repository, fetchImpl: fetch });
|
|
5119
|
+
if (!target.ok) {
|
|
5120
|
+
if (opts.json) {
|
|
5121
|
+
writeJson({ error: { code: "governing_source_unavailable", message: target.reason } });
|
|
5122
|
+
process.exitCode = 1;
|
|
5123
|
+
return;
|
|
5124
|
+
}
|
|
5125
|
+
fail(target.reason);
|
|
5126
|
+
return;
|
|
5127
|
+
}
|
|
4835
5128
|
const result = await buildRepositoryImage(
|
|
4836
5129
|
{
|
|
4837
|
-
repository:
|
|
4838
|
-
|
|
5130
|
+
repository: target.repository,
|
|
5131
|
+
...target.pinned === void 0 ? {} : { pinned: target.pinned },
|
|
5132
|
+
remote: target.pinned === void 0 ? opts.remote : void 0,
|
|
4839
5133
|
configPath,
|
|
4840
5134
|
cli: currentCliBuild(),
|
|
4841
5135
|
log: (line) => {
|
|
@@ -4883,22 +5177,22 @@ Next:
|
|
|
4883
5177
|
}
|
|
4884
5178
|
});
|
|
4885
5179
|
runnerCmd.command("stop").description("Take no more work; wait for running jobs to finish, then exit").option("--config <path>", "the cloud config file naming the runner to stop").option("--now", "end running jobs immediately, with outcome stopped").action(async (opts) => {
|
|
4886
|
-
const { defaultRunnerConfigPath } = await import('./config-
|
|
4887
|
-
const { requestStop } = await import('./loop-
|
|
5180
|
+
const { defaultRunnerConfigPath } = await import('./config-FXDG4NPJ.js');
|
|
5181
|
+
const { requestStop } = await import('./loop-UGI2BJOT.js');
|
|
4888
5182
|
const configPath = opts.config ?? defaultRunnerConfigPath();
|
|
4889
5183
|
await requestStop(configPath, Boolean(opts.now));
|
|
4890
5184
|
});
|
|
4891
5185
|
runnerCmd.command("status").description("List running jobs; with --recent, finished ones too").option("--config <path>", "the cloud config file naming the runner to inspect").option("--recent", "also list finished jobs, newest first, capped at 20").option("--json", "machine-readable JSON output").action(async (opts) => {
|
|
4892
|
-
const { defaultRunnerConfigPath, loadRunnerConfig } = await import('./config-
|
|
4893
|
-
const { jobsDir, runnerDir } = await import('./paths-
|
|
4894
|
-
const { listJobFiles, runnerProcessState } = await import('./loop-
|
|
4895
|
-
const { renderStatus } = await import('./status-
|
|
4896
|
-
const { readHousekeepingRecord } = await import('./record-
|
|
5186
|
+
const { defaultRunnerConfigPath, loadRunnerConfig } = await import('./config-FXDG4NPJ.js');
|
|
5187
|
+
const { jobsDir, runnerDir } = await import('./paths-7XP63OAX.js');
|
|
5188
|
+
const { listJobFiles, runnerProcessState } = await import('./loop-UGI2BJOT.js');
|
|
5189
|
+
const { renderStatus } = await import('./status-TKCLLKFG.js');
|
|
5190
|
+
const { readHousekeepingRecord } = await import('./record-3WP6V2K5.js');
|
|
4897
5191
|
const path2 = await import('path');
|
|
4898
5192
|
const configPath = opts.config ?? defaultRunnerConfigPath();
|
|
4899
5193
|
const all = listJobFiles(configPath);
|
|
4900
5194
|
const housekeeping = readHousekeepingRecord(runnerDir(configPath));
|
|
4901
|
-
const { readPendingUpdate } = await import('./pending-
|
|
5195
|
+
const { readPendingUpdate } = await import('./pending-532ABZYC.js');
|
|
4902
5196
|
const pendingUpdate = readPendingUpdate(runnerDir(configPath));
|
|
4903
5197
|
let host = "unknown";
|
|
4904
5198
|
let concurrency = 1;
|
|
@@ -4912,7 +5206,7 @@ Next:
|
|
|
4912
5206
|
const service = await (async () => {
|
|
4913
5207
|
if (process.platform !== "linux" || !existsSync("/run/systemd/system")) return void 0;
|
|
4914
5208
|
const { inspectService, realInspectProbes } = await import('./inspect-6UYAAXH7.js');
|
|
4915
|
-
const { DEFAULT_UNIT_NAME } = await import('./install-
|
|
5209
|
+
const { DEFAULT_UNIT_NAME } = await import('./install-CBWIEF3R.js');
|
|
4916
5210
|
const facts = inspectService(DEFAULT_UNIT_NAME, path2.dirname(configPath), realInspectProbes());
|
|
4917
5211
|
return facts === void 0 ? void 0 : { unit: facts.unit, running: facts.mainPid !== void 0, delegated: facts.delegate };
|
|
4918
5212
|
})();
|
|
@@ -4947,9 +5241,9 @@ Next:
|
|
|
4947
5241
|
);
|
|
4948
5242
|
});
|
|
4949
5243
|
runnerCmd.command("logs").argument("<item>", "the work item's number in the factory").description("Print the newest attempt's log for one item").option("--config <path>", "the cloud config file naming the runner to inspect").option("-f, --follow", "keep printing as the log grows").action(async (itemArg, opts) => {
|
|
4950
|
-
const { defaultRunnerConfigPath } = await import('./config-
|
|
4951
|
-
const { listJobFiles } = await import('./loop-
|
|
4952
|
-
const { newestAttempt, logPathFor, tail, RunnerLogsError } = await import('./logs-
|
|
5244
|
+
const { defaultRunnerConfigPath } = await import('./config-FXDG4NPJ.js');
|
|
5245
|
+
const { listJobFiles } = await import('./loop-UGI2BJOT.js');
|
|
5246
|
+
const { newestAttempt, logPathFor, tail, RunnerLogsError } = await import('./logs-AMLKC3VP.js');
|
|
4953
5247
|
const configPath = opts.config ?? defaultRunnerConfigPath();
|
|
4954
5248
|
const item = parseTrackerNumber(itemArg);
|
|
4955
5249
|
if (item === void 0) {
|
|
@@ -5170,9 +5464,22 @@ function registerMcpCommands(program2) {
|
|
|
5170
5464
|
const mcpCmd = program2.command("mcp").description("Configure MCP clients against the OuterLayer gateway");
|
|
5171
5465
|
mcpCmd.command("install").description("Write or update the OuterLayer entry in .mcp.json or .outerlayer/mcp.json").option("--transport <stdio|http>", "how the client connects (default: stdio)").option("--command <exe>", "stdio only: executable the client spawns (default: outerlayer)").option("--url <url>", "gateway MCP endpoint (defaults to the gateway you logged in to)").option("--name <name>", 'mcpServers key to write under (default: "outerlayer")').option("--dir <path>", "repo root to write into (default: cwd)").option("--app-id <uuid>", "self-host only: factory id sent as X-Outerlayer-App-Id").option("--json", "machine-readable JSON output").addHelpText(
|
|
5172
5466
|
"after",
|
|
5173
|
-
|
|
5467
|
+
`
|
|
5468
|
+
The API key is never a flag and never written to .mcp.json as a literal value.
|
|
5469
|
+
stdio (default): the client spawns \`${cliInvocation()} mcp serve\`, which reads the key
|
|
5470
|
+
from ~/.outerlayer/config.json (or OUTERLAYER_API_KEY) on every connect, so a
|
|
5471
|
+
rotated key is picked up without rewriting the entry.
|
|
5472
|
+
http: the entry carries the \${OUTERLAYER_API_KEY} placeholder, which the client
|
|
5473
|
+
resolves from the environment it was launched with.
|
|
5474
|
+
|
|
5475
|
+
--command: use an absolute or \${HOME}-relative path when the CLI is not on PATH.
|
|
5476
|
+
--url: with stdio the endpoint resolves from OUTERLAYER_URL / the config file at
|
|
5477
|
+
connect time; for self-host pass your gateway-node origin + /v1/mcp.
|
|
5478
|
+
Self-host deployments also need --app-id: without a key service to resolve the
|
|
5479
|
+
caller from the bearer token, the gateway answers 401 without that header.
|
|
5480
|
+
`
|
|
5174
5481
|
).action(async (opts) => {
|
|
5175
|
-
const { runMcpInstall, handleMcpInstallError, McpInstallError } = await import('./mcp-install-cmd-
|
|
5482
|
+
const { runMcpInstall, handleMcpInstallError, McpInstallError } = await import('./mcp-install-cmd-GGWB3JJ2.js');
|
|
5176
5483
|
try {
|
|
5177
5484
|
if (opts.transport !== void 0 && opts.transport !== "stdio" && opts.transport !== "http") {
|
|
5178
5485
|
throw new McpInstallError(`--transport must be "stdio" or "http", got "${opts.transport}"`);
|
|
@@ -5194,7 +5501,7 @@ function registerMcpCommands(program2) {
|
|
|
5194
5501
|
"after",
|
|
5195
5502
|
"\nWhat the stdio .mcp.json entry spawns. Reads newline-delimited JSON-RPC 2.0 on\nstdin and writes responses on stdout. The API key comes from OUTERLAYER_API_KEY\nor ~/.outerlayer/config.json at start-up; with neither the command exits 1 and\nprints why, which the MCP client shows as the connect error.\n"
|
|
5196
5503
|
).action(async (opts) => {
|
|
5197
|
-
const { runMcpServe, handleMcpServeError } = await import('./mcp-serve-cmd-
|
|
5504
|
+
const { runMcpServe, handleMcpServeError } = await import('./mcp-serve-cmd-DOTY5FKY.js');
|
|
5198
5505
|
try {
|
|
5199
5506
|
await runMcpServe({ url: opts.url, appId: opts.appId });
|
|
5200
5507
|
} catch (err) {
|
|
@@ -5205,7 +5512,7 @@ function registerMcpCommands(program2) {
|
|
|
5205
5512
|
function registerImportCommands(program2) {
|
|
5206
5513
|
const importCmd = program2.command("import").description("Import an existing config format into .outerlayer/");
|
|
5207
5514
|
importCmd.command("ruler").description("Port a .ruler/ tree into the equivalent .outerlayer/ tree").option("--dir <path>", "repo root to read from (default: cwd)").option("--json", "machine-readable JSON output").addHelpText("after", "\nRuler: https://github.com/intellectronica/ruler. Mostly a rename.\n").action(async (opts) => {
|
|
5208
|
-
const { runImportRuler, ImportRulerError } = await import('./import-ruler-cmd-
|
|
5515
|
+
const { runImportRuler, ImportRulerError } = await import('./import-ruler-cmd-KJMWL5V6.js');
|
|
5209
5516
|
try {
|
|
5210
5517
|
const result = runImportRuler({ cwd: opts.dir, json: opts.json });
|
|
5211
5518
|
if (result.exitCode !== 0) process.exitCode = result.exitCode;
|
|
@@ -5221,7 +5528,7 @@ function registerImportCommands(program2) {
|
|
|
5221
5528
|
"after",
|
|
5222
5529
|
"\nInstalls the four maintained skills (outerlayer-evidence, outerlayer-amend,\nouterlayer-findings, outerlayer-cli) and an AGENTS.md snippet teaching agents to run\n`emit artifact`. A skill that differs from this CLI's bundle is rewritten to it, and the output says so.\n"
|
|
5223
5530
|
).action(async (opts) => {
|
|
5224
|
-
const { runImportCapture, ImportCaptureError } = await import('./import-capture-cmd-
|
|
5531
|
+
const { runImportCapture, ImportCaptureError } = await import('./import-capture-cmd-ZO6KGHI2.js');
|
|
5225
5532
|
try {
|
|
5226
5533
|
runImportCapture({ cwd: opts.dir, json: opts.json });
|
|
5227
5534
|
} catch (err) {
|
|
@@ -5264,7 +5571,7 @@ function registerContextCommands(program2) {
|
|
|
5264
5571
|
await compileContext({ dir: opts.dir, check: opts.check, json: opts.json });
|
|
5265
5572
|
});
|
|
5266
5573
|
contextCmd.command("adopt <stagedDir>", { hidden: true }).description("Copy context the runner staged into this checkout (container builds)").option("--json", "machine-readable JSON output").action(async (stagedDir) => {
|
|
5267
|
-
const { runContextAdopt } = await import('./context-adopt-
|
|
5574
|
+
const { runContextAdopt } = await import('./context-adopt-O5OFXMKI.js');
|
|
5268
5575
|
const { exitCode, stdout } = runContextAdopt(stagedDir, process.cwd());
|
|
5269
5576
|
process.stdout.write(stdout);
|
|
5270
5577
|
process.exitCode = exitCode;
|
|
@@ -5273,7 +5580,7 @@ function registerContextCommands(program2) {
|
|
|
5273
5580
|
"after",
|
|
5274
5581
|
"\nThe same flow SessionStart runs automatically, exposed for a manual retry or a\nfirst check outside a session. Writes AGENTS.md, .claude/**, and .outerlayer/**.\n"
|
|
5275
5582
|
).action(async (opts) => {
|
|
5276
|
-
const { materializeContext } = await import('./context-materialize-
|
|
5583
|
+
const { materializeContext } = await import('./context-materialize-Y5IJ4MQT.js');
|
|
5277
5584
|
const result = await materializeContext({ cwd: process.cwd(), sessionId: `manual-${Date.now()}` });
|
|
5278
5585
|
const output = formatContextMaterializeOutput(result);
|
|
5279
5586
|
if (output.exitCode !== void 0) process.exitCode = output.exitCode;
|