@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.
Files changed (65) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +11 -11
  3. package/dist/{agent-setup-K3ABU5NL.js → agent-setup-T624CWPD.js} +2 -2
  4. package/dist/artifact-link-cmd-2F47LT7F.js +24 -0
  5. package/dist/build-info.json +1 -1
  6. package/dist/{check-CNTMSGOG.js → check-5XE7XMC4.js} +14 -14
  7. package/dist/{chunk-YDSMROTB.js → chunk-3NSNIIBE.js} +8 -4
  8. package/dist/{chunk-NPQWKGUA.js → chunk-6Y5RUTHO.js} +1 -1
  9. package/dist/{chunk-6JNURGOA.js → chunk-BWQ66M6N.js} +1 -1
  10. package/dist/{chunk-R4ZQQ7U2.js → chunk-G5NPRL2K.js} +7 -8
  11. package/dist/{chunk-W3EKCZSQ.js → chunk-HGECYFEI.js} +55 -5
  12. package/dist/{chunk-5FEK6PNE.js → chunk-KG5ECZGJ.js} +1 -1
  13. package/dist/{chunk-FWX735W7.js → chunk-LWSJQJC6.js} +3 -3
  14. package/dist/{chunk-EWORLJMO.js → chunk-MAK5LYRF.js} +16 -7
  15. package/dist/{chunk-ONRCEE6D.js → chunk-NNRTPG7X.js} +2 -2
  16. package/dist/{chunk-U3HXXRTY.js → chunk-NWQTTSBB.js} +1 -1
  17. package/dist/{chunk-RSPXEVDX.js → chunk-ONKJUM6R.js} +1 -1
  18. package/dist/{chunk-6QRMLNH3.js → chunk-S3NYLI2P.js} +3 -3
  19. package/dist/{chunk-CA3XMYFN.js → chunk-VQYBXPI7.js} +3 -3
  20. package/dist/{chunk-EHAAPRWY.js → chunk-WVUIRTWA.js} +7 -7
  21. package/dist/{chunk-JJEGKEFV.js → chunk-YU3VKZ5F.js} +1 -1
  22. package/dist/{chunk-JEHRUE3F.js → chunk-YZ5F4PIS.js} +91 -20
  23. package/dist/{cli-AEWH62UE.js → cli-A76AXELQ.js} +71 -63
  24. package/dist/{command-HHPBR6CS.js → command-R2QCVX55.js} +6 -6
  25. package/dist/{connect-cmd-JUAW6MU4.js → connect-cmd-JBKAQNSF.js} +1 -1
  26. package/dist/{context-adopt-VMMGFRUZ.js → context-adopt-NFHCLVUB.js} +1 -1
  27. package/dist/{context-materialize-2WXTS4CW.js → context-materialize-IV2TUUFO.js} +1 -1
  28. package/dist/{doctor-N6Y7HKK3.js → doctor-4TAIARIG.js} +10 -9
  29. package/dist/{emit-artifact-cmd-H5MH3AOP.js → emit-artifact-cmd-MPZVR56N.js} +4 -4
  30. package/dist/{emit-criteria-cmd-HBP6XS5C.js → emit-criteria-cmd-EFGYI23V.js} +2 -2
  31. package/dist/{emit-finding-cmd-ZXDRL6PG.js → emit-finding-cmd-5GF3V4LR.js} +2 -2
  32. package/dist/{emit-result-cmd-RFKALS5Z.js → emit-result-cmd-I4OADKMD.js} +4 -4
  33. package/dist/hidden-prompt-UXBFMQC5.js +68 -0
  34. package/dist/{hook-fast-D7HV4IXG.js → hook-fast-R4FVSZ2H.js} +1 -1
  35. package/dist/index.js +3 -3
  36. package/dist/{init-MYX7YMIH.js → init-6XPDRDTC.js} +7 -7
  37. package/dist/{init-FBCA4DRA.js → init-PWU5YVL7.js} +49 -25
  38. package/dist/{init-cmd-CAG572UE.js → init-cmd-XAVO7HYZ.js} +5 -5
  39. package/dist/{init-update-VDFF4K3B.js → init-update-CVCWD6VS.js} +3 -3
  40. package/dist/{loop-75J4YXLZ.js → loop-FK3LPMMZ.js} +14 -14
  41. package/dist/{machine-A6ZCTUGS.js → machine-SQXEBAM2.js} +6 -6
  42. package/dist/runner-key-6SLBI7PP.js +174 -0
  43. package/dist/{session-sender-24L5EW25.js → session-sender-FO3LCREV.js} +3 -3
  44. package/dist/{status-XHSGEYO5.js → status-7VNQN5PW.js} +9 -9
  45. package/dist/{sync-cmd-5G5EIEHD.js → sync-cmd-GVPPFZ3G.js} +2 -2
  46. package/dist/{watch-UTOXO4SE.js → watch-23HSAEI6.js} +2 -2
  47. package/dist/{work-claim-cmd-RKHYFE5Y.js → work-claim-cmd-LKL3GHFQ.js} +5 -5
  48. package/dist/{work-cmd-DJQJEZVB.js → work-cmd-Z2WXLZPH.js} +3 -3
  49. package/dist/{work-comment-cmd-A55CUSYE.js → work-comment-cmd-AWHP56M2.js} +3 -3
  50. package/dist/{work-open-pr-cmd-E6O53IJD.js → work-open-pr-cmd-IOM4AVQQ.js} +4 -4
  51. package/dist/{work-pr-cmd-L77K32WK.js → work-pr-cmd-HNEUIEN7.js} +3 -3
  52. package/package.json +1 -1
  53. package/skill-pack/maintained/outerlayer-amend/SKILL.md +2 -0
  54. package/skill-pack/maintained/outerlayer-cli/SKILL.md +2 -0
  55. package/skill-pack/maintained/outerlayer-evidence/SKILL.md +4 -2
  56. package/skill-pack/maintained/outerlayer-findings/SKILL.md +2 -0
  57. package/skill-pack/shipped.json +10 -3
  58. package/skill-pack/template/build/SKILL.md +2 -0
  59. package/skill-pack/template/build/references/release.md +13 -11
  60. package/skill-pack/template/build/scripts/criterion-citations.mjs +8 -3
  61. package/skill-pack/template/build/scripts/record-criteria.mjs +8 -2
  62. package/skill-pack/template/spec/SKILL.md +2 -0
  63. package/skill-pack/validators/acceptance-criteria.yaml +6 -5
  64. package/skill-pack/validators/code-review.yaml +6 -5
  65. 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-R4ZQQ7U2.js';
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-ONRCEE6D.js';
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-EWORLJMO.js';
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-6QRMLNH3.js';
16
- import './chunk-NPQWKGUA.js';
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-YDSMROTB.js';
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-JEHRUE3F.js';
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-6JNURGOA.js';
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-U3HXXRTY.js';
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-6JNURGOA.js';
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-U3HXXRTY.js';
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-6JNURGOA.js';
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-6QRMLNH3.js';
5
- export { WorkCommandError } from './chunk-6QRMLNH3.js';
6
- import './chunk-NPQWKGUA.js';
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-YDSMROTB.js';
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-D7HV4IXG.js');
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-6QRMLNH3.js';
4
- import './chunk-NPQWKGUA.js';
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-YDSMROTB.js';
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-6QRMLNH3.js';
4
- import './chunk-NPQWKGUA.js';
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-YDSMROTB.js';
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-JJEGKEFV.js';
4
- import { resolveCredentials } from './chunk-6QRMLNH3.js';
5
- import './chunk-NPQWKGUA.js';
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-YDSMROTB.js';
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-JJEGKEFV.js';
4
- import './chunk-NPQWKGUA.js';
3
+ export { WorkPrCommandError, itemLabel, runWorkPr } from './chunk-YU3VKZ5F.js';
4
+ import './chunk-6Y5RUTHO.js';
5
5
  import './chunk-IP7BIBXJ.js';
