nightralph 0.0.2 → 0.0.3
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.
- package/README.md +106 -33
- package/dist/index.js +80 -22
- package/dist/index.js.map +2 -2
- package/dist/merge.js +194 -0
- package/dist/merge.js.map +7 -0
- package/dist/meta.json +183 -17
- package/dist/orchestrator.js +459 -44
- package/dist/orchestrator.js.map +2 -2
- package/dist/progress.js +164 -0
- package/dist/progress.js.map +7 -0
- package/dist/resolve.js +16 -8
- package/dist/resolve.js.map +2 -2
- package/dist/setup.js +33 -5
- package/dist/setup.js.map +2 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/merge.d.ts +25 -0
- package/dist/src/merge.d.ts.map +1 -0
- package/dist/src/orchestrator.d.ts +27 -3
- package/dist/src/orchestrator.d.ts.map +1 -1
- package/dist/src/progress.d.ts +27 -0
- package/dist/src/progress.d.ts.map +1 -0
- package/dist/src/resolve.d.ts +2 -1
- package/dist/src/resolve.d.ts.map +1 -1
- package/dist/src/setup.d.ts +1 -0
- package/dist/src/setup.d.ts.map +1 -1
- package/dist/src/worktree.d.ts +18 -0
- package/dist/src/worktree.d.ts.map +1 -0
- package/dist/worktree.js +139 -0
- package/dist/worktree.js.map +7 -0
- package/package.json +8 -4
- package/.claude/settings.local.json +0 -5
- package/.github/dependabot.yml +0 -28
- package/.github/workflows/nodejs.yml +0 -30
- package/AGENTS.md +0 -60
- package/CLAUDE.md +0 -1
- package/PROMPT.md +0 -95
- package/WIP.md +0 -5
- package/dist/test/integration.test.js +0 -848
- package/dist/test/integration.test.js.map +0 -7
- package/dist/test/orchestrator.test.js +0 -749
- package/dist/test/orchestrator.test.js.map +0 -7
- package/dist/test/setup.test.js +0 -574
- package/dist/test/setup.test.js.map +0 -7
- package/docs/README.md +0 -12
- package/docs/agents/domain.md +0 -36
- package/docs/agents/issue-tracker.md +0 -30
- package/docs/agents/triage-labels.md +0 -15
- package/docs/implementation-plans/2026-08-27-issue-tracker-choice/phase-2-future-work.md +0 -144
- package/docs/implementation-plans/2026-08-27-issue-tracker-choice/phase_01.md +0 -292
- package/docs/implementation-plans/2026-08-27-issue-tracker-choice/phase_02.md +0 -212
- package/docs/implementation-plans/2026-08-27-issue-tracker-choice/test-requirements.md +0 -203
- package/docs/skills.md +0 -58
- package/docs/test-plans/2026-08-27-issue-tracker-choice.md +0 -95
- package/eslint.config.js +0 -142
- package/lib.es5.d.ts +0 -19
- package/progress.log +0 -190
- package/ralph_claude.sh +0 -263
- package/scripts/clone-skills.sh +0 -52
- package/specs/prd.json +0 -172
- package/src/docs-templates/domain.md +0 -36
- package/src/docs-templates/issue-tracker-github.md +0 -228
- package/src/docs-templates/issue-tracker.md +0 -30
- package/src/docs-templates/triage-labels.md +0 -15
- package/src/index.ts +0 -184
- package/src/orchestrator.ts +0 -324
- package/src/resolve.ts +0 -73
- package/src/setup.ts +0 -157
- package/src/skills/domain-modeling/ADR-FORMAT.md +0 -47
- package/src/skills/domain-modeling/CONTEXT-FORMAT.md +0 -60
- package/src/skills/domain-modeling/SKILL.md +0 -74
- package/src/skills/domain-modeling/agents/openai.yaml +0 -3
- package/src/skills/grill/SKILL.md +0 -7
- package/src/skills/grill/agents/openai.yaml +0 -5
- package/src/skills/grilling/SKILL.md +0 -28
- package/src/skills/grilling/agents/openai.yaml +0 -3
- package/src/skills/tdd/SKILL.md +0 -38
- package/src/skills/tdd/agents/openai.yaml +0 -3
- package/src/skills/tdd/mocking.md +0 -59
- package/src/skills/tdd/tests.md +0 -77
- package/src/skills/to-spec/SKILL.md +0 -75
- package/src/skills/to-spec/agents/openai.yaml +0 -5
- package/src/skills/to-tickets/SKILL.md +0 -105
- package/src/skills/to-tickets/agents/openai.yaml +0 -5
- package/src/skills/upstream.json +0 -5
- package/tasks/prd-integration-test-coverage.md +0 -243
- package/test/integration.test.ts +0 -636
- package/test/mock-agent-echo-args.js +0 -4
- package/test/mock-agent-fail.js +0 -3
- package/test/mock-agent-pass.js +0 -3
- package/test/orchestrator.test.ts +0 -609
- package/test/setup.test.ts +0 -417
- package/tsconfig.build.json +0 -7
- package/tsconfig.json +0 -31
package/dist/src/resolve.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
export declare function getScriptDir(metaUrl: string): string;
|
|
1
2
|
export declare function findFeatureDirs(cwd: string): {
|
|
2
3
|
name: string;
|
|
3
4
|
dir: string;
|
|
4
5
|
spec: string;
|
|
5
6
|
}[];
|
|
6
|
-
export declare function resolveIssuesDir(
|
|
7
|
+
export declare function resolveIssuesDir(specName: string | undefined, cwd?: string): Promise<{
|
|
7
8
|
dir: string;
|
|
8
9
|
spec: string;
|
|
9
10
|
}>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../src/resolve.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../src/resolve.ts"],"names":[],"mappings":"AAKA,wBAAgB,YAAY,CAAE,OAAO,EAAC,MAAM,GAAE,MAAM,CAEnD;AAED,wBAAgB,eAAe,CAAE,GAAG,EAAC,MAAM,GAAE;IACzC,IAAI,EAAC,MAAM,CAAC;IACZ,GAAG,EAAC,MAAM,CAAC;IACX,IAAI,EAAC,MAAM,CAAA;CACd,EAAE,CAwBF;AAED,wBAAsB,gBAAgB,CAClC,QAAQ,EAAC,MAAM,GAAC,SAAS,EACzB,GAAG,GAAC,MAAsB,GAC5B,OAAO,CAAC;IAAE,GAAG,EAAC,MAAM,CAAC;IAAC,IAAI,EAAC,MAAM,CAAA;CAAE,CAAC,CAmCrC"}
|
package/dist/src/setup.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export declare const SKILL_DIRS: readonly ["grill", "grilling", "domain-modeling", "to-spec", "to-tickets", "tdd"];
|
|
2
2
|
export declare const DOC_TEMPLATES: readonly ["triage-labels.md", "domain.md"];
|
|
3
|
+
export declare function writeManagedSection(filePath: string, content: string): void;
|
|
3
4
|
export declare function checkGhAuth(): boolean;
|
|
4
5
|
export type TrackerKind = 'github' | 'local';
|
|
5
6
|
export type SetupOpts = {
|
package/dist/src/setup.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/setup.ts"],"names":[],"mappings":"AAYA,eAAO,MAAM,UAAU,mFAGb,CAAA;AAEV,eAAO,MAAM,aAAa,4CAGhB,CAAA;
|
|
1
|
+
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/setup.ts"],"names":[],"mappings":"AAYA,eAAO,MAAM,UAAU,mFAGb,CAAA;AAEV,eAAO,MAAM,aAAa,4CAGhB,CAAA;AAKV,wBAAgB,mBAAmB,CAC/B,QAAQ,EAAC,MAAM,EACf,OAAO,EAAC,MAAM,GAChB,IAAI,CA0BL;AAED,wBAAgB,WAAW,IAAI,OAAO,CAOrC;AAED,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAC,OAAO,CAAA;AAE1C,MAAM,MAAM,SAAS,GAAG;IACpB,gBAAgB,EAAC,MAAM,CAAA;IACvB,gBAAgB,EAAC,MAAM,CAAA;IACvB,UAAU,EAAC,MAAM,CAAA;IACjB,MAAM,CAAC,EAAC,OAAO,CAAA;IACf,OAAO,EAAC,WAAW,CAAA;CACtB,CAAA;AAOD,wBAAgB,KAAK,CAAE,IAAI,EAAC,SAAS,GAAE,IAAI,CA8G1C"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Ticket } from './orchestrator.js';
|
|
2
|
+
export declare function getRepoRoot(): string;
|
|
3
|
+
export declare function getRepoName(): string;
|
|
4
|
+
export declare function getCurrentBranch(): string;
|
|
5
|
+
export declare function createWorktree(opts: {
|
|
6
|
+
repoRoot: string;
|
|
7
|
+
repoName: string;
|
|
8
|
+
baseBranch: string;
|
|
9
|
+
ticket: Ticket;
|
|
10
|
+
}): Promise<{
|
|
11
|
+
worktreePath: string;
|
|
12
|
+
branchName: string;
|
|
13
|
+
}>;
|
|
14
|
+
export declare function removeWorktree(worktreePath: string): Promise<void>;
|
|
15
|
+
export declare function hasNewCommits(repoRoot: string, base: string, branch: string): boolean;
|
|
16
|
+
export declare function isDirty(cwd: string): boolean;
|
|
17
|
+
export declare function listWorktrees(repoRoot: string): Promise<Array<string>>;
|
|
18
|
+
//# sourceMappingURL=worktree.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worktree.d.ts","sourceRoot":"","sources":["../../src/worktree.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAI/C,wBAAgB,WAAW,IAAI,MAAM,CAOpC;AAED,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAED,wBAAgB,gBAAgB,IAAI,MAAM,CAOzC;AAkBD,wBAAsB,cAAc,CAChC,IAAI,EAAC;IACD,QAAQ,EAAC,MAAM,CAAA;IACf,QAAQ,EAAC,MAAM,CAAA;IACf,UAAU,EAAC,MAAM,CAAA;IACjB,MAAM,EAAC,MAAM,CAAA;CAChB,GACH,OAAO,CAAC;IAAE,YAAY,EAAC,MAAM,CAAC;IAAC,UAAU,EAAC,MAAM,CAAA;CAAE,CAAC,CA2DpD;AAED,wBAAsB,cAAc,CAChC,YAAY,EAAC,MAAM,GACrB,OAAO,CAAC,IAAI,CAAC,CAOd;AAED,wBAAgB,aAAa,CACzB,QAAQ,EAAC,MAAM,EACf,IAAI,EAAC,MAAM,EACX,MAAM,EAAC,MAAM,GACf,OAAO,CAOR;AAED,wBAAgB,OAAO,CAAE,GAAG,EAAC,MAAM,GAAE,OAAO,CAO3C;AAED,wBAAsB,aAAa,CAC/B,QAAQ,EAAC,MAAM,GACjB,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAWvB"}
|
package/dist/worktree.js
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
|
+
import { execFile, execFileSync } from "node:child_process";
|
|
4
|
+
import { promisify } from "node:util";
|
|
5
|
+
import { basename, join } from "node:path";
|
|
6
|
+
import { existsSync } from "node:fs";
|
|
7
|
+
const execFileAsync = promisify(execFile);
|
|
8
|
+
function getRepoRoot() {
|
|
9
|
+
const stdout = execFileSync(
|
|
10
|
+
"git",
|
|
11
|
+
["rev-parse", "--show-toplevel"],
|
|
12
|
+
{ encoding: "utf8" }
|
|
13
|
+
);
|
|
14
|
+
return stdout.trim();
|
|
15
|
+
}
|
|
16
|
+
__name(getRepoRoot, "getRepoRoot");
|
|
17
|
+
function getRepoName() {
|
|
18
|
+
return basename(getRepoRoot());
|
|
19
|
+
}
|
|
20
|
+
__name(getRepoName, "getRepoName");
|
|
21
|
+
function getCurrentBranch() {
|
|
22
|
+
const stdout = execFileSync(
|
|
23
|
+
"git",
|
|
24
|
+
["rev-parse", "--abbrev-ref", "HEAD"],
|
|
25
|
+
{ encoding: "utf8" }
|
|
26
|
+
);
|
|
27
|
+
return stdout.trim();
|
|
28
|
+
}
|
|
29
|
+
__name(getCurrentBranch, "getCurrentBranch");
|
|
30
|
+
async function branchExists(repoRoot, branchName) {
|
|
31
|
+
try {
|
|
32
|
+
await execFileAsync(
|
|
33
|
+
"git",
|
|
34
|
+
["show-ref", "--verify", "--quiet", `refs/heads/${branchName}`],
|
|
35
|
+
{ cwd: repoRoot }
|
|
36
|
+
);
|
|
37
|
+
return true;
|
|
38
|
+
} catch {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
__name(branchExists, "branchExists");
|
|
43
|
+
async function createWorktree(opts) {
|
|
44
|
+
const { repoRoot, repoName, baseBranch, ticket } = opts;
|
|
45
|
+
const branchName = `${repoName}/${String(
|
|
46
|
+
ticket.num
|
|
47
|
+
).padStart(2, "0")}-${ticket.slug}`;
|
|
48
|
+
const worktreePath = join(
|
|
49
|
+
repoRoot,
|
|
50
|
+
"..",
|
|
51
|
+
`${repoName}.${String(
|
|
52
|
+
ticket.num
|
|
53
|
+
).padStart(2, "0")}-${ticket.slug}`
|
|
54
|
+
);
|
|
55
|
+
if (existsSync(worktreePath)) {
|
|
56
|
+
try {
|
|
57
|
+
await execFileAsync(
|
|
58
|
+
"git",
|
|
59
|
+
["worktree", "remove", "--force", worktreePath],
|
|
60
|
+
{ cwd: repoRoot }
|
|
61
|
+
);
|
|
62
|
+
} catch {
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
try {
|
|
66
|
+
await execFileAsync(
|
|
67
|
+
"git",
|
|
68
|
+
["worktree", "prune"],
|
|
69
|
+
{ cwd: repoRoot }
|
|
70
|
+
);
|
|
71
|
+
} catch {
|
|
72
|
+
}
|
|
73
|
+
if (await branchExists(repoRoot, branchName)) {
|
|
74
|
+
await execFileAsync(
|
|
75
|
+
"git",
|
|
76
|
+
["branch", "-D", branchName],
|
|
77
|
+
{ cwd: repoRoot }
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
await execFileAsync(
|
|
81
|
+
"git",
|
|
82
|
+
[
|
|
83
|
+
"worktree",
|
|
84
|
+
"add",
|
|
85
|
+
"-b",
|
|
86
|
+
branchName,
|
|
87
|
+
worktreePath,
|
|
88
|
+
baseBranch
|
|
89
|
+
],
|
|
90
|
+
{ cwd: repoRoot }
|
|
91
|
+
);
|
|
92
|
+
return { worktreePath, branchName };
|
|
93
|
+
}
|
|
94
|
+
__name(createWorktree, "createWorktree");
|
|
95
|
+
async function removeWorktree(worktreePath) {
|
|
96
|
+
await execFileAsync(
|
|
97
|
+
"git",
|
|
98
|
+
["-C", worktreePath, "worktree", "remove", worktreePath]
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
__name(removeWorktree, "removeWorktree");
|
|
102
|
+
function hasNewCommits(repoRoot, base, branch) {
|
|
103
|
+
const stdout = execFileSync(
|
|
104
|
+
"git",
|
|
105
|
+
["rev-list", "--count", `${base}..${branch}`],
|
|
106
|
+
{ cwd: repoRoot, encoding: "utf8" }
|
|
107
|
+
);
|
|
108
|
+
return Number(stdout.trim()) > 0;
|
|
109
|
+
}
|
|
110
|
+
__name(hasNewCommits, "hasNewCommits");
|
|
111
|
+
function isDirty(cwd) {
|
|
112
|
+
const stdout = execFileSync(
|
|
113
|
+
"git",
|
|
114
|
+
["status", "--porcelain"],
|
|
115
|
+
{ cwd, encoding: "utf8" }
|
|
116
|
+
);
|
|
117
|
+
return stdout.trim().length > 0;
|
|
118
|
+
}
|
|
119
|
+
__name(isDirty, "isDirty");
|
|
120
|
+
async function listWorktrees(repoRoot) {
|
|
121
|
+
const { stdout } = await execFileAsync(
|
|
122
|
+
"git",
|
|
123
|
+
["worktree", "list", "--porcelain"],
|
|
124
|
+
{ cwd: repoRoot }
|
|
125
|
+
);
|
|
126
|
+
return stdout.trim().split("\n").filter((line) => line.startsWith("worktree ")).map((line) => line.substring("worktree ".length));
|
|
127
|
+
}
|
|
128
|
+
__name(listWorktrees, "listWorktrees");
|
|
129
|
+
export {
|
|
130
|
+
createWorktree,
|
|
131
|
+
getCurrentBranch,
|
|
132
|
+
getRepoName,
|
|
133
|
+
getRepoRoot,
|
|
134
|
+
hasNewCommits,
|
|
135
|
+
isDirty,
|
|
136
|
+
listWorktrees,
|
|
137
|
+
removeWorktree
|
|
138
|
+
};
|
|
139
|
+
//# sourceMappingURL=worktree.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/worktree.ts"],
|
|
4
|
+
"sourcesContent": ["import { execFile, execFileSync } from 'node:child_process'\nimport { promisify } from 'node:util'\nimport { basename, join } from 'node:path'\nimport { existsSync } from 'node:fs'\nimport type { Ticket } from './orchestrator.js'\n\nconst execFileAsync = promisify(execFile)\n\nexport function getRepoRoot ():string {\n const stdout = execFileSync(\n 'git',\n ['rev-parse', '--show-toplevel'],\n { encoding:'utf8' }\n )\n return stdout.trim()\n}\n\nexport function getRepoName ():string {\n return basename(getRepoRoot())\n}\n\nexport function getCurrentBranch ():string {\n const stdout = execFileSync(\n 'git',\n ['rev-parse', '--abbrev-ref', 'HEAD'],\n { encoding:'utf8' }\n )\n return stdout.trim()\n}\n\nasync function branchExists (\n repoRoot:string,\n branchName:string\n):Promise<boolean> {\n try {\n await execFileAsync(\n 'git',\n ['show-ref', '--verify', '--quiet', `refs/heads/${branchName}`],\n { cwd:repoRoot }\n )\n return true\n } catch {\n return false\n }\n}\n\nexport async function createWorktree (\n opts:{\n repoRoot:string\n repoName:string\n baseBranch:string\n ticket:Ticket\n }\n):Promise<{ worktreePath:string; branchName:string }> {\n const { repoRoot, repoName, baseBranch, ticket } = opts\n const branchName = `${repoName}/${String(\n ticket.num\n ).padStart(2, '0')}-${ticket.slug}`\n const worktreePath = join(\n repoRoot,\n '..',\n `${repoName}.${String(\n ticket.num\n ).padStart(2, '0')}-${ticket.slug}`\n )\n\n if (existsSync(worktreePath)) {\n try {\n await execFileAsync(\n 'git',\n ['worktree', 'remove', '--force', worktreePath],\n { cwd:repoRoot }\n )\n } catch {\n // directory may not be a registered worktree anymore;\n // prune stale entries below and let worktree add fail\n // loudly if the path is still unusable\n }\n }\n\n try {\n await execFileAsync(\n 'git',\n ['worktree', 'prune'],\n { cwd:repoRoot }\n )\n } catch {\n // best-effort cleanup of stale worktree metadata\n }\n\n if (await branchExists(repoRoot, branchName)) {\n await execFileAsync(\n 'git',\n ['branch', '-D', branchName],\n { cwd:repoRoot }\n )\n }\n\n await execFileAsync(\n 'git',\n [\n 'worktree',\n 'add',\n '-b',\n branchName,\n worktreePath,\n baseBranch,\n ],\n { cwd:repoRoot }\n )\n\n return { worktreePath, branchName }\n}\n\nexport async function removeWorktree (\n worktreePath:string\n):Promise<void> {\n // Use git -C to run the command from the worktree directory context\n // so git can resolve the repository\n await execFileAsync(\n 'git',\n ['-C', worktreePath, 'worktree', 'remove', worktreePath]\n )\n}\n\nexport function hasNewCommits (\n repoRoot:string,\n base:string,\n branch:string\n):boolean {\n const stdout = execFileSync(\n 'git',\n ['rev-list', '--count', `${base}..${branch}`],\n { cwd:repoRoot, encoding:'utf8' }\n )\n return Number(stdout.trim()) > 0\n}\n\nexport function isDirty (cwd:string):boolean {\n const stdout = execFileSync(\n 'git',\n ['status', '--porcelain'],\n { cwd, encoding:'utf8' }\n )\n return stdout.trim().length > 0\n}\n\nexport async function listWorktrees (\n repoRoot:string\n):Promise<Array<string>> {\n const { stdout } = await execFileAsync(\n 'git',\n ['worktree', 'list', '--porcelain'],\n { cwd:repoRoot }\n )\n return stdout\n .trim()\n .split('\\n')\n .filter(line => line.startsWith('worktree '))\n .map(line => line.substring('worktree '.length))\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/package.json
CHANGED
|
@@ -1,26 +1,30 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nightralph",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Orchestrator that runs a single-agent session per issue.",
|
|
6
6
|
"bin": {
|
|
7
7
|
"nightralph": "dist/index.js"
|
|
8
8
|
},
|
|
9
|
+
"files": [
|
|
10
|
+
"dist/**",
|
|
11
|
+
"!dist/test"
|
|
12
|
+
],
|
|
9
13
|
"engines": {
|
|
10
|
-
"node": ">=
|
|
14
|
+
"node": ">=24"
|
|
11
15
|
},
|
|
12
16
|
"scripts": {
|
|
13
17
|
"lint": "eslint \"./**/*.{ts,js}\"",
|
|
14
18
|
"start": "npm run build && node dist/index.js",
|
|
15
19
|
"build": "mkdir -p ./dist && rm -rf ./dist/* && npm run build-esm && npm run copy",
|
|
16
|
-
"build-esm": "esbuild src/index.ts src/orchestrator.ts src/setup.ts src/resolve.ts --format=esm --metafile=dist/meta.json --keep-names --tsconfig=tsconfig.build.json --outdir=./dist --sourcemap && tsc --emitDeclarationOnly --project tsconfig.build.json",
|
|
20
|
+
"build-esm": "esbuild src/index.ts src/orchestrator.ts src/setup.ts src/resolve.ts src/worktree.ts src/progress.ts src/merge.ts --format=esm --metafile=dist/meta.json --keep-names --tsconfig=tsconfig.build.json --outdir=./dist --sourcemap && tsc --emitDeclarationOnly --project tsconfig.build.json",
|
|
17
21
|
"copy": "mkdir -p ./dist/skills ./dist/docs-templates && cp -r ./src/skills/* ./dist/skills && cp -r ./src/docs-templates/* ./dist/docs-templates",
|
|
18
22
|
"clone-skills": "bash scripts/clone-skills.sh",
|
|
19
23
|
"toc": "markdown-toc --maxdepth 3 -i README.md",
|
|
20
24
|
"preversion": "npm run lint",
|
|
21
25
|
"version": "npm run toc",
|
|
22
26
|
"postversion": "git push --follow-tags && npm publish",
|
|
23
|
-
"test": "esbuild test/setup.test.ts test/orchestrator.test.ts test/integration.test.ts --format=esm --bundle --packages=external --outdir=dist/test --sourcemap && node dist/test/setup.test.js && node dist/test/orchestrator.test.js && node dist/test/integration.test.js"
|
|
27
|
+
"test": "esbuild test/setup.test.ts test/orchestrator.test.ts test/worktree.test.ts test/progress.test.ts test/merge.test.ts test/integration.test.ts --format=esm --bundle --packages=external --outdir=dist/test --sourcemap && node dist/test/setup.test.js && node dist/test/orchestrator.test.js && node dist/test/worktree.test.js && node dist/test/progress.test.js && node dist/test/merge.test.js && node dist/test/integration.test.js"
|
|
24
28
|
},
|
|
25
29
|
"dependencies": {
|
|
26
30
|
"@inquirer/prompts": "^8.7.0",
|
package/.github/dependabot.yml
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
version: 2
|
|
2
|
-
updates:
|
|
3
|
-
# Enable version updates for npm
|
|
4
|
-
- package-ecosystem: "npm"
|
|
5
|
-
# Look for `package.json` and `lock` files in the `root` directory
|
|
6
|
-
directory: "/"
|
|
7
|
-
# Check the npm registry for updates every day (weekdays)
|
|
8
|
-
schedule:
|
|
9
|
-
interval: "monthly"
|
|
10
|
-
groups:
|
|
11
|
-
# This is the name of your group. It will be used in PR titles and branch names
|
|
12
|
-
dev-dependencies:
|
|
13
|
-
patterns:
|
|
14
|
-
- "*"
|
|
15
|
-
ignore:
|
|
16
|
-
- dependency-name: "eslint"
|
|
17
|
-
update-types: ["version-update:semver-major"]
|
|
18
|
-
- dependency-name: "eslint*"
|
|
19
|
-
update-types: ["version-update:semver-major"]
|
|
20
|
-
- dependency-name: "typescript-eslint"
|
|
21
|
-
update-types: ["version-update:semver-major"]
|
|
22
|
-
- dependency-name: "neostandard"
|
|
23
|
-
update-types: ["version-update:semver-major"]
|
|
24
|
-
# Enable updates to github actions
|
|
25
|
-
- package-ecosystem: "github-actions"
|
|
26
|
-
directory: "/"
|
|
27
|
-
schedule:
|
|
28
|
-
interval: "monthly"
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
name: Node CI
|
|
2
|
-
|
|
3
|
-
on: [push]
|
|
4
|
-
|
|
5
|
-
jobs:
|
|
6
|
-
build:
|
|
7
|
-
|
|
8
|
-
runs-on: ubuntu-22.04
|
|
9
|
-
timeout-minutes: 5
|
|
10
|
-
|
|
11
|
-
strategy:
|
|
12
|
-
matrix:
|
|
13
|
-
node-version: [25.x]
|
|
14
|
-
|
|
15
|
-
steps:
|
|
16
|
-
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
17
|
-
- name: Use Node.js ${{ matrix.node-version }}
|
|
18
|
-
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
|
19
|
-
with:
|
|
20
|
-
node-version: ${{ matrix.node-version }}
|
|
21
|
-
- name: npm install, build
|
|
22
|
-
run: |
|
|
23
|
-
npm install
|
|
24
|
-
npm run build --if-present
|
|
25
|
-
npm run lint
|
|
26
|
-
env:
|
|
27
|
-
CI: true
|
|
28
|
-
- name: Run tap tests
|
|
29
|
-
run: |
|
|
30
|
-
npm test
|
package/AGENTS.md
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
# nightralph
|
|
2
|
-
|
|
3
|
-
Last verified: 2026-08-27
|
|
4
|
-
|
|
5
|
-
Small orchestrator that runs a single-agent session per issue.
|
|
6
|
-
|
|
7
|
-
## Tech Stack
|
|
8
|
-
- TypeScript, Node >= 18, ESM
|
|
9
|
-
- CLI: yargs + @inquirer/prompts
|
|
10
|
-
- Testing: @substrate-system/tapzero
|
|
11
|
-
|
|
12
|
-
## Commands
|
|
13
|
-
- `npm run build` -- build to dist/
|
|
14
|
-
- `npm test` -- build and run tests
|
|
15
|
-
- `npm run lint` -- eslint
|
|
16
|
-
|
|
17
|
-
## Project Structure
|
|
18
|
-
- `src/index.ts` -- CLI entry point (yargs commands)
|
|
19
|
-
- `src/setup.ts` -- project scaffolding module
|
|
20
|
-
- `src/orchestrator.ts` -- ticket scanning and wave execution
|
|
21
|
-
- `src/skills/` -- bundled skill definitions
|
|
22
|
-
- `src/docs-templates/` -- doc templates copied to target projects
|
|
23
|
-
|
|
24
|
-
## Contracts
|
|
25
|
-
|
|
26
|
-
### setup module (`src/setup.ts`)
|
|
27
|
-
- **Exposes**: `setup(opts)`, `checkGhAuth()`,
|
|
28
|
-
`TrackerKind`, `SetupOpts`, `SKILL_DIRS`, `DOC_TEMPLATES`
|
|
29
|
-
- **TrackerKind**: `'github'|'local'`
|
|
30
|
-
- **SetupOpts.tracker**: required -- selects which
|
|
31
|
-
issue-tracker template is installed and what AGENTS.md
|
|
32
|
-
content is generated in the target project
|
|
33
|
-
- **checkGhAuth()**: returns true when
|
|
34
|
-
`gh auth status` succeeds
|
|
35
|
-
- **DOC_TEMPLATES**: `['triage-labels.md', 'domain.md']` --
|
|
36
|
-
issue-tracker.md is handled separately via tracker selection
|
|
37
|
-
- **Guarantees**: `setup()` always overwrites
|
|
38
|
-
`issue-tracker.md` (not skip-if-exists like other
|
|
39
|
-
templates); always writes AGENTS.md to the target project
|
|
40
|
-
|
|
41
|
-
### CLI (`src/index.ts`)
|
|
42
|
-
- `nightralph setup [--claude]` -- prompts for tracker
|
|
43
|
-
format, then scaffolds skills and docs
|
|
44
|
-
- `nightralph <provider> [options]` -- executes tickets
|
|
45
|
-
|
|
46
|
-
## Agent skills
|
|
47
|
-
|
|
48
|
-
### Issue tracker
|
|
49
|
-
|
|
50
|
-
Issues are tracked as local markdown files under
|
|
51
|
-
`.scratch/`. See `docs/agents/issue-tracker.md`.
|
|
52
|
-
|
|
53
|
-
### Triage labels
|
|
54
|
-
|
|
55
|
-
Default label vocabulary.
|
|
56
|
-
See `docs/agents/triage-labels.md`.
|
|
57
|
-
|
|
58
|
-
### Domain docs
|
|
59
|
-
|
|
60
|
-
Single-context layout. See `docs/agents/domain.md`.
|
package/CLAUDE.md
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
Read @./AGENTS.md and treat its contents as if they were in CLAUDE.md
|
package/PROMPT.md
DELETED
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
# MISSION
|
|
2
|
-
|
|
3
|
-
Build and maintain nightralph -- a small orchestrator CLI that runs
|
|
4
|
-
single-agent sessions per issue.
|
|
5
|
-
|
|
6
|
-
# Role
|
|
7
|
-
You are an expert TypeScript/Node.js engineer specializing in CLI tools,
|
|
8
|
-
process orchestration, and test automation.
|
|
9
|
-
|
|
10
|
-
# Objective
|
|
11
|
-
|
|
12
|
-
Develop and test a CLI orchestrator using:
|
|
13
|
-
|
|
14
|
-
- Runtime: Node >= 18, ESM
|
|
15
|
-
- CLI: yargs for command parsing, @inquirer/prompts for interactive input
|
|
16
|
-
- Build: esbuild (ESM output to dist/)
|
|
17
|
-
- Testing: @substrate-system/tapzero
|
|
18
|
-
|
|
19
|
-
## META INSTRUCTION
|
|
20
|
-
|
|
21
|
-
Before performing any tool call or code change, emit a short, one-line status
|
|
22
|
-
update in the terminal starting with 'LOG: [Action]'. This helps me track your
|
|
23
|
-
progress in the Ralph Loop.
|
|
24
|
-
|
|
25
|
-
## EXECUTION RULES
|
|
26
|
-
|
|
27
|
-
1. READ: At the start of EVERY session, read `specs/prd.json` and `progress.log`.
|
|
28
|
-
2. SCOPE: Pick the highest-priority task where `passes: false` (or missing).
|
|
29
|
-
Work ONLY on that one task. Do not touch or mark any other story.
|
|
30
|
-
3. WRITE TESTS FIRST: Write failing tests for the feature/bug, then implement
|
|
31
|
-
until they pass.
|
|
32
|
-
4. TARGETED TESTING WHILE WORKING:
|
|
33
|
-
- DO NOT run the full suite (`npm test`) for every minor change.
|
|
34
|
-
- DO run only the tests relevant to the file you are editing
|
|
35
|
-
(e.g., `npx vitest run path/to/file.spec.ts`).
|
|
36
|
-
5. VERIFY BEFORE COMMIT (and only then run the full suite):
|
|
37
|
-
- Run `npm run lint`.
|
|
38
|
-
- Run the FULL suite `npm test` ONCE, when you believe the task is complete.
|
|
39
|
-
- If lint or the full suite fails, fix it before committing.
|
|
40
|
-
(Rules 4 and 5 are complementary: targeted tests during the work, one full
|
|
41
|
-
suite run as the final gate. Never run the full suite after every edit.)
|
|
42
|
-
6. DOCUMENT: Append to `progress.log` what changed and any new patterns or
|
|
43
|
-
gotchas discovered (these become context for future sessions).
|
|
44
|
-
7. UPDATE PRD: In `specs/prd.json`, set `passes: true` for the completed story
|
|
45
|
-
ONLY. Leave every other story untouched.
|
|
46
|
-
8. COMMIT: After the full suite passes, commit with a descriptive message like
|
|
47
|
-
`FEATURE: [TaskID] - [Description]`. ALWAYS COMMIT AFTER COMPLETING A TASK —
|
|
48
|
-
an uncommitted change does not count as progress.
|
|
49
|
-
9. ATOMICITY: Complete EXACTLY ONE task per session, then STOP.
|
|
50
|
-
|
|
51
|
-
## CRITICAL: NON-INTERACTIVE MODE
|
|
52
|
-
|
|
53
|
-
This is an autonomous session. You must NEVER:
|
|
54
|
-
- Ask clarifying questions.
|
|
55
|
-
- Wait for user input.
|
|
56
|
-
- Output questions like 'What would you like me to work on?'
|
|
57
|
-
If a detail is genuinely ambiguous, make the most reasonable assumption,
|
|
58
|
-
record it in `progress.log`, and proceed.
|
|
59
|
-
|
|
60
|
-
## Strict Constraints
|
|
61
|
-
|
|
62
|
-
- Do NOT add new dependencies. If you believe one is truly required, do not
|
|
63
|
-
install it -- document the need in `progress.log` and proceed without it.
|
|
64
|
-
- Prefer standard Node.js APIs over third-party alternatives wherever possible.
|
|
65
|
-
- Stay within the tech stack above. Do not introduce other test runners or
|
|
66
|
-
build tools.
|
|
67
|
-
|
|
68
|
-
# Technical Constraints
|
|
69
|
-
|
|
70
|
-
- CLI entry point: `src/index.ts` (yargs commands)
|
|
71
|
-
- Project scaffolding: `src/setup.ts`
|
|
72
|
-
- Ticket scanning and wave execution: `src/orchestrator.ts`
|
|
73
|
-
- Bundled skills: `src/skills/`
|
|
74
|
-
- Doc templates: `src/docs-templates/`
|
|
75
|
-
- Build: `npm run build` (esbuild to dist/)
|
|
76
|
-
- Test: `npm test` (esbuild + node to run tapzero tests)
|
|
77
|
-
- Lint: `npm run lint` (eslint)
|
|
78
|
-
|
|
79
|
-
# Error Handling
|
|
80
|
-
|
|
81
|
-
If you hit a bug you cannot fix this session, document the failure and what you
|
|
82
|
-
tried in `progress.log`, then stop. Do not loop on the same failing approach --
|
|
83
|
-
a future session (with stronger reasoning hints) will pick it up.
|
|
84
|
-
|
|
85
|
-
## STOP CONDITION
|
|
86
|
-
|
|
87
|
-
Once ALL tasks in `specs/prd.json` have `passes: true`, output the EXACT string
|
|
88
|
-
on its own line, as your final message, after the work is verified:
|
|
89
|
-
|
|
90
|
-
<promise>COMPLETE</promise>
|
|
91
|
-
|
|
92
|
-
Do not emit that string in any other context (e.g., while planning or
|
|
93
|
-
explaining) -- the loop treats it as a completion signal only when the PRD also
|
|
94
|
-
shows zero pending tasks, so emitting it early just wastes a check. Do not
|
|
95
|
-
perform any further work once all tasks are verified.
|