@outerlayer/cli 0.16.1 → 0.17.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 +17 -0
- package/README.md +11 -11
- package/dist/{agent-setup-K3ABU5NL.js → agent-setup-T624CWPD.js} +2 -2
- package/dist/artifact-link-cmd-2F47LT7F.js +24 -0
- package/dist/build-info.json +1 -1
- package/dist/{check-CNTMSGOG.js → check-5XE7XMC4.js} +14 -14
- package/dist/{chunk-YDSMROTB.js → chunk-3NSNIIBE.js} +8 -4
- package/dist/{chunk-NPQWKGUA.js → chunk-6Y5RUTHO.js} +1 -1
- package/dist/{chunk-6JNURGOA.js → chunk-BWQ66M6N.js} +1 -1
- package/dist/{chunk-R4ZQQ7U2.js → chunk-G5NPRL2K.js} +7 -8
- package/dist/{chunk-W3EKCZSQ.js → chunk-HGECYFEI.js} +55 -5
- package/dist/{chunk-5FEK6PNE.js → chunk-KG5ECZGJ.js} +1 -1
- package/dist/{chunk-FWX735W7.js → chunk-LWSJQJC6.js} +3 -3
- package/dist/{chunk-EWORLJMO.js → chunk-MAK5LYRF.js} +16 -7
- package/dist/{chunk-ONRCEE6D.js → chunk-NNRTPG7X.js} +2 -2
- package/dist/{chunk-U3HXXRTY.js → chunk-NWQTTSBB.js} +1 -1
- package/dist/{chunk-RSPXEVDX.js → chunk-ONKJUM6R.js} +1 -1
- package/dist/{chunk-6QRMLNH3.js → chunk-S3NYLI2P.js} +3 -3
- package/dist/{chunk-CA3XMYFN.js → chunk-VQYBXPI7.js} +3 -3
- package/dist/{chunk-EHAAPRWY.js → chunk-WVUIRTWA.js} +7 -7
- package/dist/{chunk-JJEGKEFV.js → chunk-YU3VKZ5F.js} +1 -1
- package/dist/{chunk-JEHRUE3F.js → chunk-YZ5F4PIS.js} +91 -20
- package/dist/{cli-AEWH62UE.js → cli-A76AXELQ.js} +71 -63
- package/dist/{command-HHPBR6CS.js → command-R2QCVX55.js} +6 -6
- package/dist/{connect-cmd-JUAW6MU4.js → connect-cmd-JBKAQNSF.js} +1 -1
- package/dist/{context-adopt-VMMGFRUZ.js → context-adopt-NFHCLVUB.js} +1 -1
- package/dist/{context-materialize-2WXTS4CW.js → context-materialize-IV2TUUFO.js} +1 -1
- package/dist/{doctor-N6Y7HKK3.js → doctor-4TAIARIG.js} +10 -9
- package/dist/{emit-artifact-cmd-H5MH3AOP.js → emit-artifact-cmd-MPZVR56N.js} +4 -4
- package/dist/{emit-criteria-cmd-HBP6XS5C.js → emit-criteria-cmd-EFGYI23V.js} +2 -2
- package/dist/{emit-finding-cmd-ZXDRL6PG.js → emit-finding-cmd-5GF3V4LR.js} +2 -2
- package/dist/{emit-result-cmd-RFKALS5Z.js → emit-result-cmd-I4OADKMD.js} +4 -4
- package/dist/hidden-prompt-UXBFMQC5.js +68 -0
- package/dist/{hook-fast-D7HV4IXG.js → hook-fast-R4FVSZ2H.js} +1 -1
- package/dist/index.js +3 -3
- package/dist/{init-MYX7YMIH.js → init-6XPDRDTC.js} +7 -7
- package/dist/{init-FBCA4DRA.js → init-PWU5YVL7.js} +49 -25
- package/dist/{init-cmd-CAG572UE.js → init-cmd-XAVO7HYZ.js} +5 -5
- package/dist/{init-update-VDFF4K3B.js → init-update-CVCWD6VS.js} +3 -3
- package/dist/{loop-75J4YXLZ.js → loop-FK3LPMMZ.js} +14 -14
- package/dist/{machine-A6ZCTUGS.js → machine-SQXEBAM2.js} +6 -6
- package/dist/runner-key-6SLBI7PP.js +174 -0
- package/dist/{session-sender-24L5EW25.js → session-sender-FO3LCREV.js} +3 -3
- package/dist/{status-XHSGEYO5.js → status-7VNQN5PW.js} +9 -9
- package/dist/{sync-cmd-5G5EIEHD.js → sync-cmd-GVPPFZ3G.js} +2 -2
- package/dist/{watch-UTOXO4SE.js → watch-23HSAEI6.js} +2 -2
- package/dist/{work-claim-cmd-RKHYFE5Y.js → work-claim-cmd-LKL3GHFQ.js} +5 -5
- package/dist/{work-cmd-DJQJEZVB.js → work-cmd-Z2WXLZPH.js} +3 -3
- package/dist/{work-comment-cmd-A55CUSYE.js → work-comment-cmd-AWHP56M2.js} +3 -3
- package/dist/{work-open-pr-cmd-E6O53IJD.js → work-open-pr-cmd-IOM4AVQQ.js} +4 -4
- package/dist/{work-pr-cmd-L77K32WK.js → work-pr-cmd-HNEUIEN7.js} +3 -3
- package/package.json +1 -1
- package/skill-pack/maintained/outerlayer-amend/SKILL.md +2 -0
- package/skill-pack/maintained/outerlayer-cli/SKILL.md +2 -0
- package/skill-pack/maintained/outerlayer-evidence/SKILL.md +4 -2
- package/skill-pack/maintained/outerlayer-findings/SKILL.md +2 -0
- package/skill-pack/shipped.json +10 -3
- package/skill-pack/template/build/SKILL.md +2 -0
- package/skill-pack/template/build/references/release.md +13 -11
- package/skill-pack/template/build/scripts/criterion-citations.mjs +8 -3
- package/skill-pack/template/build/scripts/record-criteria.mjs +8 -2
- package/skill-pack/template/spec/SKILL.md +2 -0
- package/skill-pack/validators/acceptance-criteria.yaml +6 -5
- package/skill-pack/validators/code-review.yaml +6 -5
- package/dist/runner-key-W25ISHI3.js +0 -155
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import { LEASE_SECONDS, ALREADY_RELEASED, RENEW_INTERVAL_SECONDS } from './chunk-
|
|
3
|
+
import { LEASE_SECONDS, ALREADY_RELEASED, RENEW_INTERVAL_SECONDS } from './chunk-G5NPRL2K.js';
|
|
4
4
|
import './chunk-RMWLBUCJ.js';
|
|
5
|
+
import './chunk-NNRTPG7X.js';
|
|
5
6
|
import './chunk-HYZRY4KZ.js';
|
|
6
|
-
import './chunk-
|
|
7
|
-
import './chunk-U3HXXRTY.js';
|
|
7
|
+
import './chunk-NWQTTSBB.js';
|
|
8
8
|
import './chunk-HHJDN6AU.js';
|
|
9
9
|
import { formatBytes } from './chunk-YYYRBYWG.js';
|
|
10
10
|
import './chunk-TBT347UY.js';
|
|
11
|
-
import { formatDuration, formatClock, relativeToRunner } from './chunk-
|
|
11
|
+
import { formatDuration, formatClock, relativeToRunner } from './chunk-MAK5LYRF.js';
|
|
12
12
|
import './chunk-KMDLFI4P.js';
|
|
13
13
|
import './chunk-QKFB4K7X.js';
|
|
14
14
|
import './chunk-RSNSZ2LJ.js';
|
|
15
|
-
import './chunk-
|
|
16
|
-
import './chunk-
|
|
15
|
+
import './chunk-S3NYLI2P.js';
|
|
16
|
+
import './chunk-6Y5RUTHO.js';
|
|
17
17
|
import './chunk-IP7BIBXJ.js';
|
|
18
18
|
import './chunk-22RMZBGW.js';
|
|
19
19
|
import './chunk-UXYLWVTQ.js';
|
|
@@ -27,7 +27,7 @@ import './chunk-4Q7OMKAT.js';
|
|
|
27
27
|
import './chunk-CX22S5BA.js';
|
|
28
28
|
import './chunk-F7CU5ABH.js';
|
|
29
29
|
import './chunk-BKO6JEZI.js';
|
|
30
|
-
import './chunk-
|
|
30
|
+
import './chunk-3NSNIIBE.js';
|
|
31
31
|
import './chunk-WUYTWNMA.js';
|
|
32
32
|
import './chunk-JXYVA45C.js';
|
|
33
33
|
import './chunk-4KSQKQXE.js';
|
|
@@ -36,7 +36,7 @@ import './chunk-YRYMNBGQ.js';
|
|
|
36
36
|
import './chunk-GQD22KKN.js';
|
|
37
37
|
import './chunk-WZBHBH3J.js';
|
|
38
38
|
import './chunk-5QRP3MVS.js';
|
|
39
|
-
import './chunk-
|
|
39
|
+
import './chunk-YZ5F4PIS.js';
|
|
40
40
|
import './chunk-WTE3MQML.js';
|
|
41
41
|
import './chunk-C5Y5ZJJZ.js';
|
|
42
42
|
import './chunk-ZJSNLVCE.js';
|
|
@@ -50,7 +50,7 @@ import './chunk-EABW6AJQ.js';
|
|
|
50
50
|
import './chunk-RA3O54FC.js';
|
|
51
51
|
import './chunk-V7NIVOFD.js';
|
|
52
52
|
import { runnerDir, jobsDir } from './chunk-ZM2IMMYN.js';
|
|
53
|
-
import './chunk-
|
|
53
|
+
import './chunk-BWQ66M6N.js';
|
|
54
54
|
import './chunk-XCCLFVXM.js';
|
|
55
55
|
import './chunk-BJ3KTMDH.js';
|
|
56
56
|
import './chunk-VNVZDWO3.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
export { CHUNK_PART_TARGET_BYTES, RETRYABLE_STATUSES, SyncConfigError, SyncTransportError, detectCi, isLoopbackUrl, resolveTier, runSync } from './chunk-
|
|
3
|
+
export { CHUNK_PART_TARGET_BYTES, RETRYABLE_STATUSES, SyncConfigError, SyncTransportError, detectCi, isLoopbackUrl, resolveTier, runSync } from './chunk-NWQTTSBB.js';
|
|
4
4
|
import './chunk-HHJDN6AU.js';
|
|
5
5
|
import './chunk-TBT347UY.js';
|
|
6
6
|
import './chunk-IP7BIBXJ.js';
|
|
@@ -19,7 +19,7 @@ import './chunk-J5M7BSJQ.js';
|
|
|
19
19
|
export { cloudConfigPath, readCloudConfig, writeCloudConfig } from './chunk-EABW6AJQ.js';
|
|
20
20
|
import './chunk-V7NIVOFD.js';
|
|
21
21
|
import './chunk-ZM2IMMYN.js';
|
|
22
|
-
import './chunk-
|
|
22
|
+
import './chunk-BWQ66M6N.js';
|
|
23
23
|
import './chunk-XCCLFVXM.js';
|
|
24
24
|
import './chunk-BJ3KTMDH.js';
|
|
25
25
|
import './chunk-VNVZDWO3.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import { LiveUploader } from './chunk-
|
|
3
|
+
import { LiveUploader } from './chunk-NWQTTSBB.js';
|
|
4
4
|
import './chunk-HHJDN6AU.js';
|
|
5
5
|
import './chunk-TBT347UY.js';
|
|
6
6
|
import './chunk-IP7BIBXJ.js';
|
|
@@ -19,7 +19,7 @@ import './chunk-J5M7BSJQ.js';
|
|
|
19
19
|
import './chunk-EABW6AJQ.js';
|
|
20
20
|
import './chunk-V7NIVOFD.js';
|
|
21
21
|
import './chunk-ZM2IMMYN.js';
|
|
22
|
-
import './chunk-
|
|
22
|
+
import './chunk-BWQ66M6N.js';
|
|
23
23
|
import './chunk-XCCLFVXM.js';
|
|
24
24
|
import './chunk-BJ3KTMDH.js';
|
|
25
25
|
import { homeFromEnv } from './chunk-VNVZDWO3.js';
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
3
|
import { RUNNER_PROTOCOL } from './chunk-ADJRGVZC.js';
|
|
4
|
-
import { resolveCredentials, WorkCommandError, parsePositiveInt, postJson, environmentFacts, resolveRepository, findLiveItem } from './chunk-
|
|
5
|
-
export { WorkCommandError } from './chunk-
|
|
6
|
-
import './chunk-
|
|
4
|
+
import { resolveCredentials, WorkCommandError, parsePositiveInt, postJson, environmentFacts, resolveRepository, findLiveItem } from './chunk-S3NYLI2P.js';
|
|
5
|
+
export { WorkCommandError } from './chunk-S3NYLI2P.js';
|
|
6
|
+
import './chunk-6Y5RUTHO.js';
|
|
7
7
|
import './chunk-IP7BIBXJ.js';
|
|
8
8
|
import { defaultRunnerConfigPath } from './chunk-22RMZBGW.js';
|
|
9
9
|
import './chunk-UXYLWVTQ.js';
|
|
10
10
|
import './chunk-7RQ73DLO.js';
|
|
11
11
|
import './chunk-4Q7OMKAT.js';
|
|
12
|
-
import './chunk-
|
|
12
|
+
import './chunk-3NSNIIBE.js';
|
|
13
13
|
import './chunk-WUYTWNMA.js';
|
|
14
14
|
import './chunk-JXYVA45C.js';
|
|
15
15
|
import './chunk-4KSQKQXE.js';
|
|
@@ -118,7 +118,7 @@ async function runWorkRelease(opts) {
|
|
|
118
118
|
{ sessionId, ended: true },
|
|
119
119
|
fetchImpl
|
|
120
120
|
);
|
|
121
|
-
const { markWorkLeaseRenewed } = await import('./hook-fast-
|
|
121
|
+
const { markWorkLeaseRenewed } = await import('./hook-fast-R4FVSZ2H.js');
|
|
122
122
|
markWorkLeaseRenewed(sessionId, opts.home ?? homeFromEnv(env));
|
|
123
123
|
const output2 = opts.json ? JSON.stringify(data2) : `released session ${sessionId}'s lease on #${itemId}, if it held one`;
|
|
124
124
|
if (!opts.quiet) process.stdout.write(output2 + "\n");
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
export { WorkCommandError, environmentFacts, findLiveItem, getJson, parsePositiveInt, postJson, resolveCredentials, resolveRepository, runWorkBuild, runWorkLinkSession, runWorkList, runWorkRemove, runWorkStatus } from './chunk-
|
|
4
|
-
import './chunk-
|
|
3
|
+
export { WorkCommandError, environmentFacts, findLiveItem, getJson, parsePositiveInt, postJson, resolveCredentials, resolveRepository, runWorkBuild, runWorkLinkSession, runWorkList, runWorkRemove, runWorkStatus } from './chunk-S3NYLI2P.js';
|
|
4
|
+
import './chunk-6Y5RUTHO.js';
|
|
5
5
|
import './chunk-IP7BIBXJ.js';
|
|
6
|
-
import './chunk-
|
|
6
|
+
import './chunk-3NSNIIBE.js';
|
|
7
7
|
import './chunk-WUYTWNMA.js';
|
|
8
8
|
import './chunk-JXYVA45C.js';
|
|
9
9
|
import './chunk-4KSQKQXE.js';
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import { resolveCredentials, postJson, getJson } from './chunk-
|
|
4
|
-
import './chunk-
|
|
3
|
+
import { resolveCredentials, postJson, getJson } from './chunk-S3NYLI2P.js';
|
|
4
|
+
import './chunk-6Y5RUTHO.js';
|
|
5
5
|
import { detectActiveSession } from './chunk-IP7BIBXJ.js';
|
|
6
|
-
import './chunk-
|
|
6
|
+
import './chunk-3NSNIIBE.js';
|
|
7
7
|
import { sanitizeTerminal } from './chunk-WUYTWNMA.js';
|
|
8
8
|
import { resolveRepoIdentity } from './chunk-JXYVA45C.js';
|
|
9
9
|
import './chunk-4KSQKQXE.js';
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import { itemLabel, runWorkPr, WorkPrCommandError } from './chunk-
|
|
4
|
-
import { resolveCredentials } from './chunk-
|
|
5
|
-
import './chunk-
|
|
3
|
+
import { itemLabel, runWorkPr, WorkPrCommandError } from './chunk-YU3VKZ5F.js';
|
|
4
|
+
import { resolveCredentials } from './chunk-S3NYLI2P.js';
|
|
5
|
+
import './chunk-6Y5RUTHO.js';
|
|
6
6
|
import './chunk-IP7BIBXJ.js';
|
|
7
|
-
import './chunk-
|
|
7
|
+
import './chunk-3NSNIIBE.js';
|
|
8
8
|
import './chunk-WUYTWNMA.js';
|
|
9
9
|
import './chunk-JXYVA45C.js';
|
|
10
10
|
import './chunk-4KSQKQXE.js';
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
export { WorkPrCommandError, itemLabel, runWorkPr } from './chunk-
|
|
4
|
-
import './chunk-
|
|
3
|
+
export { WorkPrCommandError, itemLabel, runWorkPr } from './chunk-YU3VKZ5F.js';
|
|
4
|
+
import './chunk-6Y5RUTHO.js';
|
|
5
5
|
import './chunk-IP7BIBXJ.js';
|
|
6
|
-
import './chunk-
|
|
6
|
+
import './chunk-3NSNIIBE.js';
|
|
7
7
|
import './chunk-WUYTWNMA.js';
|
|
8
8
|
import './chunk-JXYVA45C.js';
|
|
9
9
|
import './chunk-4KSQKQXE.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@outerlayer/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.0",
|
|
4
4
|
"description": "OuterLayer CLI — commands: init, connect, doctor, login, logout, sync, daemon (alias: watch), emit, work, runner, hooks, mcp, import, context. Capture and sync coding-agent sessions, and record proof of factory work.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Magu Studios, Inc.",
|
|
@@ -8,6 +8,8 @@ description: >
|
|
|
8
8
|
"fix what the reviewer failed". Invoke with /outerlayer-amend.
|
|
9
9
|
---
|
|
10
10
|
|
|
11
|
+
Run the CLI as `outerlayer`. If that command is not on PATH, run `npx -y @outerlayer/cli` with the same arguments. Every `outerlayer ...` command below follows this rule.
|
|
12
|
+
|
|
11
13
|
Answer every thread waiting on an agent on one work item's pull request, then
|
|
12
14
|
stop. A work item has one general thread and one thread per acceptance
|
|
13
15
|
criterion. A person's fail on the general thread leaves it waiting on an agent.
|
|
@@ -9,6 +9,8 @@ description: >
|
|
|
9
9
|
review.
|
|
10
10
|
---
|
|
11
11
|
|
|
12
|
+
Run the CLI as `outerlayer`. If that command is not on PATH, run `npx -y @outerlayer/cli` with the same arguments. Every `outerlayer ...` command below follows this rule.
|
|
13
|
+
|
|
12
14
|
OuterLayer is a software factory. An issue goes in. A reviewed and verified
|
|
13
15
|
pull request comes out, with the evidence that backs it. An agent builds it in
|
|
14
16
|
this repository, on the machine it already runs on.
|
|
@@ -8,6 +8,8 @@ description: >
|
|
|
8
8
|
works", and in CI steps that produce verifiable output.
|
|
9
9
|
---
|
|
10
10
|
|
|
11
|
+
Run the CLI as `outerlayer`. If that command is not on PATH, run `npx -y @outerlayer/cli` with the same arguments. Every `outerlayer ...` command below follows this rule.
|
|
12
|
+
|
|
11
13
|
An artifact is an exhibit: evidence *of* a specific change, anchored to the
|
|
12
14
|
pull request and rendered in its evidence comment. Emit the few exhibits the
|
|
13
15
|
spec asks for — a reviewer should see the change working, not a gallery.
|
|
@@ -98,7 +100,7 @@ Emit the review report, an HTML file, as a report artifact with no `--for`:
|
|
|
98
100
|
|
|
99
101
|
outerlayer emit artifact review.html --caption "Review of the change and what it found"
|
|
100
102
|
|
|
101
|
-
Then run `outerlayer sync
|
|
103
|
+
Then run `outerlayer sync`. It prints a line for the report that ends with its link (`outerlayer sync --json` lists them under `uploadedArtifacts`). Take the link from that line. If `sync` printed no line for the report, another sync already uploaded it: run `outerlayer sync --link <the artifact id>`, with the id `emit artifact` printed. Never build the link by hand, and never link a pull request comment. Record the review's verdict on the `code-review` check that `outerlayer init` writes, with that link as its proof:
|
|
102
104
|
|
|
103
105
|
outerlayer emit code-review --item "$OUTERLAYER_WORK" --result pass --link <the report's deep link>
|
|
104
106
|
|
|
@@ -108,7 +110,7 @@ Use `--result fail` when the review left a finding unfixed. Record it once. Outs
|
|
|
108
110
|
|
|
109
111
|
Bind the judge's report on each criterion, an HTML file, with `--for acceptance-criteria`. The item page links it at the top of its Criteria tab for the reviewer. Emit it only when the item has recorded criteria.
|
|
110
112
|
|
|
111
|
-
Then run `outerlayer sync`,
|
|
113
|
+
Then run `outerlayer sync`, take the report's deep link from the line it prints the same way, and record the judge's verdict on the `acceptance-criteria` check that `outerlayer init` writes:
|
|
112
114
|
|
|
113
115
|
outerlayer emit acceptance-criteria --item "$OUTERLAYER_WORK" --result pass --link <the report's deep link>
|
|
114
116
|
|
|
@@ -12,6 +12,8 @@ description: >
|
|
|
12
12
|
`outerlayer emit finding` command.
|
|
13
13
|
---
|
|
14
14
|
|
|
15
|
+
Run the CLI as `outerlayer`. If that command is not on PATH, run `npx -y @outerlayer/cli` with the same arguments. Every `outerlayer ...` command below follows this rule.
|
|
16
|
+
|
|
15
17
|
## What this is for
|
|
16
18
|
|
|
17
19
|
A finding is a problem in the factory, not in the change: an instruction
|
package/skill-pack/shipped.json
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
"a6743050c5c387e962ad4264526d9a3c10edf36823e4b6829f200bf79a4e45e7",
|
|
15
15
|
"b0aa9b6962675f772b67a4390c15b6b0100390983d958c656a826a066399f3d0",
|
|
16
16
|
"b95986e95ea3b1ef4202f7f0c00bfcd35865d4fda033b3d6947a5bb9d33cd24c",
|
|
17
|
+
"e9d086f6b989e3a17f14d6dcaacabd438bed861076f9a620fce61accc8fce4fb",
|
|
17
18
|
"f4e1661c6f87d7ff6d23c6182530fa0a9cb87c4dc3f31e48f2be11f32ebb2c00"
|
|
18
19
|
],
|
|
19
20
|
".outerlayer/skills/build/references/agent-briefs.md": [
|
|
@@ -36,6 +37,7 @@
|
|
|
36
37
|
"1d0e000433676a39c7ac4fbf3e92b1fe4235b10240c09f87ec0003f3c8d7956e",
|
|
37
38
|
"1f4fe97ca8f11d6681db5734f3103af5ea175a9472ff1d38b10cb463f4956a6a",
|
|
38
39
|
"4687f56bcec766f1926d58a208418f800a1727c073b5e6047b40e3aaac2bd6c9",
|
|
40
|
+
"4cfc10bc9d380e67b0ec5c243eb5f2c63f03ee3348d7956a45467620acc656fc",
|
|
39
41
|
"81a764eb317fcb4672bedd35e7b9aa68d1c0b73f82fc2dfa03e5a78758db8f14",
|
|
40
42
|
"985e02b98105b00c356014e003b2d60e9c458c3dcbeef7378274ccb84af031fc"
|
|
41
43
|
],
|
|
@@ -51,15 +53,18 @@
|
|
|
51
53
|
"9d4d2e5e0307ea8c38cf885cd67d06a939b7fc2bed65f5080ca9610178949d74"
|
|
52
54
|
],
|
|
53
55
|
".outerlayer/skills/build/scripts/criterion-citations.mjs": [
|
|
54
|
-
"0902118ec216182f9d0ba0f6c7966306ad6891d8e846022123d3f86aaf175fce"
|
|
56
|
+
"0902118ec216182f9d0ba0f6c7966306ad6891d8e846022123d3f86aaf175fce",
|
|
57
|
+
"aa9446b29c7c8fa4d312b8ec54b2a2a154f52708691a7eaf61e3a1b67ae6a9ef"
|
|
55
58
|
],
|
|
56
59
|
".outerlayer/skills/build/scripts/record-criteria.mjs": [
|
|
57
60
|
"36f19e730bc220fa21622b3bb0a306999f038b8220a0a07a1efe21ec0f748729",
|
|
58
61
|
"596e9a78e62cbea040a3bf428cd54bf59687e9e89001fad719304f88d03ca2ea",
|
|
59
|
-
"64de9445087b247b0781a4e6e025ef97b1259ce1c91819bf541decc26b8f8400"
|
|
62
|
+
"64de9445087b247b0781a4e6e025ef97b1259ce1c91819bf541decc26b8f8400",
|
|
63
|
+
"f3d6ed58118209d8b169d00b4283d48f25d3cac5121d2e29364274dd36ed113a"
|
|
60
64
|
],
|
|
61
65
|
".outerlayer/skills/spec/SKILL.md": [
|
|
62
66
|
"71e81fabf353ad6117c54e061868538bf00066b78c2528f5a8364445d1def02e",
|
|
67
|
+
"82f75a53c591f94615dc27c099e94fcf95e2a09b95aceb38b9022d5f7f054cb0",
|
|
63
68
|
"9039ae30d4e836b5c5cfba4a14344e46fd13694ae9e4d88e750abce34dfcd9e6"
|
|
64
69
|
],
|
|
65
70
|
".outerlayer/skills/writing-specs/SKILL.md": [
|
|
@@ -74,10 +79,12 @@
|
|
|
74
79
|
"b00f5970b568159ca0bfbc75c3834938749ad5e2e73a80769d88bbe3c8c26737"
|
|
75
80
|
],
|
|
76
81
|
".outerlayer/validators/acceptance-criteria.yaml": [
|
|
77
|
-
"3b2054aa1d4bd9f7441e88eec1a3bdf61b61ad00efa79736e26a5dd601d43910"
|
|
82
|
+
"3b2054aa1d4bd9f7441e88eec1a3bdf61b61ad00efa79736e26a5dd601d43910",
|
|
83
|
+
"d9bef4bf0962015c662f1bc16d86807414dfc6e095f99aa3727bc4613676ab2a"
|
|
78
84
|
],
|
|
79
85
|
".outerlayer/validators/code-review.yaml": [
|
|
80
86
|
"05041976e4d84d6256ed88995ea4fd1566abc6d3a9574863065cf855dcafcf70",
|
|
87
|
+
"40653bc6b170f28be1df410d9d8e270987184a2d04cbec588ae07f50afa59ba3",
|
|
81
88
|
"fbdf0baca0064b09e47f5984afc322d582accd142c3377c06622bc6567b0e98c"
|
|
82
89
|
]
|
|
83
90
|
}
|
|
@@ -8,6 +8,8 @@ description: >
|
|
|
8
8
|
disable-model-invocation: true
|
|
9
9
|
---
|
|
10
10
|
|
|
11
|
+
Run the CLI as `outerlayer`. If that command is not on PATH, run `npx -y @outerlayer/cli` with the same arguments. Every `outerlayer ...` command below follows this rule.
|
|
12
|
+
|
|
11
13
|
Build one issue into an evidenced pull request. `/spec` writes and gets
|
|
12
14
|
approval for the issue. This skill builds it. It never writes the spec.
|
|
13
15
|
|
|
@@ -48,16 +48,18 @@ request before going on.
|
|
|
48
48
|
|
|
49
49
|
## Record the code review
|
|
50
50
|
|
|
51
|
-
Once the pull request is linked, run `outerlayer sync`.
|
|
52
|
-
report
|
|
53
|
-
|
|
54
|
-
|
|
51
|
+
Once the pull request is linked, run `outerlayer sync`. It prints a line for
|
|
52
|
+
the review report that ends with its link. Take the link from that line. If
|
|
53
|
+
`sync` printed no line for the report, another sync already uploaded it: run
|
|
54
|
+
`outerlayer sync --link <the artifact id>`, with the id `emit artifact`
|
|
55
|
+
printed. Never build the link by hand, and never link a pull request comment.
|
|
56
|
+
Then record the review's verdict on the `code-review` check, once:
|
|
55
57
|
|
|
56
58
|
outerlayer emit code-review --item "$OUTERLAYER_WORK" --result pass --link <the report's deep link>
|
|
57
59
|
|
|
58
60
|
Record `--result fail` when the review ended with a blocking finding unfixed.
|
|
59
|
-
When
|
|
60
|
-
|
|
61
|
+
When neither command gives a link, stop and name it as a blocker in the final
|
|
62
|
+
report. Never record the result with another link.
|
|
61
63
|
|
|
62
64
|
## Judge the criteria
|
|
63
65
|
|
|
@@ -83,11 +85,11 @@ that is missing in the evidence phase.
|
|
|
83
85
|
|
|
84
86
|
## Record the criteria verdict
|
|
85
87
|
|
|
86
|
-
Once the judge's report is synced,
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
the link by hand, and never link a pull request comment.
|
|
90
|
-
judge's verdict on the `acceptance-criteria` check, once:
|
|
88
|
+
Once the judge's report is synced, take its deep link from the line `sync`
|
|
89
|
+
printed for it. If `sync` printed no line for the report, run
|
|
90
|
+
`outerlayer sync --link <the artifact id>`, with the id `emit artifact`
|
|
91
|
+
printed. Never build the link by hand, and never link a pull request comment.
|
|
92
|
+
Then record the judge's verdict on the `acceptance-criteria` check, once:
|
|
91
93
|
|
|
92
94
|
outerlayer emit acceptance-criteria --item "$OUTERLAYER_WORK" --result pass --link <the judge report's deep link>
|
|
93
95
|
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
// The criteria come from the file `record-criteria.mjs` wrote, by default
|
|
10
10
|
// `<git dir>/build-reports/criteria.json`. A test cites a criterion when the
|
|
11
11
|
// criterion's id appears as a whole token in a test's title or in a comment
|
|
12
|
-
// above it.
|
|
12
|
+
// above it. `WC-01 counts`, `WC-01: counts` and `WC-01 - counts` all cite
|
|
13
|
+
// WC-01. Only git-tracked test files are scanned, so every link names code
|
|
13
14
|
// that a commit contains. The link names the HEAD commit and is written only
|
|
14
15
|
// when the origin remote is on GitHub; otherwise the test is listed unlinked.
|
|
15
16
|
// A criterion no test cites gets an empty list. An existing block in the
|
|
@@ -32,9 +33,13 @@ function escapeRegExp(text) {
|
|
|
32
33
|
return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
33
34
|
}
|
|
34
35
|
|
|
35
|
-
/**
|
|
36
|
+
/**
|
|
37
|
+
* A pattern that finds `id` as a whole token: not inside a longer id such as
|
|
38
|
+
* `WC-10` for `WC-1` or `WC-1:b` for `WC-1`, and still found before a
|
|
39
|
+
* sentence's full stop or a title's colon, as in `WC-1: counts words`.
|
|
40
|
+
*/
|
|
36
41
|
export function idPattern(id) {
|
|
37
|
-
return new RegExp(`(?<![A-Za-z0-9_:-])${escapeRegExp(id)}(?![A-Za-z0-9_
|
|
42
|
+
return new RegExp(`(?<![A-Za-z0-9_:-])${escapeRegExp(id)}(?![A-Za-z0-9_-]|:[A-Za-z0-9_-]|\\.[A-Za-z0-9])`);
|
|
38
43
|
}
|
|
39
44
|
|
|
40
45
|
/** The ids of a criteria file shaped `{ "criteria": [{ "id" }] }`. */
|
|
@@ -85,10 +85,16 @@ export function classifyEmitFailure(message) {
|
|
|
85
85
|
return /\brefused \(409\):/.test(message) ? "item-list-stands" : "refused";
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
-
/**
|
|
88
|
+
/**
|
|
89
|
+
* Builds the `emit` function that runs `outerlayer emit criteria`; `spawn` is `spawnSync`, or a stand-in in tests.
|
|
90
|
+
* A machine that ran the CLI through `npx` has no `outerlayer` on PATH, so a missing command falls back to `npx -y @outerlayer/cli`.
|
|
91
|
+
*/
|
|
89
92
|
export function makeEmit(spawn, item) {
|
|
90
93
|
return (file) => {
|
|
91
|
-
const
|
|
94
|
+
const args = ["emit", "criteria", file, "--item", item];
|
|
95
|
+
const options = { encoding: "utf8", timeout: 120000 };
|
|
96
|
+
let run = spawn("outerlayer", args, options);
|
|
97
|
+
if (run.error?.code === "ENOENT") run = spawn("npx", ["-y", "@outerlayer/cli", ...args], options);
|
|
92
98
|
if (run.status === 0) return { ok: true };
|
|
93
99
|
if (run.error) return { ok: false, message: `could not run outerlayer emit criteria: ${run.error.message}` };
|
|
94
100
|
if (run.signal) return { ok: false, message: `outerlayer emit criteria was stopped by ${run.signal}` };
|
|
@@ -9,6 +9,8 @@ description: >
|
|
|
9
9
|
/spec <what you want built>.
|
|
10
10
|
---
|
|
11
11
|
|
|
12
|
+
Run the CLI as `outerlayer`. If that command is not on PATH, run `npx -y @outerlayer/cli` with the same arguments. Every `outerlayer ...` command below follows this rule.
|
|
13
|
+
|
|
12
14
|
Take one idea from a sentence to an issue a person can build from. This file
|
|
13
15
|
is the procedure. The content discipline is the `writing-specs` skill: summary
|
|
14
16
|
block, problem before solution, non-goals, Given/When/Then criteria and the
|
|
@@ -5,11 +5,12 @@
|
|
|
5
5
|
# the test that cites it. Write its verdicts as an .html file and emit it as
|
|
6
6
|
# a report artifact bound to this check:
|
|
7
7
|
# outerlayer emit artifact criteria.html --for acceptance-criteria --caption "Each criterion judged against the test that cites it"
|
|
8
|
-
# Then run `outerlayer sync
|
|
9
|
-
#
|
|
10
|
-
#
|
|
11
|
-
#
|
|
12
|
-
#
|
|
8
|
+
# Then run `outerlayer sync`. It prints a line for the report that ends with
|
|
9
|
+
# its link; take the link from that line. If `sync` printed no line for it,
|
|
10
|
+
# another sync already uploaded the report: run
|
|
11
|
+
# `outerlayer sync --link <the artifact id>`, with the id `emit artifact`
|
|
12
|
+
# printed. Never build the link by hand, and never link a pull request
|
|
13
|
+
# comment: a comment can be edited or deleted later.
|
|
13
14
|
#
|
|
14
15
|
# Then record the verdict once, with that link as its proof:
|
|
15
16
|
# outerlayer emit acceptance-criteria --item "$OUTERLAYER_WORK" --result pass --link <the report's deep link>
|
|
@@ -4,11 +4,12 @@
|
|
|
4
4
|
# findings report (each confirmed finding with its severity and fix, or a
|
|
5
5
|
# clean bill) as an .html file. Emit it as a report artifact with no --for:
|
|
6
6
|
# outerlayer emit artifact review.html --caption "Review of the change and what it found"
|
|
7
|
-
# Then run `outerlayer sync
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
#
|
|
11
|
-
#
|
|
7
|
+
# Then run `outerlayer sync`. It prints a line for the report that ends with
|
|
8
|
+
# its link; take the link from that line. If `sync` printed no line for it,
|
|
9
|
+
# another sync already uploaded the report: run
|
|
10
|
+
# `outerlayer sync --link <the artifact id>`, with the id `emit artifact`
|
|
11
|
+
# printed. Never build the link by hand, and never link a pull request
|
|
12
|
+
# comment: a comment can be edited or deleted later.
|
|
12
13
|
#
|
|
13
14
|
# Then record the verdict once, with that link as its proof:
|
|
14
15
|
# outerlayer emit code-review --item "$OUTERLAYER_WORK" --result pass --link <the report's deep link>
|
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { createRequire } from 'node:module';
|
|
3
|
-
import { readConfigObject, RunnerInitError } from './chunk-CA3XMYFN.js';
|
|
4
|
-
import './chunk-RSPXEVDX.js';
|
|
5
|
-
import './chunk-EWORLJMO.js';
|
|
6
|
-
import './chunk-KMDLFI4P.js';
|
|
7
|
-
import './chunk-QKFB4K7X.js';
|
|
8
|
-
import './chunk-RSNSZ2LJ.js';
|
|
9
|
-
import './chunk-OZGHL5Y5.js';
|
|
10
|
-
import './chunk-RLYZLUQ7.js';
|
|
11
|
-
import './chunk-6MZSX4M7.js';
|
|
12
|
-
import { postJson, WorkCommandError, getJson } from './chunk-6QRMLNH3.js';
|
|
13
|
-
import './chunk-NPQWKGUA.js';
|
|
14
|
-
import './chunk-IP7BIBXJ.js';
|
|
15
|
-
import { runnerCredentialProblem } from './chunk-22RMZBGW.js';
|
|
16
|
-
import './chunk-UXYLWVTQ.js';
|
|
17
|
-
import './chunk-R7PF5OOU.js';
|
|
18
|
-
import './chunk-QOZKPLVJ.js';
|
|
19
|
-
import './chunk-N5FOE5PS.js';
|
|
20
|
-
import './chunk-OGFGZQA3.js';
|
|
21
|
-
import './chunk-4NPZVMJU.js';
|
|
22
|
-
import './chunk-7RQ73DLO.js';
|
|
23
|
-
import './chunk-4Q7OMKAT.js';
|
|
24
|
-
import './chunk-CX22S5BA.js';
|
|
25
|
-
import './chunk-YDSMROTB.js';
|
|
26
|
-
import './chunk-WUYTWNMA.js';
|
|
27
|
-
import './chunk-JXYVA45C.js';
|
|
28
|
-
import './chunk-4KSQKQXE.js';
|
|
29
|
-
import './chunk-N6LURUEF.js';
|
|
30
|
-
import './chunk-YRYMNBGQ.js';
|
|
31
|
-
import './chunk-WZBHBH3J.js';
|
|
32
|
-
import './chunk-JEHRUE3F.js';
|
|
33
|
-
import './chunk-WTE3MQML.js';
|
|
34
|
-
import './chunk-C5Y5ZJJZ.js';
|
|
35
|
-
import './chunk-ZJSNLVCE.js';
|
|
36
|
-
import './chunk-YO4PSLVB.js';
|
|
37
|
-
import './chunk-BYT5O5RV.js';
|
|
38
|
-
import './chunk-POJMEEJJ.js';
|
|
39
|
-
import './chunk-OHVJA253.js';
|
|
40
|
-
import './chunk-PLMTLGYH.js';
|
|
41
|
-
import './chunk-J5M7BSJQ.js';
|
|
42
|
-
import { readCloudConfig } from './chunk-EABW6AJQ.js';
|
|
43
|
-
import './chunk-RA3O54FC.js';
|
|
44
|
-
import './chunk-V7NIVOFD.js';
|
|
45
|
-
import './chunk-ZM2IMMYN.js';
|
|
46
|
-
import './chunk-XCCLFVXM.js';
|
|
47
|
-
import { readRepoConnection } from './chunk-BJ3KTMDH.js';
|
|
48
|
-
import { homeFromEnv } from './chunk-VNVZDWO3.js';
|
|
49
|
-
import './chunk-Z5GEFMRW.js';
|
|
50
|
-
import { existsSync } from 'fs';
|
|
51
|
-
import { hostname } from 'os';
|
|
52
|
-
|
|
53
|
-
createRequire(import.meta.url);
|
|
54
|
-
var RUNNER_KEY_PERMISSIONS = [
|
|
55
|
-
"sessions.ingest",
|
|
56
|
-
"evidence.insert",
|
|
57
|
-
"work.read",
|
|
58
|
-
"git.read",
|
|
59
|
-
"context.read",
|
|
60
|
-
"work.update",
|
|
61
|
-
"work.claim",
|
|
62
|
-
"hosts.ingest"
|
|
63
|
-
];
|
|
64
|
-
var MAX_NAME_ATTEMPTS = 10;
|
|
65
|
-
var PASTED_KEY_FALLBACK = "Ask a member who can create keys to make one with the Runner preset on the factory's API keys page, then put it in the runner's config file as apiKey, with the Factory Id as appId, and run this again.";
|
|
66
|
-
function runnerKeyLogin(configPath, opts = {}) {
|
|
67
|
-
const env = opts.env ?? process.env;
|
|
68
|
-
const config = existsSync(configPath) ? readConfigObject(configPath) : {};
|
|
69
|
-
if (config.apiKey !== void 0) {
|
|
70
|
-
if (opts.appId !== void 0 && opts.appId !== config.appId) {
|
|
71
|
-
throw new RunnerInitError(
|
|
72
|
-
`${configPath} already holds a runner key, for the factory its appId names, so --app-id ${opts.appId} creates no key. Leave --app-id out, or give it the same id.`
|
|
73
|
-
);
|
|
74
|
-
}
|
|
75
|
-
return void 0;
|
|
76
|
-
}
|
|
77
|
-
const saved = readCloudConfig(opts.home ?? homeFromEnv(env));
|
|
78
|
-
const own = typeof config.accountToken === "string" && config.accountToken !== "";
|
|
79
|
-
const accountToken = own ? config.accountToken : saved.accountToken;
|
|
80
|
-
if (accountToken === void 0 || accountToken === "") return void 0;
|
|
81
|
-
const url = config.url ?? (own ? void 0 : saved.url);
|
|
82
|
-
const appId = opts.appId ?? (env.OUTERLAYER_APP_ID || void 0) ?? config.appId ?? readRepoConnection(opts.cwd ?? process.cwd())?.appId;
|
|
83
|
-
if (appId === void 0) {
|
|
84
|
-
throw new RunnerInitError(
|
|
85
|
-
"you are logged in, so this command creates the runner's key, but no factory is chosen. Pass --app-id with the Factory Id from the factory's Settings \u2192 General, or set OUTERLAYER_APP_ID."
|
|
86
|
-
);
|
|
87
|
-
}
|
|
88
|
-
const problem = runnerCredentialProblem({ url, apiKey: accountToken, appId });
|
|
89
|
-
if (problem !== void 0) {
|
|
90
|
-
const where = problem.field === "appId" ? "the factory id" : `${configPath}: ${problem.field}`;
|
|
91
|
-
throw new RunnerInitError(`${where} ${problem.reason}.`);
|
|
92
|
-
}
|
|
93
|
-
return { url, accountToken, appId };
|
|
94
|
-
}
|
|
95
|
-
function defaultRunnerKeyName(host = hostname()) {
|
|
96
|
-
const short = host.replace(/\..*$/, "").trim();
|
|
97
|
-
return short === "" ? "runner" : short;
|
|
98
|
-
}
|
|
99
|
-
function clause(message) {
|
|
100
|
-
return message.replace(/\.+$/, "");
|
|
101
|
-
}
|
|
102
|
-
function forbidden(err) {
|
|
103
|
-
return new RunnerInitError(`your login cannot create a runner key on this factory: ${clause(err.message)}. ${PASTED_KEY_FALLBACK}`);
|
|
104
|
-
}
|
|
105
|
-
async function createKey(login, name, fetchImpl) {
|
|
106
|
-
for (let attempt = 1; attempt <= MAX_NAME_ATTEMPTS; attempt++) {
|
|
107
|
-
const tried = attempt === 1 ? name : `${name}-${attempt}`;
|
|
108
|
-
try {
|
|
109
|
-
const { data } = await postJson(
|
|
110
|
-
login.url,
|
|
111
|
-
"/v1/api-keys",
|
|
112
|
-
login.accountToken,
|
|
113
|
-
login.appId,
|
|
114
|
-
{ name: tried, permissions: [...RUNNER_KEY_PERMISSIONS], app_id: login.appId },
|
|
115
|
-
fetchImpl
|
|
116
|
-
);
|
|
117
|
-
const apiKey = data.plaintext_key;
|
|
118
|
-
if (typeof apiKey !== "string" || apiKey === "") {
|
|
119
|
-
throw new RunnerInitError(`the gateway created the key ${tried} but did not return it. Delete it on the factory's API keys page, then run this again.`);
|
|
120
|
-
}
|
|
121
|
-
return { apiKey, name: tried };
|
|
122
|
-
} catch (err) {
|
|
123
|
-
if (!(err instanceof WorkCommandError)) throw err;
|
|
124
|
-
if (err.status === 409) continue;
|
|
125
|
-
if (err.status === 403) throw forbidden(err);
|
|
126
|
-
throw new RunnerInitError(`the runner key was not created: ${clause(err.message)}.`);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
throw new RunnerInitError(
|
|
130
|
-
`the names ${name} to ${name}-${MAX_NAME_ATTEMPTS} are all taken by keys on this factory. Pass --key-name with another name.`
|
|
131
|
-
);
|
|
132
|
-
}
|
|
133
|
-
async function checkKey(key, fetchImpl) {
|
|
134
|
-
const unusable = (why) => new RunnerInitError(
|
|
135
|
-
`the runner key ${key.name} was created, but ${why}. Nothing else was changed. Delete the key on the factory's API keys page, then run this again.`
|
|
136
|
-
);
|
|
137
|
-
let data;
|
|
138
|
-
try {
|
|
139
|
-
({ data } = await getJson(key.url, "/v1/runner/host-key", key.apiKey, key.appId, fetchImpl));
|
|
140
|
-
} catch (err) {
|
|
141
|
-
throw unusable(`the gateway did not accept it: ${clause(err instanceof Error ? err.message : String(err))}`);
|
|
142
|
-
}
|
|
143
|
-
if (data.bound !== false) {
|
|
144
|
-
throw unusable("the gateway did not report it as a new runner key");
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
async function createRunnerKey(login, opts = {}) {
|
|
148
|
-
const fetchImpl = opts.fetchImpl ?? fetch;
|
|
149
|
-
const created = await createKey(login, opts.name ?? defaultRunnerKeyName(), fetchImpl);
|
|
150
|
-
const key = { url: login.url, apiKey: created.apiKey, appId: login.appId, name: created.name };
|
|
151
|
-
await checkKey(key, fetchImpl);
|
|
152
|
-
return key;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
export { RUNNER_KEY_PERMISSIONS, createRunnerKey, defaultRunnerKeyName, runnerKeyLogin };
|