@pat-lewczuk/cezar 0.1.4 → 0.1.5

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 (85) hide show
  1. package/README.md +124 -37
  2. package/dist/config.d.ts +46 -0
  3. package/dist/config.js +31 -0
  4. package/dist/config.js.map +1 -1
  5. package/dist/core/agent-runner.d.ts +16 -0
  6. package/dist/core/agent-runner.js +9 -0
  7. package/dist/core/agent-runner.js.map +1 -1
  8. package/dist/core/claude-cli-runner.d.ts +6 -0
  9. package/dist/core/claude-cli-runner.js +27 -43
  10. package/dist/core/claude-cli-runner.js.map +1 -1
  11. package/dist/core/codex-app-server-runner.js +42 -5
  12. package/dist/core/codex-app-server-runner.js.map +1 -1
  13. package/dist/core/opencode-server-runner.js +42 -5
  14. package/dist/core/opencode-server-runner.js.map +1 -1
  15. package/dist/git-worktree.d.ts +21 -0
  16. package/dist/git-worktree.js +48 -4
  17. package/dist/git-worktree.js.map +1 -1
  18. package/dist/handoff.d.ts +1 -1
  19. package/dist/handoff.js +2 -0
  20. package/dist/handoff.js.map +1 -1
  21. package/dist/index.js +34 -4
  22. package/dist/index.js.map +1 -1
  23. package/dist/runs/store.d.ts +82 -1
  24. package/dist/runs/store.js +57 -5
  25. package/dist/runs/store.js.map +1 -1
  26. package/dist/server/git.js +12 -1
  27. package/dist/server/git.js.map +1 -1
  28. package/dist/server/github.d.ts +8 -29
  29. package/dist/server/github.js +7 -139
  30. package/dist/server/github.js.map +1 -1
  31. package/dist/server/pr.d.ts +5 -20
  32. package/dist/server/pr.js +4 -95
  33. package/dist/server/pr.js.map +1 -1
  34. package/dist/server/server.d.ts +30 -1
  35. package/dist/server/server.js +448 -19
  36. package/dist/server/server.js.map +1 -1
  37. package/dist/workflows/run.d.ts +90 -0
  38. package/dist/workflows/run.js +412 -29
  39. package/dist/workflows/run.js.map +1 -1
  40. package/dist/workflows/types.d.ts +16 -16
  41. package/package.json +44 -6
  42. package/scripts/check-pack.mjs +46 -0
  43. package/scripts/dev.mjs +74 -0
  44. package/scripts/mock-claude.mjs +54 -2
  45. package/scripts/test-process-usage.mjs +47 -0
  46. package/web/dist/assets/{toaster-BS2E1bhz.js → centered-state-zgEVNWsj.js} +1 -1
  47. package/web/dist/assets/compare-variants-ChHCcSQX.js +1 -0
  48. package/web/dist/assets/dialog-DDRjj-uK.js +1 -0
  49. package/web/dist/assets/{diff-view-CctnJHWe.js → diff-view-CWRO0GMe.js} +1 -1
  50. package/web/dist/assets/dist-id2CeyV-.js +1 -0
  51. package/web/dist/assets/git-toolbar-C4jo602L.js +1 -0
  52. package/web/dist/assets/github-BOIzQFwE.js +1 -0
  53. package/web/dist/assets/index-Cv1pQs9U.js +11 -0
  54. package/web/dist/assets/repo-git-BuyJiqna.js +1 -0
  55. package/web/dist/assets/{run-diff-C7mfxj7f.js → run-diff-BocG6LVd.js} +1 -1
  56. package/web/dist/assets/run-header-CDKw22ek.js +1 -0
  57. package/web/dist/assets/skill-detail-CcFFKmGO.js +1 -0
  58. package/web/dist/assets/skills-Bc_4U3yq.js +1 -0
  59. package/web/dist/assets/tab-link-C77EP3i6.js +1 -0
  60. package/web/dist/assets/task-changes-DsDgN8-x.js +1 -0
  61. package/web/dist/assets/task-commits-Dve6Fozc.js +1 -0
  62. package/web/dist/assets/{task-files-FOAAz2FB.js → task-files-BDMc_z0B.js} +1 -1
  63. package/web/dist/assets/{task-thread-Bncxe8Os.js → task-thread-CmRuPj9H.js} +2 -2
  64. package/web/dist/assets/use-desktop-CyEWsxSU.js +3 -0
  65. package/web/dist/assets/{workflows-Dg2wQg6i.js → workflows-J3z3kYic.js} +1 -1
  66. package/web/dist/index.html +5 -5
  67. package/web/app/node_modules/.vite/vitest/ca84d1343b96baa8137c943ed1860e522cacb238/results.json +0 -1
  68. package/web/app/src/components/app-shell-container.tsx +0 -76
  69. package/web/app.js +0 -3428
  70. package/web/dist/assets/compare-variants-D6fPL9cS.js +0 -1
  71. package/web/dist/assets/dialog-BEgEWFDS.js +0 -1
  72. package/web/dist/assets/dist-CW7M_Jhs.js +0 -1
  73. package/web/dist/assets/git-toolbar-D8OPPqBP.js +0 -1
  74. package/web/dist/assets/github-BYIHwIJB.js +0 -1
  75. package/web/dist/assets/index-9qG98Orw.js +0 -11
  76. package/web/dist/assets/repo-git-XTqlVOl2.js +0 -1
  77. package/web/dist/assets/run-header-CfVeY3uM.js +0 -1
  78. package/web/dist/assets/skill-detail-C9cniyId.js +0 -1
  79. package/web/dist/assets/skills-DXgY1uXJ.js +0 -1
  80. package/web/dist/assets/tab-link-phWEqSBy.js +0 -1
  81. package/web/dist/assets/task-changes-DYwnPnTN.js +0 -1
  82. package/web/dist/assets/task-commits-DZzxEzbn.js +0 -1
  83. package/web/dist/assets/use-desktop-eHm2iTXX.js +0 -3
  84. package/web/index.html +0 -108
  85. package/web/style.css +0 -1767
