ghostrail 0.0.0 → 0.2.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 (163) hide show
  1. package/README.md +49 -3
  2. package/dist/agent/claude-code.d.ts +10 -0
  3. package/dist/agent/claude-code.d.ts.map +1 -1
  4. package/dist/agent/claude-code.js +20 -0
  5. package/dist/agent/claude-code.js.map +1 -1
  6. package/dist/agent/result.d.ts.map +1 -1
  7. package/dist/agent/result.js +13 -2
  8. package/dist/agent/result.js.map +1 -1
  9. package/dist/backend/container.d.ts +18 -0
  10. package/dist/backend/container.d.ts.map +1 -1
  11. package/dist/backend/container.js +33 -10
  12. package/dist/backend/container.js.map +1 -1
  13. package/dist/backend/git-credentials.d.ts +18 -0
  14. package/dist/backend/git-credentials.d.ts.map +1 -0
  15. package/dist/backend/git-credentials.js +30 -0
  16. package/dist/backend/git-credentials.js.map +1 -0
  17. package/dist/backend/local-worktree.d.ts.map +1 -1
  18. package/dist/backend/local-worktree.js +21 -0
  19. package/dist/backend/local-worktree.js.map +1 -1
  20. package/dist/backend/types.d.ts +12 -1
  21. package/dist/backend/types.d.ts.map +1 -1
  22. package/dist/claude-profile/classify.d.ts +41 -0
  23. package/dist/claude-profile/classify.d.ts.map +1 -0
  24. package/dist/claude-profile/classify.js +103 -0
  25. package/dist/claude-profile/classify.js.map +1 -0
  26. package/dist/claude-profile/index.d.ts +3 -0
  27. package/dist/claude-profile/index.d.ts.map +1 -0
  28. package/dist/claude-profile/index.js +3 -0
  29. package/dist/claude-profile/index.js.map +1 -0
  30. package/dist/claude-profile/setup.d.ts +33 -0
  31. package/dist/claude-profile/setup.d.ts.map +1 -0
  32. package/dist/claude-profile/setup.js +81 -0
  33. package/dist/claude-profile/setup.js.map +1 -0
  34. package/dist/cli/commands.d.ts +67 -2
  35. package/dist/cli/commands.d.ts.map +1 -1
  36. package/dist/cli/commands.js +420 -17
  37. package/dist/cli/commands.js.map +1 -1
  38. package/dist/cli.d.ts.map +1 -1
  39. package/dist/cli.js +13 -1
  40. package/dist/cli.js.map +1 -1
  41. package/dist/commands/help.d.ts.map +1 -1
  42. package/dist/commands/help.js +20 -2
  43. package/dist/commands/help.js.map +1 -1
  44. package/dist/config/load.d.ts.map +1 -1
  45. package/dist/config/load.js +61 -9
  46. package/dist/config/load.js.map +1 -1
  47. package/dist/config/schema.d.ts +51 -3
  48. package/dist/config/schema.d.ts.map +1 -1
  49. package/dist/config/schema.js +4 -0
  50. package/dist/config/schema.js.map +1 -1
  51. package/dist/factory/build.d.ts +24 -0
  52. package/dist/factory/build.d.ts.map +1 -1
  53. package/dist/factory/build.js +80 -11
  54. package/dist/factory/build.js.map +1 -1
  55. package/dist/loop/concurrency.d.ts +13 -0
  56. package/dist/loop/concurrency.d.ts.map +1 -0
  57. package/dist/loop/concurrency.js +27 -0
  58. package/dist/loop/concurrency.js.map +1 -0
  59. package/dist/loop/engine.d.ts.map +1 -1
  60. package/dist/loop/engine.js +19 -14
  61. package/dist/loop/engine.js.map +1 -1
  62. package/dist/loop/index.d.ts +2 -0
  63. package/dist/loop/index.d.ts.map +1 -1
  64. package/dist/loop/index.js +2 -0
  65. package/dist/loop/index.js.map +1 -1
  66. package/dist/loop/ports.d.ts +37 -1
  67. package/dist/loop/ports.d.ts.map +1 -1
  68. package/dist/loop/watch.d.ts +25 -0
  69. package/dist/loop/watch.d.ts.map +1 -0
  70. package/dist/loop/watch.js +45 -0
  71. package/dist/loop/watch.js.map +1 -0
  72. package/dist/publish/gh.d.ts +20 -1
  73. package/dist/publish/gh.d.ts.map +1 -1
  74. package/dist/publish/gh.js +37 -3
  75. package/dist/publish/gh.js.map +1 -1
  76. package/dist/publish/githost.d.ts +12 -0
  77. package/dist/publish/githost.d.ts.map +1 -1
  78. package/dist/publish/githost.js +14 -0
  79. package/dist/publish/githost.js.map +1 -1
  80. package/dist/publish/github-publisher.d.ts +1 -1
  81. package/dist/publish/github-publisher.d.ts.map +1 -1
  82. package/dist/publish/github-publisher.js +6 -5
  83. package/dist/publish/github-publisher.js.map +1 -1
  84. package/dist/respond/respond.d.ts +10 -1
  85. package/dist/respond/respond.d.ts.map +1 -1
  86. package/dist/respond/respond.js +37 -3
  87. package/dist/respond/respond.js.map +1 -1
  88. package/dist/secrets/env-file.d.ts +23 -0
  89. package/dist/secrets/env-file.d.ts.map +1 -0
  90. package/dist/secrets/env-file.js +70 -0
  91. package/dist/secrets/env-file.js.map +1 -0
  92. package/dist/secrets/index.d.ts +4 -0
  93. package/dist/secrets/index.d.ts.map +1 -0
  94. package/dist/secrets/index.js +4 -0
  95. package/dist/secrets/index.js.map +1 -0
  96. package/dist/secrets/load.d.ts +24 -0
  97. package/dist/secrets/load.d.ts.map +1 -0
  98. package/dist/secrets/load.js +43 -0
  99. package/dist/secrets/load.js.map +1 -0
  100. package/dist/skill/install.d.ts +56 -0
  101. package/dist/skill/install.d.ts.map +1 -0
  102. package/dist/skill/install.js +93 -0
  103. package/dist/skill/install.js.map +1 -0
  104. package/dist/source/linear.d.ts +51 -8
  105. package/dist/source/linear.d.ts.map +1 -1
  106. package/dist/source/linear.js +213 -23
  107. package/dist/source/linear.js.map +1 -1
  108. package/dist/triage/apply.d.ts +28 -0
  109. package/dist/triage/apply.d.ts.map +1 -0
  110. package/dist/triage/apply.js +68 -0
  111. package/dist/triage/apply.js.map +1 -0
  112. package/dist/triage/engine.d.ts +31 -0
  113. package/dist/triage/engine.d.ts.map +1 -0
  114. package/dist/triage/engine.js +122 -0
  115. package/dist/triage/engine.js.map +1 -0
  116. package/dist/triage/index.d.ts +4 -0
  117. package/dist/triage/index.d.ts.map +1 -0
  118. package/dist/triage/index.js +4 -0
  119. package/dist/triage/index.js.map +1 -0
  120. package/dist/triage/plan.d.ts +37 -0
  121. package/dist/triage/plan.d.ts.map +1 -0
  122. package/dist/triage/plan.js +75 -0
  123. package/dist/triage/plan.js.map +1 -0
  124. package/dist/vendor/skilltend/apply.d.ts +25 -0
  125. package/dist/vendor/skilltend/apply.d.ts.map +1 -0
  126. package/dist/vendor/skilltend/apply.js +85 -0
  127. package/dist/vendor/skilltend/apply.js.map +1 -0
  128. package/dist/vendor/skilltend/detect.d.ts +35 -0
  129. package/dist/vendor/skilltend/detect.d.ts.map +1 -0
  130. package/dist/vendor/skilltend/detect.js +187 -0
  131. package/dist/vendor/skilltend/detect.js.map +1 -0
  132. package/dist/vendor/skilltend/frontmatter.d.ts +5 -0
  133. package/dist/vendor/skilltend/frontmatter.d.ts.map +1 -0
  134. package/dist/vendor/skilltend/frontmatter.js +59 -0
  135. package/dist/vendor/skilltend/frontmatter.js.map +1 -0
  136. package/dist/vendor/skilltend/fsFacade.d.ts +24 -0
  137. package/dist/vendor/skilltend/fsFacade.d.ts.map +1 -0
  138. package/dist/vendor/skilltend/fsFacade.js +68 -0
  139. package/dist/vendor/skilltend/fsFacade.js.map +1 -0
  140. package/dist/vendor/skilltend/paths.d.ts +28 -0
  141. package/dist/vendor/skilltend/paths.d.ts.map +1 -0
  142. package/dist/vendor/skilltend/paths.js +24 -0
  143. package/dist/vendor/skilltend/paths.js.map +1 -0
  144. package/dist/vendor/skilltend/plan.d.ts +46 -0
  145. package/dist/vendor/skilltend/plan.d.ts.map +1 -0
  146. package/dist/vendor/skilltend/plan.js +79 -0
  147. package/dist/vendor/skilltend/plan.js.map +1 -0
  148. package/dist/vendor/skilltend/registry.d.ts +56 -0
  149. package/dist/vendor/skilltend/registry.d.ts.map +1 -0
  150. package/dist/vendor/skilltend/registry.js +129 -0
  151. package/dist/vendor/skilltend/registry.js.map +1 -0
  152. package/docker/factory.Dockerfile +39 -0
  153. package/package.json +4 -3
  154. package/skill/ghostrail/SKILL.md +145 -0
  155. package/templates/{fix-bugs-local → code-local}/README.md +3 -3
  156. package/templates/code-local/ghostrail.toml +44 -0
  157. package/templates/code-local/prompts/resolve-issue.md +31 -0
  158. package/templates/code-local/prompts/respond.md +27 -0
  159. package/templates/code-local/prompts/triage.md +51 -0
  160. package/templates/content-loop/ghostrail.toml +5 -2
  161. package/templates/content-loop/prompts/respond.md +25 -0
  162. package/templates/fix-bugs-local/ghostrail.toml +0 -37
  163. package/templates/fix-bugs-local/prompts/fix-bug.md +0 -27