6
- import './chunk-YDSMROTB.js';
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.16.1",
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`, and copy the report's deep link from the pull request's evidence comment. 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:
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`, copy the report's deep link from the evidence comment the same way, and record the judge's verdict on the `acceptance-criteria` check that `outerlayer init` writes:
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
@@ -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`. Copy the review
52
- report's deep link from the pull request's evidence comment. Never build the
53
- link by hand, and never link a pull request comment. Then record the review's
54
- verdict on the `code-review` check, once:
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 the link has not appeared after a sync, stop and name it as a blocker in
60
- the final report. Never record the result with another link.
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, copy its deep link from the pull request's
87
- evidence comment. The link can take up to a minute to appear after the sync.
88
- If it is not there yet, wait a minute and read the comment again. Never build
89
- the link by hand, and never link a pull request comment. Then record the
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. Only git-tracked test files are scanned, so every link names code
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
- /** A pattern that finds `id` as a whole token: not inside a longer id such as `WC-10` for `WC-1`, and still found before a sentence's full stop. */
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_:-]|\\.[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
- /** Builds the `emit` function that runs `outerlayer emit criteria`; `spawn` is `spawnSync`, or a stand-in in tests. */
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 run = spawn("outerlayer", ["emit", "criteria", file, "--item", item], { encoding: "utf8", timeout: 120000 });
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`, and copy the report's deep link from the pull
9
- # request's evidence comment. The link can take up to a minute to appear
10
- # after the sync. If it is not there yet, wait a minute and read the comment
11
- # again; do not give up after one look. Never build the link by hand, and
12
- # never link a pull request comment: a comment can be edited or deleted later.
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`, and copy the report's deep link from the pull
8
- # request's evidence comment. The link can take up to a minute to appear
9
- # after the sync. If it is not there yet, wait a minute and read the comment
10
- # again; do not give up after one look. Never build the link by hand, and
11
- # never link a pull request comment: a comment can be edited or deleted later.
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 };