@@ -1,140 +1,8 @@
1
- import { execFile } from 'node:child_process';
2
- import { promisify } from 'node:util';
3
- import { z } from 'zod';
4
- const exec = promisify(execFile);
5
- // `gh --json` output validated at the boundary, extras stripped.
6
- const ghAuthor = z.object({ login: z.string() }).nullish();
7
- const ghLabel = z.object({ name: z.string() });
8
- const ghIssueSchema = z.object({
9
- number: z.number(),
10
- title: z.string(),
11
- author: ghAuthor,
12
- createdAt: z.string(),
13
- labels: z.array(ghLabel).default([]),
14
- body: z.string().nullish(),
15
- url: z.string(),
16
- });
17
- const ghPrSchema = ghIssueSchema.extend({
18
- isDraft: z.boolean().default(false),
19
- additions: z.number().default(0),
20
- deletions: z.number().default(0),
21
- statusCheckRollup: z
22
- .array(z.object({ state: z.string().nullish(), status: z.string().nullish(), conclusion: z.string().nullish() }))
23
- .nullish(),
24
- });
25
- function rollupToChecks(rollup) {
26
- if (!rollup || rollup.length === 0)
27
- return null;
28
- const states = rollup.map((r) => (r.conclusion || r.state || r.status || '').toUpperCase());
29
- if (states.some((s) => ['FAILURE', 'ERROR', 'TIMED_OUT', 'ACTION_REQUIRED'].includes(s)))
30
- return 'failing';
31
- if (states.some((s) => ['PENDING', 'IN_PROGRESS', 'QUEUED', 'EXPECTED', ''].includes(s)))
32
- return 'pending';
33
- return 'passing';
34
- }
35
- async function gh(repoRoot, args, timeout = 15_000) {
36
- const { stdout } = await exec('gh', args, {
37
- cwd: repoRoot,
38
- timeout,
39
- maxBuffer: 50 * 1024 * 1024,
40
- });
41
- return stdout;
42
- }
43
- /* Reads degrade to `available: false` with a hint — never an error (plan rule
44
- 7): no `gh`, no remote, offline all land on the same quiet path. A short
45
- cache keeps tab switches from hammering the GitHub API; a cached fetch with
46
- a bigger limit than asked serves fine (it's a superset). */
47
- let cache = null;
48
- const CACHE_MS = 60_000;
49
- export const GH_MAX_LIMIT = 1000;
50
- export async function fetchGithub(repoRoot, refresh = false, limit = 30) {
51
- if (process.env.CEZ_DRY_RUN === '1')
52
- return mockGithub();
53
- const capped = Math.min(Math.max(limit, 1), GH_MAX_LIMIT);
54
- if (!refresh && cache && Date.now() - cache.at < CACHE_MS && cache.limit >= capped) {
55
- return cache.data;
56
- }
57
- try {
58
- // No `comments` field — `gh … --json comments` ships full comment bodies.
59
- // Big fetches (the GUI's follow-up "give me everything" shot) get a
60
- // longer wall clock — statusCheckRollup on hundreds of PRs is slow.
61
- const timeout = capped > 100 ? 60_000 : 15_000;
62
- const fields = 'number,title,author,createdAt,labels,body,url';
63
- const [repoOut, issuesOut, prsOut] = await Promise.all([
64
- gh(repoRoot, ['repo', 'view', '--json', 'nameWithOwner', '--jq', '.nameWithOwner'], timeout),
65
- gh(repoRoot, ['issue', 'list', '--limit', String(capped), '--json', fields], timeout),
66
- gh(repoRoot, ['pr', 'list', '--limit', String(capped), '--json', `${fields},isDraft,additions,deletions,statusCheckRollup`], timeout),
67
- ]);
68
- const issues = z.array(ghIssueSchema).parse(JSON.parse(issuesOut)).map((i) => ({
69
- kind: 'issue',
70
- number: i.number,
71
- title: i.title,
72
- author: i.author?.login ?? '?',
73
- createdAt: i.createdAt,
74
- labels: i.labels.map((l) => l.name),
75
- body: (i.body ?? '').slice(0, 8_000),
76
- url: i.url,
77
- comments: 0,
78
- }));
79
- const prs = z.array(ghPrSchema).parse(JSON.parse(prsOut)).map((p) => ({
80
- kind: 'pr',
81
- number: p.number,
82
- title: p.title,
83
- author: p.author?.login ?? '?',
84
- createdAt: p.createdAt,
85
- labels: [...p.labels.map((l) => l.name), ...(p.isDraft ? ['draft'] : [])],
86
- body: (p.body ?? '').slice(0, 8_000),
87
- url: p.url,
88
- comments: 0,
89
- isDraft: p.isDraft,
90
- additions: p.additions,
91
- deletions: p.deletions,
92
- checks: rollupToChecks(p.statusCheckRollup),
93
- }));
94
- const data = {
95
- available: true,
96
- repo: repoOut.trim() || undefined,
97
- syncedAt: new Date().toISOString(),
98
- issues,
99
- prs,
100
- };
101
- cache = { at: Date.now(), limit: capped, data };
102
- return data;
103
- }
104
- catch (err) {
105
- const message = err instanceof Error ? err.message : String(err);
106
- const reason = /ENOENT/.test(message)
107
- ? 'gh CLI not found — install it and run `gh auth login`'
108
- : firstLine(message);
109
- return { available: false, reason, issues: [], prs: [] };
110
- }
111
- }
112
- function firstLine(s) {
113
- return s.split('\n').find((l) => l.trim().length > 0)?.trim() ?? 'gh failed';
114
- }
115
- /** CEZ_DRY_RUN=1 — a small fixed catalog so the GitHub tab is demoable offline. */
116
- function mockGithub() {
117
- const mk = (over) => ({
118
- author: 'mock',
119
- createdAt: new Date(Date.now() - over.number * 3_600_000).toISOString(),
120
- labels: [],
121
- url: `https://github.com/mock/repo/${over.kind === 'pr' ? 'pull' : 'issues'}/${over.number}`,
122
- comments: 0,
123
- ...over,
124
- });
125
- return {
126
- available: true,
127
- repo: 'mock/repo',
128
- syncedAt: new Date().toISOString(),
129
- issues: [
130
- mk({ kind: 'issue', number: 142, title: 'Login form drops session on refresh', labels: ['bug', 'auth'], comments: 3, body: 'Repro: log in, hit reload — you land back on /login. The session cookie is set correctly, but the client store rehydrates before the cookie check resolves, so the auth guard redirects.' }),
131
- mk({ kind: 'issue', number: 139, title: 'Add --json flag to cez CLI output', labels: ['enhancement', 'cli'], comments: 1, body: 'For scripting it would help if `cez list` and `cez status` could emit machine-readable JSON instead of the table view.' }),
132
- mk({ kind: 'issue', number: 135, title: 'Flaky e2e: worktree cleanup race on cancel', labels: ['bug', 'flaky-test'], comments: 6, body: 'Cancelling a run while the agent holds a file lock leaves a dangling worktree. The next run on the same branch then fails with "worktree already exists".' }),
133
- ],
134
- prs: [
135
- mk({ kind: 'pr', number: 128, title: 'Fix flaky auth test in CI', labels: ['tests'], checks: 'passing', additions: 6, deletions: 3, body: 'Loosens the timing assertion in refresh.test.ts to a realistic budget.' }),
136
- mk({ kind: 'pr', number: 124, title: 'Rate limit /api/runs', labels: ['server', 'draft'], isDraft: true, checks: 'failing', additions: 118, deletions: 7, comments: 4, body: 'Draft: token-bucket middleware on the runs router. Still needs the config surface and README docs before review.' }),
137
- ],
138
- };
139
- }
1
+ /**
2
+ * Thin delegate the gh-CLI listing logic moved behind the forge-driver seam
3
+ * (`src/server/forge/github.ts`, cockpit-ui redesign spec §"Forge-driver
4
+ * seam"). Kept so existing imports and the protected `/api/github` response
5
+ * shape (BACKWARD_COMPATIBILITY.md §2) stay exactly as they were.
6
+ */
7
+ export { fetchGithub, GH_MAX_LIMIT } from './forge/github.js';
140
8
  //# sourceMappingURL=github.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"github.js","sourceRoot":"","sources":["../../src/server/github.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"github.js","sourceRoot":"","sources":["../../src/server/github.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC"}