package/README.md CHANGED
@@ -19,14 +19,33 @@ A software factory is thin glue over three primitive layers: where work comes fr
19
19
  ## Quickstart
20
20
 
21
21
  ```bash
22
- npm i -g ghostrail
23
- ghostrail init fix-bugs-local # or: content-loop
22
+ npx ghostrail install # CLI on your PATH + the /ghostrail agent skill
23
+ ghostrail init code-local # or: content-loop
24
24
  export LINEAR_API_KEY=... # a Linear personal API key; gh must be authed
25
25
  ghostrail run # one tick: claim, isolate, run, gate, open PRs
26
26
  ghostrail respond # fold new human PR comments back into branches
27
27
  ghostrail board # watch runs at http://127.0.0.1:4369/
28
28
  ```
29
29
 
30
+ ## Drive it from your coding agent
31
+
32
+ `ghostrail skill` installs a `/ghostrail` skill into whichever coding agents you
33
+ have configured, so you can work from inside them instead of the shell. The one
34
+ worth knowing: **`/ghostrail customize`** reads the repo (stack, CI workflow,
35
+ test conventions) and proposes the edits that turn the generic scaffold into a
36
+ factory that fits *this* codebase. Also `doctor`, `status`, `init`, `run`,
37
+ `respond`, `triage`.
38
+
39
+ It is idempotent — re-run it to install or update, whichever applies:
40
+
41
+ ```bash
42
+ ghostrail skill # install/update for detected agents
43
+ ghostrail skill --project # commit it with this repo instead of your user config
44
+ ghostrail skill --check # is my copy out of date?
45
+ ghostrail skill uninstall # remove it (never touches another product's skill)
46
+ ghostrail self-update # update the CLI, then its skill
47
+ ```
48
+
30
49
  `ghostrail artifacts` lists the shared references in your global store
31
50
  (`~/.config/ghostrail/artifacts/`), staged into each run so the same voice and
32
51
  rules apply across every factory instance.
@@ -34,7 +53,7 @@ rules apply across every factory instance.
34
53
  ## Self-host and cutover
35
54
 
36
55
  Ghostrail builds itself: [`ghostrail.toml`](./ghostrail.toml) +
