@outerlayer/cli 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (141) hide show
  1. package/CHANGELOG.md +124 -0
  2. package/README.md +226 -59
  3. package/dist/agent-setup-IFH3FB5X.js +197 -0
  4. package/dist/build-TZUUTRGH.js +9 -0
  5. package/dist/build-info.json +1 -1
  6. package/dist/check-WQP2CZDW.js +94 -0
  7. package/dist/chunk-2E54Z3P5.js +232 -0
  8. package/dist/chunk-3TT7RQYB.js +55 -0
  9. package/dist/{chunk-U32VSRLO.js → chunk-3YPKXE5L.js} +90 -632
  10. package/dist/{chunk-Q6CL5THG.js → chunk-5DLBAXY5.js} +208 -61
  11. package/dist/{chunk-R5KBGVII.js → chunk-5QRP3MVS.js} +30 -14
  12. package/dist/chunk-5Y3QQRUH.js +300 -0
  13. package/dist/chunk-6Y63SXFO.js +383 -0
  14. package/dist/chunk-774HEQL6.js +178 -0
  15. package/dist/chunk-7A6RVXPZ.js +2233 -0
  16. package/dist/chunk-7YIOOFVJ.js +71 -0
  17. package/dist/chunk-ABIWDUMS.js +104 -0
  18. package/dist/chunk-AUFG23AA.js +534 -0
  19. package/dist/chunk-B2G7JHHB.js +42 -0
  20. package/dist/chunk-BCJNHMZT.js +34 -0
  21. package/dist/chunk-BCLJSQCV.js +56 -0
  22. package/dist/chunk-BFESLKPP.js +61 -0
  23. package/dist/chunk-BJ3KTMDH.js +63 -0
  24. package/dist/chunk-BKO6JEZI.js +47 -0
  25. package/dist/chunk-BOLTI6LR.js +37 -0
  26. package/dist/chunk-CBPPJSAR.js +89 -0
  27. package/dist/chunk-CBZB6XY6.js +102 -0
  28. package/dist/{chunk-65WXAANR.js → chunk-DVDEBNQJ.js} +17 -2
  29. package/dist/{work-pr-cmd-AZQPWH4H.js → chunk-DVYHCMB2.js} +9 -26
  30. package/dist/{chunk-TFUIDMOB.js → chunk-EABW6AJQ.js} +12 -1
  31. package/dist/{chunk-KFYJV2ZG.js → chunk-EMY4I27X.js} +1 -1
  32. package/dist/{chunk-NTTPJV35.js → chunk-F47JBIAW.js} +3 -1
  33. package/dist/chunk-F6GFZXZ3.js +60 -0
  34. package/dist/{chunk-YOOSBOKS.js → chunk-F7CU5ABH.js} +1 -1
  35. package/dist/chunk-FAJSS2WN.js +1357 -0
  36. package/dist/chunk-FS2VYGZT.js +1764 -0
  37. package/dist/chunk-FV2CCGXK.js +9 -0
  38. package/dist/{chunk-4TNZMO7V.js → chunk-G7FSV7JX.js} +3452 -751
  39. package/dist/{emit-cmd-TWSYYEZI.js → chunk-H5NCNVDA.js} +68 -17
  40. package/dist/chunk-HE2D4EY5.js +83 -0
  41. package/dist/chunk-L2DBRKRA.js +94 -0
  42. package/dist/chunk-LF6MLJCY.js +38 -0
  43. package/dist/chunk-M5POMKKW.js +1051 -0
  44. package/dist/{mcp-install-cmd-FDQH6SEN.js → chunk-MQ3IPHIZ.js} +35 -18
  45. package/dist/{chunk-D77LS3UI.js → chunk-N5FOE5PS.js} +33 -4
  46. package/dist/chunk-N6LURUEF.js +64 -0
  47. package/dist/chunk-NYC54VBD.js +1084 -0
  48. package/dist/chunk-OGFGZQA3.js +23 -0
  49. package/dist/chunk-QOZKPLVJ.js +226 -0
  50. package/dist/chunk-RA3O54FC.js +30 -0
  51. package/dist/chunk-TBT347UY.js +41 -0
  52. package/dist/{chunk-NXLLURA4.js → chunk-UFFXNXLQ.js} +115 -71
  53. package/dist/chunk-USO2DKBD.js +421 -0
  54. package/dist/chunk-W4SQCOZU.js +206 -0
  55. package/dist/{chunk-A3WLZX2F.js → chunk-WIOZAJ2W.js} +15 -2
  56. package/dist/chunk-WO2BXCTQ.js +83 -0
  57. package/dist/{chunk-I3ETLSNE.js → chunk-XCCLFVXM.js} +120 -11
  58. package/dist/{context-materialize-6WKT3RBQ.js → chunk-XDDW4FRS.js} +134 -26
  59. package/dist/chunk-YYYXRJUW.js +101 -0
  60. package/dist/chunk-ZM2IMMYN.js +76 -0
  61. package/dist/chunk-ZMYPLFG3.js +71 -0
  62. package/dist/chunk-ZNA27WEV.js +470 -0
  63. package/dist/{cli-G7DILYJY.js → cli-NHUXABYH.js} +590 -876
  64. package/dist/{paths-D2VGWWFI.js → cli-build-K56DK4DS.js} +1 -1
  65. package/dist/config-XVJYZ4IQ.js +9 -0
  66. package/dist/connect-cmd-OOG4TPU7.js +16 -0
  67. package/dist/context-adopt-UMA4O5NY.js +105 -0
  68. package/dist/context-materialize-G2FUFC72.js +19 -0
  69. package/dist/dist-RW4UPPC2.js +6 -0
  70. package/dist/docker-NEGDLU6D.js +7 -0
  71. package/dist/doctor-53F2PYY7.js +43 -0
  72. package/dist/doctor-UFVL4PZY.js +426 -0
  73. package/dist/{emit-artifact-cmd-UQVT3OKW.js → emit-artifact-cmd-KTYW2TN2.js} +24 -20
  74. package/dist/emit-cmd-DCERAU27.js +9 -0
  75. package/dist/emit-criteria-cmd-VAUUSAYD.js +166 -0
  76. package/dist/{emit-finding-cmd-FDOU2OPD.js → emit-finding-cmd-UR4ID45Z.js} +34 -31
  77. package/dist/{emit-result-cmd-H2T4C2K3.js → emit-result-cmd-FDTUKGKE.js} +34 -62
  78. package/dist/exec-client-4XGXV3XN.js +8 -0
  79. package/dist/guest-init-GENRHNP7.js +8 -0
  80. package/dist/hook-fast-EYENPK6F.js +9 -0
  81. package/dist/{hook-wrap-fast-KXYNX3AD.js → hook-wrap-fast-NPLHJXFK.js} +2 -2
  82. package/dist/host-key-KDYZ5ECC.js +7 -0
  83. package/dist/import-capture-cmd-AVZ4VIVJ.js +68 -0
  84. package/dist/{import-ruler-cmd-7LH2QOMG.js → import-ruler-cmd-GUHL6IY5.js} +1 -1
  85. package/dist/index.js +4 -4
  86. package/dist/init-DXBCOAJK.js +36 -0
  87. package/dist/init-YEXK35CF.js +221 -0
  88. package/dist/init-cmd-NHR7PRSQ.js +135 -0
  89. package/dist/install-cmd-7WXOIFDO.js +55 -0
  90. package/dist/lima-XN65D7GN.js +55 -0
  91. package/dist/login-browser-7XGSV7MA.js +10 -0
  92. package/dist/{config-POF7DEQW.js → logout-cmd-QAUFDJ6J.js} +3 -1
  93. package/dist/{logs-TRNPQM42.js → logs-7RYUH5A6.js} +1 -1
  94. package/dist/loop-VZOLL4WQ.js +43 -0
  95. package/dist/machine-WSG52J75.js +35 -0
  96. package/dist/mcp-install-cmd-RLK4SO3N.js +9 -0
  97. package/dist/{mcp-serve-cmd-57EZZOTL.js → mcp-serve-cmd-JPTP5FMS.js} +20 -9
  98. package/dist/paths-OYKMVYJP.js +6 -0
  99. package/dist/{pidfile-PTW76F56.js → pidfile-UZRH774M.js} +2 -3
  100. package/dist/real-deps-SU24ZA2K.js +21 -0
  101. package/dist/relay-L76HDX72.js +46 -0
  102. package/dist/settings-J2652U5N.js +7 -0
  103. package/dist/starter-pack-LIZYMKYQ.js +10 -0
  104. package/dist/{status-I27IST4L.js → status-2UZKKNB7.js} +30 -13
  105. package/dist/{statusline-fast-3C5OXHDD.js → statusline-fast-SVTMBMD7.js} +3 -2
  106. package/dist/sync-cmd-VPPYCNNM.js +28 -0
  107. package/dist/version-BWM6VLDI.js +6 -0
  108. package/dist/{watch-3DTPJETH.js → watch-5C4ZBBGO.js} +19 -8
  109. package/dist/{work-claim-cmd-5AUNCLS2.js → work-claim-cmd-LSO2B2EX.js} +33 -20
  110. package/dist/work-cmd-UOQO2AD4.js +17 -0
  111. package/dist/work-comment-cmd-WF3EOLAE.js +106 -0
  112. package/dist/{work-launch-LT663PB3.js → work-launch-YI4CJDAP.js} +1 -1
  113. package/dist/work-open-pr-cmd-4SSQZMYG.js +156 -0
  114. package/dist/work-pr-cmd-6AN6RRQJ.js +16 -0
  115. package/package.json +13 -3
  116. package/skill-pack/maintained/amend/SKILL.md +104 -0
  117. package/skill-pack/maintained/emitting-evidence/SKILL.md +99 -0
  118. package/skill-pack/maintained/emitting-evidence/references/agents-snippet.md +20 -0
  119. package/skill-pack/maintained/outerlayer/SKILL.md +55 -0
  120. package/skill-pack/maintained/reporting-findings/SKILL.md +148 -0
  121. package/skill-pack/template/build/SKILL.md +193 -0
  122. package/skill-pack/template/build/references/agent-briefs.md +243 -0
  123. package/skill-pack/template/build/references/criteria-judge.md +91 -0
  124. package/skill-pack/template/build/references/evidence.md +42 -0
  125. package/skill-pack/template/build/references/release.md +74 -0
  126. package/skill-pack/template/build/references/review-briefs.md +275 -0
  127. package/skill-pack/template/build/references/review-loop.md +158 -0
  128. package/skill-pack/template/build/scripts/record-criteria.mjs +235 -0
  129. package/skill-pack/template/spec/SKILL.md +84 -0
  130. package/skill-pack/template/writing-specs/SKILL.md +134 -0
  131. package/dist/chunk-DCNOXRMV.js +0 -589
  132. package/dist/chunk-JJP7YLMN.js +0 -25
  133. package/dist/chunk-OZ7C3XUE.js +0 -34
  134. package/dist/chunk-WQ6VGRGZ.js +0 -150
  135. package/dist/hook-fast-J5LCDHUJ.js +0 -8
  136. package/dist/import-capture-cmd-EUMBGIV3.js +0 -176
  137. package/dist/init-PTBITAUO.js +0 -103
  138. package/dist/login-cmd-IRX6LZT7.js +0 -62
  139. package/dist/loop-ASZRX3CZ.js +0 -648
  140. package/dist/sync-cmd-BBAUZ5JD.js +0 -17
  141. package/dist/work-cmd-2P4BVX47.js +0 -18