@@ -1,22 +1,7 @@
1
- import type { RunRecord } from '../runs/store.js';
2
- export type DraftPrOutcome = {
3
- ok: true;
4
- url: string;
5
- dryRun: boolean;
6
- } | {
7
- ok: false;
8
- error: string;
9
- };
10
- export interface DraftPrInput {
11
- repoRoot: string;
12
- run: RunRecord;
13
- /** The task's handoff.md — becomes the PR body (goal + progress skim). */
14
- handoffText: string;
15
- }
16
- export declare function createDraftPr(input: DraftPrInput): Promise<DraftPrOutcome>;
17
1
  /**
18
- * PR body from the handoff journal: the "## Goal" section (task text as
19
- * fallback) + the first ~10 lines of "## Progress log" (newest first) +
20
- * the cezar footer.
2
+ * Thin delegate draft-PR creation (review gate, spec 009) moved behind the
3
+ * forge-driver seam (`src/server/forge/github.ts`, cockpit-ui redesign spec
4
+ * §"Forge-driver seam"). Kept so existing imports keep working.
21
5
  */
22
- export declare function buildPrBody(handoffText: string, task: string): string;
6
+ export { buildPrBody, createDraftPr } from './forge/github.js';
7
+ export type { DraftPrInput, DraftPrOutcome } from './forge/types.js';
package/dist/server/pr.js CHANGED
@@ -1,98 +1,7 @@
1
- import { execFile } from 'node:child_process';
2
- import { autosaveCommit } from '../git-worktree.js';
3
1
  /**
4
- * Draft-PR creation for the review gate (spec 009): final autosave-commit
5
- * `git push -u origin cez/<id8>` → `gh pr create --draft`, all executed in
6
- * the task worktree (gh picks the repo up from the worktree's remote).
7
- * Every failure maps to a one-line human error — the GUI shows it as a toast
8
- * plus the manual `git merge <branch>` fallback. Never throws.
2
+ * Thin delegate — draft-PR creation (review gate, spec 009) moved behind the
3
+ * forge-driver seam (`src/server/forge/github.ts`, cockpit-ui redesign spec
4
+ * §"Forge-driver seam"). Kept so existing imports keep working.
9
5
  */
