agent-composer 0.3.1 → 0.4.1

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 (180) hide show
  1. package/README.md +495 -180
  2. package/composer.config.schema.json +206 -2
  3. package/dist/cli/cleanup.d.ts +24 -0
  4. package/dist/cli/cleanup.js +151 -0
  5. package/dist/cli/cleanup.js.map +1 -0
  6. package/dist/cli/doctor.d.ts +12 -0
  7. package/dist/cli/doctor.js +244 -4
  8. package/dist/cli/doctor.js.map +1 -1
  9. package/dist/cli/goal.d.ts +28 -0
  10. package/dist/cli/goal.js +251 -0
  11. package/dist/cli/goal.js.map +1 -0
  12. package/dist/cli/help.d.ts +3 -0
  13. package/dist/cli/help.js +31 -0
  14. package/dist/cli/help.js.map +1 -0
  15. package/dist/cli/init.d.ts +5 -0
  16. package/dist/cli/init.js +116 -21
  17. package/dist/cli/init.js.map +1 -1
  18. package/dist/cli/initArgs.d.ts +16 -0
  19. package/dist/cli/initArgs.js +19 -0
  20. package/dist/cli/initArgs.js.map +1 -0
  21. package/dist/cli/installGitHook.d.ts +7 -0
  22. package/dist/cli/installGitHook.js +61 -0
  23. package/dist/cli/installGitHook.js.map +1 -0
  24. package/dist/cli/mode.d.ts +6 -0
  25. package/dist/cli/mode.js +25 -0
  26. package/dist/cli/mode.js.map +1 -0
  27. package/dist/cli/status.d.ts +105 -0
  28. package/dist/cli/status.js +400 -0
  29. package/dist/cli/status.js.map +1 -0
  30. package/dist/config/env.d.ts +1 -1
  31. package/dist/config/modes.d.ts +10 -0
  32. package/dist/config/modes.js +26 -0
  33. package/dist/config/modes.js.map +1 -0
  34. package/dist/config/oracleRole.d.ts +10 -0
  35. package/dist/config/oracleRole.js +11 -0
  36. package/dist/config/oracleRole.js.map +1 -0
  37. package/dist/config/schema.d.ts +246 -0
  38. package/dist/config/schema.js +127 -2
  39. package/dist/config/schema.js.map +1 -1
  40. package/dist/evolve/reflection.d.ts +9 -0
  41. package/dist/evolve/reflection.js +14 -0
  42. package/dist/evolve/reflection.js.map +1 -1
  43. package/dist/evolve/runner.d.ts +2 -1
  44. package/dist/evolve/runner.js +2 -1
  45. package/dist/evolve/runner.js.map +1 -1
  46. package/dist/index.js +115 -6
  47. package/dist/index.js.map +1 -1
  48. package/dist/providers/AnthropicCompatibleProvider.d.ts +13 -1
  49. package/dist/providers/AnthropicCompatibleProvider.js +115 -9
  50. package/dist/providers/AnthropicCompatibleProvider.js.map +1 -1
  51. package/dist/providers/CLIProvider.d.ts +18 -0
  52. package/dist/providers/CLIProvider.js +265 -62
  53. package/dist/providers/CLIProvider.js.map +1 -1
  54. package/dist/providers/IProvider.d.ts +12 -0
  55. package/dist/providers/SpendGuardProvider.d.ts +32 -0
  56. package/dist/providers/SpendGuardProvider.js +98 -0
  57. package/dist/providers/SpendGuardProvider.js.map +1 -0
  58. package/dist/registry.d.ts +5 -2
  59. package/dist/registry.js +17 -2
  60. package/dist/registry.js.map +1 -1
  61. package/dist/server/activeRuns.d.ts +17 -0
  62. package/dist/server/activeRuns.js +114 -0
  63. package/dist/server/activeRuns.js.map +1 -0
  64. package/dist/server/codexLifecycleRunner.d.ts +29 -0
  65. package/dist/server/codexLifecycleRunner.js +188 -0
  66. package/dist/server/codexLifecycleRunner.js.map +1 -0
  67. package/dist/server/configMutation.d.ts +22 -0
  68. package/dist/server/configMutation.js +121 -0
  69. package/dist/server/configMutation.js.map +1 -0
  70. package/dist/server/handoffContext.d.ts +1 -0
  71. package/dist/server/handoffContext.js +12 -0
  72. package/dist/server/handoffContext.js.map +1 -0
  73. package/dist/server/progress.d.ts +24 -0
  74. package/dist/server/progress.js +109 -0
  75. package/dist/server/progress.js.map +1 -0
  76. package/dist/server/toolDescriptions.d.ts +60 -0
  77. package/dist/server/toolDescriptions.js +134 -0
  78. package/dist/server/toolDescriptions.js.map +1 -0
  79. package/dist/server.d.ts +19 -25
  80. package/dist/server.js +87 -377
  81. package/dist/server.js.map +1 -1
  82. package/dist/tools/audit.d.ts +2 -0
  83. package/dist/tools/audit.js +66 -0
  84. package/dist/tools/audit.js.map +1 -0
  85. package/dist/tools/code.d.ts +2 -0
  86. package/dist/tools/code.js +160 -0
  87. package/dist/tools/code.js.map +1 -0
  88. package/dist/tools/codexLifecycle.d.ts +2 -0
  89. package/dist/tools/codexLifecycle.js +206 -0
  90. package/dist/tools/codexLifecycle.js.map +1 -0
  91. package/dist/tools/config.d.ts +2 -0
  92. package/dist/tools/config.js +183 -0
  93. package/dist/tools/config.js.map +1 -0
  94. package/dist/tools/context.d.ts +31 -0
  95. package/dist/tools/context.js +2 -0
  96. package/dist/tools/context.js.map +1 -0
  97. package/dist/tools/goal.d.ts +2 -0
  98. package/dist/tools/goal.js +159 -0
  99. package/dist/tools/goal.js.map +1 -0
  100. package/dist/tools/handoff.d.ts +2 -0
  101. package/dist/tools/handoff.js +57 -0
  102. package/dist/tools/handoff.js.map +1 -0
  103. package/dist/tools/oracle.d.ts +2 -0
  104. package/dist/tools/oracle.js +248 -0
  105. package/dist/tools/oracle.js.map +1 -0
  106. package/dist/tools/research.d.ts +2 -0
  107. package/dist/tools/research.js +51 -0
  108. package/dist/tools/research.js.map +1 -0
  109. package/dist/tools/review.d.ts +2 -0
  110. package/dist/tools/review.js +233 -0
  111. package/dist/tools/review.js.map +1 -0
  112. package/dist/tools/route.d.ts +2 -0
  113. package/dist/tools/route.js +69 -0
  114. package/dist/tools/route.js.map +1 -0
  115. package/dist/tools/session.d.ts +2 -0
  116. package/dist/tools/session.js +37 -0
  117. package/dist/tools/session.js.map +1 -0
  118. package/dist/tools/status.d.ts +2 -0
  119. package/dist/tools/status.js +34 -0
  120. package/dist/tools/status.js.map +1 -0
  121. package/dist/tools/workflow.d.ts +2 -0
  122. package/dist/tools/workflow.js +27 -0
  123. package/dist/tools/workflow.js.map +1 -0
  124. package/dist/util/applyFileBlocks.d.ts +18 -0
  125. package/dist/util/applyFileBlocks.js +163 -0
  126. package/dist/util/applyFileBlocks.js.map +1 -0
  127. package/dist/util/asyncControl.d.ts +14 -0
  128. package/dist/util/asyncControl.js +106 -0
  129. package/dist/util/asyncControl.js.map +1 -0
  130. package/dist/util/auditLog.d.ts +56 -0
  131. package/dist/util/auditLog.js +232 -0
  132. package/dist/util/auditLog.js.map +1 -0
  133. package/dist/util/codexLifecycle.d.ts +55 -0
  134. package/dist/util/codexLifecycle.js +102 -0
  135. package/dist/util/codexLifecycle.js.map +1 -0
  136. package/dist/util/codexLifecycleJob.d.ts +209 -0
  137. package/dist/util/codexLifecycleJob.js +360 -0
  138. package/dist/util/codexLifecycleJob.js.map +1 -0
  139. package/dist/util/composerDisabled.d.ts +6 -0
  140. package/dist/util/composerDisabled.js +27 -0
  141. package/dist/util/composerDisabled.js.map +1 -0
  142. package/dist/util/dispatchHint.d.ts +5 -3
  143. package/dist/util/dispatchHint.js +62 -2
  144. package/dist/util/dispatchHint.js.map +1 -1
  145. package/dist/util/goal.d.ts +132 -0
  146. package/dist/util/goal.js +616 -0
  147. package/dist/util/goal.js.map +1 -0
  148. package/dist/util/goalReport.d.ts +51 -0
  149. package/dist/util/goalReport.js +164 -0
  150. package/dist/util/goalReport.js.map +1 -0
  151. package/dist/util/jobPolling.d.ts +9 -0
  152. package/dist/util/jobPolling.js +17 -0
  153. package/dist/util/jobPolling.js.map +1 -0
  154. package/dist/util/oracleJob.d.ts +66 -0
  155. package/dist/util/oracleJob.js +295 -0
  156. package/dist/util/oracleJob.js.map +1 -0
  157. package/dist/util/oracleLock.d.ts +38 -0
  158. package/dist/util/oracleLock.js +182 -0
  159. package/dist/util/oracleLock.js.map +1 -0
  160. package/dist/util/reviewDiff.d.ts +8 -0
  161. package/dist/util/reviewDiff.js +29 -0
  162. package/dist/util/reviewDiff.js.map +1 -0
  163. package/dist/util/reviewJob.d.ts +57 -0
  164. package/dist/util/reviewJob.js +207 -0
  165. package/dist/util/reviewJob.js.map +1 -0
  166. package/dist/util/workflowPlan.d.ts +24 -0
  167. package/dist/util/workflowPlan.js +49 -0
  168. package/dist/util/workflowPlan.js.map +1 -0
  169. package/package.json +8 -1
  170. package/plugin/composer-mastermind/commands/evolve.md +4 -0
  171. package/plugin/composer-mastermind/hooks/boundary_guard.sh +43 -2
  172. package/plugin/composer-mastermind/hooks/codex_warm_review.sh +161 -9
  173. package/plugin/composer-mastermind/hooks/learn.sh +172 -32
  174. package/plugin/composer-mastermind/hooks/precommit_codex_review.sh +438 -64
  175. package/plugin/composer-mastermind/skills/composer-mastermind/SKILL.md +190 -4
  176. package/scripts/composer-oracle-router-safe.sh +47 -0
  177. package/scripts/composer-statusline-segment.mjs +40 -0
  178. package/scripts/oracle-codex-handoff-safe.sh +49 -0
  179. package/scripts/oracle-plan-mcp.sh +66 -0
  180. package/scripts/oracle-pro-safe.sh +572 -0