37
- [`prompts/fix-bug.md`](./prompts/fix-bug.md) point the factory at its own repo.
56
+ [`prompts/resolve-issue.md`](./prompts/resolve-issue.md) point the factory at its own repo.
38
57
  To replace the bespoke bash factories in `echotime`, `tjwrite`, and `research`,
39
58
  see [`docs/cutover.md`](./docs/cutover.md) and the configs in
40
59
  [`examples/`](./examples/).
@@ -51,6 +70,33 @@ pnpm lint # lint + format check (Biome)
51
70
  pnpm build # compile to dist/
52
71
  ```
53
72
 
73
+ ## Releasing
74
+
75
+ Releases publish from CI on a tag, so `main` and npm cannot drift.
76
+
77
+ 1. Bump `version` in `package.json` and add the release to [`CHANGELOG.md`](CHANGELOG.md).
78
+ 2. Merge that to `main`.
79
+ 3. Tag and push: `git tag v0.1.0 && git push origin v0.1.0`.
80
+
81
+ [`.github/workflows/release.yml`](.github/workflows/release.yml) then verifies the
82
+ tag matches `package.json`, runs lint/typecheck/tests/build, checks the package
83
+ contents (the `bin` shebang, both templates and their prompts, the Dockerfile, and
84
+ that every advertised command appears in `help`), and publishes with provenance.
85
+
86
+ Auth is npm **Trusted Publishing** (OIDC): the workflow exchanges its GitHub
87
+ Actions OIDC token for a short-lived registry token at publish time, so there is
88
+ no long-lived `NPM_TOKEN` secret to leak or rotate.
89
+
90
+ One-time setup on npmjs.com: open the `ghostrail` package → **Settings** →
91
+ **Trusted Publisher** → GitHub Actions, and point it at this repository with
92
+ workflow filename `release.yml`. Allowed action: `npm publish`.
93
+
94
+ Provenance (the Sigstore attestation binding a tarball to its source commit and
95
+ build) requires a **public** repository, so the workflow gates that flag on
96
+ visibility: releases cut while the repo is private publish unattested, and the
97
+ first release after it goes public attests automatically. Provenance is
98
+ per-version, so earlier versions stay unattested — it cannot be backfilled.
99
+
54
100
  ## License
55
101
 
56
102
  [Apache-2.0](./LICENSE).
@@ -16,6 +16,8 @@ export interface ClaudeArgsOptions {
16
16
  maxBudgetUsd?: number;
17
17
  /** `--model`, when set. */
18
18
  model?: string;
19
+ /** Explicit settings file for the run, passed as `--settings`. */
20
+ settingsPath?: string;
19
21
  }
20
22
  /**
21
23
  * Build the `claude` CLI arguments (everything after the binary) for a headless
@@ -32,6 +34,14 @@ export declare function buildClaudeArgs(options: ClaudeArgsOptions): string[];
32
34
  * and parses. Budget and timeout come from the guardrails.
33
35
  */
34
36
  export declare class ClaudeCodeAgent implements Agent {
37
+ private readonly profileDir?;
38
+ /**
39
+ * @param profileDir Optional ghostrail Claude profile. When set, the run uses
40
+ * it as Claude's config home (via `HOME`/`CLAUDE_CONFIG_DIR`) and its
41
+ * settings.json, so factory runs get the pinned skills/CLAUDE.md and never the
42
+ * user's interactive config.
43
+ */
44
+ constructor(profileDir?: string | undefined);
35
45
  run(context: AgentContext): Promise<AgentOutcome>;
36
46
  }
37
47
  //# sourceMappingURL=claude-code.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"claude-code.d.ts","sourceRoot":"","sources":["../../src/agent/claude-code.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAI1E,+EAA+E;AAC/E,eAAO,MAAM,WAAW,2BAA2B,CAAC;AAEpD,MAAM,WAAW,iBAAiB;IAChC,4EAA4E;IAC5E,MAAM,EAAE,MAAM,CAAC;IACf,4EAA4E;IAC5E,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,8EAA8E;IAC9E,MAAM,EAAE,MAAM,CAAC;IACf,6CAA6C;IAC7C,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,aAAa,CAAC;IAC/C,sDAAsD;IACtD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,oCAAoC;IACpC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,2BAA2B;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,iBAAiB,GAAG,MAAM,EAAE,CAqBpE;AAYD;;;;;;GAMG;AACH,qBAAa,eAAgB,YAAW,KAAK;IACrC,GAAG,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;CA+BxD"}
1
+ {"version":3,"file":"claude-code.d.ts","sourceRoot":"","sources":["../../src/agent/claude-code.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAI1E,+EAA+E;AAC/E,eAAO,MAAM,WAAW,2BAA2B,CAAC;AAEpD,MAAM,WAAW,iBAAiB;IAChC,4EAA4E;IAC5E,MAAM,EAAE,MAAM,CAAC;IACf,4EAA4E;IAC5E,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,8EAA8E;IAC9E,MAAM,EAAE,MAAM,CAAC;IACf,6CAA6C;IAC7C,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,aAAa,CAAC;IAC/C,sDAAsD;IACtD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,oCAAoC;IACpC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,2BAA2B;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kEAAkE;IAClE,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,iBAAiB,GAAG,MAAM,EAAE,CAwBpE;AAYD;;;;;;GAMG;AACH,qBAAa,eAAgB,YAAW,KAAK;IAO/B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC;IANxC;;;;;OAKG;gBAC0B,UAAU,CAAC,EAAE,MAAM,YAAA;IAE1C,GAAG,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;CAqCxD"}
@@ -1,3 +1,4 @@
1
+ import { join } from "node:path";
1
2
  import { renderPrompt } from "./prompt.js";
2
3
  import { parseAgentResult } from "./result.js";
3
4
  /** Path, relative to the workspace root, where the agent writes its result. */
@@ -19,6 +20,9 @@ export function buildClaudeArgs(options) {
19
20
  "--add-dir",
20
21
  options.addDir,
21
22
  ];
23
+ if (options.settingsPath !== undefined) {
24
+ args.push("--settings", options.settingsPath);
25
+ }
22
26
  if (options.allowedTools.length > 0) {
23
27
  args.push("--allowedTools", options.allowedTools.join(","));
24
28
  }
@@ -43,6 +47,16 @@ async function readFile(backend, workspace, path) {
43
47
  * and parses. Budget and timeout come from the guardrails.
44
48
  */
45
49
  export class ClaudeCodeAgent {
50
+ profileDir;
51
+ /**
52
+ * @param profileDir Optional ghostrail Claude profile. When set, the run uses
53
+ * it as Claude's config home (via `HOME`/`CLAUDE_CONFIG_DIR`) and its
54
+ * settings.json, so factory runs get the pinned skills/CLAUDE.md and never the
55
+ * user's interactive config.
56
+ */
57
+ constructor(profileDir) {
58
+ this.profileDir = profileDir;
59
+ }
46
60
  async run(context) {
47
61
  const { backend, workspace, item, agent, guardrails } = context;
48
62
  const template = await readFile(backend, workspace, agent.prompt);
@@ -54,9 +68,15 @@ export class ClaudeCodeAgent {
54
68
  allowedTools: agent.allowedTools,
55
69
  addDir: ".",
56
70
  maxBudgetUsd: guardrails.budgetUsdPerItem,
71
+ ...(this.profileDir === undefined
72
+ ? {}
73
+ : { settingsPath: join(this.profileDir, ".claude", "settings.json") }),
57
74
  });
58
75
  const run = await backend.exec(workspace, ["claude", ...args], {
59
76
  timeoutMs: guardrails.timeoutMs,
77
+ ...(this.profileDir === undefined
78
+ ? {}
79
+ : { env: { HOME: this.profileDir, CLAUDE_CONFIG_DIR: join(this.profileDir, ".claude") } }),
60
80
  });
61
81
  if (run.timedOut) {
62
82
  return { status: "failed", error: "agent timed out" };
@@ -1 +1 @@
1
- {"version":3,"file":"claude-code.js","sourceRoot":"","sources":["../../src/agent/claude-code.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"claude-code.js","sourceRoot":"","sources":["../../src/agent/claude-code.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"result.d.ts","sourceRoot":"","sources":["../../src/agent/result.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAErD;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,CAuC1D"}
1
+ {"version":3,"file":"result.d.ts","sourceRoot":"","sources":["../../src/agent/result.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAErD;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,CAmD1D"}
@@ -25,8 +25,19 @@ export function parseAgentResult(raw) {
25
25
  const record = value;
26
26
  const status = record.status;
27
27
  switch (status) {
28
- case "done":
29
- return { status: "done", summary: asString(record.summary) };
28
+ case "done": {
29
+ // An optional conventional-commit type (feat/fix/docs/refactor/chore/...),
30
+ // lowercased word chars only; ignored if malformed.
31
+ const rawType = record.type;
32
+ const type = typeof rawType === "string" && /^[a-z]+$/.test(rawType.trim().toLowerCase())
33
+ ? rawType.trim().toLowerCase()
34
+ : undefined;
35
+ return {
36
+ status: "done",
37
+ summary: asString(record.summary),
38
+ ...(type === undefined ? {} : { type }),
39
+ };
40
+ }
30
41
  case "noop":
31
42
  return { status: "noop" };
32
43
  case "blocked": {
@@ -1 +1 @@
1
- {"version":3,"file":"result.js","sourceRoot":"","sources":["../../src/agent/result.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,gBAAgB,CAAC,GAAW;IAC1C,IAAI,KAAc,CAAC;IACnB,IAAI,CAAC;QACH,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC1B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,iCAAiC,EAAE,CAAC;IACxE,CAAC;IACD,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACxE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,oCAAoC,EAAE,CAAC;IAC3E,CAAC;IAED,MAAM,MAAM,GAAG,KAAgC,CAAC;IAChD,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;IAE7B,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,MAAM;YACT,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;QAC/D,KAAK,MAAM;YACT,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;QAC5B,KAAK,SAAS,CAAC,CAAC,CAAC;YACf,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC;YACnC,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC5D,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,+CAA+C,EAAE,CAAC;YACtF,CAAC;YACD,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC;QAC1C,CAAC;QACD,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;YAC3B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACpD,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,mDAAmD,EAAE,CAAC;YAC1F,CAAC;YACD,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;QACrC,CAAC;QACD;YACE,OAAO;gBACL,MAAM,EAAE,QAAQ;gBAChB,KAAK,EAAE,uCAAuC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE;aACvE,CAAC;IACN,CAAC;AACH,CAAC;AAED,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;AAChD,CAAC"}
1
+ {"version":3,"file":"result.js","sourceRoot":"","sources":["../../src/agent/result.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,gBAAgB,CAAC,GAAW;IAC1C,IAAI,KAAc,CAAC;IACnB,IAAI,CAAC;QACH,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC1B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,iCAAiC,EAAE,CAAC;IACxE,CAAC;IACD,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACxE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,oCAAoC,EAAE,CAAC;IAC3E,CAAC;IAED,MAAM,MAAM,GAAG,KAAgC,CAAC;IAChD,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;IAE7B,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,MAAM,CAAC,CAAC,CAAC;YACZ,2EAA2E;YAC3E,oDAAoD;YACpD,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC;YAC5B,MAAM,IAAI,GACR,OAAO,OAAO,KAAK,QAAQ,IAAI,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;gBAC1E,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE;gBAC9B,CAAC,CAAC,SAAS,CAAC;YAChB,OAAO;gBACL,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC;gBACjC,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;aACxC,CAAC;QACJ,CAAC;QACD,KAAK,MAAM;YACT,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;QAC5B,KAAK,SAAS,CAAC,CAAC,CAAC;YACf,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC;YACnC,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC5D,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,+CAA+C,EAAE,CAAC;YACtF,CAAC;YACD,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC;QAC1C,CAAC;QACD,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;YAC3B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACpD,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,mDAAmD,EAAE,CAAC;YAC1F,CAAC;YACD,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;QACrC,CAAC;QACD;YACE,OAAO;gBACL,MAAM,EAAE,QAAQ;gBAChB,KAAK,EAAE,uCAAuC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE;aACvE,CAAC;IACN,CAAC;AACH,CAAC;AAED,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;AAChD,CAAC"}
@@ -6,8 +6,26 @@ import type { Backend, ExecOptions, ExecResult, LogLine, ProvisionSpec, Workspac
6
6
  * container, so the image only needs a shell (not git); commands run via
7
7
  * `docker exec`. Teardown force-removes the container.
8
8
  */
9
+ export interface ContainerBackendOptions {
10
+ /**
11
+ * Environment variable names to forward from the host into every `docker exec`
12
+ * (via `-e`), so secrets like ANTHROPIC_API_KEY / GH_TOKEN reach the agent and
13
+ * gate inside the container. Only names, never values, are configured; values
14
+ * are read from `env` at exec time.
15
+ */
16
+ forwardEnv?: readonly string[];
17
+ /** Source of forwarded values; defaults to the process environment. */
18
+ env?: Record<string, string | undefined>;
19
+ }
9
20
  export declare class ContainerBackend implements Backend {
10
21
  readonly kind = "container";
22
+ private readonly forwardEnv;
23
+ private readonly env;
24
+ constructor(options?: ContainerBackendOptions);
25
+ /** The forwarded keys that are actually set, as a KEY=VALUE env map. */
26
+ private forwardedEnv;
27
+ /** Merge forwarded host env under the call's own env. */
28
+ private withForwardedEnv;
11
29
  /** True if the Docker CLI and daemon are reachable. */
12
30
  static isAvailable(): Promise<boolean>;
13
31
  provision(spec: ProvisionSpec): Promise<Workspace>;
@@ -1 +1 @@
1
- {"version":3,"file":"container.d.ts","sourceRoot":"","sources":["../../src/backend/container.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EACV,OAAO,EACP,WAAW,EACX,UAAU,EACV,OAAO,EACP,aAAa,EACb,SAAS,EACV,MAAM,YAAY,CAAC;AAQpB;;;;;;GAMG;AACH,qBAAa,gBAAiB,YAAW,OAAO;IAC9C,QAAQ,CAAC,IAAI,eAAQ;IAErB,uDAAuD;WAC1C,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAKtC,SAAS,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,SAAS,CAAC;IAiCxD,IAAI,CACF,SAAS,EAAE,SAAS,EACpB,OAAO,EAAE,SAAS,MAAM,EAAE,EAC1B,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,UAAU,CAAC;IAItB,MAAM,CACJ,SAAS,EAAE,SAAS,EACpB,OAAO,EAAE,SAAS,MAAM,EAAE,EAC1B,KAAK,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,EAC9B,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,UAAU,CAAC;IAQhB,QAAQ,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;CAGpD"}
1
+ {"version":3,"file":"container.d.ts","sourceRoot":"","sources":["../../src/backend/container.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EACV,OAAO,EACP,WAAW,EACX,UAAU,EACV,OAAO,EACP,aAAa,EACb,SAAS,EACV,MAAM,YAAY,CAAC;AAQpB;;;;;;GAMG;AACH,MAAM,WAAW,uBAAuB;IACtC;;;;;OAKG;IACH,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,uEAAuE;IACvE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;CAC1C;AAED,qBAAa,gBAAiB,YAAW,OAAO;IAC9C,QAAQ,CAAC,IAAI,eAAQ;IACrB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAoB;IAC/C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAqC;gBAE7C,OAAO,GAAE,uBAA4B;IAKjD,wEAAwE;IACxE,OAAO,CAAC,YAAY;IASpB,yDAAyD;IACzD,OAAO,CAAC,gBAAgB;IAMxB,uDAAuD;WAC1C,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAKtC,SAAS,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,SAAS,CAAC;IAuCxD,IAAI,CACF,SAAS,EAAE,SAAS,EACpB,OAAO,EAAE,SAAS,MAAM,EAAE,EAC1B,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,UAAU,CAAC;IAKtB,MAAM,CACJ,SAAS,EAAE,SAAS,EACpB,OAAO,EAAE,SAAS,MAAM,EAAE,EAC1B,KAAK,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,EAC9B,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,UAAU,CAAC;IAShB,QAAQ,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;CAGpD"}
@@ -2,21 +2,39 @@ import { randomUUID } from "node:crypto";
2
2
  import { mkdir, rm } from "node:fs/promises";
3
3
  import { tmpdir } from "node:os";
4
4
  import { join } from "node:path";
5
+ import process from "node:process";
5
6
  import { DEFAULT_CONTAINER_IMAGE, dockerCpArgs, dockerExecArgs, dockerRmArgs, dockerRunArgs, } from "./docker.js";
7
+ import { CLONE_TOKEN_ENV, cloneCredentialArgs } from "./git-credentials.js";
6
8
  import { spawnCollect } from "./proc.js";
7
9
  const KIND = "container";
8
10
  async function docker(args, timeoutMs) {
9
11
  return spawnCollect(["docker", ...args], timeoutMs === undefined ? {} : { timeoutMs });
10
12
  }
11
- /**
12
- * The recommended default for a shared tool: a fresh, disposable container per
13
- * item, on its own branch, with a clean filesystem and nothing bleeding between
14
- * runs. The repo is cloned on the host onto the new branch and copied into the
15
- * container, so the image only needs a shell (not git); commands run via
16
- * `docker exec`. Teardown force-removes the container.
17
- */
18
13
  export class ContainerBackend {
19
14
  kind = KIND;
15
+ forwardEnv;
16
+ env;
17
+ constructor(options = {}) {
18
+ this.forwardEnv = options.forwardEnv ?? [];
19
+ this.env = options.env ?? process.env;
20
+ }
21
+ /** The forwarded keys that are actually set, as a KEY=VALUE env map. */
22
+ forwardedEnv() {
23
+ const out = {};
24
+ for (const key of this.forwardEnv) {
25
+ const value = this.env[key];
26
+ if (value !== undefined)
27
+ out[key] = value;
28
+ }
29
+ return out;
30
+ }
31
+ /** Merge forwarded host env under the call's own env. */
32
+ withForwardedEnv(options) {
33
+ const forwarded = this.forwardedEnv();
34
+ if (Object.keys(forwarded).length === 0)
35
+ return options;
36
+ return { ...options, env: { ...forwarded, ...options.env } };
37
+ }
20
38
  /** True if the Docker CLI and daemon are reachable. */
21
39
  static async isAvailable() {
22
40
  const result = await docker(["version", "--format", "{{.Server.Version}}"], 10_000);
@@ -29,7 +47,10 @@ export class ContainerBackend {
29
47
  const hostClone = join(tmpdir(), "ghostrail-cc", id);
30
48
  await mkdir(join(tmpdir(), "ghostrail-cc"), { recursive: true });
31
49
  try {
32
- const clone = await spawnCollect(["git", "clone", "--quiet", spec.repoPath, hostClone]);
50
+ const token = this.env.GH_TOKEN ?? this.env.GITHUB_TOKEN;
51
+ const credArgs = cloneCredentialArgs(spec.repoPath, token !== undefined);
52
+ const cloneOpts = token === undefined ? {} : { env: { [CLONE_TOKEN_ENV]: token } };
53
+ const clone = await spawnCollect(["git", ...credArgs, "clone", "--quiet", spec.repoPath, hostClone], cloneOpts);
33
54
  if (clone.exitCode !== 0)
34
55
  throw new Error(`git clone failed: ${clone.stderr.trim()}`);
35
56
  // "create" makes a new branch off the base; "attach" checks out an existing branch.
@@ -54,10 +75,12 @@ export class ContainerBackend {
54
75
  }
55
76
  }
56
77
  exec(workspace, command, options = {}) {
57
- return docker(dockerExecArgs(workspace.ref, command, options), options.timeoutMs);
78
+ const opts = this.withForwardedEnv(options);
79
+ return docker(dockerExecArgs(workspace.ref, command, opts), opts.timeoutMs);
58
80
  }
59
81
  stream(workspace, command, onLog, options = {}) {
60
- const args = dockerExecArgs(workspace.ref, command, options);
82
+ const opts = this.withForwardedEnv(options);
83
+ const args = dockerExecArgs(workspace.ref, command, opts);
61
84
  return spawnCollect(["docker", ...args], {
62
85
  onLog,
63
86
  ...(options.timeoutMs === undefined ? {} : { timeoutMs: options.timeoutMs }),
@@ -1 +1 @@
1
- {"version":3,"file":"container.js","sourceRoot":"","sources":["../../src/backend/container.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"container.js","sourceRoot":"","sources":["../../src/backend/container.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Token-free git auth for cloning private GitHub repos. Instead of embedding a
3
+ * token in the clone URL (which would persist in the workspace's `origin`), we
4
+ * pass an inline git credential helper that reads the token from an environment
5
+ * variable at clone time. The persisted `origin` stays a clean URL, so the later
6
+ * push (in the container) authenticates through the image's baked `gh` helper.
7
+ */
8
+ /** Env var the inline clone credential helper reads the token from. */
9
+ export declare const CLONE_TOKEN_ENV = "GHOSTRAIL_GIT_TOKEN";
10
+ /** True for an `https://github.com/...` URL, which needs a token to clone privately. */
11
+ export declare function isGithubHttps(url: string): boolean;
12
+ /**
13
+ * Extra `git` arguments (before the subcommand) that authenticate a GitHub https
14
+ * clone from {@link CLONE_TOKEN_ENV}. Empty when there is no token or the URL is
15
+ * not a GitHub https URL (local paths and other hosts clone unchanged).
16
+ */
17
+ export declare function cloneCredentialArgs(url: string, hasToken: boolean): string[];
18
+ //# sourceMappingURL=git-credentials.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-credentials.d.ts","sourceRoot":"","sources":["../../src/backend/git-credentials.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,uEAAuE;AACvE,eAAO,MAAM,eAAe,wBAAwB,CAAC;AASrD,wFAAwF;AACxF,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAElD;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,MAAM,EAAE,CAG5E"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Token-free git auth for cloning private GitHub repos. Instead of embedding a
3
+ * token in the clone URL (which would persist in the workspace's `origin`), we
4
+ * pass an inline git credential helper that reads the token from an environment
5
+ * variable at clone time. The persisted `origin` stays a clean URL, so the later
6
+ * push (in the container) authenticates through the image's baked `gh` helper.
7
+ */
8
+ /** Env var the inline clone credential helper reads the token from. */
9
+ export const CLONE_TOKEN_ENV = "GHOSTRAIL_GIT_TOKEN";
10
+ /**
11
+ * The inline helper git runs (via `sh`) to answer a GitHub https credential
12
+ * request: username `x-access-token`, password from {@link CLONE_TOKEN_ENV}. The
13
+ * token is never in the process arguments, only in the environment.
14
+ */
15
+ const GITHUB_CREDENTIAL_HELPER = `!f() { test "$1" = get && printf 'username=x-access-token\\npassword=%s\\n' "$${CLONE_TOKEN_ENV}"; }; f`;
16
+ /** True for an `https://github.com/...` URL, which needs a token to clone privately. */
17
+ export function isGithubHttps(url) {
18
+ return /^https:\/\/github\.com\//i.test(url.trim());
19
+ }
20
+ /**
21
+ * Extra `git` arguments (before the subcommand) that authenticate a GitHub https
22
+ * clone from {@link CLONE_TOKEN_ENV}. Empty when there is no token or the URL is
23
+ * not a GitHub https URL (local paths and other hosts clone unchanged).
24
+ */
25
+ export function cloneCredentialArgs(url, hasToken) {
26
+ if (!hasToken || !isGithubHttps(url))
27
+ return [];
28
+ return ["-c", `credential.https://github.com.helper=${GITHUB_CREDENTIAL_HELPER}`];
29
+ }
30
+ //# sourceMappingURL=git-credentials.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-credentials.js","sourceRoot":"","sources":["../../src/backend/git-credentials.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,uEAAuE;AACvE,MAAM,CAAC,MAAM,eAAe,GAAG,qBAAqB,CAAC;AAErD;;;;GAIG;AACH,MAAM,wBAAwB,GAAG,iFAAiF,eAAe,SAAS,CAAC;AAE3I,wFAAwF;AACxF,MAAM,UAAU,aAAa,CAAC,GAAW;IACvC,OAAO,2BAA2B,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;AACtD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,GAAW,EAAE,QAAiB;IAChE,IAAI,CAAC,QAAQ,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,CAAC;IAChD,OAAO,CAAC,IAAI,EAAE,wCAAwC,wBAAwB,EAAE,CAAC,CAAC;AACpF,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"local-worktree.d.ts","sourceRoot":"","sources":["../../src/backend/local-worktree.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,OAAO,EACP,WAAW,EACX,UAAU,EACV,OAAO,EACP,aAAa,EACb,SAAS,EACV,MAAM,YAAY,CAAC;AAIpB;;;;GAIG;AACH,qBAAa,oBAAqB,YAAW,OAAO;IAClD,QAAQ,CAAC,IAAI,oBAAQ;IACrB,4EAA4E;IAC5E,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA6B;IAEvD,SAAS,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,SAAS,CAAC;IAqBxD,IAAI,CACF,SAAS,EAAE,SAAS,EACpB,OAAO,EAAE,SAAS,MAAM,EAAE,EAC1B,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,UAAU,CAAC;IAItB,MAAM,CACJ,SAAS,EAAE,SAAS,EACpB,OAAO,EAAE,SAAS,MAAM,EAAE,EAC1B,KAAK,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,EAC9B,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,UAAU,CAAC;IAIhB,QAAQ,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAUnD,OAAO,CAAC,WAAW;CAIpB"}
1
+ {"version":3,"file":"local-worktree.d.ts","sourceRoot":"","sources":["../../src/backend/local-worktree.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACV,OAAO,EACP,WAAW,EACX,UAAU,EACV,OAAO,EACP,aAAa,EACb,SAAS,EACV,MAAM,YAAY,CAAC;AAIpB;;;;GAIG;AACH,qBAAa,oBAAqB,YAAW,OAAO;IAClD,QAAQ,CAAC,IAAI,oBAAQ;IACrB,4EAA4E;IAC5E,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA6B;IAEvD,SAAS,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,SAAS,CAAC;IA+CxD,IAAI,CACF,SAAS,EAAE,SAAS,EACpB,OAAO,EAAE,SAAS,MAAM,EAAE,EAC1B,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,UAAU,CAAC;IAItB,MAAM,CACJ,SAAS,EAAE,SAAS,EACpB,OAAO,EAAE,SAAS,MAAM,EAAE,EAC1B,KAAK,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,EAC9B,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,UAAU,CAAC;IAIhB,QAAQ,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAUnD,OAAO,CAAC,WAAW;CAIpB"}
@@ -2,6 +2,8 @@ import { randomUUID } from "node:crypto";
2
2
  import { mkdir, rm } from "node:fs/promises";
3
3
  import { tmpdir } from "node:os";
4
4
  import { join } from "node:path";
5
+ import process from "node:process";
6
+ import { CLONE_TOKEN_ENV, cloneCredentialArgs } from "./git-credentials.js";
5
7
  import { spawnCollect } from "./proc.js";
6
8
  const KIND = "local-worktree";
7
9
  /**
@@ -17,6 +19,25 @@ export class LocalWorktreeBackend {
17
19
  const id = randomUUID();
18
20
  const dir = join(tmpdir(), "ghostrail-wt", id);
19
21
  await mkdir(join(tmpdir(), "ghostrail-wt"), { recursive: true });
22
+ if (spec.clone === true) {
23
+ // A fresh full clone (repoPath may be a remote URL); teardown just deletes it.
24
+ const token = process.env.GH_TOKEN ?? process.env.GITHUB_TOKEN;
25
+ const credArgs = cloneCredentialArgs(spec.repoPath, token !== undefined);
26
+ const cloneOpts = token === undefined ? {} : { env: { [CLONE_TOKEN_ENV]: token } };
27
+ const clone = await spawnCollect(["git", ...credArgs, "clone", "--quiet", spec.repoPath, dir], cloneOpts);
28
+ if (clone.exitCode !== 0) {
29
+ throw new Error(`local-clone provision failed: ${clone.stderr.trim() || clone.stdout.trim()}`);
30
+ }
31
+ const checkoutArgs = spec.mode === "attach"
32
+ ? ["checkout", spec.branch]
33
+ : ["checkout", "-B", spec.branch, spec.baseBranch];
34
+ const checkout = await spawnCollect(["git", "-C", dir, ...checkoutArgs]);
35
+ if (checkout.exitCode !== 0) {
36
+ await rm(dir, { recursive: true, force: true });
37
+ throw new Error(`local-clone checkout failed: ${checkout.stderr.trim()}`);
38
+ }
39
+ return { id, backend: KIND, ref: dir, branch: spec.branch };
40
+ }
20
41
  // "create" makes a new branch off the base; "attach" checks out an existing branch.
21
42
  const addArgs = spec.mode === "attach"
22
43
  ? ["worktree", "add", dir, spec.branch]
@@ -1 +1 @@
1
- {"version":3,"file":"local-worktree.js","sourceRoot":"","sources":["../../src/backend/local-worktree.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"local-worktree.js","sourceRoot":"","sources":["../../src/backend/local-worktree.ts"],"names":[],"mappings":"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"}
@@ -10,7 +10,10 @@
10
10
  */
11
11
  /** How to create an isolated workspace for one item. */
12
12
  export interface ProvisionSpec {
13
- /** Absolute path to the source git repository on the host. */
13
+ /**
14
+ * The source git repository: a local path OR a remote URL. A URL requires
15
+ * `clone: true`. `git clone`/`git worktree` accept either form of local path.
16
+ */
14
17
  repoPath: string;
15
18
  /** Existing ref to branch from (e.g. "main"). Ignored when `mode` is "attach". */
16
19
  baseBranch: string;
@@ -21,6 +24,14 @@ export interface ProvisionSpec {
21
24
  * an existing `branch` (e.g. a PR's head branch, for the respond pass).
22
25
  */
23
26
  mode?: "create" | "attach";
27
+ /**
28
+ * When true, provision a **fresh full clone** of `repoPath` (which may be a
29
+ * remote URL) into a throwaway directory, torn down after the run, so nothing
30
+ * persists. When false/absent, local-worktree adds a worktree off an existing
31
+ * local repo. The container backend always clones; this flag is for the local
32
+ * backend.
33
+ */
34
+ clone?: boolean;
24
35
  /** Container image, for backends that need one. Ignored by local-worktree. */
25
36
  image?: string;
26
37
  }
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/backend/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,wDAAwD;AACxD,MAAM,WAAW,aAAa;IAC5B,8DAA8D;IAC9D,QAAQ,EAAE,MAAM,CAAC;IACjB,kFAAkF;IAClF,UAAU,EAAE,MAAM,CAAC;IACnB,yFAAyF;IACzF,MAAM,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,IAAI,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC3B,8EAA8E;IAC9E,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,8EAA8E;AAC9E,MAAM,WAAW,SAAS;IACxB,uCAAuC;IACvC,EAAE,EAAE,MAAM,CAAC;IACX,yCAAyC;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ,sCAAsC;IACtC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,WAAW;IAC1B,2DAA2D;IAC3D,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,mDAAmD;IACnD,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,wEAAwE;IACxE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,2EAA2E;AAC3E,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,kEAAkE;IAClE,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,2CAA2C;AAC3C,MAAM,WAAW,OAAO;IACtB,MAAM,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC5B,IAAI,EAAE,MAAM,CAAC;CACd;AAED,qCAAqC;AACrC,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,iFAAiF;IACjF,SAAS,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IACnD,0EAA0E;IAC1E,IAAI,CACF,SAAS,EAAE,SAAS,EACpB,OAAO,EAAE,SAAS,MAAM,EAAE,EAC1B,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,UAAU,CAAC,CAAC;IACvB,yFAAyF;IACzF,MAAM,CACJ,SAAS,EAAE,SAAS,EACpB,OAAO,EAAE,SAAS,MAAM,EAAE,EAC1B,KAAK,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,EAC9B,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,UAAU,CAAC,CAAC;IACvB,qFAAqF;IACrF,QAAQ,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/C"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/backend/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,wDAAwD;AACxD,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB,kFAAkF;IAClF,UAAU,EAAE,MAAM,CAAC;IACnB,yFAAyF;IACzF,MAAM,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,IAAI,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC3B;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,8EAA8E;IAC9E,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,8EAA8E;AAC9E,MAAM,WAAW,SAAS;IACxB,uCAAuC;IACvC,EAAE,EAAE,MAAM,CAAC;IACX,yCAAyC;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ,sCAAsC;IACtC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,WAAW;IAC1B,2DAA2D;IAC3D,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,mDAAmD;IACnD,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,wEAAwE;IACxE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,2EAA2E;AAC3E,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,kEAAkE;IAClE,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,2CAA2C;AAC3C,MAAM,WAAW,OAAO;IACtB,MAAM,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC5B,IAAI,EAAE,MAAM,CAAC;CACd;AAED,qCAAqC;AACrC,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,iFAAiF;IACjF,SAAS,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IACnD,0EAA0E;IAC1E,IAAI,CACF,SAAS,EAAE,SAAS,EACpB,OAAO,EAAE,SAAS,MAAM,EAAE,EAC1B,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,UAAU,CAAC,CAAC;IACvB,yFAAyF;IACzF,MAAM,CACJ,SAAS,EAAE,SAAS,EACpB,OAAO,EAAE,SAAS,MAAM,EAAE,EAC1B,KAAK,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,EAC9B,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,UAAU,CAAC,CAAC;IACvB,qFAAqF;IACrF,QAAQ,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/C"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Pure classification + composition for the ghostrail Claude profile: split a
3
+ * CLAUDE.md into sections, judge which belong in a headless factory run, flag
4
+ * interactive-only settings, and compose the factory CLAUDE.md + settings.
5
+ */
6
+ export type Verdict = "keep" | "drop";
7
+ export interface Section {
8
+ /** Heading text without the leading `#`s; "(preamble)" for text before the first heading. */
9
+ heading: string;
10
+ /** The section's full text, including its heading line. */
11
+ body: string;
12
+ }
13
+ export interface ClaudeMdSection extends Section {
14
+ verdict: Verdict;
15
+ /** Why a section was flagged to drop. */
16
+ reason?: string;
17
+ }
18
+ export interface SettingsKeyReport {
19
+ key: string;
20
+ /** Whether the key is carried into the factory settings (false = interactive-only). */
21
+ carried: boolean;
22
+ reason?: string;
23
+ }
24
+ /**
25
+ * Split a CLAUDE.md into sections at top-level (`#`/`##`) headings. Text before
26
+ * the first heading becomes a `(preamble)` section. Each section's `body`
27
+ * includes its heading line.
28
+ */
29
+ export declare function splitSections(content: string): Section[];
30
+ /** Judge each section keep/drop; a section is dropped if it names an interactive-only concern. */
31
+ export declare function classifyClaudeMdSections(sections: readonly Section[]): ClaudeMdSection[];
32
+ /** Report which top-level settings keys are carried into the factory profile. */
33
+ export declare function classifySettingsKeys(settings: Record<string, unknown>): SettingsKeyReport[];
34
+ /**
35
+ * Compose the factory CLAUDE.md: a fixed header followed by the bodies of the
36
+ * kept sections, collapsing blank runs.
37
+ */
38
+ export declare function composeFactoryClaudeMd(sections: readonly ClaudeMdSection[], header?: string): string;
39
+ /** The minimal, headless-safe factory settings.json (hooks land via the declarative block later). */
40
+ export declare function composeFactorySettings(): Record<string, unknown>;
41
+ //# sourceMappingURL=classify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"classify.d.ts","sourceRoot":"","sources":["../../src/claude-profile/classify.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,MAAM,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;AAEtC,MAAM,WAAW,OAAO;IACtB,6FAA6F;IAC7F,OAAO,EAAE,MAAM,CAAC;IAChB,2DAA2D;IAC3D,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,eAAgB,SAAQ,OAAO;IAC9C,OAAO,EAAE,OAAO,CAAC;IACjB,yCAAyC;IACzC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,uFAAuF;IACvF,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAkCD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,EAAE,CAwBxD;AAED,kGAAkG;AAClG,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,GAAG,eAAe,EAAE,CAQxF;AAED,iFAAiF;AACjF,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,iBAAiB,EAAE,CAM3F;AASD;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,SAAS,eAAe,EAAE,EACpC,MAAM,GAAE,MAAuB,GAC9B,MAAM,CAMR;AAED,qGAAqG;AACrG,wBAAgB,sBAAsB,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEhE"}