@@ -1,11 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
3
  import { C } from './chunk-YRYMNBGQ.js';
4
- import { readCloudConfig } from './chunk-TFUIDMOB.js';
5
- import './chunk-VNVZDWO3.js';
6
- import './chunk-Z5GEFMRW.js';
7
- import { existsSync, readFileSync, writeFileSync } from 'fs';
8
- import { join } from 'path';
4
+ import { readCloudConfig } from './chunk-EABW6AJQ.js';
5
+ import { existsSync, mkdirSync, writeFileSync, readFileSync } from 'fs';
6
+ import { join, dirname } from 'path';
9
7
 
10
8
  createRequire(import.meta.url);
11
9
  var McpInstallError = class extends Error {
@@ -14,7 +12,7 @@ function defaultMcpUrl(home) {
14
12
  const origin = readCloudConfig(home).url;
15
13
  if (!origin) {
16
14
  throw new McpInstallError(
17
- "no gateway URL: pass --url <your gateway>, or run `outerlayer login --url <your gateway>` first."
15
+ "no gateway URL: pass --url <your gateway>, or run `outerlayer login` first."
18
16
  );
19
17
  }
20
18
  return `${origin.replace(/\/+$/, "")}/v1/mcp`;
@@ -33,6 +31,35 @@ function buildStdioServerEntry(command, url, appId) {
33
31
  if (appId) args.push("--app-id", appId);
34
32
  return { type: "stdio", command, args };
35
33
  }
34
+ function readMcpDoc(absPath, relPath) {
35
+ if (!existsSync(absPath)) return {};
36
+ let doc;
37
+ try {
38
+ doc = JSON.parse(readFileSync(absPath, "utf8"));
39
+ } catch {
40
+ throw new McpInstallError(`${relPath} exists and is not valid JSON \u2014 fix or remove it, then run the command again`);
41
+ }
42
+ if (doc === null || typeof doc !== "object" || Array.isArray(doc)) {
43
+ throw new McpInstallError(`${relPath} exists and its top level is not a JSON object \u2014 refusing to overwrite`);
44
+ }
45
+ return doc;
46
+ }
47
+ function addStdioMcpEntryIfAbsent(repoRoot, name = "outerlayer") {
48
+ const relPath = existsSync(join(repoRoot, ".outerlayer", "mcp.json")) ? ".outerlayer/mcp.json" : ".mcp.json";
49
+ const absPath = join(repoRoot, relPath);
50
+ const doc = readMcpDoc(absPath, relPath);
51
+ const servers = doc.mcpServers;
52
+ if (servers !== void 0 && (servers === null || typeof servers !== "object" || Array.isArray(servers))) {
53
+ throw new McpInstallError(`${relPath} has an "mcpServers" value that is not an object \u2014 refusing to overwrite`);
54
+ }
55
+ const existing = servers ?? {};
56
+ if (name in existing) return { path: relPath, added: false };
57
+ const entry = buildStdioServerEntry(DEFAULT_MCP_COMMAND, void 0, void 0);
58
+ mkdirSync(dirname(absPath), { recursive: true });
59
+ writeFileSync(absPath, `${JSON.stringify({ ...doc, mcpServers: { ...existing, [name]: entry } }, null, 2)}
60
+ `);
61
+ return { path: relPath, added: true };
62
+ }
36
63
  function runMcpInstall(opts = {}) {
37
64
  const cwd = opts.cwd ?? process.cwd();
38
65
  if (!existsSync(cwd)) throw new McpInstallError(`no such directory: ${cwd}`);
@@ -41,17 +68,7 @@ function runMcpInstall(opts = {}) {
41
68
  const url = transport === "http" ? opts.url ?? defaultMcpUrl(opts.home) : opts.url ?? null;
42
69
  const relPath = ".mcp.json";
43
70
  const absPath = join(cwd, relPath);
44
- let doc = {};
45
- if (existsSync(absPath)) {
46
- try {
47
- doc = JSON.parse(readFileSync(absPath, "utf8"));
48
- } catch {
49
- throw new McpInstallError(`${relPath} exists and is not valid JSON \u2014 fix or remove it before running "mcp install"`);
50
- }
51
- if (doc === null || typeof doc !== "object" || Array.isArray(doc)) {
52
- throw new McpInstallError(`${relPath} exists and its top level is not a JSON object \u2014 refusing to overwrite`);
53
- }
54
- }
71
+ const doc = readMcpDoc(absPath, relPath);
55
72
  const existingServers = doc.mcpServers && typeof doc.mcpServers === "object" && !Array.isArray(doc.mcpServers) ? doc.mcpServers : {};
56
73
  const entry = transport === "http" ? buildServerEntry(url, opts.appId) : buildStdioServerEntry(opts.command ?? DEFAULT_MCP_COMMAND, url ?? void 0, opts.appId);
57
74
  const changed = JSON.stringify(existingServers[name] ?? null) !== JSON.stringify(entry);
@@ -72,4 +89,4 @@ function handleMcpInstallError(err) {
72
89
  process.exitCode = 1;
73
90
  }
74
91
 
75
- export { DEFAULT_MCP_COMMAND, McpInstallError, buildServerEntry, buildStdioServerEntry, defaultMcpUrl, handleMcpInstallError, runMcpInstall };
92
+ export { DEFAULT_MCP_COMMAND, McpInstallError, addStdioMcpEntryIfAbsent, buildServerEntry, buildStdioServerEntry, defaultMcpUrl, handleMcpInstallError, runMcpInstall };
@@ -1,11 +1,40 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { isSameProcess } from './chunk-OZ7C3XUE.js';
4
- import { RUNNER_DIR_MODE, RUNNER_FILE_MODE } from './chunk-JJP7YLMN.js';
5
- import { existsSync, readFileSync, rmSync, mkdirSync, writeFileSync } from 'fs';
3
+ import { RUNNER_DIR_MODE, RUNNER_FILE_MODE } from './chunk-ZM2IMMYN.js';
4
+ import { readFileSync, existsSync, rmSync, mkdirSync, writeFileSync } from 'fs';
6
5
  import { dirname } from 'path';
6
+ import { execFileSync } from 'child_process';
7
7
 
8
8
  createRequire(import.meta.url);
9
+ function startTimeOf(pid) {
10
+ if (process.platform === "linux") return startTimeOfLinux(pid);
11
+ return startTimeOfPs(pid);
12
+ }
13
+ function startTimeOfLinux(pid) {
14
+ try {
15
+ const stat = readFileSync(`/proc/${pid}/stat`, "utf8");
16
+ const afterComm = stat.slice(stat.lastIndexOf(")") + 1).trim();
17
+ const fields = afterComm.split(/\s+/);
18
+ if (fields[0] === "Z" || fields[0] === "X") return null;
19
+ const starttime = fields[19];
20
+ return starttime ?? null;
21
+ } catch {
22
+ return null;
23
+ }
24
+ }
25
+ function startTimeOfPs(pid) {
26
+ try {
27
+ const out = execFileSync("ps", ["-o", "lstart=", "-p", String(pid)], { encoding: "utf8" }).trim();
28
+ return out.length > 0 ? out : null;
29
+ } catch {
30
+ return null;
31
+ }
32
+ }
33
+ function isSameProcess(pid, start) {
34
+ return startTimeOf(pid) === start;
35
+ }
36
+
37
+ // src/runner/pidfile.ts
9
38
  function readPidFile(path) {
10
39
  if (!existsSync(path)) return null;
11
40
  try {
@@ -39,4 +68,4 @@ function claimPidFile(path, self, isSameProcessFn = isSameProcess) {
39
68
  writePidFile(path, self);
40
69
  }
41
70
 
42
- export { RunnerAlreadyRunningError, claimPidFile, readPidFile, releasePidFile };
71
+ export { RunnerAlreadyRunningError, claimPidFile, isSameProcess, readPidFile, releasePidFile, startTimeOf };
@@ -0,0 +1,64 @@
1
+ #!/usr/bin/env node
2
+ import { createRequire } from 'node:module';
3
+ import { C } from './chunk-YRYMNBGQ.js';
4
+ import { readCloudConfig, removeCloudConfigKeys } from './chunk-EABW6AJQ.js';
5
+ import { homeFromEnv } from './chunk-VNVZDWO3.js';
6
+
7
+ createRequire(import.meta.url);
8
+
9
+ // src/logout-cmd.ts
10
+ var DEFAULT_DASHBOARD = "https://app.outerlayer.ai";
11
+ var REQUEST_TIMEOUT_MS = 15e3;
12
+ function realLogoutDeps() {
13
+ return { fetchImpl: fetch, stdout: process.stdout, stderr: process.stderr };
14
+ }
15
+ async function revokeTokenOnDashboard(fetchImpl, dashboard, token) {
16
+ try {
17
+ const res = await fetchImpl(`${dashboard.replace(/\/+$/, "")}/api/cli/logout`, {
18
+ method: "POST",
19
+ headers: { authorization: `Bearer ${token}` },
20
+ signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
21
+ });
22
+ if (res.status >= 500) return "unreachable";
23
+ return res.status >= 200 && res.status < 300 ? "revoked" : "refused";
24
+ } catch {
25
+ return "unreachable";
26
+ }
27
+ }
28
+ async function runLogoutCommand(deps) {
29
+ const home = deps.home ?? homeFromEnv();
30
+ const config = readCloudConfig(home);
31
+ const token = config.accountToken;
32
+ if (!token) {
33
+ deps.stdout.write("Not logged in.\n");
34
+ return 0;
35
+ }
36
+ const outcome = await revokeTokenOnDashboard(deps.fetchImpl, config.dashboard ?? DEFAULT_DASHBOARD, token);
37
+ try {
38
+ removeCloudConfigKeys(["accountToken", "dashboard"], home);
39
+ } catch (err) {
40
+ deps.stderr.write(
41
+ `${C.red}\u2717${C.reset} Could not remove the login from the config file: ${err instanceof Error ? err.message : String(err)}. ` + (outcome === "revoked" ? "The token is revoked on the dashboard, but a copy is still on this machine; delete it from the config file.\n" : "The token may still be valid; revoke it on the CLI logins list at /profile/security.\n")
42
+ );
43
+ return 1;
44
+ }
45
+ if (outcome === "refused") {
46
+ deps.stderr.write(
47
+ `${C.red}\u2717${C.reset} Removed the login from this machine, but the dashboard did not confirm the revoke. The token may stay valid until you revoke it on the CLI logins list at /profile/security.
48
+ `
49
+ );
50
+ return 1;
51
+ }
52
+ if (outcome === "unreachable") {
53
+ deps.stderr.write(
54
+ `${C.red}\u2717${C.reset} Removed the login from this machine, but could not reach the dashboard to revoke it. The token may stay valid until you revoke it on the CLI logins list at /profile/security.
55
+ `
56
+ );
57
+ return 1;
58
+ }
59
+ deps.stdout.write(`${C.green}\u2713${C.reset} Logged out. The token is revoked and removed from this machine.
60
+ `);
61
+ return 0;
62
+ }
63
+
64
+ export { realLogoutDeps, revokeTokenOnDashboard, runLogoutCommand };