@magnusekdahl/parallix 1.2.1 → 1.3.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 (81) hide show
  1. package/index.js +190 -185
  2. package/lib/agents/agents.js +34 -4
  3. package/lib/agents/agents.ts +40 -5
  4. package/lib/commands/active.js +502 -579
  5. package/lib/commands/active.ts +665 -0
  6. package/lib/commands/checkpoint.js +98 -74
  7. package/lib/commands/checkpoint.ts +79 -0
  8. package/lib/commands/config.js +61 -31
  9. package/lib/commands/config.ts +47 -0
  10. package/lib/commands/coverage-gate.js +271 -246
  11. package/lib/commands/coverage-gate.ts +362 -0
  12. package/lib/commands/diff.js +140 -119
  13. package/lib/commands/diff.ts +125 -0
  14. package/lib/commands/draft.js +770 -923
  15. package/lib/commands/draft.ts +1021 -0
  16. package/lib/commands/handoff.js +588 -608
  17. package/lib/commands/handoff.ts +694 -0
  18. package/lib/commands/integrate.js +1331 -1468
  19. package/lib/commands/integrate.ts +1688 -0
  20. package/lib/commands/mission-start.js +279 -237
  21. package/lib/commands/mission-start.ts +263 -0
  22. package/lib/commands/rebase.js +606 -582
  23. package/lib/commands/rebase.ts +635 -0
  24. package/lib/commands/repair-handoff.js +181 -179
  25. package/lib/commands/repair-handoff.ts +228 -0
  26. package/lib/commands/resolve-conflict.js +121 -102
  27. package/lib/commands/resolve-conflict.ts +112 -0
  28. package/lib/commands/review.js +3 -4
  29. package/lib/commands/review.ts +14 -0
  30. package/lib/commands/setup-review.js +4 -5
  31. package/lib/commands/setup-review.ts +14 -0
  32. package/lib/commands/setup.js +3 -3
  33. package/lib/commands/setup.ts +2 -0
  34. package/lib/commands/stats-backfill.js +394 -359
  35. package/lib/commands/stats-backfill.ts +418 -0
  36. package/lib/commands/stats.js +1424 -1665
  37. package/lib/commands/stats.ts +2186 -0
  38. package/lib/commands/status.js +219 -200
  39. package/lib/commands/status.ts +219 -0
  40. package/lib/commands/verify.js +3 -1
  41. package/lib/commands/verify.ts +2 -0
  42. package/lib/core/nels.js +112 -127
  43. package/lib/core/nels.ts +189 -0
  44. package/lib/core/subagent-limit.js +15 -16
  45. package/lib/core/subagent-limit.ts +25 -0
  46. package/lib/index.js +142 -59
  47. package/lib/index.ts +134 -0
  48. package/lib/review/rebase.js +142 -145
  49. package/lib/review/rebase.ts +188 -0
  50. package/lib/review/review-adapter.js +99 -87
  51. package/lib/review/review-adapter.ts +198 -0
  52. package/lib/review/review-artifacts.js +486 -629
  53. package/lib/review/review-artifacts.ts +622 -0
  54. package/lib/review/review-commands.js +1220 -1373
  55. package/lib/review/review-commands.ts +1579 -0
  56. package/lib/review/review-events.js +544 -886
  57. package/lib/review/review-events.ts +954 -0
  58. package/lib/review/review-loop.js +945 -1020
  59. package/lib/review/review-loop.ts +1174 -0
  60. package/lib/review/review-polling.js +86 -115
  61. package/lib/review/review-polling.ts +194 -0
  62. package/lib/review/review-prompts.js +154 -189
  63. package/lib/review/review-prompts.ts +182 -0
  64. package/lib/review/review-state.js +246 -225
  65. package/lib/review/review-state.ts +353 -0
  66. package/lib/review/review.js +63 -84
  67. package/lib/review/review.ts +138 -0
  68. package/lib/tools/backlog.js +694 -680
  69. package/lib/tools/backlog.ts +835 -0
  70. package/lib/tools/forgejo.js +1270 -1405
  71. package/lib/tools/forgejo.ts +1793 -0
  72. package/lib/tools/gatekeeper.js +106 -96
  73. package/lib/tools/gatekeeper.ts +124 -0
  74. package/lib/tools/redgreen.js +200 -181
  75. package/lib/tools/redgreen.ts +221 -0
  76. package/lib/tools/sessions.js +58 -52
  77. package/lib/tools/sessions.ts +81 -0
  78. package/lib/tools/setup-review.js +902 -975
  79. package/lib/tools/setup-review.ts +1152 -0
  80. package/package.json +4 -4
  81. package/px.js +226 -208