@@ -0,0 +1,38 @@
1
+ export declare const ORACLE_LOCK_DIR = "oracle-locks";
2
+ export declare const COMPOSER_ORACLE_LOCK_TTL_MS_ENV = "COMPOSER_ORACLE_LOCK_TTL_MS";
3
+ export declare const DEFAULT_ORACLE_LOCK_TTL_MS: number;
4
+ type OracleLockHolder = {
5
+ pid: number;
6
+ token: string;
7
+ jobId?: string;
8
+ label?: string;
9
+ startedAt: string;
10
+ };
11
+ export interface OracleLockHandle {
12
+ release(): void;
13
+ }
14
+ export type OracleLockRecovery = {
15
+ reasonCode: "stale_lock_recovery";
16
+ stage: "oracle_lock_acquire";
17
+ elapsedWallMs: number;
18
+ lockAgeMs: number;
19
+ holder: OracleLockHolder;
20
+ };
21
+ export type OracleLockAcquireOptions = {
22
+ ttlMs?: number;
23
+ nowMs?: () => number;
24
+ };
25
+ export type OracleLockResult = {
26
+ acquired: true;
27
+ handle: OracleLockHandle;
28
+ recovery?: OracleLockRecovery;
29
+ } | {
30
+ acquired: false;
31
+ holder: OracleLockHolder;
32
+ recovery?: undefined;
33
+ };
34
+ export declare function acquireOracleLock(root: string, info: {
35
+ jobId?: string;
36
+ label?: string;
37
+ }, opts?: OracleLockAcquireOptions): OracleLockResult;
38
+ export {};
@@ -0,0 +1,182 @@
1
+ import { createHash, randomUUID } from "node:crypto";
2
+ import { existsSync, lstatSync, mkdirSync, readFileSync, realpathSync, rmSync, writeFileSync, } from "node:fs";
3
+ import os from "node:os";
4
+ import path from "node:path";
5
+ import { COMPOSER_STATE_DIR_ENV } from "./codexLifecycleJob.js";
6
+ export const ORACLE_LOCK_DIR = "oracle-locks";
7
+ export const COMPOSER_ORACLE_LOCK_TTL_MS_ENV = "COMPOSER_ORACLE_LOCK_TTL_MS";
8
+ export const DEFAULT_ORACLE_LOCK_TTL_MS = 30 * 60 * 1000; // generous: longer than any Oracle run
9
+ const ORACLE_LOCK_CLOCK_SKEW_GRACE_MS = 5 * 60 * 1000;
10
+ export function acquireOracleLock(root, info, opts = {}) {
11
+ const startedMs = (opts.nowMs ?? Date.now)();
12
+ const ttlMs = resolveOracleLockTtlMs(opts.ttlMs);
13
+ const lockPath = oracleLockPath(root);
14
+ const token = randomUUID();
15
+ const holder = {
16
+ pid: process.pid,
17
+ token,
18
+ jobId: info.jobId,
19
+ label: info.label,
20
+ startedAt: new Date().toISOString(),
21
+ };
22
+ try {
23
+ return writeLock(lockPath, holder, token);
24
+ }
25
+ catch (error) {
26
+ if (error.code !== "EEXIST")
27
+ throw error;
28
+ }
29
+ const existing = readLockHolder(lockPath);
30
+ const staleRecovery = existing
31
+ ? staleLockRecovery(lockPath, existing, ttlMs, (opts.nowMs ?? Date.now)(), startedMs)
32
+ : null;
33
+ // Steal ONLY a malformed lock, a dead-process lock, or a stale lock.
34
+ // A live holder (including the SAME process) is a real concurrent holder.
35
+ if (!existing || !isProcessAlive(existing.pid) || staleRecovery) {
36
+ rmSync(lockPath, { force: true });
37
+ try {
38
+ return writeLock(lockPath, holder, token, staleRecovery ?? undefined);
39
+ }
40
+ catch (error) {
41
+ if (error.code === "EEXIST") {
42
+ const racer = readLockHolder(lockPath);
43
+ if (racer)
44
+ return { acquired: false, holder: racer };
45
+ }
46
+ throw error;
47
+ }
48
+ }
49
+ return { acquired: false, holder: existing };
50
+ }
51
+ function oracleLockPath(root) {
52
+ const rootReal = realpathSync(root);
53
+ const stateRoot = oracleStateRoot();
54
+ const lockRoot = path.join(stateRoot, ORACLE_LOCK_DIR);
55
+ ensureDirectory(stateRoot, "Composer state root");
56
+ ensureDirectory(lockRoot, "Oracle lock state root");
57
+ return path.join(lockRoot, `${projectStateKey(rootReal)}.lock`);
58
+ }
59
+ function writeLock(lockPath, holder, token, recovery) {
60
+ writeFileSync(lockPath, JSON.stringify(holder), {
61
+ encoding: "utf8",
62
+ mode: 0o600,
63
+ flag: "wx",
64
+ });
65
+ return {
66
+ acquired: true,
67
+ handle: {
68
+ release: () => {
69
+ try {
70
+ const current = readLockHolder(lockPath);
71
+ if (current?.pid === process.pid && current.token === token) {
72
+ rmSync(lockPath, { force: true });
73
+ }
74
+ }
75
+ catch {
76
+ // Best-effort cleanup only.
77
+ }
78
+ },
79
+ },
80
+ ...(recovery ? { recovery } : {}),
81
+ };
82
+ }
83
+ function readLockHolder(lockPath) {
84
+ try {
85
+ const parsed = JSON.parse(readFileSync(lockPath, "utf8"));
86
+ if (typeof parsed.pid !== "number" ||
87
+ !Number.isInteger(parsed.pid) ||
88
+ typeof parsed.token !== "string" ||
89
+ typeof parsed.startedAt !== "string") {
90
+ return null;
91
+ }
92
+ return parsed;
93
+ }
94
+ catch {
95
+ return null;
96
+ }
97
+ }
98
+ function oracleStateRoot() {
99
+ const override = process.env[COMPOSER_STATE_DIR_ENV]?.trim();
100
+ if (override)
101
+ return path.resolve(override);
102
+ return path.join(os.homedir(), ".local", "state", "composer");
103
+ }
104
+ function projectStateKey(rootReal) {
105
+ const basename = path.basename(rootReal).replace(/[^A-Za-z0-9._-]+/g, "-") || "project";
106
+ const slug = basename.slice(0, 48);
107
+ const digest = createHash("sha256").update(rootReal).digest("hex").slice(0, 24);
108
+ return `${slug}-${digest}`;
109
+ }
110
+ function isProcessAlive(pid) {
111
+ try {
112
+ process.kill(pid, 0);
113
+ return true;
114
+ }
115
+ catch (error) {
116
+ // EPERM = process exists but not signalable by us -> alive.
117
+ return error.code === "EPERM";
118
+ }
119
+ }
120
+ function resolveOracleLockTtlMs(override) {
121
+ if (override !== undefined && Number.isFinite(override) && override > 0) {
122
+ return Math.floor(override);
123
+ }
124
+ const raw = process.env[COMPOSER_ORACLE_LOCK_TTL_MS_ENV]?.trim();
125
+ if (raw) {
126
+ const parsed = Number(raw);
127
+ if (Number.isFinite(parsed) && parsed > 0)
128
+ return Math.floor(parsed);
129
+ }
130
+ return DEFAULT_ORACLE_LOCK_TTL_MS;
131
+ }
132
+ function staleLockRecovery(lockPath, holder, ttlMs, nowMs, acquiredStartedMs) {
133
+ const startedAtMs = Date.parse(holder.startedAt);
134
+ const fileAgeMs = lockFileAgeMs(lockPath, nowMs);
135
+ if (Number.isNaN(startedAtMs)) {
136
+ return {
137
+ reasonCode: "stale_lock_recovery",
138
+ stage: "oracle_lock_acquire",
139
+ elapsedWallMs: Math.max(0, nowMs - acquiredStartedMs),
140
+ lockAgeMs: Math.max(0, fileAgeMs ?? 0),
141
+ holder,
142
+ };
143
+ }
144
+ const startedAgeMs = nowMs - startedAtMs;
145
+ const effectiveAgeMs = Math.max(0, startedAgeMs, fileAgeMs ?? 0);
146
+ const clockSkewedFuture = startedAgeMs < -ORACLE_LOCK_CLOCK_SKEW_GRACE_MS;
147
+ const staleByStartedAt = startedAgeMs > ttlMs;
148
+ const staleByMtime = fileAgeMs !== null && fileAgeMs > ttlMs;
149
+ if (!staleByStartedAt && !staleByMtime)
150
+ return null;
151
+ return {
152
+ reasonCode: "stale_lock_recovery",
153
+ stage: "oracle_lock_acquire",
154
+ elapsedWallMs: Math.max(0, nowMs - acquiredStartedMs),
155
+ lockAgeMs: clockSkewedFuture ? Math.max(0, fileAgeMs ?? 0) : effectiveAgeMs,
156
+ holder,
157
+ };
158
+ }
159
+ function lockFileAgeMs(lockPath, nowMs) {
160
+ try {
161
+ return Math.max(0, nowMs - lstatSync(lockPath).mtimeMs);
162
+ }
163
+ catch {
164
+ return null;
165
+ }
166
+ }
167
+ function ensureDirectory(dir, label) {
168
+ if (!existsSync(dir)) {
169
+ mkdirSync(dir, { recursive: true, mode: 0o700 });
170
+ }
171
+ assertUsableDirectory(dir, label);
172
+ }
173
+ function assertUsableDirectory(dir, label) {
174
+ const stat = lstatSync(dir);
175
+ if (stat.isSymbolicLink()) {
176
+ throw new Error(`Oracle lock directory must not be a symlink: ${label}`);
177
+ }
178
+ if (!stat.isDirectory()) {
179
+ throw new Error(`Oracle lock path must be a directory: ${label}`);
180
+ }
181
+ }
182
+ //# sourceMappingURL=oracleLock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oracleLock.js","sourceRoot":"","sources":["../../src/util/oracleLock.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ export type ReviewScope = "staged" | "unstaged" | "working-tree" | "branch";
2
+ export interface ReviewDiffOptions {
3
+ base?: string;
4
+ files?: string[];
5
+ }
6
+ /** Compute a git diff for the requested scope, rooted at `root`. Throws on git
7
+ * failure or when the scope yields no changes. `files` narrows any scope to a pathspec. */
8
+ export declare function computeReviewDiff(root: string, scope: ReviewScope, opts?: ReviewDiffOptions): string;
@@ -0,0 +1,29 @@
1
+ import { spawnSync } from "node:child_process";
2
+ /** Compute a git diff for the requested scope, rooted at `root`. Throws on git
3
+ * failure or when the scope yields no changes. `files` narrows any scope to a pathspec. */
4
+ export function computeReviewDiff(root, scope, opts = {}) {
5
+ const args = ["-C", root, "--no-pager", "diff", "--no-ext-diff"];
6
+ if (scope === "staged")
7
+ args.push("--cached");
8
+ else if (scope === "working-tree")
9
+ args.push("HEAD");
10
+ else if (scope === "branch")
11
+ args.push(`${opts.base ?? "main"}...HEAD`);
12
+ // "unstaged" => plain `git diff`
13
+ if (opts.files && opts.files.length > 0) {
14
+ args.push("--", ...opts.files);
15
+ }
16
+ const result = spawnSync("git", args, { encoding: "utf8", timeout: 15000, maxBuffer: 32 * 1024 * 1024 });
17
+ if (result.error) {
18
+ throw new Error(`composer review: git diff failed: ${result.error.message}`);
19
+ }
20
+ if (typeof result.status === "number" && result.status !== 0) {
21
+ throw new Error(`composer review: git diff exited ${result.status}: ${(result.stderr ?? "").slice(0, 300)}`);
22
+ }
23
+ const diff = result.stdout ?? "";
24
+ if (diff.trim().length === 0) {
25
+ throw new Error(`composer review: no changes for scope "${scope}"${opts.files?.length ? ` (files: ${opts.files.join(", ")})` : ""}`);
26
+ }
27
+ return diff;
28
+ }
29
+ //# sourceMappingURL=reviewDiff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reviewDiff.js","sourceRoot":"","sources":["../../src/util/reviewDiff.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAS/C;4FAC4F;AAC5F,MAAM,UAAU,iBAAiB,CAAC,IAAY,EAAE,KAAkB,EAAE,OAA0B,EAAE;IAC9F,MAAM,IAAI,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,eAAe,CAAC,CAAC;IACjE,IAAI,KAAK,KAAK,QAAQ;QAAE,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;SACzC,IAAI,KAAK,KAAK,cAAc;QAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;SAChD,IAAI,KAAK,KAAK,QAAQ;QAAE,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,IAAI,MAAM,SAAS,CAAC,CAAC;IACxE,iCAAiC;IACjC,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;IACjC,CAAC;IACD,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI,EAAE,CAAC,CAAC;IACzG,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,qCAAqC,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;IAC/E,CAAC;IACD,IAAI,OAAO,MAAM,CAAC,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7D,MAAM,IAAI,KAAK,CAAC,oCAAoC,MAAM,CAAC,MAAM,KAAK,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;IAC/G,CAAC;IACD,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC;IACjC,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,0CAA0C,KAAK,IAAI,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,YAAY,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACvI,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,57 @@
1
+ import { z } from "zod";
2
+ export declare const REVIEW_JOB_DIR = "review-jobs";
3
+ export declare const ReviewJobStatusSchema: z.ZodEnum<{
4
+ queued: "queued";
5
+ running: "running";
6
+ succeeded: "succeeded";
7
+ failed: "failed";
8
+ }>;
9
+ export type ReviewJobStatus = z.infer<typeof ReviewJobStatusSchema>;
10
+ export declare const ReviewJobScopeSchema: z.ZodEnum<{
11
+ "working-tree": "working-tree";
12
+ branch: "branch";
13
+ staged: "staged";
14
+ unstaged: "unstaged";
15
+ }>;
16
+ export type ReviewJobScope = z.infer<typeof ReviewJobScopeSchema>;
17
+ export declare const ReviewJobSchema: z.ZodObject<{
18
+ jobId: z.ZodString;
19
+ status: z.ZodEnum<{
20
+ queued: "queued";
21
+ running: "running";
22
+ succeeded: "succeeded";
23
+ failed: "failed";
24
+ }>;
25
+ scope: z.ZodOptional<z.ZodEnum<{
26
+ "working-tree": "working-tree";
27
+ branch: "branch";
28
+ staged: "staged";
29
+ unstaged: "unstaged";
30
+ }>>;
31
+ base: z.ZodOptional<z.ZodString>;
32
+ reviewFiles: z.ZodOptional<z.ZodArray<z.ZodString>>;
33
+ promptPreview: z.ZodString;
34
+ claude: z.ZodOptional<z.ZodBoolean>;
35
+ result: z.ZodOptional<z.ZodObject<{
36
+ verdict: z.ZodOptional<z.ZodString>;
37
+ summary: z.ZodOptional<z.ZodString>;
38
+ text: z.ZodOptional<z.ZodString>;
39
+ }, z.core.$strip>>;
40
+ error: z.ZodOptional<z.ZodString>;
41
+ createdAt: z.ZodString;
42
+ startedAt: z.ZodOptional<z.ZodString>;
43
+ completedAt: z.ZodOptional<z.ZodString>;
44
+ }, z.core.$strict>;
45
+ export type ReviewJob = z.infer<typeof ReviewJobSchema>;
46
+ export declare function newReviewJob(input: {
47
+ scope?: ReviewJobScope;
48
+ base?: string;
49
+ reviewFiles?: string[];
50
+ promptPreview: string;
51
+ claude?: boolean;
52
+ }): ReviewJob;
53
+ export declare function writeReviewJob(root: string, job: ReviewJob): ReviewJob;
54
+ export declare function updateReviewJob(root: string, job: ReviewJob, patch: Partial<Omit<ReviewJob, "jobId" | "createdAt">>): ReviewJob;
55
+ export declare function readReviewJob(root: string, jobId: string): ReviewJob | null;
56
+ export declare function readLatestReviewJob(root: string): ReviewJob | null;
57
+ export declare function failInFlightReviewJobs(root: string, error: string): number;
@@ -0,0 +1,207 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { chmodSync, existsSync, lstatSync, mkdirSync, readdirSync, readFileSync, realpathSync, renameSync, rmSync, statSync, writeFileSync, } from "node:fs";
3
+ import path from "node:path";
4
+ import { z } from "zod";
5
+ export const REVIEW_JOB_DIR = "review-jobs";
6
+ const LATEST_REVIEW_JOB_POINTER = ".latest";
7
+ export const ReviewJobStatusSchema = z.enum(["queued", "running", "succeeded", "failed"]);
8
+ export const ReviewJobScopeSchema = z.enum(["staged", "unstaged", "working-tree", "branch"]);
9
+ export const ReviewJobSchema = z
10
+ .object({
11
+ jobId: z.string().uuid(),
12
+ status: ReviewJobStatusSchema,
13
+ scope: ReviewJobScopeSchema.optional(),
14
+ base: z.string().optional(),
15
+ reviewFiles: z.array(z.string()).optional(),
16
+ promptPreview: z.string(),
17
+ claude: z.boolean().optional(),
18
+ result: z
19
+ .object({
20
+ verdict: z.string().optional(),
21
+ summary: z.string().optional(),
22
+ text: z.string().optional(),
23
+ })
24
+ .optional(),
25
+ error: z.string().optional(),
26
+ createdAt: z.string().datetime(),
27
+ startedAt: z.string().datetime().optional(),
28
+ completedAt: z.string().datetime().optional(),
29
+ })
30
+ .strict();
31
+ export function newReviewJob(input) {
32
+ return ReviewJobSchema.parse({
33
+ jobId: randomUUID(),
34
+ status: "queued",
35
+ scope: input.scope,
36
+ base: input.base,
37
+ reviewFiles: input.reviewFiles,
38
+ promptPreview: input.promptPreview,
39
+ claude: input.claude,
40
+ createdAt: new Date().toISOString(),
41
+ });
42
+ }
43
+ export function writeReviewJob(root, job) {
44
+ const next = ReviewJobSchema.parse(job);
45
+ const dir = ensureReviewJobDir(root);
46
+ const resultPath = path.join(dir, `${next.jobId}.json`);
47
+ writeFileAtomically(resultPath, `${JSON.stringify(next, null, 2)}\n`);
48
+ writeFileAtomically(path.join(dir, LATEST_REVIEW_JOB_POINTER), `${next.jobId}\n`);
49
+ return next;
50
+ }
51
+ export function updateReviewJob(root, job, patch) {
52
+ return writeReviewJob(root, ReviewJobSchema.parse({
53
+ ...job,
54
+ ...patch,
55
+ }));
56
+ }
57
+ export function readReviewJob(root, jobId) {
58
+ const parsed = z.string().uuid().safeParse(jobId);
59
+ if (!parsed.success)
60
+ return null;
61
+ const dir = existingReviewJobDir(root);
62
+ if (!dir)
63
+ return null;
64
+ const filePath = path.join(dir, `${parsed.data}.json`);
65
+ try {
66
+ if (!existsSync(filePath))
67
+ return null;
68
+ if (lstatSync(filePath).isSymbolicLink())
69
+ return null;
70
+ const raw = readFileSync(filePath, "utf8");
71
+ return ReviewJobSchema.parse(JSON.parse(raw));
72
+ }
73
+ catch {
74
+ return null;
75
+ }
76
+ }
77
+ export function readLatestReviewJob(root) {
78
+ const dir = existingReviewJobDir(root);
79
+ if (!dir)
80
+ return null;
81
+ const pointed = readLatestReviewJobPointer(root, dir);
82
+ if (pointed)
83
+ return pointed;
84
+ const candidates = readdirSync(dir)
85
+ .filter((name) => name.endsWith(".json"))
86
+ .map((name) => path.join(dir, name))
87
+ .filter((filePath) => {
88
+ try {
89
+ return !lstatSync(filePath).isSymbolicLink() && statSync(filePath).isFile();
90
+ }
91
+ catch {
92
+ return false;
93
+ }
94
+ })
95
+ .sort((a, b) => statSync(b).mtimeMs - statSync(a).mtimeMs);
96
+ for (const filePath of candidates) {
97
+ try {
98
+ const raw = readFileSync(filePath, "utf8");
99
+ return ReviewJobSchema.parse(JSON.parse(raw));
100
+ }
101
+ catch {
102
+ continue;
103
+ }
104
+ }
105
+ return null;
106
+ }
107
+ export function failInFlightReviewJobs(root, error) {
108
+ const dir = existingReviewJobDir(root);
109
+ if (!dir)
110
+ return 0;
111
+ let failed = 0;
112
+ for (const name of readdirSync(dir)) {
113
+ if (!name.endsWith(".json"))
114
+ continue;
115
+ const filePath = path.join(dir, name);
116
+ try {
117
+ if (lstatSync(filePath).isSymbolicLink() || !statSync(filePath).isFile())
118
+ continue;
119
+ const job = ReviewJobSchema.parse(JSON.parse(readFileSync(filePath, "utf8")));
120
+ if (job.status !== "queued" && job.status !== "running")
121
+ continue;
122
+ const next = ReviewJobSchema.parse({
123
+ ...job,
124
+ status: "failed",
125
+ completedAt: new Date().toISOString(),
126
+ error,
127
+ });
128
+ writeFileAtomically(filePath, `${JSON.stringify(next, null, 2)}\n`);
129
+ failed++;
130
+ }
131
+ catch {
132
+ continue;
133
+ }
134
+ }
135
+ return failed;
136
+ }
137
+ function readLatestReviewJobPointer(root, dir) {
138
+ const pointerPath = path.join(dir, LATEST_REVIEW_JOB_POINTER);
139
+ try {
140
+ if (!existsSync(pointerPath))
141
+ return null;
142
+ if (lstatSync(pointerPath).isSymbolicLink())
143
+ return null;
144
+ const jobId = readFileSync(pointerPath, "utf8").trim();
145
+ const parsed = z.string().uuid().safeParse(jobId);
146
+ if (!parsed.success)
147
+ return null;
148
+ const job = readReviewJob(root, parsed.data);
149
+ if (!job || job.jobId !== parsed.data)
150
+ return null;
151
+ return job;
152
+ }
153
+ catch {
154
+ return null;
155
+ }
156
+ }
157
+ function reviewJobDir(root) {
158
+ return path.join(realpathSync(root), ".composer", REVIEW_JOB_DIR);
159
+ }
160
+ function ensureReviewJobDir(root) {
161
+ const composerDir = path.join(realpathSync(root), ".composer");
162
+ const dir = path.join(composerDir, REVIEW_JOB_DIR);
163
+ ensureDirectory(composerDir, "Composer project state");
164
+ ensureDirectory(dir, "Review job state");
165
+ return realpathSync(dir);
166
+ }
167
+ function existingReviewJobDir(root) {
168
+ if (!existsSync(reviewJobDir(root)))
169
+ return null;
170
+ try {
171
+ const dir = reviewJobDir(root);
172
+ assertUsableDirectory(dir, "Review job state");
173
+ return realpathSync(dir);
174
+ }
175
+ catch {
176
+ return null;
177
+ }
178
+ }
179
+ function ensureDirectory(dir, label) {
180
+ if (!existsSync(dir)) {
181
+ mkdirSync(dir, { recursive: true, mode: 0o700 });
182
+ }
183
+ assertUsableDirectory(dir, label);
184
+ }
185
+ function assertUsableDirectory(dir, label) {
186
+ const stat = lstatSync(dir);
187
+ if (stat.isSymbolicLink()) {
188
+ throw new Error(`Review job directory must not be a symlink: ${label}`);
189
+ }
190
+ if (!stat.isDirectory()) {
191
+ throw new Error(`Review job path must be a directory: ${label}`);
192
+ }
193
+ }
194
+ function writeFileAtomically(filePath, content) {
195
+ const dir = path.dirname(filePath);
196
+ const tmp = path.join(dir, `.${path.basename(filePath)}.${process.pid}.${Date.now()}.tmp`);
197
+ try {
198
+ writeFileSync(tmp, content, { encoding: "utf8", mode: 0o600, flag: "wx" });
199
+ renameSync(tmp, filePath);
200
+ chmodSync(filePath, 0o600);
201
+ }
202
+ catch (error) {
203
+ rmSync(tmp, { force: true });
204
+ throw error;
205
+ }
206
+ }
207
+ //# sourceMappingURL=reviewJob.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reviewJob.js","sourceRoot":"","sources":["../../src/util/reviewJob.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ export type WorkflowKind = "feature" | "debug" | "review" | "research";
2
+ export type WorkflowMode = "fast" | "balanced" | "strict";
3
+ export type WorkflowRisk = "low" | "medium" | "high";
4
+ export interface WorkflowPlanInput {
5
+ goal: string;
6
+ workflow?: WorkflowKind;
7
+ mode?: WorkflowMode;
8
+ risk?: WorkflowRisk;
9
+ needsCurrentDocs?: boolean;
10
+ }
11
+ export interface WorkflowStep {
12
+ tool: string;
13
+ why: string;
14
+ optional?: boolean;
15
+ }
16
+ export interface WorkflowPlan {
17
+ goal: string;
18
+ workflow: WorkflowKind;
19
+ mode: WorkflowMode;
20
+ risk: WorkflowRisk;
21
+ steps: WorkflowStep[];
22
+ notes: string[];
23
+ }
24
+ export declare function planWorkflow(input: WorkflowPlanInput): WorkflowPlan;
@@ -0,0 +1,49 @@
1
+ export function planWorkflow(input) {
2
+ const workflow = input.workflow ?? "feature";
3
+ const mode = input.mode ?? "balanced";
4
+ const risk = input.risk ?? "medium";
5
+ const steps = [];
6
+ const includeReview = mode !== "fast";
7
+ const includeOracle = risk === "high";
8
+ const includeResearch = input.needsCurrentDocs === true;
9
+ switch (workflow) {
10
+ case "feature":
11
+ steps.push({ tool: "composer_handoff_create", why: "Capture a compact, provider-neutral brief for the workers." });
12
+ if (includeResearch)
13
+ steps.push({ tool: "composer_research", why: "Fetch current docs/API shape before implementing.", optional: true });
14
+ if (includeOracle)
15
+ steps.push({ tool: "composer_oracle_plan", why: "High risk / architecture uncertainty — get an extended-reasoning plan (sync).", optional: true });
16
+ steps.push({ tool: "composer_code_cli", why: "Apply the implementation off the main session." });
17
+ if (includeReview)
18
+ steps.push({ tool: "composer_review", why: "Review the scoped diff (reviewScope: staged|branch) before commit." });
19
+ steps.push({ tool: "composer_audit_record", why: "Record the route + outcome for evidence.", optional: true });
20
+ break;
21
+ case "debug":
22
+ if (includeOracle)
23
+ steps.push({ tool: "composer_oracle_plan", why: "Hard root-cause — extended reasoning (sync).", optional: true });
24
+ if (includeResearch)
25
+ steps.push({ tool: "composer_research", why: "Look up error/API specifics.", optional: true });
26
+ steps.push({ tool: "composer_code_cli", why: "Apply the fix off the main session." });
27
+ if (includeReview)
28
+ steps.push({ tool: "composer_review", why: "Review the fix diff." });
29
+ steps.push({ tool: "composer_audit_record", why: "Record the outcome.", optional: true });
30
+ break;
31
+ case "review":
32
+ steps.push({ tool: "composer_review", why: "Review the scoped diff (use reviewScope to avoid pasting)." });
33
+ steps.push({ tool: "composer_audit_record", why: "Record the verdict.", optional: true });
34
+ break;
35
+ case "research":
36
+ steps.push({ tool: "composer_research", why: "Gather external context/docs." });
37
+ steps.push({ tool: "composer_handoff_create", why: "Persist findings for the implementing step.", optional: true });
38
+ break;
39
+ }
40
+ const notes = [];
41
+ if (mode === "fast")
42
+ notes.push("fast mode: review + lifecycle gates skipped — use for tiny, low-risk changes.");
43
+ if (mode === "strict")
44
+ notes.push("strict mode: review gate + fail-closed pre-commit expected.");
45
+ if (!includeOracle && (workflow === "feature" || workflow === "debug"))
46
+ notes.push("Oracle skipped (risk<high). Tag [oracle:plan] explicitly if architecture is uncertain.");
47
+ return { goal: input.goal, workflow, mode, risk, steps, notes };
48
+ }
49
+ //# sourceMappingURL=workflowPlan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workflowPlan.js","sourceRoot":"","sources":["../../src/util/workflowPlan.ts"],"names":[],"mappings":"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"}