@magnusekdahl/parallix 1.2.1 → 1.3.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 (79) hide show
  1. package/index.js +190 -185
  2. package/lib/commands/active.js +502 -579
  3. package/lib/commands/active.ts +665 -0
  4. package/lib/commands/checkpoint.js +98 -74
  5. package/lib/commands/checkpoint.ts +79 -0
  6. package/lib/commands/config.js +61 -31
  7. package/lib/commands/config.ts +47 -0
  8. package/lib/commands/coverage-gate.js +271 -246
  9. package/lib/commands/coverage-gate.ts +362 -0
  10. package/lib/commands/diff.js +140 -119
  11. package/lib/commands/diff.ts +125 -0
  12. package/lib/commands/draft.js +770 -923
  13. package/lib/commands/draft.ts +1021 -0
  14. package/lib/commands/handoff.js +588 -608
  15. package/lib/commands/handoff.ts +694 -0
  16. package/lib/commands/integrate.js +1331 -1468
  17. package/lib/commands/integrate.ts +1688 -0
  18. package/lib/commands/mission-start.js +279 -237
  19. package/lib/commands/mission-start.ts +263 -0
  20. package/lib/commands/rebase.js +606 -582
  21. package/lib/commands/rebase.ts +635 -0
  22. package/lib/commands/repair-handoff.js +181 -179
  23. package/lib/commands/repair-handoff.ts +228 -0
  24. package/lib/commands/resolve-conflict.js +121 -102
  25. package/lib/commands/resolve-conflict.ts +112 -0
  26. package/lib/commands/review.js +3 -4
  27. package/lib/commands/review.ts +14 -0
  28. package/lib/commands/setup-review.js +4 -5
  29. package/lib/commands/setup-review.ts +14 -0
  30. package/lib/commands/setup.js +3 -3
  31. package/lib/commands/setup.ts +2 -0
  32. package/lib/commands/stats-backfill.js +394 -359
  33. package/lib/commands/stats-backfill.ts +418 -0
  34. package/lib/commands/stats.js +1424 -1665
  35. package/lib/commands/stats.ts +2186 -0
  36. package/lib/commands/status.js +219 -200
  37. package/lib/commands/status.ts +219 -0
  38. package/lib/commands/verify.js +3 -1
  39. package/lib/commands/verify.ts +2 -0
  40. package/lib/core/nels.js +112 -127
  41. package/lib/core/nels.ts +189 -0
  42. package/lib/core/subagent-limit.js +15 -16
  43. package/lib/core/subagent-limit.ts +25 -0
  44. package/lib/index.js +142 -59
  45. package/lib/index.ts +134 -0
  46. package/lib/review/rebase.js +142 -145
  47. package/lib/review/rebase.ts +188 -0
  48. package/lib/review/review-adapter.js +99 -87
  49. package/lib/review/review-adapter.ts +198 -0
  50. package/lib/review/review-artifacts.js +486 -629
  51. package/lib/review/review-artifacts.ts +622 -0
  52. package/lib/review/review-commands.js +1220 -1373
  53. package/lib/review/review-commands.ts +1579 -0
  54. package/lib/review/review-events.js +544 -886
  55. package/lib/review/review-events.ts +954 -0
  56. package/lib/review/review-loop.js +945 -1020
  57. package/lib/review/review-loop.ts +1174 -0
  58. package/lib/review/review-polling.js +86 -115
  59. package/lib/review/review-polling.ts +194 -0
  60. package/lib/review/review-prompts.js +154 -189
  61. package/lib/review/review-prompts.ts +182 -0
  62. package/lib/review/review-state.js +246 -225
  63. package/lib/review/review-state.ts +353 -0
  64. package/lib/review/review.js +63 -84
  65. package/lib/review/review.ts +138 -0
  66. package/lib/tools/backlog.js +694 -680
  67. package/lib/tools/backlog.ts +835 -0
  68. package/lib/tools/forgejo.js +1270 -1405
  69. package/lib/tools/forgejo.ts +1793 -0
  70. package/lib/tools/gatekeeper.js +106 -96
  71. package/lib/tools/gatekeeper.ts +124 -0
  72. package/lib/tools/redgreen.js +200 -181
  73. package/lib/tools/redgreen.ts +221 -0
  74. package/lib/tools/sessions.js +58 -52
  75. package/lib/tools/sessions.ts +81 -0
  76. package/lib/tools/setup-review.js +902 -975
  77. package/lib/tools/setup-review.ts +1152 -0
  78. package/package.json +4 -4
  79. 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;