@@ -0,0 +1,125 @@
1
+ import childProcess from 'node:child_process';
2
+ import path from 'node:path';
3
+ import { git } from '../core/git.js';
4
+ import { getPrimaryBranch, missionBranchName, inferSlug, resolveWorktree } from '../core/mission-utils.js';
5
+ import * as fmt from '../core/fmt.js';
6
+
7
+ /** @param {string[]} args @param {{gitFn?: Function, spawnSyncFn?: Function, getPrimaryBranchFn?: Function, missionBranchNameFn?: Function, inferSlugFn?: Function, resolveWorktreeFn?: Function, exitFn?: Function, failFn?: Function}} opts */
8
+ async function diff(args: any, {
9
+ gitFn = git,
10
+ spawnSyncFn = childProcess.spawnSync,
11
+ getPrimaryBranchFn = getPrimaryBranch,
12
+ missionBranchNameFn = missionBranchName,
13
+ inferSlugFn = inferSlug,
14
+ resolveWorktreeFn = resolveWorktree,
15
+ exitFn = process.exit,
16
+ failFn = fmt.log.fail,
17
+ } = {}) {
18
+ /** @param {string} a */
19
+ const explicitSlug = args.filter((a: string) => !a.startsWith('--'))[0];
20
+ const slug = inferSlugFn(explicitSlug);
21
+
22
+ if (!slug) {
23
+ failFn('Usage: node parallix diff [<slug>]');
24
+ exitFn(1);
25
+ return;
26
+ }
27
+
28
+ const worktree = resolveWorktreeFn(slug);
29
+ if (!worktree) {
30
+ failFn(`Mission worktree not found for ${fmt.slug(slug)}. Run this from the mission worktree or create it first.`);
31
+ exitFn(1);
32
+ return;
33
+ }
34
+
35
+ let primary;
36
+ try {
37
+ primary = getPrimaryBranchFn(worktree);
38
+ } catch (err) {
39
+ failFn((err as Error).message);
40
+ exitFn(1);
41
+ return;
42
+ }
43
+
44
+ const branch = missionBranchNameFn(slug);
45
+ const target = `${primary}..HEAD`;
46
+
47
+ // Detect configured diff tool/pager
48
+ /** @param {string} key */
49
+ const getGitConfig = (key: string) => {
50
+ const result = gitFn(['-C', worktree, 'config', '--get', key]);
51
+ return result.status === 0 ? result.stdout.trim() : null;
52
+ };
53
+
54
+ /** @param {string} cmd */
55
+ const isSpecializedTool = (cmd: string) => {
56
+ if (!cmd) {return false;}
57
+ const parts = cmd.split(/\s+/);
58
+ // Handle cases like "LESS=FRX less" or "/usr/bin/delta"
59
+ /** @param {string} p */
60
+ const exePart = parts.find((p: string) => !p.includes('='));
61
+ if (!exePart) {return false;}
62
+ const exe = path.basename(exePart).toLowerCase();
63
+
64
+ // Explicitly reject known default pagers
65
+ if (['less', 'cat', 'more'].includes(exe)) {return false;}
66
+
67
+ // Accept known specialized tools documented in review-tooling.md
68
+ if (['delta', 'difft', 'diff-so-fancy'].includes(exe)) {return true;}
69
+
70
+ // Fallback: if it's not a known default, and we have a value, treat it as specialized
71
+ // for now to avoid breaking custom setups like "vimdiff", but we've rejected plain "less".
72
+ return true;
73
+ };
74
+
75
+ /** @param {childProcess.SpawnSyncReturns<string>} result @param {string} toolName */
76
+ const handleLaunchResult = (result: any, toolName: string) => {
77
+ if (result.error) {
78
+ failFn(`Failed to launch ${toolName}: ${result.error.message}`);
79
+ exitFn(1);
80
+ return;
81
+ }
82
+ if (result.signal) {
83
+ failFn(`${toolName} terminated by signal: ${result.signal}`);
84
+ exitFn(1);
85
+ return;
86
+ }
87
+ if (result.status === null) {
88
+ failFn(`${toolName} exited with unknown status.`);
89
+ exitFn(1);
90
+ return;
91
+ }
92
+ exitFn(result.status);
93
+ };
94
+
95
+ const diffTool = getGitConfig('diff.tool');
96
+ if (diffTool) {
97
+ fmt.log.info(`Launching ${fmt.command('git difftool')} for ${fmt.branch(branch)} (tool: ${fmt.bold(diffTool)})...`);
98
+ const result = spawnSyncFn('git', ['difftool', '-d', '--no-prompt', target], { cwd: worktree, stdio: 'inherit' });
99
+ handleLaunchResult(result, 'git difftool');
100
+ return;
101
+ }
102
+
103
+ const pagerDiff = getGitConfig('pager.diff');
104
+ if (isSpecializedTool(pagerDiff || '')) {
105
+ fmt.log.info(`Launching ${fmt.command('git diff')} for ${fmt.branch(branch)} (pager: ${fmt.bold(pagerDiff || "")})...`);
106
+ const result = spawnSyncFn('git', ['diff', target], { cwd: worktree, stdio: 'inherit' });
107
+ handleLaunchResult(result, 'git diff');
108
+ return;
109
+ }
110
+
111
+ const corePager = getGitConfig('core.pager');
112
+ if (isSpecializedTool(corePager || '')) {
113
+ fmt.log.info(`Launching ${fmt.command('git diff')} for ${fmt.branch(branch)} (core.pager: ${fmt.bold(corePager || "")})...`);
114
+ const result = spawnSyncFn('git', ['diff', target], { cwd: worktree, stdio: 'inherit' });
115
+ handleLaunchResult(result, 'git diff');
116
+ return;
117
+ }
118
+
119
+ failFn('No specialized local diff tool (e.g., delta, difftastic) is configured in Git.');
120
+ fmt.log.info('The workflow diff command requires an explicitly configured diff.tool or a non-default core.pager.');
121
+ fmt.log.info(`Refer to ${fmt.path('docs/developer-setup/review-tooling.md')} for setup guidance.`);
122
+ exitFn(1);
123
+ }
124
+
125
+ export = diff;