10
- const PR_URL_RE = /https:\/\/github\.com\/[^/\s]+\/[^/\s]+\/pull\/\d+/;
11
- const PUSH_TIMEOUT_MS = 60_000;
12
- const PROGRESS_LINES_MAX = 10;
13
- export async function createDraftPr(input) {
14
- const { run } = input;
15
- const worktree = run.worktreePath;
16
- const branch = run.branch;
17
- if (!worktree || !branch) {
18
- return { ok: false, error: 'this task has no worktree/branch to publish' };
19
- }
20
- // Final autosave: the branch must hold everything before it leaves the box.
21
- await autosaveCommit(worktree);
22
- // DRY-RUN (CEZ_DRY_RUN=1): no push, no gh — simulate success with a fake PR
23
- // URL so the whole review → PR flow is testable without GitHub.
24
- if (process.env.CEZ_DRY_RUN === '1') {
25
- return { ok: true, url: 'https://github.com/open-mercato/demo/pull/777', dryRun: true };
26
- }
27
- const remote = await exec('git', ['remote', 'get-url', 'origin'], worktree);
28
- if (!remote.ok || !remote.stdout.trim()) {
29
- return { ok: false, error: 'no git remote — add one (git remote add origin <url>) or merge the branch locally' };
30
- }
31
- const push = await exec('git', ['push', '-u', 'origin', branch], worktree, PUSH_TIMEOUT_MS);
32
- if (!push.ok) {
33
- return { ok: false, error: `git push failed — ${tail(push.stderr) || 'unknown error'}` };
34
- }
35
- const body = buildPrBody(input.handoffText, run.task);
36
- // Target the branch the worktree forked from (config `baseBranch`) — without
37
- // --base, gh aims at the repo default (main) even when work started on
38
- // develop. `origin/x` normalizes to `x`; a raw sha (detached-HEAD fork
39
- // point) can't be a PR base, so gh falls back to the default branch.
40
- const prBase = run.baseBranch?.replace(/^origin\//, '');
41
- const baseArgs = prBase && !/^[0-9a-f]{7,40}$/i.test(prBase) ? ['--base', prBase] : [];
42
- const pr = await exec('gh', ['pr', 'create', '--draft', '--head', branch, ...baseArgs, '--title', run.title, '--body', body], worktree, PUSH_TIMEOUT_MS);
43
- if (!pr.ok) {
44
- if (pr.notFound) {
45
- return { ok: false, error: 'gh not found — install the GitHub CLI and run `gh auth login`, or merge the branch locally' };
46
- }
47
- const hint = /auth|log ?in|credential/i.test(pr.stderr) ? ' (try `gh auth login`)' : '';
48
- return { ok: false, error: `gh pr create failed — ${tail(pr.stderr) || 'unknown error'}${hint}` };
49
- }
50
- // gh prints the PR URL on stdout; some versions echo it to stderr instead.
51
- const match = PR_URL_RE.exec(`${pr.stdout}\n${pr.stderr}`);
52
- if (!match) {
53
- return { ok: false, error: 'gh pr create returned no PR URL — check `gh pr list` manually' };
54
- }
55
- return { ok: true, url: match[0], dryRun: false };
56
- }
57
- /**
58
- * PR body from the handoff journal: the "## Goal" section (task text as
59
- * fallback) + the first ~10 lines of "## Progress log" (newest first) +
60
- * the cezar footer.
61
- */
62
- export function buildPrBody(handoffText, task) {
63
- const goal = section(handoffText, '## Goal') || task.trim();
64
- const progress = section(handoffText, '## Progress log')
65
- .split('\n')
66
- .filter((l) => l.trim())
67
- .slice(0, PROGRESS_LINES_MAX)
68
- .join('\n');
69
- const parts = ['## Goal', '', goal];
70
- if (progress)
71
- parts.push('', '## Progress log', '', progress);
72
- parts.push('', '---', '', '🤖 made with cezar');
73
- return parts.join('\n');
74
- }
75
- /** Text of one `## Header` section, up to the next `## ` header. */
76
- function section(text, header) {
77
- const start = text.indexOf(`${header}\n`);
78
- if (start < 0)
79
- return '';
80
- const rest = text.slice(start + header.length + 1);
81
- const next = rest.indexOf('\n## ');
82
- return (next >= 0 ? rest.slice(0, next) : rest).trim();
83
- }
84
- /** Last 3 stderr lines, pipe-joined — enough context, toast-sized. */
85
- function tail(stderr) {
86
- return stderr.trim().split('\n').slice(-3).join(' | ').slice(0, 300);
87
- }
88
- function exec(bin, args, cwd, timeoutMs = 30_000) {
89
- return new Promise((resolve) => {
90
- execFile(bin, args, { cwd, timeout: timeoutMs, maxBuffer: 4 * 1024 * 1024, encoding: 'utf8' }, (err, stdout, stderr) => resolve({
91
- ok: !err,
92
- stdout: stdout ?? '',
93
- stderr: stderr ?? '',
94
- notFound: err?.code === 'ENOENT',
95
- }));
96
- });
97
- }
6
+ export { buildPrBody, createDraftPr } from './forge/github.js';
98
7
  //# sourceMappingURL=pr.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"pr.js","sourceRoot":"","sources":["../../src/server/pr.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"pr.js","sourceRoot":"","sources":["../../src/server/pr.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC"}
@@ -1,12 +1,41 @@
1
1
  import { Hono } from 'hono';
2
2
  import { type ServerType } from '@hono/node-server';
3
- import type { RunStore } from '../runs/store.js';
3
+ import type { RunRecord, RunStatus, RunStore } from '../runs/store.js';
4
4
  import type { RunManager } from '../workflows/run.js';
5
5
  export interface ServerDeps {
6
6
  repoRoot: string;
7
7
  store: RunStore;
8
8
  manager: RunManager;
9
9
  version: string;
10
+ /** Mutable holder for the async npm-registry update check (#368) —
11
+ * `latest` appears once the registry answers with a newer version. */
12
+ update?: {
13
+ latest?: string;
14
+ };
15
+ /** Host the HTTP server binds (default 127.0.0.1). A non-loopback host
16
+ * implies hosted mode — `capabilities.localHandoff:false`. */
17
+ bindHost?: string;
18
+ }
19
+ /** One column of `GET /api/groups/:groupId`. NOTE: `diffStat` here is the raw
20
+ * `git diff --stat` text (worktreeDiffStat), NOT the numeric `RunRecord.diffStat`. */
21
+ export interface GroupVariant {
22
+ id: string;
23
+ variant: string;
24
+ title: string;
25
+ status: RunStatus;
26
+ archived: boolean;
27
+ tokensUsed: number;
28
+ costUsd?: number;
29
+ diffStat: string;
30
+ handoffExcerpt: string;
31
+ }
32
+ export interface GroupResponse {
33
+ groupId: string;
34
+ runs: GroupVariant[];
35
+ }
36
+ /** `POST /api/groups/:groupId/pick` — the winner, parked at `review` when it has a diff. */
37
+ export interface PickVariantResponse {
38
+ winner?: RunRecord;
10
39
  }
11
40
  export declare function createApp(deps: ServerDeps): Hono;
12
41
  export declare function startServer(deps: ServerDeps, port: number): ServerType;