@holdpoint/cli 0.1.0-alpha.1 → 0.1.0-alpha.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/dist/index.js +196 -64
- package/dist/index.js.map +1 -1
- package/dist/templates/MASTER_PROMPT.md +15 -15
- package/dist/templates/_base.yaml +1 -1
- package/dist/templates/fullstack.yaml +1 -1
- package/dist/templates/go.yaml +1 -1
- package/dist/templates/nextjs.yaml +1 -1
- package/dist/templates/python.yaml +1 -1
- package/dist/templates/typescript.yaml +1 -1
- package/package.json +8 -7
package/dist/index.js
CHANGED
|
@@ -4,23 +4,42 @@
|
|
|
4
4
|
import { Command } from "commander";
|
|
5
5
|
|
|
6
6
|
// src/commands/init.ts
|
|
7
|
-
import { existsSync as existsSync2, readFileSync, writeFileSync, mkdirSync, copyFileSync } from "fs";
|
|
7
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync, mkdirSync, copyFileSync } from "fs";
|
|
8
8
|
import { join, dirname } from "path";
|
|
9
9
|
import { fileURLToPath } from "url";
|
|
10
10
|
import chalk from "chalk";
|
|
11
11
|
import ora from "ora";
|
|
12
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
buildHookJson,
|
|
14
|
+
buildCheckScript,
|
|
15
|
+
buildConfigJson,
|
|
16
|
+
buildEngine
|
|
17
|
+
} from "@holdpoint/engine-copilot";
|
|
13
18
|
import { buildEngineJson as buildClaudeEngineJson } from "@holdpoint/engine-claude";
|
|
14
19
|
import { buildEngine as buildCursorEngine } from "@holdpoint/engine-cursor";
|
|
20
|
+
import {
|
|
21
|
+
buildHooksJson as buildCodexHooksJson,
|
|
22
|
+
buildCheckScript as buildCodexCheckScript,
|
|
23
|
+
spliceAgentsMd
|
|
24
|
+
} from "@holdpoint/engine-codex";
|
|
15
25
|
import { parseHoldpointYaml } from "@holdpoint/yaml-core";
|
|
16
26
|
|
|
17
27
|
// src/detect.ts
|
|
18
|
-
import { existsSync } from "fs";
|
|
19
|
-
function
|
|
20
|
-
|
|
21
|
-
if (existsSync(".
|
|
22
|
-
if (existsSync(".
|
|
23
|
-
|
|
28
|
+
import { existsSync, readFileSync } from "fs";
|
|
29
|
+
function detectInstalledAgents() {
|
|
30
|
+
const agents = [];
|
|
31
|
+
if (existsSync(".github/hooks/holdpoint.json")) agents.push("copilot");
|
|
32
|
+
if (existsSync(".claude/settings.json")) agents.push("claude");
|
|
33
|
+
if (existsSync(".cursorrules")) {
|
|
34
|
+
try {
|
|
35
|
+
if (readFileSync(".cursorrules", "utf8").includes("Holdpoint Rules")) {
|
|
36
|
+
agents.push("cursor");
|
|
37
|
+
}
|
|
38
|
+
} catch {
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if (existsSync(".codex/holdpoint-check.mjs")) agents.push("codex");
|
|
42
|
+
return agents;
|
|
24
43
|
}
|
|
25
44
|
function detectStack() {
|
|
26
45
|
const hasNext = existsSync("next.config.ts") || existsSync("next.config.js") || existsSync("next.config.mjs");
|
|
@@ -84,35 +103,39 @@ checks:
|
|
|
84
103
|
async function initCommand(options) {
|
|
85
104
|
const spinner = ora("Initialising Holdpoint\u2026").start();
|
|
86
105
|
const stack = options.stack ?? detectStack();
|
|
87
|
-
const
|
|
88
|
-
|
|
106
|
+
const agentOpt = options.agent;
|
|
107
|
+
const agents = !agentOpt || agentOpt === "all" ? ["copilot", "claude", "cursor", "codex"] : [agentOpt];
|
|
108
|
+
spinner.text = `Stack: ${chalk.cyan(stack)} \u2014 installing for: ${chalk.cyan(agents.join(", "))}`;
|
|
89
109
|
let yamlContent = MINIMAL_CHECKS_YAML;
|
|
90
110
|
if (!existsSync2("checks.yaml")) {
|
|
91
111
|
const templatePath = getTemplatePath(stack);
|
|
92
112
|
if (templatePath) {
|
|
93
|
-
yamlContent =
|
|
113
|
+
yamlContent = readFileSync2(templatePath, "utf8");
|
|
94
114
|
}
|
|
95
115
|
writeFileSync("checks.yaml", yamlContent, "utf8");
|
|
96
116
|
} else {
|
|
97
|
-
yamlContent =
|
|
117
|
+
yamlContent = readFileSync2("checks.yaml", "utf8");
|
|
98
118
|
}
|
|
99
119
|
const config = parseHoldpointYaml(yamlContent);
|
|
100
120
|
const generatedDir = ".github/holdpoint/generated";
|
|
101
121
|
mkdirSync(generatedDir, { recursive: true });
|
|
102
122
|
writeFileSync(`${generatedDir}/checks.immutable.json`, buildConfigJson(config), "utf8");
|
|
103
|
-
if (
|
|
123
|
+
if (agents.includes("copilot")) {
|
|
104
124
|
const hooksDir = ".github/hooks";
|
|
105
125
|
mkdirSync(hooksDir, { recursive: true });
|
|
106
126
|
writeFileSync(join(hooksDir, "holdpoint.json"), buildHookJson(config), "utf8");
|
|
107
127
|
writeFileSync(join(hooksDir, "holdpoint-check.mjs"), buildCheckScript(config), "utf8");
|
|
128
|
+
const extDir = ".github/extensions/holdpoint";
|
|
129
|
+
mkdirSync(extDir, { recursive: true });
|
|
130
|
+
writeFileSync(join(extDir, "extension.mjs"), buildEngine(config), "utf8");
|
|
108
131
|
}
|
|
109
|
-
if (
|
|
132
|
+
if (agents.includes("claude")) {
|
|
110
133
|
mkdirSync(".claude", { recursive: true });
|
|
111
134
|
const settingsPath = ".claude/settings.json";
|
|
112
135
|
let existing = {};
|
|
113
136
|
if (existsSync2(settingsPath)) {
|
|
114
137
|
try {
|
|
115
|
-
existing = JSON.parse(
|
|
138
|
+
existing = JSON.parse(readFileSync2(settingsPath, "utf8"));
|
|
116
139
|
} catch {
|
|
117
140
|
}
|
|
118
141
|
}
|
|
@@ -123,11 +146,11 @@ async function initCommand(options) {
|
|
|
123
146
|
"utf8"
|
|
124
147
|
);
|
|
125
148
|
}
|
|
126
|
-
if (
|
|
149
|
+
if (agents.includes("cursor")) {
|
|
127
150
|
const cursorRules = buildCursorEngine(config);
|
|
128
151
|
const cursorPath = ".cursorrules";
|
|
129
152
|
if (existsSync2(cursorPath)) {
|
|
130
|
-
const existing =
|
|
153
|
+
const existing = readFileSync2(cursorPath, "utf8");
|
|
131
154
|
if (!existing.includes("Holdpoint Rules")) {
|
|
132
155
|
writeFileSync(cursorPath, existing + "\n" + cursorRules, "utf8");
|
|
133
156
|
}
|
|
@@ -135,6 +158,14 @@ async function initCommand(options) {
|
|
|
135
158
|
writeFileSync(cursorPath, cursorRules, "utf8");
|
|
136
159
|
}
|
|
137
160
|
}
|
|
161
|
+
if (agents.includes("codex")) {
|
|
162
|
+
mkdirSync(".codex", { recursive: true });
|
|
163
|
+
writeFileSync(".codex/hooks.json", buildCodexHooksJson(config), "utf8");
|
|
164
|
+
writeFileSync(".codex/holdpoint-check.mjs", buildCodexCheckScript(), "utf8");
|
|
165
|
+
const agentsMdPath = "AGENTS.md";
|
|
166
|
+
const existing = existsSync2(agentsMdPath) ? readFileSync2(agentsMdPath, "utf8") : "";
|
|
167
|
+
writeFileSync(agentsMdPath, spliceAgentsMd(existing, config), "utf8");
|
|
168
|
+
}
|
|
138
169
|
if (!existsSync2("MASTER_PROMPT.md")) {
|
|
139
170
|
const guidePath = getMasterPromptPath();
|
|
140
171
|
if (guidePath) {
|
|
@@ -142,7 +173,7 @@ async function initCommand(options) {
|
|
|
142
173
|
} else {
|
|
143
174
|
writeFileSync(
|
|
144
175
|
"MASTER_PROMPT.md",
|
|
145
|
-
"# Holdpoint\n\nRun `npx holdpoint check` before marking any task complete.\nSee `checks.yaml` for the full list of checks.\n",
|
|
176
|
+
"# Holdpoint\n\nRun `npx @holdpoint/cli@alpha check` before marking any task complete.\nSee `checks.yaml` for the full list of checks.\n",
|
|
146
177
|
"utf8"
|
|
147
178
|
);
|
|
148
179
|
}
|
|
@@ -152,15 +183,16 @@ async function initCommand(options) {
|
|
|
152
183
|
${chalk.cyan("Next steps:")}
|
|
153
184
|
1. Edit ${chalk.yellow("checks.yaml")} to customise your eval checkpoints
|
|
154
185
|
2. Commit ${chalk.yellow("checks.yaml")} and the generated engine files
|
|
155
|
-
3. Run ${chalk.yellow("npx holdpoint check")} at any time to validate
|
|
186
|
+
3. Run ${chalk.yellow("npx @holdpoint/cli@alpha check")} at any time to validate
|
|
156
187
|
|
|
157
|
-
Visual builder: ${chalk.yellow("npx holdpoint builder")} (opens localhost:4321)
|
|
158
|
-
Stack: ${chalk.cyan(stack)}
|
|
188
|
+
Visual builder: ${chalk.yellow("npx @holdpoint/cli@alpha builder")} (opens localhost:4321)
|
|
189
|
+
Stack: ${chalk.cyan(stack)} Agents: ${chalk.cyan(agents.join(", "))}
|
|
159
190
|
`);
|
|
160
191
|
}
|
|
161
192
|
|
|
162
193
|
// src/commands/check.ts
|
|
163
|
-
import { existsSync as existsSync5, readFileSync as
|
|
194
|
+
import { existsSync as existsSync5, readFileSync as readFileSync4, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "fs";
|
|
195
|
+
import { join as join4 } from "path";
|
|
164
196
|
import chalk2 from "chalk";
|
|
165
197
|
import ora2 from "ora";
|
|
166
198
|
import { parseHoldpointYaml as parseHoldpointYaml2, matchesWhen } from "@holdpoint/yaml-core";
|
|
@@ -168,19 +200,19 @@ import { runDeterministicChecks } from "@holdpoint/yaml-core/runner";
|
|
|
168
200
|
import { execSync as execSync3 } from "child_process";
|
|
169
201
|
|
|
170
202
|
// src/evolve/scanner.ts
|
|
171
|
-
import { existsSync as existsSync3, readFileSync as
|
|
203
|
+
import { existsSync as existsSync3, readFileSync as readFileSync3, readdirSync } from "fs";
|
|
172
204
|
import { join as join2 } from "path";
|
|
173
205
|
import { execSync } from "child_process";
|
|
174
206
|
function tryReadJson(path) {
|
|
175
207
|
try {
|
|
176
|
-
return JSON.parse(
|
|
208
|
+
return JSON.parse(readFileSync3(path, "utf8"));
|
|
177
209
|
} catch {
|
|
178
210
|
return null;
|
|
179
211
|
}
|
|
180
212
|
}
|
|
181
213
|
function tryReadText(path) {
|
|
182
214
|
try {
|
|
183
|
-
return
|
|
215
|
+
return readFileSync3(path, "utf8");
|
|
184
216
|
} catch {
|
|
185
217
|
return "";
|
|
186
218
|
}
|
|
@@ -523,6 +555,8 @@ function detectStaleChecks(config, repoFiles) {
|
|
|
523
555
|
}
|
|
524
556
|
|
|
525
557
|
// src/commands/check.ts
|
|
558
|
+
var COMMIT_CACHE_PATH = ".holdpoint/checked-commits.json";
|
|
559
|
+
var COMMIT_CACHE_MAX = 100;
|
|
526
560
|
function getStagedFiles() {
|
|
527
561
|
try {
|
|
528
562
|
const out = execSync3("git diff --cached --name-only", {
|
|
@@ -545,12 +579,51 @@ function getAllChangedFiles() {
|
|
|
545
579
|
return [];
|
|
546
580
|
}
|
|
547
581
|
}
|
|
582
|
+
function getLastCommitFiles() {
|
|
583
|
+
try {
|
|
584
|
+
const out = execSync3("git diff --name-only HEAD~1 HEAD", {
|
|
585
|
+
encoding: "utf8",
|
|
586
|
+
stdio: ["pipe", "pipe", "ignore"]
|
|
587
|
+
});
|
|
588
|
+
return out.trim().split("\n").filter(Boolean);
|
|
589
|
+
} catch {
|
|
590
|
+
return [];
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
function getHeadSha() {
|
|
594
|
+
try {
|
|
595
|
+
return execSync3("git rev-parse HEAD", {
|
|
596
|
+
encoding: "utf8",
|
|
597
|
+
stdio: ["pipe", "pipe", "ignore"]
|
|
598
|
+
}).trim();
|
|
599
|
+
} catch {
|
|
600
|
+
return null;
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
function readCommitCache() {
|
|
604
|
+
try {
|
|
605
|
+
const raw = readFileSync4(COMMIT_CACHE_PATH, "utf8");
|
|
606
|
+
const parsed = JSON.parse(raw);
|
|
607
|
+
return new Set(Array.isArray(parsed.verified) ? parsed.verified : []);
|
|
608
|
+
} catch {
|
|
609
|
+
return /* @__PURE__ */ new Set();
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
function recordCommitCache(sha) {
|
|
613
|
+
try {
|
|
614
|
+
const existing = readCommitCache();
|
|
615
|
+
const updated = [sha, ...[...existing].filter((s) => s !== sha)].slice(0, COMMIT_CACHE_MAX);
|
|
616
|
+
mkdirSync2(join4(COMMIT_CACHE_PATH, ".."), { recursive: true });
|
|
617
|
+
writeFileSync2(COMMIT_CACHE_PATH, JSON.stringify({ verified: updated }, null, 2) + "\n", "utf8");
|
|
618
|
+
} catch {
|
|
619
|
+
}
|
|
620
|
+
}
|
|
548
621
|
async function checkCommand(options) {
|
|
549
622
|
if (!existsSync5("checks.yaml")) {
|
|
550
623
|
console.error(chalk2.red("No checks.yaml found. Run `holdpoint init` first."));
|
|
551
624
|
process.exit(1);
|
|
552
625
|
}
|
|
553
|
-
const yamlContent =
|
|
626
|
+
const yamlContent = readFileSync4("checks.yaml", "utf8");
|
|
554
627
|
let config;
|
|
555
628
|
try {
|
|
556
629
|
config = parseHoldpointYaml2(yamlContent);
|
|
@@ -558,7 +631,39 @@ async function checkCommand(options) {
|
|
|
558
631
|
console.error(chalk2.red("Invalid checks.yaml:"), err.message);
|
|
559
632
|
process.exit(1);
|
|
560
633
|
}
|
|
561
|
-
|
|
634
|
+
let changedFiles;
|
|
635
|
+
let headSha = null;
|
|
636
|
+
if (options.staged) {
|
|
637
|
+
const staged = getStagedFiles();
|
|
638
|
+
if (staged.length > 0) {
|
|
639
|
+
changedFiles = staged;
|
|
640
|
+
} else {
|
|
641
|
+
headSha = getHeadSha();
|
|
642
|
+
if (headSha && readCommitCache().has(headSha)) {
|
|
643
|
+
console.log(
|
|
644
|
+
chalk2.green(`\u2713 Commit ${headSha.slice(0, 8)} already verified \u2014 nothing to re-check.`)
|
|
645
|
+
);
|
|
646
|
+
process.exit(0);
|
|
647
|
+
}
|
|
648
|
+
const lastCommit = getLastCommitFiles();
|
|
649
|
+
if (lastCommit.length > 0) {
|
|
650
|
+
changedFiles = lastCommit;
|
|
651
|
+
console.log(
|
|
652
|
+
chalk2.yellow("No staged files. Running checks scoped to the most recent commit's files.")
|
|
653
|
+
);
|
|
654
|
+
} else {
|
|
655
|
+
console.log(chalk2.green("\u2713 No staged changes and no recent commit \u2014 nothing to check."));
|
|
656
|
+
process.exit(0);
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
} else {
|
|
660
|
+
changedFiles = getAllChangedFiles();
|
|
661
|
+
if (changedFiles.length === 0) {
|
|
662
|
+
console.log(
|
|
663
|
+
chalk2.yellow("No changed files detected. Running all checks with no file filter.")
|
|
664
|
+
);
|
|
665
|
+
}
|
|
666
|
+
}
|
|
562
667
|
const guides = Object.entries(config.context?.guides ?? {});
|
|
563
668
|
if (guides.length > 0) {
|
|
564
669
|
console.log(chalk2.cyan("\nProject guides:"));
|
|
@@ -567,9 +672,6 @@ async function checkCommand(options) {
|
|
|
567
672
|
}
|
|
568
673
|
console.log("");
|
|
569
674
|
}
|
|
570
|
-
if (changedFiles.length === 0) {
|
|
571
|
-
console.log(chalk2.yellow("No changed files detected. Running all checks with no file filter."));
|
|
572
|
-
}
|
|
573
675
|
const taskCount = config.checks.filter((c) => c.cmd !== void 0).length;
|
|
574
676
|
const spinner = ora2(`Running ${taskCount} task(s)\u2026`).start();
|
|
575
677
|
const effectiveFiles = changedFiles.length > 0 ? changedFiles : ["__all__"];
|
|
@@ -592,7 +694,7 @@ async function checkCommand(options) {
|
|
|
592
694
|
lines.push(`${staleChecks.length} stale check(s) no longer match your project:`);
|
|
593
695
|
for (const s of staleChecks) lines.push(` - ${s.check.label}: ${s.reason}`);
|
|
594
696
|
}
|
|
595
|
-
lines.push("\nRun: npx holdpoint evolve --apply");
|
|
697
|
+
lines.push("\nRun: npx @holdpoint/cli@alpha evolve --apply");
|
|
596
698
|
results.push({
|
|
597
699
|
check: { id: "__holdpoint_evolve__", label: "Evolve checks with project structure" },
|
|
598
700
|
status: "fail",
|
|
@@ -628,6 +730,9 @@ ${chalk2.cyan("Agent prompts to act on:")}`);
|
|
|
628
730
|
if (failed.length > 0) {
|
|
629
731
|
process.exit(1);
|
|
630
732
|
}
|
|
733
|
+
if (headSha) {
|
|
734
|
+
recordCommitCache(headSha);
|
|
735
|
+
}
|
|
631
736
|
}
|
|
632
737
|
function printResult(result) {
|
|
633
738
|
const icon = result.status === "pass" ? chalk2.green("\u2713") : result.status === "fail" ? chalk2.red("\u2717") : result.status === "skip" ? chalk2.gray("\u25CC") : chalk2.yellow("\u2026");
|
|
@@ -643,7 +748,7 @@ function printResult(result) {
|
|
|
643
748
|
}
|
|
644
749
|
|
|
645
750
|
// src/commands/validate.ts
|
|
646
|
-
import { existsSync as existsSync6, readFileSync as
|
|
751
|
+
import { existsSync as existsSync6, readFileSync as readFileSync5 } from "fs";
|
|
647
752
|
import chalk3 from "chalk";
|
|
648
753
|
import { parseHoldpointYaml as parseHoldpointYaml3, validateConfig } from "@holdpoint/yaml-core";
|
|
649
754
|
async function validateCommand() {
|
|
@@ -651,7 +756,7 @@ async function validateCommand() {
|
|
|
651
756
|
console.error(chalk3.red("No checks.yaml found. Run `holdpoint init` first."));
|
|
652
757
|
process.exit(1);
|
|
653
758
|
}
|
|
654
|
-
const text =
|
|
759
|
+
const text = readFileSync5("checks.yaml", "utf8");
|
|
655
760
|
let config;
|
|
656
761
|
try {
|
|
657
762
|
config = parseHoldpointYaml3(text);
|
|
@@ -677,67 +782,91 @@ async function validateCommand() {
|
|
|
677
782
|
}
|
|
678
783
|
|
|
679
784
|
// src/commands/update.ts
|
|
680
|
-
import { existsSync as existsSync7, readFileSync as
|
|
785
|
+
import { existsSync as existsSync7, readFileSync as readFileSync6, writeFileSync as writeFileSync3, mkdirSync as mkdirSync3 } from "fs";
|
|
681
786
|
import chalk4 from "chalk";
|
|
682
787
|
import ora3 from "ora";
|
|
683
788
|
import { parseHoldpointYaml as parseHoldpointYaml4 } from "@holdpoint/yaml-core";
|
|
684
|
-
import {
|
|
789
|
+
import {
|
|
790
|
+
buildHookJson as buildHookJson2,
|
|
791
|
+
buildCheckScript as buildCheckScript2,
|
|
792
|
+
buildConfigJson as buildConfigJson2,
|
|
793
|
+
buildEngine as buildEngine2
|
|
794
|
+
} from "@holdpoint/engine-copilot";
|
|
685
795
|
import { buildEngineJson as buildClaudeEngineJson2 } from "@holdpoint/engine-claude";
|
|
686
796
|
import { buildEngine as buildCursorEngine2 } from "@holdpoint/engine-cursor";
|
|
797
|
+
import {
|
|
798
|
+
buildHooksJson as buildCodexHooksJson2,
|
|
799
|
+
buildCheckScript as buildCodexCheckScript2,
|
|
800
|
+
spliceAgentsMd as spliceAgentsMd2
|
|
801
|
+
} from "@holdpoint/engine-codex";
|
|
687
802
|
async function updateCommand() {
|
|
688
803
|
if (!existsSync7("checks.yaml")) {
|
|
689
804
|
console.error(chalk4.red("No checks.yaml found. Run `holdpoint init` first."));
|
|
690
805
|
process.exit(1);
|
|
691
806
|
}
|
|
692
807
|
const spinner = ora3("Updating Holdpoint engine files\u2026").start();
|
|
693
|
-
const
|
|
694
|
-
const
|
|
808
|
+
const config = parseHoldpointYaml4(readFileSync6("checks.yaml", "utf8"));
|
|
809
|
+
const detected = detectInstalledAgents();
|
|
810
|
+
const agents = detected.length > 0 ? detected : ["copilot", "claude", "cursor", "codex"];
|
|
695
811
|
const generatedDir = ".github/holdpoint/generated";
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
if (
|
|
812
|
+
mkdirSync3(generatedDir, { recursive: true });
|
|
813
|
+
writeFileSync3(`${generatedDir}/checks.immutable.json`, buildConfigJson2(config), "utf8");
|
|
814
|
+
if (agents.includes("copilot")) {
|
|
699
815
|
const hooksDir = ".github/hooks";
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
816
|
+
mkdirSync3(hooksDir, { recursive: true });
|
|
817
|
+
writeFileSync3(`${hooksDir}/holdpoint.json`, buildHookJson2(config), "utf8");
|
|
818
|
+
writeFileSync3(`${hooksDir}/holdpoint-check.mjs`, buildCheckScript2(config), "utf8");
|
|
819
|
+
const extDir = ".github/extensions/holdpoint";
|
|
820
|
+
mkdirSync3(extDir, { recursive: true });
|
|
821
|
+
writeFileSync3(`${extDir}/extension.mjs`, buildEngine2(config), "utf8");
|
|
704
822
|
}
|
|
705
|
-
if (
|
|
706
|
-
|
|
823
|
+
if (agents.includes("claude")) {
|
|
824
|
+
mkdirSync3(".claude", { recursive: true });
|
|
707
825
|
const settingsPath = ".claude/settings.json";
|
|
708
826
|
let existing = {};
|
|
709
827
|
if (existsSync7(settingsPath)) {
|
|
710
828
|
try {
|
|
711
|
-
existing = JSON.parse(
|
|
829
|
+
existing = JSON.parse(readFileSync6(settingsPath, "utf8"));
|
|
712
830
|
} catch {
|
|
713
831
|
}
|
|
714
832
|
}
|
|
715
833
|
const hooks = JSON.parse(buildClaudeEngineJson2(config));
|
|
716
|
-
|
|
834
|
+
writeFileSync3(
|
|
835
|
+
settingsPath,
|
|
836
|
+
JSON.stringify({ ...existing, hooks: hooks.hooks }, null, 2) + "\n"
|
|
837
|
+
);
|
|
717
838
|
}
|
|
718
|
-
if (
|
|
839
|
+
if (agents.includes("cursor")) {
|
|
719
840
|
const cursorRules = buildCursorEngine2(config);
|
|
720
841
|
const cursorPath = ".cursorrules";
|
|
721
842
|
if (existsSync7(cursorPath)) {
|
|
722
|
-
const content =
|
|
843
|
+
const content = readFileSync6(cursorPath, "utf8");
|
|
723
844
|
const start = content.indexOf("# \u2500\u2500\u2500 Holdpoint Rules");
|
|
724
845
|
const end = content.indexOf("# \u2500\u2500\u2500 End Holdpoint Rules \u2500\u2500\u2500");
|
|
725
846
|
if (start !== -1 && end !== -1) {
|
|
726
847
|
const afterEnd = content.indexOf("\n", end);
|
|
727
848
|
const updated = content.slice(0, start) + cursorRules + content.slice(afterEnd === -1 ? end : afterEnd + 1);
|
|
728
|
-
|
|
849
|
+
writeFileSync3(cursorPath, updated);
|
|
729
850
|
} else {
|
|
730
|
-
|
|
851
|
+
writeFileSync3(cursorPath, content + "\n" + cursorRules);
|
|
731
852
|
}
|
|
732
853
|
}
|
|
733
854
|
}
|
|
855
|
+
if (agents.includes("codex")) {
|
|
856
|
+
mkdirSync3(".codex", { recursive: true });
|
|
857
|
+
writeFileSync3(".codex/hooks.json", buildCodexHooksJson2(config), "utf8");
|
|
858
|
+
writeFileSync3(".codex/holdpoint-check.mjs", buildCodexCheckScript2(), "utf8");
|
|
859
|
+
const agentsMdPath = "AGENTS.md";
|
|
860
|
+
const existing = existsSync7(agentsMdPath) ? readFileSync6(agentsMdPath, "utf8") : "";
|
|
861
|
+
writeFileSync3(agentsMdPath, spliceAgentsMd2(existing, config), "utf8");
|
|
862
|
+
}
|
|
734
863
|
spinner.succeed(chalk4.green("Engine files updated from current checks.yaml"));
|
|
735
864
|
}
|
|
736
865
|
|
|
737
866
|
// src/commands/build.ts
|
|
738
867
|
import { createServer } from "http";
|
|
739
868
|
import { createReadStream, existsSync as existsSync8 } from "fs";
|
|
740
|
-
import { join as
|
|
869
|
+
import { join as join5, extname, dirname as dirname2 } from "path";
|
|
741
870
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
742
871
|
import { execSync as execSync4 } from "child_process";
|
|
743
872
|
import chalk5 from "chalk";
|
|
@@ -763,7 +892,7 @@ function serveFile(res, filePath) {
|
|
|
763
892
|
function handleRequest(req, res, uiDir) {
|
|
764
893
|
const url = (req.url ?? "/").split("?")[0] ?? "/";
|
|
765
894
|
if (url === "/__holdpoint/initial-yaml") {
|
|
766
|
-
const checksPath =
|
|
895
|
+
const checksPath = join5(process.cwd(), "checks.yaml");
|
|
767
896
|
if (existsSync8(checksPath)) {
|
|
768
897
|
res.writeHead(200, { "Content-Type": "text/yaml; charset=utf-8" });
|
|
769
898
|
createReadStream(checksPath).pipe(res);
|
|
@@ -773,13 +902,13 @@ function handleRequest(req, res, uiDir) {
|
|
|
773
902
|
}
|
|
774
903
|
return;
|
|
775
904
|
}
|
|
776
|
-
const candidate =
|
|
777
|
-
const filePath = existsSync8(candidate) ? candidate :
|
|
905
|
+
const candidate = join5(uiDir, url === "/" ? "index.html" : url);
|
|
906
|
+
const filePath = existsSync8(candidate) ? candidate : join5(uiDir, "index.html");
|
|
778
907
|
serveFile(res, filePath);
|
|
779
908
|
}
|
|
780
909
|
async function buildCommand() {
|
|
781
910
|
const port = 4321;
|
|
782
|
-
const uiDir =
|
|
911
|
+
const uiDir = join5(__dirname2, "builder-ui");
|
|
783
912
|
if (!existsSync8(uiDir)) {
|
|
784
913
|
console.error(chalk5.red("\u2717 Builder UI not found.\n"));
|
|
785
914
|
console.log(chalk5.dim(" This is unexpected for a published build of @holdpoint/cli."));
|
|
@@ -810,7 +939,7 @@ ${chalk5.green("\u2713")} Holdpoint builder running at ${chalk5.cyan(`http://loc
|
|
|
810
939
|
}
|
|
811
940
|
|
|
812
941
|
// src/commands/evolve.ts
|
|
813
|
-
import { existsSync as existsSync9, readFileSync as
|
|
942
|
+
import { existsSync as existsSync9, readFileSync as readFileSync7, writeFileSync as writeFileSync4 } from "fs";
|
|
814
943
|
import { execSync as execSync5 } from "child_process";
|
|
815
944
|
import chalk6 from "chalk";
|
|
816
945
|
import ora4 from "ora";
|
|
@@ -843,7 +972,7 @@ async function evolveCommand(options) {
|
|
|
843
972
|
const cwd = process.cwd();
|
|
844
973
|
const profile = scanProject(cwd);
|
|
845
974
|
const repoFiles = getRepoFiles(cwd);
|
|
846
|
-
const yamlContent =
|
|
975
|
+
const yamlContent = readFileSync7("checks.yaml", "utf8");
|
|
847
976
|
let config;
|
|
848
977
|
try {
|
|
849
978
|
config = parseHoldpointYaml5(yamlContent);
|
|
@@ -916,7 +1045,7 @@ async function evolveCommand(options) {
|
|
|
916
1045
|
console.log(
|
|
917
1046
|
chalk6.red(`
|
|
918
1047
|
\u2717 checks.yaml is out of sync with the project profile.`) + `
|
|
919
|
-
Run ${chalk6.bold("npx holdpoint evolve --apply")} to apply these changes.`
|
|
1048
|
+
Run ${chalk6.bold("npx @holdpoint/cli@alpha evolve --apply")} to apply these changes.`
|
|
920
1049
|
);
|
|
921
1050
|
process.exit(1);
|
|
922
1051
|
}
|
|
@@ -957,10 +1086,10 @@ async function evolveCommand(options) {
|
|
|
957
1086
|
};
|
|
958
1087
|
const header = extractHeader(yamlContent);
|
|
959
1088
|
const newYaml = withHeader(header, generateYaml(updatedConfig));
|
|
960
|
-
|
|
1089
|
+
writeFileSync4("checks.yaml", newYaml, "utf8");
|
|
961
1090
|
applySpinner.text = "Running holdpoint update\u2026";
|
|
962
1091
|
try {
|
|
963
|
-
execSync5("npx holdpoint update", { stdio: "pipe" });
|
|
1092
|
+
execSync5("npx @holdpoint/cli@alpha update", { stdio: "pipe" });
|
|
964
1093
|
} catch {
|
|
965
1094
|
applySpinner.warn(
|
|
966
1095
|
chalk6.yellow("checks.yaml updated, but `holdpoint update` failed \u2014 run it manually.")
|
|
@@ -984,8 +1113,11 @@ function printAppliedSummary(added, wrapped) {
|
|
|
984
1113
|
|
|
985
1114
|
// src/index.ts
|
|
986
1115
|
var program = new Command();
|
|
987
|
-
program.name("holdpoint").description("Universal eval-guard for AI coding agents (alpha)").version("0.1.0-alpha.
|
|
988
|
-
program.command("init").description("Initialise Holdpoint in the current project").option("--stack <stack>", "Stack type: typescript | python | nextjs | fullstack").option(
|
|
1116
|
+
program.name("holdpoint").description("Universal eval-guard for AI coding agents (alpha)").version("0.1.0-alpha.2");
|
|
1117
|
+
program.command("init").description("Initialise Holdpoint in the current project").option("--stack <stack>", "Stack type: typescript | python | nextjs | fullstack").option(
|
|
1118
|
+
"--agent <agent>",
|
|
1119
|
+
"Agent to install for: copilot | claude | cursor | codex (default: all four)"
|
|
1120
|
+
).action(initCommand);
|
|
989
1121
|
program.command("check").description("Run task checks from checks.yaml").option("--staged", "Only check against git-staged files").action(checkCommand);
|
|
990
1122
|
program.command("validate").description("Validate checks.yaml schema and print any errors").action(validateCommand);
|
|
991
1123
|
program.command("update").description("Regenerate engine files from current checks.yaml (preserves checks.yaml)").action(updateCommand);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/commands/init.ts","../src/detect.ts","../src/commands/check.ts","../src/evolve/scanner.ts","../src/evolve/templates.ts","../src/evolve/dead-checker.ts","../src/commands/validate.ts","../src/commands/update.ts","../src/commands/build.ts","../src/commands/evolve.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { initCommand } from \"./commands/init.js\";\nimport { checkCommand } from \"./commands/check.js\";\nimport { validateCommand } from \"./commands/validate.js\";\nimport { updateCommand } from \"./commands/update.js\";\nimport { buildCommand } from \"./commands/build.js\";\nimport { evolveCommand } from \"./commands/evolve.js\";\n\nconst program = new Command();\n\nprogram\n .name(\"holdpoint\")\n .description(\"Universal eval-guard for AI coding agents (alpha)\")\n .version(\"0.1.0-alpha.1\");\n\nprogram\n .command(\"init\")\n .description(\"Initialise Holdpoint in the current project\")\n .option(\"--stack <stack>\", \"Stack type: typescript | python | nextjs | fullstack\")\n .option(\"--agent <agent>\", \"Agent type: copilot | claude | cursor\")\n .action(initCommand);\n\nprogram\n .command(\"check\")\n .description(\"Run task checks from checks.yaml\")\n .option(\"--staged\", \"Only check against git-staged files\")\n .action(checkCommand);\n\nprogram\n .command(\"validate\")\n .description(\"Validate checks.yaml schema and print any errors\")\n .action(validateCommand);\n\nprogram\n .command(\"update\")\n .description(\"Regenerate engine files from current checks.yaml (preserves checks.yaml)\")\n .action(updateCommand);\n\nprogram\n .command(\"builder\")\n .description(\"Open the visual builder UI on localhost:4321\")\n .action(buildCommand);\n\nprogram\n .command(\"evolve\")\n .description(\"Scan project and propose (or apply) new checks to keep checks.yaml in sync\")\n .option(\"--apply\", \"Write proposed changes to checks.yaml and regenerate engine files\")\n .action(evolveCommand);\n\nprogram.parse();\n","import { existsSync, readFileSync, writeFileSync, mkdirSync, copyFileSync } from \"node:fs\";\nimport { join, dirname } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport { buildHookJson, buildCheckScript, buildConfigJson } from \"@holdpoint/engine-copilot\";\nimport { buildEngineJson as buildClaudeEngineJson } from \"@holdpoint/engine-claude\";\nimport { buildEngine as buildCursorEngine } from \"@holdpoint/engine-cursor\";\nimport { parseHoldpointYaml } from \"@holdpoint/yaml-core\";\nimport type { AgentType, StackType } from \"@holdpoint/types\";\nimport { detectAgent, detectStack } from \"../detect.js\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\nfunction getTemplatePath(stack: StackType): string {\n const name = stack === \"unknown\" ? \"_base\" : stack;\n const candidates = [\n join(__dirname, \"templates\", `${name}.yaml`), // dist/templates/ (published package)\n join(__dirname, \"../../../templates\", `${name}.yaml`), // monorepo dev fallback\n join(process.cwd(), \"templates\", `${name}.yaml`), // cwd fallback\n ];\n for (const p of candidates) {\n if (existsSync(p)) return p;\n }\n return \"\";\n}\n\nfunction getMasterPromptPath(): string {\n const candidates = [\n join(__dirname, \"templates/MASTER_PROMPT.md\"), // dist/templates/ (published package)\n join(__dirname, \"../../../templates/MASTER_PROMPT.md\"), // monorepo dev fallback\n join(process.cwd(), \"templates/MASTER_PROMPT.md\"), // cwd fallback\n ];\n for (const p of candidates) {\n if (existsSync(p)) return p;\n }\n return \"\";\n}\n\nconst MINIMAL_CHECKS_YAML = `version: 1\ncontext:\n guides: {}\nconditions: []\nchecks:\n - id: lint\n label: \"Lint codebase\"\n cmd: \"echo 'Add your lint command here'\"\n\n - id: jsdoc\n label: \"JSDoc on changed public functions\"\n prompt: \"Ensure all changed public functions and exports have JSDoc comments.\"\n`;\n\nexport async function initCommand(options: { stack?: string; agent?: string }): Promise<void> {\n const spinner = ora(\"Initialising Holdpoint…\").start();\n\n const stack = (options.stack as StackType | undefined) ?? detectStack();\n const agent = (options.agent as AgentType | undefined) ?? detectAgent();\n\n spinner.text = `Detected stack: ${chalk.cyan(stack)}, agent: ${chalk.cyan(agent)}`;\n\n // 1. Read or create checks.yaml\n let yamlContent = MINIMAL_CHECKS_YAML;\n if (!existsSync(\"checks.yaml\")) {\n const templatePath = getTemplatePath(stack);\n if (templatePath) {\n yamlContent = readFileSync(templatePath, \"utf8\");\n }\n writeFileSync(\"checks.yaml\", yamlContent, \"utf8\");\n } else {\n yamlContent = readFileSync(\"checks.yaml\", \"utf8\");\n }\n\n const config = parseHoldpointYaml(yamlContent);\n\n // 2. Write checks.immutable.json — read by holdpoint-check.mjs at runtime\n const generatedDir = \".github/holdpoint/generated\";\n mkdirSync(generatedDir, { recursive: true });\n writeFileSync(`${generatedDir}/checks.immutable.json`, buildConfigJson(config), \"utf8\");\n\n // 3. Install engine files\n if (agent === \"copilot\" || agent === \"unknown\") {\n const hooksDir = \".github/hooks\";\n mkdirSync(hooksDir, { recursive: true });\n writeFileSync(join(hooksDir, \"holdpoint.json\"), buildHookJson(config), \"utf8\");\n writeFileSync(join(hooksDir, \"holdpoint-check.mjs\"), buildCheckScript(config), \"utf8\");\n }\n\n if (agent === \"claude\") {\n mkdirSync(\".claude\", { recursive: true });\n const settingsPath = \".claude/settings.json\";\n let existing: Record<string, unknown> = {};\n if (existsSync(settingsPath)) {\n try {\n existing = JSON.parse(readFileSync(settingsPath, \"utf8\")) as Record<string, unknown>;\n } catch {\n /* ignore */\n }\n }\n const holdpointHooks = JSON.parse(buildClaudeEngineJson(config)) as Record<string, unknown>;\n writeFileSync(\n settingsPath,\n JSON.stringify({ ...existing, hooks: holdpointHooks.hooks }, null, 2),\n \"utf8\",\n );\n }\n\n if (agent === \"cursor\") {\n const cursorRules = buildCursorEngine(config);\n const cursorPath = \".cursorrules\";\n if (existsSync(cursorPath)) {\n const existing = readFileSync(cursorPath, \"utf8\");\n if (!existing.includes(\"Holdpoint Rules\")) {\n writeFileSync(cursorPath, existing + \"\\n\" + cursorRules, \"utf8\");\n }\n } else {\n writeFileSync(cursorPath, cursorRules, \"utf8\");\n }\n }\n\n // 4. Create MASTER_PROMPT.md if not present\n if (!existsSync(\"MASTER_PROMPT.md\")) {\n const guidePath = getMasterPromptPath();\n if (guidePath) {\n copyFileSync(guidePath, \"MASTER_PROMPT.md\");\n } else {\n // Fallback: minimal prompt if template file is not bundled\n writeFileSync(\n \"MASTER_PROMPT.md\",\n \"# Holdpoint\\n\\nRun `npx holdpoint check` before marking any task complete.\\nSee `checks.yaml` for the full list of checks.\\n\",\n \"utf8\",\n );\n }\n }\n\n spinner.succeed(chalk.bold.green(\"Holdpoint initialised!\"));\n\n console.log(`\n${chalk.cyan(\"Next steps:\")}\n 1. Edit ${chalk.yellow(\"checks.yaml\")} to customise your eval checkpoints\n 2. Commit ${chalk.yellow(\"checks.yaml\")} and the generated engine files\n 3. Run ${chalk.yellow(\"npx holdpoint check\")} at any time to validate\n\n Visual builder: ${chalk.yellow(\"npx holdpoint builder\")} (opens localhost:4321)\n Stack: ${chalk.cyan(stack)} Agent: ${chalk.cyan(agent)}\n`);\n}\n","import { existsSync } from \"node:fs\";\nimport type { AgentType, StackType } from \"@holdpoint/types\";\n\nexport function detectAgent(): AgentType {\n // Copilot CLI: check for extensions dir or copilot binary in path\n if (existsSync(\".github/extensions\")) return \"copilot\";\n // Claude Code: check for .claude dir\n if (existsSync(\".claude\")) return \"claude\";\n // Cursor: check for .cursorrules\n if (existsSync(\".cursorrules\")) return \"cursor\";\n return \"unknown\";\n}\n\nexport function detectStack(): StackType {\n const hasNext =\n existsSync(\"next.config.ts\") || existsSync(\"next.config.js\") || existsSync(\"next.config.mjs\");\n const hasTsConfig = existsSync(\"tsconfig.json\");\n const hasPyproject =\n existsSync(\"pyproject.toml\") || existsSync(\"requirements.txt\") || existsSync(\"setup.py\");\n const hasPrisma = existsSync(\"prisma/schema.prisma\");\n const hasApi = existsSync(\"server\") || existsSync(\"api\") || existsSync(\"backend\");\n const hasGoMod = existsSync(\"go.mod\");\n\n if (hasNext && (hasPrisma || hasApi)) return \"fullstack\";\n if (hasNext) return \"nextjs\";\n if (hasTsConfig) return \"typescript\";\n if (hasPyproject) return \"python\";\n if (hasGoMod) return \"go\";\n return \"unknown\";\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport { parseHoldpointYaml, matchesWhen } from \"@holdpoint/yaml-core\";\nimport { runDeterministicChecks } from \"@holdpoint/yaml-core/runner\";\nimport type { CheckResult } from \"@holdpoint/types\";\nimport { execSync } from \"node:child_process\";\nimport { scanProject } from \"../evolve/scanner.js\";\nimport { getTemplates } from \"../evolve/templates.js\";\nimport { detectStaleChecks, getRepoFiles } from \"../evolve/dead-checker.js\";\n\nfunction getStagedFiles(): string[] {\n try {\n const out = execSync(\"git diff --cached --name-only\", {\n encoding: \"utf8\",\n stdio: [\"pipe\", \"pipe\", \"ignore\"],\n });\n return out.trim().split(\"\\n\").filter(Boolean);\n } catch {\n return [];\n }\n}\n\nfunction getAllChangedFiles(): string[] {\n try {\n const out = execSync(\"git diff --name-only HEAD\", {\n encoding: \"utf8\",\n stdio: [\"pipe\", \"pipe\", \"ignore\"],\n });\n return out.trim().split(\"\\n\").filter(Boolean);\n } catch {\n return [];\n }\n}\n\nexport async function checkCommand(options: { staged?: boolean }): Promise<void> {\n if (!existsSync(\"checks.yaml\")) {\n console.error(chalk.red(\"No checks.yaml found. Run `holdpoint init` first.\"));\n process.exit(1);\n }\n\n const yamlContent = readFileSync(\"checks.yaml\", \"utf8\");\n let config;\n try {\n config = parseHoldpointYaml(yamlContent);\n } catch (err: unknown) {\n console.error(chalk.red(\"Invalid checks.yaml:\"), (err as Error).message);\n process.exit(1);\n }\n\n const changedFiles = options.staged ? getStagedFiles() : getAllChangedFiles();\n\n // Print project guides so the agent/human sees them before running checks\n const guides = Object.entries(config.context?.guides ?? {});\n if (guides.length > 0) {\n console.log(chalk.cyan(\"\\nProject guides:\"));\n for (const [key, text] of guides) {\n console.log(chalk.bold(` ${key}:`), chalk.dim(String(text).trim()));\n }\n console.log(\"\");\n }\n\n if (changedFiles.length === 0) {\n console.log(chalk.yellow(\"No changed files detected. Running all checks with no file filter.\"));\n }\n\n const taskCount = config.checks.filter((c) => c.cmd !== undefined).length;\n const spinner = ora(`Running ${taskCount} task(s)…`).start();\n const effectiveFiles = changedFiles.length > 0 ? changedFiles : [\"__all__\"];\n const results = runDeterministicChecks(config, effectiveFiles);\n\n // Built-in structural drift detection — hardcoded into holdpoint, not user-configurable.\n // Fires when structural indicator files changed (or when all checks run with no staged files).\n const runDrift = matchesWhen(\"structural\", effectiveFiles);\n if (runDrift) {\n const profile = scanProject();\n const existingIds = new Set(config.checks.map((c) => c.id));\n const templates = getTemplates(profile);\n const proposals = templates.filter((t) => t.trigger(profile) && !existingIds.has(t.id));\n const repoFiles = getRepoFiles(process.cwd());\n const staleChecks = detectStaleChecks(config, repoFiles);\n\n if (proposals.length > 0 || staleChecks.length > 0) {\n const lines: string[] = [];\n if (proposals.length > 0) {\n lines.push(`${proposals.length} new check(s) available for your project stack:`);\n for (const p of proposals) lines.push(` + ${p.label}`);\n }\n if (staleChecks.length > 0) {\n lines.push(`${staleChecks.length} stale check(s) no longer match your project:`);\n for (const s of staleChecks) lines.push(` - ${s.check.label}: ${s.reason}`);\n }\n lines.push(\"\\nRun: npx holdpoint evolve --apply\");\n results.push({\n check: { id: \"__holdpoint_evolve__\", label: \"Evolve checks with project structure\" },\n status: \"fail\",\n output: lines.join(\"\\n\"),\n });\n }\n }\n\n const passed = results.filter((r) => r.status === \"pass\");\n const failed = results.filter((r) => r.status === \"fail\");\n const skipped = results.filter((r) => r.status === \"skip\");\n\n spinner.stop();\n\n // Print results\n for (const result of results) {\n printResult(result);\n }\n\n // Summary\n console.log(\"\");\n console.log(\n [\n chalk.green(`✓ ${passed.length} passed`),\n failed.length > 0 ? chalk.red(`✗ ${failed.length} failed`) : \"\",\n skipped.length > 0 ? chalk.gray(`◌ ${skipped.length} skipped`) : \"\",\n ]\n .filter(Boolean)\n .join(\" \"),\n );\n\n // Prompt checks: show those whose when filter matches the changed files\n const promptChecks = config.checks.filter(\n (c) =>\n c.prompt !== undefined &&\n matchesWhen(c.when, changedFiles.length > 0 ? changedFiles : [\"__all__\"], config.patterns),\n );\n if (promptChecks.length > 0) {\n console.log(`\\n${chalk.cyan(\"Agent prompts to act on:\")}`);\n for (const c of promptChecks) {\n console.log(` ${chalk.yellow(\"□\")} [${c.label}] ${c.prompt ?? \"\"}`);\n }\n }\n\n if (failed.length > 0) {\n process.exit(1);\n }\n}\n\nfunction printResult(result: CheckResult): void {\n const icon =\n result.status === \"pass\"\n ? chalk.green(\"✓\")\n : result.status === \"fail\"\n ? chalk.red(\"✗\")\n : result.status === \"skip\"\n ? chalk.gray(\"◌\")\n : chalk.yellow(\"…\");\n\n const label = result.check.label;\n console.log(`${icon} ${label}`);\n\n if (result.status === \"fail\" && result.output) {\n const trimmed = result.output.trim().split(\"\\n\").slice(0, 10).join(\"\\n\");\n console.log(chalk.dim(trimmed.replace(/^/gm, \" \")));\n }\n if (result.status === \"skip\" && result.skipReason) {\n console.log(chalk.dim(` ${result.skipReason}`));\n }\n}\n","import { existsSync, readFileSync, readdirSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { execSync } from \"node:child_process\";\n\nexport interface ProjectProfile {\n // Languages\n hasTypeScript: boolean;\n hasPython: boolean;\n hasGo: boolean;\n hasRust: boolean;\n hasJava: boolean;\n hasRuby: boolean;\n // Frameworks\n hasNext: boolean;\n hasReact: boolean;\n // Linting\n hasEslint: boolean;\n hasBiome: boolean;\n hasRuff: boolean;\n hasPrettier: boolean;\n // Testing\n hasVitest: boolean;\n hasJest: boolean;\n hasPytest: boolean;\n // DB\n hasPrisma: boolean;\n hasDrizzle: boolean;\n hasMigrations: boolean;\n hasAlembic: boolean;\n // Infra\n hasDocker: boolean;\n hasTerraform: boolean;\n hasKubernetes: boolean;\n // API\n hasOpenApi: boolean;\n // CI\n hasGithubActions: boolean;\n // Package manager\n packageManager: \"pnpm\" | \"yarn\" | \"bun\" | \"npm\";\n // Raw scripts from package.json\n scripts: Record<string, string>;\n // All dep names (deps + devDeps)\n deps: Set<string>;\n}\n\ntype PkgJson = {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n scripts?: Record<string, string>;\n};\n\nfunction tryReadJson<T>(path: string): T | null {\n try {\n return JSON.parse(readFileSync(path, \"utf8\")) as T;\n } catch {\n return null;\n }\n}\n\nfunction tryReadText(path: string): string {\n try {\n return readFileSync(path, \"utf8\");\n } catch {\n return \"\";\n }\n}\n\n/**\n * Walk a directory up to maxDepth levels, returning all file paths relative to root.\n * Excludes common build artifacts and dependency directories.\n */\nfunction walkDir(\n dir: string,\n root: string,\n depth: number,\n maxDepth: number,\n ignored: Set<string>,\n): string[] {\n if (depth > maxDepth) return [];\n let entries: string[] = [];\n try {\n entries = readdirSync(dir);\n } catch {\n return [];\n }\n const results: string[] = [];\n for (const entry of entries) {\n if (ignored.has(entry)) continue;\n const full = join(dir, entry);\n const rel = full.slice(root.length + 1);\n try {\n // Use stat-free heuristic: if it has an extension it's likely a file\n // If no extension and doesn't start with \".\", try as directory\n const hasExt = entry.includes(\".\");\n if (!hasExt || entry.startsWith(\".\")) {\n // Could be a dir — try recursing\n const children = walkDir(full, root, depth + 1, maxDepth, ignored);\n if (children.length > 0) {\n results.push(...children);\n } else if (hasExt) {\n results.push(rel);\n }\n } else {\n results.push(rel);\n }\n } catch {\n // skip\n }\n }\n return results;\n}\n\nconst WALK_IGNORED = new Set([\n \"node_modules\",\n \".git\",\n \"dist\",\n \"build\",\n \".next\",\n \".turbo\",\n \"__pycache__\",\n \".venv\",\n \"venv\",\n \".mypy_cache\",\n \"target\",\n \".cache\",\n \"coverage\",\n \".nyc_output\",\n]);\n\n/**\n * Returns a list of all files in the repo (relative paths from cwd).\n * Uses `git ls-files` when inside a git repo; falls back to directory walk.\n */\nexport function getRepoFiles(cwd: string): string[] {\n try {\n const out = execSync(\"git ls-files\", {\n cwd,\n encoding: \"utf8\",\n stdio: [\"pipe\", \"pipe\", \"ignore\"],\n });\n const files = out.trim().split(\"\\n\").filter(Boolean);\n if (files.length > 0) return files;\n } catch {\n // not a git repo or git not available\n }\n return walkDir(cwd, cwd, 0, 6, WALK_IGNORED);\n}\n\n/**\n * Returns true if the file path is a structural project indicator — i.e., a file\n * whose addition or modification may require new checks to be added to checks.yaml.\n * Mirrors the detection patterns used in `scanProject()`.\n */\nexport function isStructuralFile(file: string): boolean {\n const f = file.replace(/\\\\/g, \"/\");\n\n // JS / TS project structure\n if (f === \"package.json\") return true;\n if (/^tsconfig[^/]*\\.json$/.test(f)) return true;\n\n // Python\n if (/^requirements[^/]*\\.txt$/.test(f)) return true;\n if (f === \"pyproject.toml\") return true;\n if (f === \"Pipfile\") return true;\n if (f === \"setup.py\") return true;\n if (f === \"setup.cfg\") return true;\n if (f === \"pytest.ini\") return true;\n if (f === \"tox.ini\") return true;\n\n // Go\n if (f === \"go.mod\") return true;\n\n // Rust\n if (f === \"Cargo.toml\") return true;\n\n // Java / Kotlin\n if (f === \"pom.xml\") return true;\n if (/^build\\.gradle(\\.kts)?$/.test(f)) return true;\n\n // Ruby\n if (f === \"Gemfile\") return true;\n\n // Test frameworks\n if (/^vitest\\.config\\.[^/]+$/.test(f)) return true;\n if (/^jest\\.config\\.[^/]+$/.test(f)) return true;\n if (/^playwright\\.config\\.[^/]+$/.test(f)) return true;\n\n // Linters / formatters\n if (/^eslint\\.config\\.[^/]+$/.test(f)) return true;\n if (/^\\.eslintrc[^/]*$/.test(f)) return true;\n if (/^biome\\.jsonc?$/.test(f)) return true;\n if (/^prettier\\.config\\.[^/]+$/.test(f)) return true;\n if (/^\\.prettierrc[^/]*$/.test(f)) return true;\n\n // Next.js\n if (/^next\\.config\\.[^/]+$/.test(f)) return true;\n\n // Docker / infra\n if (/^Dockerfile[^/]*$/.test(f)) return true;\n if (/^docker-compose[^/]*\\.ya?ml$/.test(f)) return true;\n if (/[^/]*\\.tf$/.test(f)) return true;\n\n // Database\n if (f === \"prisma/schema.prisma\") return true;\n\n // OpenAPI\n if (/^(api\\/)?openapi\\.(yaml|yml|json)$/.test(f)) return true;\n\n // CI\n if (/^\\.github\\/workflows\\/[^/]+\\.ya?ml$/.test(f)) return true;\n if (/^\\.circleci\\/.+$/.test(f)) return true;\n if (f === \"Jenkinsfile\") return true;\n if (f === \".gitlab-ci.yml\") return true;\n if (f === \".travis.yml\") return true;\n\n return false;\n}\n\n/**\n * Scan the project at `cwd` and return a `ProjectProfile`.\n * All detection is pure filesystem reads — no shell commands executed.\n */\nexport function scanProject(cwd = process.cwd()): ProjectProfile {\n const exists = (p: string) => existsSync(join(cwd, p));\n\n // Package manager\n const packageManager: ProjectProfile[\"packageManager\"] = exists(\"pnpm-lock.yaml\")\n ? \"pnpm\"\n : exists(\"yarn.lock\")\n ? \"yarn\"\n : exists(\"bun.lockb\")\n ? \"bun\"\n : \"npm\";\n\n // package.json\n const pkg = tryReadJson<PkgJson>(join(cwd, \"package.json\"));\n const scripts = pkg?.scripts ?? {};\n const deps = new Set<string>([\n ...Object.keys(pkg?.dependencies ?? {}),\n ...Object.keys(pkg?.devDependencies ?? {}),\n ]);\n\n // Python manifest scanning\n const pyprojectText = tryReadText(join(cwd, \"pyproject.toml\"));\n const requirementsText = tryReadText(join(cwd, \"requirements.txt\"));\n const pipfileText = tryReadText(join(cwd, \"Pipfile\"));\n const allPyText = pyprojectText + requirementsText + pipfileText;\n\n const hasPytest =\n exists(\"pytest.ini\") ||\n exists(\"setup.cfg\") ||\n allPyText.includes(\"pytest\") ||\n allPyText.includes(\"[tool.pytest\");\n const hasRuff = allPyText.includes(\"ruff\") || deps.has(\"ruff\");\n const hasAlembic = allPyText.includes(\"alembic\") || deps.has(\"alembic\");\n\n // Root-level file listing (for Dockerfile variants and .tf files)\n let rootFiles: string[] = [];\n try {\n rootFiles = readdirSync(cwd);\n } catch {\n // ignore\n }\n\n const hasDocker =\n rootFiles.some((f) => f === \"Dockerfile\" || f.startsWith(\"Dockerfile.\")) ||\n exists(\"docker-compose.yml\") ||\n exists(\"docker-compose.yaml\") ||\n exists(\"docker-compose.dev.yml\");\n\n const hasTerraform =\n rootFiles.some((f) => f.endsWith(\".tf\")) || exists(\"terraform\") || exists(\"infra\");\n\n return {\n // Languages\n hasTypeScript: exists(\"tsconfig.json\") || deps.has(\"typescript\"),\n hasPython:\n Boolean(pyprojectText) ||\n Boolean(requirementsText) ||\n Boolean(pipfileText) ||\n exists(\"setup.py\"),\n hasGo: exists(\"go.mod\"),\n hasRust: exists(\"Cargo.toml\"),\n hasJava: exists(\"pom.xml\") || exists(\"build.gradle\") || exists(\"build.gradle.kts\"),\n hasRuby: exists(\"Gemfile\"),\n\n // Frameworks\n hasNext:\n exists(\"next.config.ts\") ||\n exists(\"next.config.js\") ||\n exists(\"next.config.mjs\") ||\n deps.has(\"next\"),\n hasReact: deps.has(\"react\"),\n\n // Linting\n hasEslint:\n exists(\"eslint.config.js\") ||\n exists(\"eslint.config.ts\") ||\n exists(\"eslint.config.mjs\") ||\n exists(\".eslintrc.js\") ||\n exists(\".eslintrc.json\") ||\n exists(\".eslintrc.yml\") ||\n exists(\".eslintrc.yaml\") ||\n deps.has(\"eslint\"),\n hasBiome: exists(\"biome.json\") || exists(\"biome.jsonc\") || deps.has(\"@biomejs/biome\"),\n hasRuff,\n hasPrettier:\n exists(\"prettier.config.js\") ||\n exists(\"prettier.config.ts\") ||\n exists(\"prettier.config.mjs\") ||\n exists(\".prettierrc\") ||\n exists(\".prettierrc.json\") ||\n deps.has(\"prettier\"),\n\n // Testing\n hasVitest: deps.has(\"vitest\") || Boolean(scripts[\"test\"]?.includes(\"vitest\")),\n hasJest: deps.has(\"jest\") || Boolean(scripts[\"test\"]?.includes(\"jest\")),\n hasPytest,\n\n // DB\n hasPrisma: exists(\"prisma/schema.prisma\") || deps.has(\"@prisma/client\"),\n hasDrizzle: deps.has(\"drizzle-orm\"),\n hasMigrations: exists(\"migrations\") || exists(\"db/migrations\") || exists(\"database/migrations\"),\n hasAlembic,\n\n // Infra\n hasDocker,\n hasTerraform,\n hasKubernetes: exists(\"k8s\") || exists(\"kubernetes\") || exists(\"helm\"),\n\n // API\n hasOpenApi:\n exists(\"openapi.yaml\") ||\n exists(\"openapi.yml\") ||\n exists(\"openapi.json\") ||\n exists(\"api/openapi.yaml\"),\n\n // CI\n hasGithubActions: exists(\".github/workflows\"),\n\n packageManager,\n scripts,\n deps,\n };\n}\n","import type { ConditionDef } from \"@holdpoint/types\";\nimport type { ProjectProfile } from \"./scanner.js\";\n\nexport interface EvolveTemplate {\n id: string;\n label: string;\n when?: string;\n cmd?: string;\n prompt?: string;\n conditionId?: string;\n /** Condition to add to checks.yaml alongside the check (only if conditionId is set) */\n condition?: Omit<ConditionDef, \"id\"> & { id: string };\n /** Returns true if this check is relevant to the given project profile */\n trigger: (p: ProjectProfile) => boolean;\n}\n\n/** Returns the correct run command for a package.json script, respecting the detected package manager. */\nfunction pmScript(profile: ProjectProfile, script: string, fallback: string): string {\n if (!profile.scripts[script]) return fallback;\n if (profile.packageManager === \"npm\") return `npm run ${script}`;\n return `${profile.packageManager} ${script}`;\n}\n\n/**\n * Returns all applicable check templates for the given project profile.\n * Caller should filter out templates whose IDs already exist in checks.yaml.\n */\nexport function getTemplates(profile: ProjectProfile): EvolveTemplate[] {\n return [\n // ── Universal checks (always proposed for any project) ──────────────────\n {\n id: \"git-commit\",\n label: \"Commit all changes before finishing\",\n cmd: 'git rev-parse --is-inside-work-tree 2>/dev/null || exit 0; [ -z \"$(git status --porcelain)\" ] && exit 0; git status --short; exit 1',\n trigger: () => true,\n },\n {\n id: \"changelog-update\",\n label: \"Add a CHANGELOG.md entry for this session\",\n prompt:\n \"Before committing, add an entry to CHANGELOG.md describing what was done. \" +\n \"Use Keep a Changelog format — add under ## [Unreleased] (create the file \" +\n \"and that section if absent). Group entries as Added, Changed, Fixed, or Removed. \" +\n \"Be concise but specific. The entry text will serve as the commit message.\",\n trigger: () => true,\n },\n {\n id: \"readme-sync\",\n label: \"Update README.md if user-facing changes were made\",\n prompt:\n \"If you added, changed, or removed user-facing functionality — CLI commands, \" +\n \"configuration options, public APIs, or significant new features — update \" +\n \"README.md to reflect those changes.\",\n trigger: () => true,\n },\n {\n id: \"no-todos\",\n label: \"No TODO/FIXME left in changed code\",\n prompt:\n \"Scan the files you changed for any TODO, FIXME, HACK, or XXX comments. \" +\n \"Either resolve them before finishing or convert them to GitHub issues. \" +\n \"Don't leave incomplete work silently behind.\",\n trigger: () => true,\n },\n\n // ── TypeScript / JavaScript ──────────────────────────────────────────────\n {\n id: \"typecheck\",\n label: \"TypeScript type check\",\n cmd: pmScript(profile, \"typecheck\", \"npx tsc --noEmit\"),\n trigger: (p) => p.hasTypeScript,\n },\n {\n id: \"lint\",\n label: \"Lint codebase\",\n cmd: profile.hasEslint\n ? pmScript(profile, \"lint\", \"npx eslint .\")\n : profile.hasBiome\n ? pmScript(profile, \"lint\", \"npx @biomejs/biome check .\")\n : pmScript(profile, \"lint\", \"echo 'No linter detected'\"),\n trigger: (p) => p.hasEslint || p.hasBiome,\n },\n {\n id: \"format-check\",\n label: \"Prettier — format check\",\n cmd: pmScript(profile, \"format:check\", \"npx prettier --check .\"),\n trigger: (p) => p.hasPrettier,\n },\n {\n id: \"test\",\n label: \"Unit tests\",\n cmd: profile.hasVitest\n ? pmScript(profile, \"test\", \"npx vitest run\")\n : pmScript(profile, \"test\", \"npx jest --passWithNoTests\"),\n trigger: (p) => p.hasVitest || p.hasJest,\n },\n {\n id: \"jsdoc\",\n label: \"JSDoc on changed public functions\",\n prompt:\n \"Ensure all changed public functions, classes, and module exports have \" +\n \"accurate JSDoc comments (description + @param + @returns where applicable).\",\n trigger: (p) => p.hasTypeScript || p.hasReact,\n },\n {\n id: \"build\",\n label: \"Production build passes\",\n cmd: pmScript(profile, \"build\", \"echo 'No build script detected'\"),\n trigger: (p) => Boolean(p.scripts[\"build\"]),\n },\n\n // ── Python ───────────────────────────────────────────────────────────────\n {\n id: \"python-lint\",\n label: \"Ruff — Python linting\",\n cmd: \"ruff check .\",\n when: \"python\",\n trigger: (p) => p.hasPython && p.hasRuff,\n },\n {\n id: \"python-test\",\n label: \"Pytest — Python unit tests\",\n cmd: \"pytest\",\n when: \"python\",\n trigger: (p) => p.hasPython && p.hasPytest,\n },\n\n // ── Go ───────────────────────────────────────────────────────────────────\n {\n id: \"go-test\",\n label: \"Go tests\",\n cmd: \"go test ./...\",\n when: \"go\",\n trigger: (p) => p.hasGo,\n },\n {\n id: \"go-vet\",\n label: \"Go vet\",\n cmd: \"go vet ./...\",\n when: \"go\",\n trigger: (p) => p.hasGo,\n },\n\n // ── Database ─────────────────────────────────────────────────────────────\n {\n id: \"db-migrations\",\n label: \"Database migration for schema changes\",\n when: \"database\",\n prompt:\n \"If schema or migration files changed, ensure the appropriate migration was \" +\n \"generated with your ORM tool (e.g. `prisma migrate dev`, `alembic revision`, \" +\n \"`rails db:migrate`) and committed alongside the schema change.\",\n trigger: (p) => p.hasPrisma || p.hasAlembic || p.hasMigrations || p.hasDrizzle,\n },\n {\n id: \"prisma-format\",\n label: \"Prisma schema format check\",\n when: \"prisma\",\n cmd: \"npx prisma format --check 2>/dev/null || npx prisma format\",\n conditionId: \"has-prisma\",\n condition: {\n id: \"has-prisma\",\n operator: \"file_exists\",\n path: \"prisma/schema.prisma\",\n },\n trigger: (p) => p.hasPrisma,\n },\n\n // ── OpenAPI ──────────────────────────────────────────────────────────────\n {\n id: \"openapi-sync\",\n label: \"OpenAPI spec updated for API changes\",\n when: \"backend\",\n conditionId: \"has-openapi\",\n condition: {\n id: \"has-openapi\",\n operator: \"file_exists\",\n path: \"openapi.yaml\",\n },\n prompt:\n \"If any API routes were added or changed, update openapi.yaml (or openapi.json) \" +\n \"to reflect the new endpoints, request/response shapes, and error codes.\",\n trigger: (p) => p.hasOpenApi,\n },\n\n // ── Infra ─────────────────────────────────────────────────────────────────\n {\n id: \"docker-build\",\n label: \"Docker build passes\",\n when: \"infra\",\n cmd: \"docker build . --quiet -t app:ci\",\n conditionId: \"has-dockerfile\",\n condition: {\n id: \"has-dockerfile\",\n operator: \"file_exists\",\n path: \"Dockerfile\",\n },\n trigger: (p) => p.hasDocker,\n },\n {\n id: \"terraform-validate\",\n label: \"Terraform validate\",\n when: \"infra\",\n cmd: \"terraform validate\",\n trigger: (p) => p.hasTerraform,\n },\n\n // ── Frontend ─────────────────────────────────────────────────────────────\n {\n id: \"i18n\",\n label: \"i18n — no hardcoded user-facing strings\",\n when: \"frontend\",\n prompt:\n \"Confirm all user-visible strings are wrapped in the project's i18n function \" +\n \"(e.g. `t()`, `useTranslation`, `<Trans>`) and that locale files are updated \" +\n \"for any new copy.\",\n trigger: (p) => p.hasNext && p.hasReact,\n },\n ];\n}\n","import { execSync } from \"node:child_process\";\nimport { readdirSync, existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { CheckDef, HoldpointConfig } from \"@holdpoint/types\";\n\nexport interface StaleCheck {\n check: CheckDef;\n reason: string;\n /** Path to use in a file_exists condition, if it can be inferred from the when: regex */\n suggestedConditionPath?: string;\n}\n\n/** Named scopes handled by matchesWhen() — these are never \"stale\" (intentionally broad) */\nconst NAMED_SCOPES = new Set([\n \"frontend\",\n \"backend\",\n \"socket\",\n \"visual\",\n \"python\",\n \"go\",\n \"rust\",\n \"java\",\n \"ruby\",\n \"database\",\n \"prisma\",\n \"testing\",\n \"infra\",\n \"ci\",\n \"docs\",\n \"structural\",\n]);\n\nconst WALK_IGNORED = new Set([\n \"node_modules\",\n \".git\",\n \"dist\",\n \"build\",\n \".next\",\n \".turbo\",\n \"__pycache__\",\n \".venv\",\n \"venv\",\n \".mypy_cache\",\n \"target\",\n \".cache\",\n \"coverage\",\n]);\n\nfunction walkDir(dir: string, root: string, depth: number, maxDepth: number): string[] {\n if (depth > maxDepth) return [];\n let entries: string[] = [];\n try {\n entries = readdirSync(dir);\n } catch {\n return [];\n }\n const results: string[] = [];\n for (const entry of entries) {\n if (WALK_IGNORED.has(entry) || entry.startsWith(\".\")) continue;\n const full = join(dir, entry);\n const rel = full.slice(root.length + 1);\n results.push(rel);\n // Try to recurse (will just return [] if it's a file, not a dir)\n const children = walkDir(full, root, depth + 1, maxDepth);\n results.push(...children);\n }\n return results;\n}\n\n/**\n * Returns a list of all files in the repo (relative paths from cwd).\n * Uses `git ls-files` when available; falls back to directory walk.\n */\nexport function getRepoFiles(cwd: string): string[] {\n try {\n const out = execSync(\"git ls-files\", {\n cwd,\n encoding: \"utf8\",\n stdio: [\"pipe\", \"pipe\", \"ignore\"],\n });\n const files = out.trim().split(\"\\n\").filter(Boolean);\n if (files.length > 0) return files;\n } catch {\n // not a git repo or git not available\n }\n return walkDir(cwd, cwd, 0, 6);\n}\n\n/**\n * Try to extract a simple path hint from a regex pattern, for use as a\n * `file_exists` condition path.\n * e.g. \"^prisma/\" → \"prisma\", \"^checks\\\\.yaml$\" → \"checks.yaml\"\n */\nfunction extractPathFromRegex(pattern: string): string | undefined {\n const cleaned = pattern\n .replace(/^\\^/, \"\")\n .replace(/\\$$/, \"\")\n .replace(/\\\\\\./g, \".\")\n .replace(/\\(\\?:/g, \"\")\n .replace(/\\)/g, \"\")\n .replace(/[|*+?[\\]{}()]/g, \"\");\n const candidate = cleaned.replace(/\\/$/, \"\").trim();\n if (candidate.length > 0 && /^[\\w\\-./]+$/.test(candidate)) return candidate;\n return undefined;\n}\n\n/**\n * Detect checks whose `when:` regex pattern matches zero files in the repo.\n * Named scope whens (frontend, backend, structural, etc.) are never flagged as stale.\n * User-defined named patterns (from config.patterns) are resolved to their regex before checking.\n * Checks that already have a conditionId are skipped (already guarded).\n */\nexport function detectStaleChecks(config: HoldpointConfig, repoFiles: string[]): StaleCheck[] {\n const stale: StaleCheck[] = [];\n const userPatterns = config.patterns ?? {};\n\n for (const check of config.checks) {\n if (!check.when) continue;\n if (NAMED_SCOPES.has(check.when)) continue;\n if (check.conditionId) continue; // already guarded by a condition\n\n // Resolve user-defined named patterns to their regex value\n const patternAlias = check.when in userPatterns ? check.when : undefined;\n const regexStr = patternAlias ? userPatterns[patternAlias]! : check.when;\n\n let re: RegExp;\n try {\n re = new RegExp(regexStr);\n } catch {\n stale.push({ check, reason: `Invalid regex: '${regexStr}'` });\n continue;\n }\n\n const matches = repoFiles.filter((f) => re.test(f));\n if (matches.length === 0) {\n const label = patternAlias\n ? `Pattern '${patternAlias}' (= '${regexStr}')`\n : `Regex '${regexStr}'`;\n const suggestedConditionPath = extractPathFromRegex(regexStr);\n // Verify the suggested path doesn't actually exist either\n const pathGone =\n !suggestedConditionPath || !existsSync(join(process.cwd(), suggestedConditionPath));\n if (pathGone) {\n stale.push({\n check,\n reason: `${label} matches 0 files in the repo`,\n ...(suggestedConditionPath ? { suggestedConditionPath } : {}),\n });\n }\n }\n }\n\n return stale;\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport chalk from \"chalk\";\nimport { parseHoldpointYaml, validateConfig } from \"@holdpoint/yaml-core\";\n\nexport async function validateCommand(): Promise<void> {\n if (!existsSync(\"checks.yaml\")) {\n console.error(chalk.red(\"No checks.yaml found. Run `holdpoint init` first.\"));\n process.exit(1);\n }\n\n const text = readFileSync(\"checks.yaml\", \"utf8\");\n\n let config;\n try {\n config = parseHoldpointYaml(text);\n } catch (err: unknown) {\n console.error(chalk.red(\"Parse error:\"), (err as Error).message);\n process.exit(1);\n }\n\n const result = validateConfig(config);\n\n if (result.valid) {\n console.log(chalk.green(\"✓ checks.yaml is valid\"));\n console.log(\n chalk.dim(\n ` ${config.checks.filter((c) => c.cmd !== undefined).length} tasks, ${config.checks.filter((c) => c.prompt !== undefined).length} prompts, ${config.conditions.length} conditions`,\n ),\n );\n } else {\n console.error(chalk.red(\"✗ checks.yaml has errors:\"));\n for (const err of result.errors) {\n console.error(` ${chalk.yellow(err.path)}: ${err.message}`);\n }\n process.exit(1);\n }\n}\n","import { existsSync, readFileSync, writeFileSync, mkdirSync } from \"node:fs\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport { parseHoldpointYaml } from \"@holdpoint/yaml-core\";\nimport { buildHookJson, buildCheckScript, buildConfigJson } from \"@holdpoint/engine-copilot\";\nimport { buildEngineJson as buildClaudeEngineJson } from \"@holdpoint/engine-claude\";\nimport { buildEngine as buildCursorEngine } from \"@holdpoint/engine-cursor\";\nimport { detectAgent } from \"../detect.js\";\nimport type { AgentType } from \"@holdpoint/types\";\n\nexport async function updateCommand(): Promise<void> {\n if (!existsSync(\"checks.yaml\")) {\n console.error(chalk.red(\"No checks.yaml found. Run `holdpoint init` first.\"));\n process.exit(1);\n }\n\n const spinner = ora(\"Updating Holdpoint engine files…\").start();\n const agent = detectAgent();\n const config = parseHoldpointYaml(readFileSync(\"checks.yaml\", \"utf8\"));\n\n // Always write checks.immutable.json — read by holdpoint-check.mjs at runtime\n const generatedDir = \".github/holdpoint/generated\";\n mkdirSync(generatedDir, { recursive: true });\n writeFileSync(`${generatedDir}/checks.immutable.json`, buildConfigJson(config), \"utf8\");\n\n if (agent === \"copilot\" || agent === \"unknown\") {\n const hooksDir = \".github/hooks\";\n mkdirSync(hooksDir, { recursive: true });\n writeFileSync(`${hooksDir}/holdpoint.json`, buildHookJson(config), \"utf8\");\n writeFileSync(`${hooksDir}/holdpoint-check.mjs`, buildCheckScript(config), \"utf8\");\n spinner.text = `Updated ${chalk.green(\".github/hooks/holdpoint.json\")} and ${chalk.green(\".github/hooks/holdpoint-check.mjs\")}`;\n }\n\n if (agent === \"claude\") {\n mkdirSync(\".claude\", { recursive: true });\n const settingsPath = \".claude/settings.json\";\n let existing: Record<string, unknown> = {};\n if (existsSync(settingsPath)) {\n try {\n existing = JSON.parse(readFileSync(settingsPath, \"utf8\")) as Record<string, unknown>;\n } catch {\n /* */\n }\n }\n const hooks = JSON.parse(buildClaudeEngineJson(config)) as Record<string, unknown>;\n writeFileSync(settingsPath, JSON.stringify({ ...existing, hooks: hooks.hooks }, null, 2));\n }\n\n if (agent === \"cursor\") {\n const cursorRules = buildCursorEngine(config);\n const cursorPath = \".cursorrules\";\n if (existsSync(cursorPath)) {\n const content = readFileSync(cursorPath, \"utf8\");\n const start = content.indexOf(\"# ─── Holdpoint Rules\");\n const end = content.indexOf(\"# ─── End Holdpoint Rules ───\");\n if (start !== -1 && end !== -1) {\n // Slice past the end-marker line (find its newline to avoid hardcoded offsets)\n const afterEnd = content.indexOf(\"\\n\", end);\n const updated =\n content.slice(0, start) +\n cursorRules +\n content.slice(afterEnd === -1 ? end : afterEnd + 1);\n writeFileSync(cursorPath, updated);\n } else {\n writeFileSync(cursorPath, content + \"\\n\" + cursorRules);\n }\n }\n }\n\n spinner.succeed(chalk.green(\"Engine files updated from current checks.yaml\"));\n}\n","import { createServer, type IncomingMessage, type ServerResponse } from \"node:http\";\nimport { createReadStream, existsSync } from \"node:fs\";\nimport { join, extname, dirname } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { execSync } from \"node:child_process\";\nimport chalk from \"chalk\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\nconst MIME: Record<string, string> = {\n \".html\": \"text/html; charset=utf-8\",\n \".js\": \"text/javascript\",\n \".mjs\": \"text/javascript\",\n \".css\": \"text/css\",\n \".svg\": \"image/svg+xml\",\n \".png\": \"image/png\",\n \".ico\": \"image/x-icon\",\n \".woff\": \"font/woff\",\n \".woff2\": \"font/woff2\",\n \".ttf\": \"font/ttf\",\n \".json\": \"application/json\",\n};\n\n/**\n * Serve a static file with the appropriate MIME type.\n */\nfunction serveFile(res: ServerResponse, filePath: string): void {\n const mime = MIME[extname(filePath)] ?? \"application/octet-stream\";\n res.writeHead(200, { \"Content-Type\": mime });\n createReadStream(filePath).pipe(res);\n}\n\n/**\n * Handle an incoming HTTP request: serve `/__holdpoint/initial-yaml` from the\n * user's `checks.yaml`, and all other paths as static files from `uiDir` with\n * a SPA fallback to `index.html`.\n */\nfunction handleRequest(req: IncomingMessage, res: ServerResponse, uiDir: string): void {\n const url = (req.url ?? \"/\").split(\"?\")[0] ?? \"/\";\n\n // Serve the user's checks.yaml for the builder UI to load\n if (url === \"/__holdpoint/initial-yaml\") {\n const checksPath = join(process.cwd(), \"checks.yaml\");\n if (existsSync(checksPath)) {\n res.writeHead(200, { \"Content-Type\": \"text/yaml; charset=utf-8\" });\n createReadStream(checksPath).pipe(res);\n } else {\n res.writeHead(404, { \"Content-Type\": \"text/plain\" });\n res.end(\"checks.yaml not found in current directory\");\n }\n return;\n }\n\n // Static files\n const candidate = join(uiDir, url === \"/\" ? \"index.html\" : url);\n const filePath = existsSync(candidate) ? candidate : join(uiDir, \"index.html\"); // SPA fallback\n serveFile(res, filePath);\n}\n\n/**\n * Start the Holdpoint visual builder on localhost:4321.\n *\n * Serves the pre-built React SPA from `dist/builder-ui/` (bundled into the CLI\n * package at publish time) and exposes a `/__holdpoint/initial-yaml` endpoint\n * that returns the user's `checks.yaml` so the builder can load it on startup.\n */\nexport async function buildCommand(): Promise<void> {\n const port = 4321;\n const uiDir = join(__dirname, \"builder-ui\");\n\n if (!existsSync(uiDir)) {\n console.error(chalk.red(\"✗ Builder UI not found.\\n\"));\n console.log(chalk.dim(\" This is unexpected for a published build of @holdpoint/cli.\"));\n console.log(chalk.dim(\" If you installed from source, rebuild with: pnpm turbo build\\n\"));\n process.exit(1);\n }\n\n const server = createServer((req, res) => handleRequest(req, res, uiDir));\n\n await new Promise<void>((resolve, reject) => {\n server.listen(port, () => {\n console.log(\n `\\n${chalk.green(\"✓\")} Holdpoint builder running at ${chalk.cyan(`http://localhost:${port}`)}`,\n );\n console.log(chalk.dim(\" Edit checks.yaml, then reload the page to see updates\"));\n console.log(chalk.dim(\" Press Ctrl+C to stop\\n\"));\n\n const openCmd =\n process.platform === \"darwin\"\n ? \"open\"\n : process.platform === \"win32\"\n ? \"start\"\n : \"xdg-open\";\n try {\n execSync(`${openCmd} http://localhost:${port}`, { stdio: \"ignore\" });\n } catch {\n /* non-fatal */\n }\n });\n\n server.on(\"error\", reject);\n\n process.on(\"SIGINT\", () => {\n console.log(chalk.dim(\"\\n Stopping builder…\"));\n server.close(() => resolve());\n });\n });\n}\n","import { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { execSync } from \"node:child_process\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport { parseHoldpointYaml, generateYaml } from \"@holdpoint/yaml-core\";\nimport type { HoldpointConfig, CheckDef, ConditionDef } from \"@holdpoint/types\";\nimport { scanProject } from \"../evolve/scanner.js\";\nimport { getRepoFiles, detectStaleChecks } from \"../evolve/dead-checker.js\";\nimport { getTemplates } from \"../evolve/templates.js\";\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\n/**\n * Strip leading comment lines from a checks.yaml so we can re-prepend them\n * after re-serialising — preserves the documentation header.\n */\nfunction extractHeader(yaml: string): string {\n const lines = yaml.split(\"\\n\");\n const commentLines: string[] = [];\n for (const line of lines) {\n if (line.startsWith(\"#\") || (commentLines.length > 0 && line.trim() === \"\")) {\n commentLines.push(line);\n } else {\n break;\n }\n }\n // Trim trailing blank lines\n while (commentLines.length > 0 && commentLines[commentLines.length - 1]?.trim() === \"\") {\n commentLines.pop();\n }\n return commentLines.join(\"\\n\");\n}\n\nfunction withHeader(header: string, newYaml: string): string {\n if (!header) return newYaml;\n return header + \"\\n\\n\" + newYaml;\n}\n\n// ── The command ───────────────────────────────────────────────────────────────\n\nexport async function evolveCommand(options: { apply?: boolean }): Promise<void> {\n if (!existsSync(\"checks.yaml\")) {\n console.error(chalk.red(\"No checks.yaml found. Run `holdpoint init` first.\"));\n process.exit(1);\n }\n\n const spinner = ora(\"Scanning project profile…\").start();\n const cwd = process.cwd();\n\n // 1. Scan project\n const profile = scanProject(cwd);\n const repoFiles = getRepoFiles(cwd);\n\n // 2. Parse checks.yaml\n const yamlContent = readFileSync(\"checks.yaml\", \"utf8\");\n let config: HoldpointConfig;\n try {\n config = parseHoldpointYaml(yamlContent);\n } catch (err: unknown) {\n spinner.fail(chalk.red(\"Invalid checks.yaml:\") + \" \" + (err as Error).message);\n process.exit(1);\n }\n\n spinner.stop();\n\n // 3. Compute proposals — templates whose trigger matches AND id not already in config\n const existingIds = new Set(config.checks.map((c) => c.id));\n const existingConditionIds = new Set(config.conditions.map((c) => c.id));\n const allTemplates = getTemplates(profile);\n const proposals = allTemplates.filter((t) => t.trigger(profile) && !existingIds.has(t.id));\n\n // 4. Detect stale checks\n const staleChecks = detectStaleChecks(config, repoFiles);\n\n // ── Print report ─────────────────────────────────────────────────────────\n\n // Profile summary — show detected items\n console.log(chalk.bold(\"\\n📋 Project profile:\"));\n const traits: [string, boolean, string][] = [\n [\"TypeScript\", profile.hasTypeScript, \"tsconfig.json\"],\n [\"ESLint\", profile.hasEslint, \"eslint.config.*\"],\n [\"Biome\", profile.hasBiome, \"biome.json\"],\n [\"Ruff\", profile.hasRuff, \"pyproject.toml / ruff\"],\n [\"Prettier\", profile.hasPrettier, \".prettierrc\"],\n [\"Vitest\", profile.hasVitest, \"devDependencies\"],\n [\"Jest\", profile.hasJest, \"devDependencies\"],\n [\"Python\", profile.hasPython, \"pyproject.toml\"],\n [\"Pytest\", profile.hasPytest, \"pytest.ini\"],\n [\"Go\", profile.hasGo, \"go.mod\"],\n [\"Rust\", profile.hasRust, \"Cargo.toml\"],\n [\"Next.js\", profile.hasNext, \"next.config.*\"],\n [\"React\", profile.hasReact, \"dependencies\"],\n [\"Prisma\", profile.hasPrisma, \"prisma/schema.prisma\"],\n [\"Drizzle\", profile.hasDrizzle, \"drizzle-orm\"],\n [\"Migrations\", profile.hasMigrations, \"migrations/\"],\n [\"Docker\", profile.hasDocker, \"Dockerfile\"],\n [\"Terraform\", profile.hasTerraform, \"*.tf\"],\n [\"Kubernetes\", profile.hasKubernetes, \"k8s/\"],\n [\"OpenAPI\", profile.hasOpenApi, \"openapi.yaml\"],\n [\"GitHub Actions\", profile.hasGithubActions, \".github/workflows/\"],\n ];\n const detected = traits.filter(([, yes]) => yes);\n if (detected.length === 0) {\n console.log(chalk.dim(\" (empty project — only universal checks apply)\"));\n } else {\n for (const [name, , hint] of detected) {\n console.log(` ${chalk.green(\"✓\")} ${name.padEnd(18)} ${chalk.dim(hint)}`);\n }\n }\n\n // Stale checks\n if (staleChecks.length > 0) {\n console.log(chalk.bold(`\\n⚠️ Stale checks (${staleChecks.length}):`));\n for (const { check, reason, suggestedConditionPath } of staleChecks) {\n const fix = suggestedConditionPath\n ? chalk.dim(` → will wrap with conditionId: file_exists: ${suggestedConditionPath}`)\n : chalk.dim(\" → no path inferred; review manually\");\n console.log(` ${chalk.yellow(\"◌\")} ${chalk.bold(check.id)} ${chalk.dim(reason)}${fix}`);\n }\n }\n\n // Proposals\n if (proposals.length === 0 && staleChecks.length === 0) {\n console.log(chalk.green(\"\\n✓ checks.yaml is fully in sync with the project profile.\"));\n return;\n }\n\n if (proposals.length > 0) {\n console.log(chalk.bold(`\\n💡 Proposed additions (${proposals.length}):`));\n for (const t of proposals) {\n const scope = t.when ? chalk.cyan(` when: ${t.when}`) : \"\";\n const type = t.cmd ? chalk.dim(\"cmd\") : chalk.dim(\"prompt\");\n const preview = t.cmd\n ? chalk.dim(` ${t.cmd.slice(0, 80)}${t.cmd.length > 80 ? \"…\" : \"\"}`)\n : chalk.dim(` ${(t.prompt ?? \"\").slice(0, 80)}${(t.prompt?.length ?? 0) > 80 ? \"…\" : \"\"}`);\n console.log(` ${chalk.green(\"+\")} ${chalk.bold(t.id.padEnd(24))} [${type}]${scope}`);\n console.log(` ${preview}`);\n }\n }\n\n if (!options.apply) {\n console.log(\n chalk.red(`\\n✗ checks.yaml is out of sync with the project profile.`) +\n `\\n Run ${chalk.bold(\"npx holdpoint evolve --apply\")} to apply these changes.`,\n );\n process.exit(1);\n }\n\n // ── Apply ───────────────────────────────────────────────────────────────\n\n const applySpinner = ora(\"Applying changes to checks.yaml…\").start();\n\n // Build updated conditions list\n const newConditions = [...config.conditions];\n\n // Collect conditions needed by proposals\n for (const t of proposals) {\n if (t.condition && !existingConditionIds.has(t.condition.id)) {\n newConditions.push(t.condition as ConditionDef);\n existingConditionIds.add(t.condition.id);\n }\n }\n\n // Wrap stale checks with file_exists conditions\n const updatedChecks: CheckDef[] = config.checks.map((check) => {\n const stale = staleChecks.find((s) => s.check.id === check.id);\n if (!stale || !stale.suggestedConditionPath) return check;\n\n const condId = `has-${check.id}`;\n if (!existingConditionIds.has(condId)) {\n newConditions.push({\n id: condId,\n operator: \"file_exists\",\n path: stale.suggestedConditionPath,\n });\n existingConditionIds.add(condId);\n }\n return { ...check, conditionId: condId };\n });\n\n // Append proposed checks\n const newChecks: CheckDef[] = proposals.map((t) => ({\n id: t.id,\n label: t.label,\n ...(t.when ? { when: t.when } : {}),\n ...(t.cmd ? { cmd: t.cmd } : {}),\n ...(t.prompt ? { prompt: t.prompt } : {}),\n ...(t.conditionId ? { conditionId: t.conditionId } : {}),\n }));\n\n const updatedConfig: HoldpointConfig = {\n ...config,\n conditions: newConditions,\n checks: [...updatedChecks, ...newChecks],\n };\n\n const header = extractHeader(yamlContent);\n const newYaml = withHeader(header, generateYaml(updatedConfig));\n writeFileSync(\"checks.yaml\", newYaml, \"utf8\");\n\n // Regenerate engine files\n applySpinner.text = \"Running holdpoint update…\";\n try {\n execSync(\"npx holdpoint update\", { stdio: \"pipe\" });\n } catch {\n // holdpoint update failure is non-fatal — checks.yaml is already written\n applySpinner.warn(\n chalk.yellow(\"checks.yaml updated, but `holdpoint update` failed — run it manually.\"),\n );\n printAppliedSummary(proposals.length, staleChecks.length);\n return;\n }\n\n applySpinner.succeed(chalk.green(\"checks.yaml updated and engine files regenerated.\"));\n printAppliedSummary(proposals.length, staleChecks.length);\n}\n\nfunction printAppliedSummary(added: number, wrapped: number): void {\n const parts: string[] = [];\n if (added > 0) parts.push(chalk.green(`${added} check${added === 1 ? \"\" : \"s\"} added`));\n if (wrapped > 0)\n parts.push(chalk.yellow(`${wrapped} stale check${wrapped === 1 ? \"\" : \"s\"} wrapped`));\n if (parts.length > 0) console.log(\" \" + parts.join(\" · \"));\n console.log(\n chalk.dim(\"\\n Review checks.yaml, then commit: \") +\n chalk.yellow(\"git add checks.yaml && git commit -m 'chore: evolve holdpoint checks'\"),\n );\n}\n"],"mappings":"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","names":["existsSync","existsSync","existsSync","readFileSync","chalk","ora","parseHoldpointYaml","execSync","existsSync","readFileSync","join","existsSync","join","execSync","readdirSync","existsSync","join","execSync","existsSync","chalk","readFileSync","parseHoldpointYaml","ora","existsSync","readFileSync","chalk","parseHoldpointYaml","existsSync","readFileSync","writeFileSync","mkdirSync","chalk","ora","parseHoldpointYaml","buildHookJson","buildCheckScript","buildConfigJson","buildClaudeEngineJson","buildCursorEngine","existsSync","chalk","ora","parseHoldpointYaml","readFileSync","mkdirSync","writeFileSync","buildConfigJson","buildHookJson","buildCheckScript","buildClaudeEngineJson","buildCursorEngine","existsSync","join","dirname","fileURLToPath","execSync","chalk","__dirname","existsSync","readFileSync","writeFileSync","execSync","chalk","ora","parseHoldpointYaml","existsSync","chalk","ora","readFileSync","parseHoldpointYaml","writeFileSync","execSync"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/commands/init.ts","../src/detect.ts","../src/commands/check.ts","../src/evolve/scanner.ts","../src/evolve/templates.ts","../src/evolve/dead-checker.ts","../src/commands/validate.ts","../src/commands/update.ts","../src/commands/build.ts","../src/commands/evolve.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { initCommand } from \"./commands/init.js\";\nimport { checkCommand } from \"./commands/check.js\";\nimport { validateCommand } from \"./commands/validate.js\";\nimport { updateCommand } from \"./commands/update.js\";\nimport { buildCommand } from \"./commands/build.js\";\nimport { evolveCommand } from \"./commands/evolve.js\";\n\nconst program = new Command();\n\nprogram\n .name(\"holdpoint\")\n .description(\"Universal eval-guard for AI coding agents (alpha)\")\n .version(\"0.1.0-alpha.2\");\n\nprogram\n .command(\"init\")\n .description(\"Initialise Holdpoint in the current project\")\n .option(\"--stack <stack>\", \"Stack type: typescript | python | nextjs | fullstack\")\n .option(\n \"--agent <agent>\",\n \"Agent to install for: copilot | claude | cursor | codex (default: all four)\",\n )\n .action(initCommand);\n\nprogram\n .command(\"check\")\n .description(\"Run task checks from checks.yaml\")\n .option(\"--staged\", \"Only check against git-staged files\")\n .action(checkCommand);\n\nprogram\n .command(\"validate\")\n .description(\"Validate checks.yaml schema and print any errors\")\n .action(validateCommand);\n\nprogram\n .command(\"update\")\n .description(\"Regenerate engine files from current checks.yaml (preserves checks.yaml)\")\n .action(updateCommand);\n\nprogram\n .command(\"builder\")\n .description(\"Open the visual builder UI on localhost:4321\")\n .action(buildCommand);\n\nprogram\n .command(\"evolve\")\n .description(\"Scan project and propose (or apply) new checks to keep checks.yaml in sync\")\n .option(\"--apply\", \"Write proposed changes to checks.yaml and regenerate engine files\")\n .action(evolveCommand);\n\nprogram.parse();\n","import { existsSync, readFileSync, writeFileSync, mkdirSync, copyFileSync } from \"node:fs\";\nimport { join, dirname } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport {\n buildHookJson,\n buildCheckScript,\n buildConfigJson,\n buildEngine,\n} from \"@holdpoint/engine-copilot\";\nimport { buildEngineJson as buildClaudeEngineJson } from \"@holdpoint/engine-claude\";\nimport { buildEngine as buildCursorEngine } from \"@holdpoint/engine-cursor\";\nimport {\n buildHooksJson as buildCodexHooksJson,\n buildCheckScript as buildCodexCheckScript,\n spliceAgentsMd,\n buildAgentsMd,\n} from \"@holdpoint/engine-codex\";\nimport { parseHoldpointYaml } from \"@holdpoint/yaml-core\";\nimport type { AgentType, StackType } from \"@holdpoint/types\";\nimport { detectStack } from \"../detect.js\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\nfunction getTemplatePath(stack: StackType): string {\n const name = stack === \"unknown\" ? \"_base\" : stack;\n const candidates = [\n join(__dirname, \"templates\", `${name}.yaml`), // dist/templates/ (published package)\n join(__dirname, \"../../../templates\", `${name}.yaml`), // monorepo dev fallback\n join(process.cwd(), \"templates\", `${name}.yaml`), // cwd fallback\n ];\n for (const p of candidates) {\n if (existsSync(p)) return p;\n }\n return \"\";\n}\n\nfunction getMasterPromptPath(): string {\n const candidates = [\n join(__dirname, \"templates/MASTER_PROMPT.md\"), // dist/templates/ (published package)\n join(__dirname, \"../../../templates/MASTER_PROMPT.md\"), // monorepo dev fallback\n join(process.cwd(), \"templates/MASTER_PROMPT.md\"), // cwd fallback\n ];\n for (const p of candidates) {\n if (existsSync(p)) return p;\n }\n return \"\";\n}\n\nconst MINIMAL_CHECKS_YAML = `version: 1\ncontext:\n guides: {}\nconditions: []\nchecks:\n - id: lint\n label: \"Lint codebase\"\n cmd: \"echo 'Add your lint command here'\"\n\n - id: jsdoc\n label: \"JSDoc on changed public functions\"\n prompt: \"Ensure all changed public functions and exports have JSDoc comments.\"\n`;\n\n/**\n * Initialise Holdpoint in the current project.\n *\n * Writes `checks.yaml` (from a stack template if available), `checks.immutable.json`,\n * and engine adapter files for each target agent (Copilot, Claude, Cursor, Codex).\n * Defaults to installing all four agents; pass `--agent` to restrict to one.\n */\nexport async function initCommand(options: { stack?: string; agent?: string }): Promise<void> {\n const spinner = ora(\"Initialising Holdpoint…\").start();\n\n const stack = (options.stack as StackType | undefined) ?? detectStack();\n\n // Default: install for all agents. Pass --agent=copilot|claude|cursor to restrict.\n const agentOpt = options.agent;\n const agents: AgentType[] =\n !agentOpt || agentOpt === \"all\"\n ? [\"copilot\", \"claude\", \"cursor\", \"codex\"]\n : [agentOpt as AgentType];\n\n spinner.text = `Stack: ${chalk.cyan(stack)} — installing for: ${chalk.cyan(agents.join(\", \"))}`;\n\n // 1. Read or create checks.yaml\n let yamlContent = MINIMAL_CHECKS_YAML;\n if (!existsSync(\"checks.yaml\")) {\n const templatePath = getTemplatePath(stack);\n if (templatePath) {\n yamlContent = readFileSync(templatePath, \"utf8\");\n }\n writeFileSync(\"checks.yaml\", yamlContent, \"utf8\");\n } else {\n yamlContent = readFileSync(\"checks.yaml\", \"utf8\");\n }\n\n const config = parseHoldpointYaml(yamlContent);\n\n // 2. Write checks.immutable.json — read by holdpoint-check.mjs at runtime\n const generatedDir = \".github/holdpoint/generated\";\n mkdirSync(generatedDir, { recursive: true });\n writeFileSync(`${generatedDir}/checks.immutable.json`, buildConfigJson(config), \"utf8\");\n\n // 3. Install engine files for each target agent\n if (agents.includes(\"copilot\")) {\n const hooksDir = \".github/hooks\";\n mkdirSync(hooksDir, { recursive: true });\n writeFileSync(join(hooksDir, \"holdpoint.json\"), buildHookJson(config), \"utf8\");\n writeFileSync(join(hooksDir, \"holdpoint-check.mjs\"), buildCheckScript(config), \"utf8\");\n // extension.mjs: loaded by the Copilot CLI local agent at session start\n const extDir = \".github/extensions/holdpoint\";\n mkdirSync(extDir, { recursive: true });\n writeFileSync(join(extDir, \"extension.mjs\"), buildEngine(config), \"utf8\");\n }\n\n if (agents.includes(\"claude\")) {\n mkdirSync(\".claude\", { recursive: true });\n const settingsPath = \".claude/settings.json\";\n let existing: Record<string, unknown> = {};\n if (existsSync(settingsPath)) {\n try {\n existing = JSON.parse(readFileSync(settingsPath, \"utf8\")) as Record<string, unknown>;\n } catch {\n /* ignore */\n }\n }\n const holdpointHooks = JSON.parse(buildClaudeEngineJson(config)) as Record<string, unknown>;\n writeFileSync(\n settingsPath,\n JSON.stringify({ ...existing, hooks: holdpointHooks.hooks }, null, 2),\n \"utf8\",\n );\n }\n\n if (agents.includes(\"cursor\")) {\n const cursorRules = buildCursorEngine(config);\n const cursorPath = \".cursorrules\";\n if (existsSync(cursorPath)) {\n const existing = readFileSync(cursorPath, \"utf8\");\n if (!existing.includes(\"Holdpoint Rules\")) {\n writeFileSync(cursorPath, existing + \"\\n\" + cursorRules, \"utf8\");\n }\n } else {\n writeFileSync(cursorPath, cursorRules, \"utf8\");\n }\n }\n\n if (agents.includes(\"codex\")) {\n mkdirSync(\".codex\", { recursive: true });\n writeFileSync(\".codex/hooks.json\", buildCodexHooksJson(config), \"utf8\");\n writeFileSync(\".codex/holdpoint-check.mjs\", buildCodexCheckScript(), \"utf8\");\n const agentsMdPath = \"AGENTS.md\";\n const existing = existsSync(agentsMdPath) ? readFileSync(agentsMdPath, \"utf8\") : \"\";\n writeFileSync(agentsMdPath, spliceAgentsMd(existing, config), \"utf8\");\n }\n\n // 4. Create MASTER_PROMPT.md if not present\n if (!existsSync(\"MASTER_PROMPT.md\")) {\n const guidePath = getMasterPromptPath();\n if (guidePath) {\n copyFileSync(guidePath, \"MASTER_PROMPT.md\");\n } else {\n // Fallback: minimal prompt if template file is not bundled\n writeFileSync(\n \"MASTER_PROMPT.md\",\n \"# Holdpoint\\n\\nRun `npx @holdpoint/cli@alpha check` before marking any task complete.\\nSee `checks.yaml` for the full list of checks.\\n\",\n \"utf8\",\n );\n }\n }\n\n spinner.succeed(chalk.bold.green(\"Holdpoint initialised!\"));\n\n console.log(`\n${chalk.cyan(\"Next steps:\")}\n 1. Edit ${chalk.yellow(\"checks.yaml\")} to customise your eval checkpoints\n 2. Commit ${chalk.yellow(\"checks.yaml\")} and the generated engine files\n 3. Run ${chalk.yellow(\"npx @holdpoint/cli@alpha check\")} at any time to validate\n\n Visual builder: ${chalk.yellow(\"npx @holdpoint/cli@alpha builder\")} (opens localhost:4321)\n Stack: ${chalk.cyan(stack)} Agents: ${chalk.cyan(agents.join(\", \"))}\n`);\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport type { AgentType, StackType } from \"@holdpoint/types\";\n\n/** @deprecated Use detectInstalledAgents() — single-agent detection is no longer the default. */\nexport function detectAgent(): AgentType {\n if (existsSync(\".github/extensions\")) return \"copilot\";\n if (existsSync(\".claude\")) return \"claude\";\n if (existsSync(\".cursorrules\")) return \"cursor\";\n if (existsSync(\".codex\")) return \"codex\";\n return \"unknown\";\n}\n\n/**\n * Returns every agent whose Holdpoint engine files are already present in the\n * current working directory. Used by `holdpoint update` so it regenerates only\n * the engines that were previously installed.\n */\nexport function detectInstalledAgents(): AgentType[] {\n const agents: AgentType[] = [];\n if (existsSync(\".github/hooks/holdpoint.json\")) agents.push(\"copilot\");\n if (existsSync(\".claude/settings.json\")) agents.push(\"claude\");\n if (existsSync(\".cursorrules\")) {\n try {\n if (readFileSync(\".cursorrules\", \"utf8\").includes(\"Holdpoint Rules\")) {\n agents.push(\"cursor\");\n }\n } catch {\n /* ignore unreadable file */\n }\n }\n // Detect Codex by the generated check script (more specific than .codex/ existence)\n if (existsSync(\".codex/holdpoint-check.mjs\")) agents.push(\"codex\");\n return agents;\n}\n\nexport function detectStack(): StackType {\n const hasNext =\n existsSync(\"next.config.ts\") || existsSync(\"next.config.js\") || existsSync(\"next.config.mjs\");\n const hasTsConfig = existsSync(\"tsconfig.json\");\n const hasPyproject =\n existsSync(\"pyproject.toml\") || existsSync(\"requirements.txt\") || existsSync(\"setup.py\");\n const hasPrisma = existsSync(\"prisma/schema.prisma\");\n const hasApi = existsSync(\"server\") || existsSync(\"api\") || existsSync(\"backend\");\n const hasGoMod = existsSync(\"go.mod\");\n\n if (hasNext && (hasPrisma || hasApi)) return \"fullstack\";\n if (hasNext) return \"nextjs\";\n if (hasTsConfig) return \"typescript\";\n if (hasPyproject) return \"python\";\n if (hasGoMod) return \"go\";\n return \"unknown\";\n}\n","import { existsSync, readFileSync, writeFileSync, mkdirSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport { parseHoldpointYaml, matchesWhen } from \"@holdpoint/yaml-core\";\nimport { runDeterministicChecks } from \"@holdpoint/yaml-core/runner\";\nimport type { CheckResult } from \"@holdpoint/types\";\nimport { execSync } from \"node:child_process\";\nimport { scanProject } from \"../evolve/scanner.js\";\nimport { getTemplates } from \"../evolve/templates.js\";\nimport { detectStaleChecks, getRepoFiles } from \"../evolve/dead-checker.js\";\n\nconst COMMIT_CACHE_PATH = \".holdpoint/checked-commits.json\";\nconst COMMIT_CACHE_MAX = 100;\n\nfunction getStagedFiles(): string[] {\n try {\n const out = execSync(\"git diff --cached --name-only\", {\n encoding: \"utf8\",\n stdio: [\"pipe\", \"pipe\", \"ignore\"],\n });\n return out.trim().split(\"\\n\").filter(Boolean);\n } catch {\n return [];\n }\n}\n\nfunction getAllChangedFiles(): string[] {\n try {\n const out = execSync(\"git diff --name-only HEAD\", {\n encoding: \"utf8\",\n stdio: [\"pipe\", \"pipe\", \"ignore\"],\n });\n return out.trim().split(\"\\n\").filter(Boolean);\n } catch {\n return [];\n }\n}\n\n/**\n * Returns the files changed in the most recent commit (HEAD vs HEAD~1).\n * Used as a fallback when no staged files exist but the agent has already committed.\n */\nfunction getLastCommitFiles(): string[] {\n try {\n const out = execSync(\"git diff --name-only HEAD~1 HEAD\", {\n encoding: \"utf8\",\n stdio: [\"pipe\", \"pipe\", \"ignore\"],\n });\n return out.trim().split(\"\\n\").filter(Boolean);\n } catch {\n return [];\n }\n}\n\n/** Returns the current HEAD commit SHA, or null if unavailable. */\nfunction getHeadSha(): string | null {\n try {\n return execSync(\"git rev-parse HEAD\", {\n encoding: \"utf8\",\n stdio: [\"pipe\", \"pipe\", \"ignore\"],\n }).trim();\n } catch {\n return null;\n }\n}\n\n/** Returns the set of already-verified commit SHAs from the local cache. */\nfunction readCommitCache(): Set<string> {\n try {\n const raw = readFileSync(COMMIT_CACHE_PATH, \"utf8\");\n const parsed = JSON.parse(raw) as { verified?: unknown };\n return new Set(Array.isArray(parsed.verified) ? (parsed.verified as string[]) : []);\n } catch {\n return new Set();\n }\n}\n\n/**\n * Records a commit SHA as verified in the local cache.\n * Caps the cache at COMMIT_CACHE_MAX entries (newest first).\n */\nfunction recordCommitCache(sha: string): void {\n try {\n const existing = readCommitCache();\n const updated = [sha, ...[...existing].filter((s) => s !== sha)].slice(0, COMMIT_CACHE_MAX);\n mkdirSync(join(COMMIT_CACHE_PATH, \"..\"), { recursive: true });\n writeFileSync(COMMIT_CACHE_PATH, JSON.stringify({ verified: updated }, null, 2) + \"\\n\", \"utf8\");\n } catch {\n // Non-fatal: cache write failure just means the next run re-checks this commit.\n }\n}\n\nexport async function checkCommand(options: { staged?: boolean }): Promise<void> {\n if (!existsSync(\"checks.yaml\")) {\n console.error(chalk.red(\"No checks.yaml found. Run `holdpoint init` first.\"));\n process.exit(1);\n }\n\n const yamlContent = readFileSync(\"checks.yaml\", \"utf8\");\n let config;\n try {\n config = parseHoldpointYaml(yamlContent);\n } catch (err: unknown) {\n console.error(chalk.red(\"Invalid checks.yaml:\"), (err as Error).message);\n process.exit(1);\n }\n\n let changedFiles: string[];\n let headSha: string | null = null;\n\n if (options.staged) {\n const staged = getStagedFiles();\n if (staged.length > 0) {\n changedFiles = staged;\n } else {\n // Nothing staged — check if HEAD was already verified to avoid a check loop.\n headSha = getHeadSha();\n if (headSha && readCommitCache().has(headSha)) {\n console.log(\n chalk.green(`✓ Commit ${headSha.slice(0, 8)} already verified — nothing to re-check.`),\n );\n process.exit(0);\n }\n\n // Fall back to files in the most recent commit (covers the\n // \"agent committed then called task_complete\" workflow).\n const lastCommit = getLastCommitFiles();\n if (lastCommit.length > 0) {\n changedFiles = lastCommit;\n console.log(\n chalk.yellow(\"No staged files. Running checks scoped to the most recent commit's files.\"),\n );\n } else {\n // Truly nothing changed (investigative session, no recent commit).\n console.log(chalk.green(\"✓ No staged changes and no recent commit — nothing to check.\"));\n process.exit(0);\n }\n }\n } else {\n changedFiles = getAllChangedFiles();\n if (changedFiles.length === 0) {\n console.log(\n chalk.yellow(\"No changed files detected. Running all checks with no file filter.\"),\n );\n }\n }\n\n // Print project guides so the agent/human sees them before running checks\n const guides = Object.entries(config.context?.guides ?? {});\n if (guides.length > 0) {\n console.log(chalk.cyan(\"\\nProject guides:\"));\n for (const [key, text] of guides) {\n console.log(chalk.bold(` ${key}:`), chalk.dim(String(text).trim()));\n }\n console.log(\"\");\n }\n\n const taskCount = config.checks.filter((c) => c.cmd !== undefined).length;\n const spinner = ora(`Running ${taskCount} task(s)…`).start();\n const effectiveFiles = changedFiles.length > 0 ? changedFiles : [\"__all__\"];\n const results = runDeterministicChecks(config, effectiveFiles);\n\n // Built-in structural drift detection — hardcoded into holdpoint, not user-configurable.\n // Fires when structural indicator files changed (or when all checks run with no staged files).\n const runDrift = matchesWhen(\"structural\", effectiveFiles);\n if (runDrift) {\n const profile = scanProject();\n const existingIds = new Set(config.checks.map((c) => c.id));\n const templates = getTemplates(profile);\n const proposals = templates.filter((t) => t.trigger(profile) && !existingIds.has(t.id));\n const repoFiles = getRepoFiles(process.cwd());\n const staleChecks = detectStaleChecks(config, repoFiles);\n\n if (proposals.length > 0 || staleChecks.length > 0) {\n const lines: string[] = [];\n if (proposals.length > 0) {\n lines.push(`${proposals.length} new check(s) available for your project stack:`);\n for (const p of proposals) lines.push(` + ${p.label}`);\n }\n if (staleChecks.length > 0) {\n lines.push(`${staleChecks.length} stale check(s) no longer match your project:`);\n for (const s of staleChecks) lines.push(` - ${s.check.label}: ${s.reason}`);\n }\n lines.push(\"\\nRun: npx @holdpoint/cli@alpha evolve --apply\");\n results.push({\n check: { id: \"__holdpoint_evolve__\", label: \"Evolve checks with project structure\" },\n status: \"fail\",\n output: lines.join(\"\\n\"),\n });\n }\n }\n\n const passed = results.filter((r) => r.status === \"pass\");\n const failed = results.filter((r) => r.status === \"fail\");\n const skipped = results.filter((r) => r.status === \"skip\");\n\n spinner.stop();\n\n // Print results\n for (const result of results) {\n printResult(result);\n }\n\n // Summary\n console.log(\"\");\n console.log(\n [\n chalk.green(`✓ ${passed.length} passed`),\n failed.length > 0 ? chalk.red(`✗ ${failed.length} failed`) : \"\",\n skipped.length > 0 ? chalk.gray(`◌ ${skipped.length} skipped`) : \"\",\n ]\n .filter(Boolean)\n .join(\" \"),\n );\n\n // Prompt checks: show those whose when filter matches the changed files\n const promptChecks = config.checks.filter(\n (c) =>\n c.prompt !== undefined &&\n matchesWhen(c.when, changedFiles.length > 0 ? changedFiles : [\"__all__\"], config.patterns),\n );\n if (promptChecks.length > 0) {\n console.log(`\\n${chalk.cyan(\"Agent prompts to act on:\")}`);\n for (const c of promptChecks) {\n console.log(` ${chalk.yellow(\"□\")} [${c.label}] ${c.prompt ?? \"\"}`);\n }\n }\n\n if (failed.length > 0) {\n process.exit(1);\n }\n\n // All checks passed — if we ran against a committed HEAD (no staged files), mark it verified\n // so subsequent task_complete calls on the same commit skip straight through.\n if (headSha) {\n recordCommitCache(headSha);\n }\n}\n\nfunction printResult(result: CheckResult): void {\n const icon =\n result.status === \"pass\"\n ? chalk.green(\"✓\")\n : result.status === \"fail\"\n ? chalk.red(\"✗\")\n : result.status === \"skip\"\n ? chalk.gray(\"◌\")\n : chalk.yellow(\"…\");\n\n const label = result.check.label;\n console.log(`${icon} ${label}`);\n\n if (result.status === \"fail\" && result.output) {\n const trimmed = result.output.trim().split(\"\\n\").slice(0, 10).join(\"\\n\");\n console.log(chalk.dim(trimmed.replace(/^/gm, \" \")));\n }\n if (result.status === \"skip\" && result.skipReason) {\n console.log(chalk.dim(` ${result.skipReason}`));\n }\n}\n","import { existsSync, readFileSync, readdirSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { execSync } from \"node:child_process\";\n\nexport interface ProjectProfile {\n // Languages\n hasTypeScript: boolean;\n hasPython: boolean;\n hasGo: boolean;\n hasRust: boolean;\n hasJava: boolean;\n hasRuby: boolean;\n // Frameworks\n hasNext: boolean;\n hasReact: boolean;\n // Linting\n hasEslint: boolean;\n hasBiome: boolean;\n hasRuff: boolean;\n hasPrettier: boolean;\n // Testing\n hasVitest: boolean;\n hasJest: boolean;\n hasPytest: boolean;\n // DB\n hasPrisma: boolean;\n hasDrizzle: boolean;\n hasMigrations: boolean;\n hasAlembic: boolean;\n // Infra\n hasDocker: boolean;\n hasTerraform: boolean;\n hasKubernetes: boolean;\n // API\n hasOpenApi: boolean;\n // CI\n hasGithubActions: boolean;\n // Package manager\n packageManager: \"pnpm\" | \"yarn\" | \"bun\" | \"npm\";\n // Raw scripts from package.json\n scripts: Record<string, string>;\n // All dep names (deps + devDeps)\n deps: Set<string>;\n}\n\ntype PkgJson = {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n scripts?: Record<string, string>;\n};\n\nfunction tryReadJson<T>(path: string): T | null {\n try {\n return JSON.parse(readFileSync(path, \"utf8\")) as T;\n } catch {\n return null;\n }\n}\n\nfunction tryReadText(path: string): string {\n try {\n return readFileSync(path, \"utf8\");\n } catch {\n return \"\";\n }\n}\n\n/**\n * Walk a directory up to maxDepth levels, returning all file paths relative to root.\n * Excludes common build artifacts and dependency directories.\n */\nfunction walkDir(\n dir: string,\n root: string,\n depth: number,\n maxDepth: number,\n ignored: Set<string>,\n): string[] {\n if (depth > maxDepth) return [];\n let entries: string[] = [];\n try {\n entries = readdirSync(dir);\n } catch {\n return [];\n }\n const results: string[] = [];\n for (const entry of entries) {\n if (ignored.has(entry)) continue;\n const full = join(dir, entry);\n const rel = full.slice(root.length + 1);\n try {\n // Use stat-free heuristic: if it has an extension it's likely a file\n // If no extension and doesn't start with \".\", try as directory\n const hasExt = entry.includes(\".\");\n if (!hasExt || entry.startsWith(\".\")) {\n // Could be a dir — try recursing\n const children = walkDir(full, root, depth + 1, maxDepth, ignored);\n if (children.length > 0) {\n results.push(...children);\n } else if (hasExt) {\n results.push(rel);\n }\n } else {\n results.push(rel);\n }\n } catch {\n // skip\n }\n }\n return results;\n}\n\nconst WALK_IGNORED = new Set([\n \"node_modules\",\n \".git\",\n \"dist\",\n \"build\",\n \".next\",\n \".turbo\",\n \"__pycache__\",\n \".venv\",\n \"venv\",\n \".mypy_cache\",\n \"target\",\n \".cache\",\n \"coverage\",\n \".nyc_output\",\n]);\n\n/**\n * Returns a list of all files in the repo (relative paths from cwd).\n * Uses `git ls-files` when inside a git repo; falls back to directory walk.\n */\nexport function getRepoFiles(cwd: string): string[] {\n try {\n const out = execSync(\"git ls-files\", {\n cwd,\n encoding: \"utf8\",\n stdio: [\"pipe\", \"pipe\", \"ignore\"],\n });\n const files = out.trim().split(\"\\n\").filter(Boolean);\n if (files.length > 0) return files;\n } catch {\n // not a git repo or git not available\n }\n return walkDir(cwd, cwd, 0, 6, WALK_IGNORED);\n}\n\n/**\n * Returns true if the file path is a structural project indicator — i.e., a file\n * whose addition or modification may require new checks to be added to checks.yaml.\n * Mirrors the detection patterns used in `scanProject()`.\n */\nexport function isStructuralFile(file: string): boolean {\n const f = file.replace(/\\\\/g, \"/\");\n\n // JS / TS project structure\n if (f === \"package.json\") return true;\n if (/^tsconfig[^/]*\\.json$/.test(f)) return true;\n\n // Python\n if (/^requirements[^/]*\\.txt$/.test(f)) return true;\n if (f === \"pyproject.toml\") return true;\n if (f === \"Pipfile\") return true;\n if (f === \"setup.py\") return true;\n if (f === \"setup.cfg\") return true;\n if (f === \"pytest.ini\") return true;\n if (f === \"tox.ini\") return true;\n\n // Go\n if (f === \"go.mod\") return true;\n\n // Rust\n if (f === \"Cargo.toml\") return true;\n\n // Java / Kotlin\n if (f === \"pom.xml\") return true;\n if (/^build\\.gradle(\\.kts)?$/.test(f)) return true;\n\n // Ruby\n if (f === \"Gemfile\") return true;\n\n // Test frameworks\n if (/^vitest\\.config\\.[^/]+$/.test(f)) return true;\n if (/^jest\\.config\\.[^/]+$/.test(f)) return true;\n if (/^playwright\\.config\\.[^/]+$/.test(f)) return true;\n\n // Linters / formatters\n if (/^eslint\\.config\\.[^/]+$/.test(f)) return true;\n if (/^\\.eslintrc[^/]*$/.test(f)) return true;\n if (/^biome\\.jsonc?$/.test(f)) return true;\n if (/^prettier\\.config\\.[^/]+$/.test(f)) return true;\n if (/^\\.prettierrc[^/]*$/.test(f)) return true;\n\n // Next.js\n if (/^next\\.config\\.[^/]+$/.test(f)) return true;\n\n // Docker / infra\n if (/^Dockerfile[^/]*$/.test(f)) return true;\n if (/^docker-compose[^/]*\\.ya?ml$/.test(f)) return true;\n if (/[^/]*\\.tf$/.test(f)) return true;\n\n // Database\n if (f === \"prisma/schema.prisma\") return true;\n\n // OpenAPI\n if (/^(api\\/)?openapi\\.(yaml|yml|json)$/.test(f)) return true;\n\n // CI\n if (/^\\.github\\/workflows\\/[^/]+\\.ya?ml$/.test(f)) return true;\n if (/^\\.circleci\\/.+$/.test(f)) return true;\n if (f === \"Jenkinsfile\") return true;\n if (f === \".gitlab-ci.yml\") return true;\n if (f === \".travis.yml\") return true;\n\n return false;\n}\n\n/**\n * Scan the project at `cwd` and return a `ProjectProfile`.\n * All detection is pure filesystem reads — no shell commands executed.\n */\nexport function scanProject(cwd = process.cwd()): ProjectProfile {\n const exists = (p: string) => existsSync(join(cwd, p));\n\n // Package manager\n const packageManager: ProjectProfile[\"packageManager\"] = exists(\"pnpm-lock.yaml\")\n ? \"pnpm\"\n : exists(\"yarn.lock\")\n ? \"yarn\"\n : exists(\"bun.lockb\")\n ? \"bun\"\n : \"npm\";\n\n // package.json\n const pkg = tryReadJson<PkgJson>(join(cwd, \"package.json\"));\n const scripts = pkg?.scripts ?? {};\n const deps = new Set<string>([\n ...Object.keys(pkg?.dependencies ?? {}),\n ...Object.keys(pkg?.devDependencies ?? {}),\n ]);\n\n // Python manifest scanning\n const pyprojectText = tryReadText(join(cwd, \"pyproject.toml\"));\n const requirementsText = tryReadText(join(cwd, \"requirements.txt\"));\n const pipfileText = tryReadText(join(cwd, \"Pipfile\"));\n const allPyText = pyprojectText + requirementsText + pipfileText;\n\n const hasPytest =\n exists(\"pytest.ini\") ||\n exists(\"setup.cfg\") ||\n allPyText.includes(\"pytest\") ||\n allPyText.includes(\"[tool.pytest\");\n const hasRuff = allPyText.includes(\"ruff\") || deps.has(\"ruff\");\n const hasAlembic = allPyText.includes(\"alembic\") || deps.has(\"alembic\");\n\n // Root-level file listing (for Dockerfile variants and .tf files)\n let rootFiles: string[] = [];\n try {\n rootFiles = readdirSync(cwd);\n } catch {\n // ignore\n }\n\n const hasDocker =\n rootFiles.some((f) => f === \"Dockerfile\" || f.startsWith(\"Dockerfile.\")) ||\n exists(\"docker-compose.yml\") ||\n exists(\"docker-compose.yaml\") ||\n exists(\"docker-compose.dev.yml\");\n\n const hasTerraform =\n rootFiles.some((f) => f.endsWith(\".tf\")) || exists(\"terraform\") || exists(\"infra\");\n\n return {\n // Languages\n hasTypeScript: exists(\"tsconfig.json\") || deps.has(\"typescript\"),\n hasPython:\n Boolean(pyprojectText) ||\n Boolean(requirementsText) ||\n Boolean(pipfileText) ||\n exists(\"setup.py\"),\n hasGo: exists(\"go.mod\"),\n hasRust: exists(\"Cargo.toml\"),\n hasJava: exists(\"pom.xml\") || exists(\"build.gradle\") || exists(\"build.gradle.kts\"),\n hasRuby: exists(\"Gemfile\"),\n\n // Frameworks\n hasNext:\n exists(\"next.config.ts\") ||\n exists(\"next.config.js\") ||\n exists(\"next.config.mjs\") ||\n deps.has(\"next\"),\n hasReact: deps.has(\"react\"),\n\n // Linting\n hasEslint:\n exists(\"eslint.config.js\") ||\n exists(\"eslint.config.ts\") ||\n exists(\"eslint.config.mjs\") ||\n exists(\".eslintrc.js\") ||\n exists(\".eslintrc.json\") ||\n exists(\".eslintrc.yml\") ||\n exists(\".eslintrc.yaml\") ||\n deps.has(\"eslint\"),\n hasBiome: exists(\"biome.json\") || exists(\"biome.jsonc\") || deps.has(\"@biomejs/biome\"),\n hasRuff,\n hasPrettier:\n exists(\"prettier.config.js\") ||\n exists(\"prettier.config.ts\") ||\n exists(\"prettier.config.mjs\") ||\n exists(\".prettierrc\") ||\n exists(\".prettierrc.json\") ||\n deps.has(\"prettier\"),\n\n // Testing\n hasVitest: deps.has(\"vitest\") || Boolean(scripts[\"test\"]?.includes(\"vitest\")),\n hasJest: deps.has(\"jest\") || Boolean(scripts[\"test\"]?.includes(\"jest\")),\n hasPytest,\n\n // DB\n hasPrisma: exists(\"prisma/schema.prisma\") || deps.has(\"@prisma/client\"),\n hasDrizzle: deps.has(\"drizzle-orm\"),\n hasMigrations: exists(\"migrations\") || exists(\"db/migrations\") || exists(\"database/migrations\"),\n hasAlembic,\n\n // Infra\n hasDocker,\n hasTerraform,\n hasKubernetes: exists(\"k8s\") || exists(\"kubernetes\") || exists(\"helm\"),\n\n // API\n hasOpenApi:\n exists(\"openapi.yaml\") ||\n exists(\"openapi.yml\") ||\n exists(\"openapi.json\") ||\n exists(\"api/openapi.yaml\"),\n\n // CI\n hasGithubActions: exists(\".github/workflows\"),\n\n packageManager,\n scripts,\n deps,\n };\n}\n","import type { ConditionDef } from \"@holdpoint/types\";\nimport type { ProjectProfile } from \"./scanner.js\";\n\nexport interface EvolveTemplate {\n id: string;\n label: string;\n when?: string;\n cmd?: string;\n prompt?: string;\n conditionId?: string;\n /** Condition to add to checks.yaml alongside the check (only if conditionId is set) */\n condition?: Omit<ConditionDef, \"id\"> & { id: string };\n /** Returns true if this check is relevant to the given project profile */\n trigger: (p: ProjectProfile) => boolean;\n}\n\n/** Returns the correct run command for a package.json script, respecting the detected package manager. */\nfunction pmScript(profile: ProjectProfile, script: string, fallback: string): string {\n if (!profile.scripts[script]) return fallback;\n if (profile.packageManager === \"npm\") return `npm run ${script}`;\n return `${profile.packageManager} ${script}`;\n}\n\n/**\n * Returns all applicable check templates for the given project profile.\n * Caller should filter out templates whose IDs already exist in checks.yaml.\n */\nexport function getTemplates(profile: ProjectProfile): EvolveTemplate[] {\n return [\n // ── Universal checks (always proposed for any project) ──────────────────\n {\n id: \"git-commit\",\n label: \"Commit all changes before finishing\",\n cmd: 'git rev-parse --is-inside-work-tree 2>/dev/null || exit 0; [ -z \"$(git status --porcelain)\" ] && exit 0; git status --short; exit 1',\n trigger: () => true,\n },\n {\n id: \"changelog-update\",\n label: \"Add a CHANGELOG.md entry for this session\",\n prompt:\n \"Before committing, add an entry to CHANGELOG.md describing what was done. \" +\n \"Use Keep a Changelog format — add under ## [Unreleased] (create the file \" +\n \"and that section if absent). Group entries as Added, Changed, Fixed, or Removed. \" +\n \"Be concise but specific. The entry text will serve as the commit message.\",\n trigger: () => true,\n },\n {\n id: \"readme-sync\",\n label: \"Update README.md if user-facing changes were made\",\n prompt:\n \"If you added, changed, or removed user-facing functionality — CLI commands, \" +\n \"configuration options, public APIs, or significant new features — update \" +\n \"README.md to reflect those changes.\",\n trigger: () => true,\n },\n {\n id: \"no-todos\",\n label: \"No TODO/FIXME left in changed code\",\n prompt:\n \"Scan the files you changed for any TODO, FIXME, HACK, or XXX comments. \" +\n \"Either resolve them before finishing or convert them to GitHub issues. \" +\n \"Don't leave incomplete work silently behind.\",\n trigger: () => true,\n },\n\n // ── TypeScript / JavaScript ──────────────────────────────────────────────\n {\n id: \"typecheck\",\n label: \"TypeScript type check\",\n cmd: pmScript(profile, \"typecheck\", \"npx tsc --noEmit\"),\n trigger: (p) => p.hasTypeScript,\n },\n {\n id: \"lint\",\n label: \"Lint codebase\",\n cmd: profile.hasEslint\n ? pmScript(profile, \"lint\", \"npx eslint .\")\n : profile.hasBiome\n ? pmScript(profile, \"lint\", \"npx @biomejs/biome check .\")\n : pmScript(profile, \"lint\", \"echo 'No linter detected'\"),\n trigger: (p) => p.hasEslint || p.hasBiome,\n },\n {\n id: \"format-check\",\n label: \"Prettier — format check\",\n cmd: pmScript(profile, \"format:check\", \"npx prettier --check .\"),\n trigger: (p) => p.hasPrettier,\n },\n {\n id: \"test\",\n label: \"Unit tests\",\n cmd: profile.hasVitest\n ? pmScript(profile, \"test\", \"npx vitest run\")\n : pmScript(profile, \"test\", \"npx jest --passWithNoTests\"),\n trigger: (p) => p.hasVitest || p.hasJest,\n },\n {\n id: \"jsdoc\",\n label: \"JSDoc on changed public functions\",\n prompt:\n \"Ensure all changed public functions, classes, and module exports have \" +\n \"accurate JSDoc comments (description + @param + @returns where applicable).\",\n trigger: (p) => p.hasTypeScript || p.hasReact,\n },\n {\n id: \"build\",\n label: \"Production build passes\",\n cmd: pmScript(profile, \"build\", \"echo 'No build script detected'\"),\n trigger: (p) => Boolean(p.scripts[\"build\"]),\n },\n\n // ── Python ───────────────────────────────────────────────────────────────\n {\n id: \"python-lint\",\n label: \"Ruff — Python linting\",\n cmd: \"ruff check .\",\n when: \"python\",\n trigger: (p) => p.hasPython && p.hasRuff,\n },\n {\n id: \"python-test\",\n label: \"Pytest — Python unit tests\",\n cmd: \"pytest\",\n when: \"python\",\n trigger: (p) => p.hasPython && p.hasPytest,\n },\n\n // ── Go ───────────────────────────────────────────────────────────────────\n {\n id: \"go-test\",\n label: \"Go tests\",\n cmd: \"go test ./...\",\n when: \"go\",\n trigger: (p) => p.hasGo,\n },\n {\n id: \"go-vet\",\n label: \"Go vet\",\n cmd: \"go vet ./...\",\n when: \"go\",\n trigger: (p) => p.hasGo,\n },\n\n // ── Database ─────────────────────────────────────────────────────────────\n {\n id: \"db-migrations\",\n label: \"Database migration for schema changes\",\n when: \"database\",\n prompt:\n \"If schema or migration files changed, ensure the appropriate migration was \" +\n \"generated with your ORM tool (e.g. `prisma migrate dev`, `alembic revision`, \" +\n \"`rails db:migrate`) and committed alongside the schema change.\",\n trigger: (p) => p.hasPrisma || p.hasAlembic || p.hasMigrations || p.hasDrizzle,\n },\n {\n id: \"prisma-format\",\n label: \"Prisma schema format check\",\n when: \"prisma\",\n cmd: \"npx prisma format --check 2>/dev/null || npx prisma format\",\n conditionId: \"has-prisma\",\n condition: {\n id: \"has-prisma\",\n operator: \"file_exists\",\n path: \"prisma/schema.prisma\",\n },\n trigger: (p) => p.hasPrisma,\n },\n\n // ── OpenAPI ──────────────────────────────────────────────────────────────\n {\n id: \"openapi-sync\",\n label: \"OpenAPI spec updated for API changes\",\n when: \"backend\",\n conditionId: \"has-openapi\",\n condition: {\n id: \"has-openapi\",\n operator: \"file_exists\",\n path: \"openapi.yaml\",\n },\n prompt:\n \"If any API routes were added or changed, update openapi.yaml (or openapi.json) \" +\n \"to reflect the new endpoints, request/response shapes, and error codes.\",\n trigger: (p) => p.hasOpenApi,\n },\n\n // ── Infra ─────────────────────────────────────────────────────────────────\n {\n id: \"docker-build\",\n label: \"Docker build passes\",\n when: \"infra\",\n cmd: \"docker build . --quiet -t app:ci\",\n conditionId: \"has-dockerfile\",\n condition: {\n id: \"has-dockerfile\",\n operator: \"file_exists\",\n path: \"Dockerfile\",\n },\n trigger: (p) => p.hasDocker,\n },\n {\n id: \"terraform-validate\",\n label: \"Terraform validate\",\n when: \"infra\",\n cmd: \"terraform validate\",\n trigger: (p) => p.hasTerraform,\n },\n\n // ── Frontend ─────────────────────────────────────────────────────────────\n {\n id: \"i18n\",\n label: \"i18n — no hardcoded user-facing strings\",\n when: \"frontend\",\n prompt:\n \"Confirm all user-visible strings are wrapped in the project's i18n function \" +\n \"(e.g. `t()`, `useTranslation`, `<Trans>`) and that locale files are updated \" +\n \"for any new copy.\",\n trigger: (p) => p.hasNext && p.hasReact,\n },\n ];\n}\n","import { execSync } from \"node:child_process\";\nimport { readdirSync, existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { CheckDef, HoldpointConfig } from \"@holdpoint/types\";\n\nexport interface StaleCheck {\n check: CheckDef;\n reason: string;\n /** Path to use in a file_exists condition, if it can be inferred from the when: regex */\n suggestedConditionPath?: string;\n}\n\n/** Named scopes handled by matchesWhen() — these are never \"stale\" (intentionally broad) */\nconst NAMED_SCOPES = new Set([\n \"frontend\",\n \"backend\",\n \"socket\",\n \"visual\",\n \"python\",\n \"go\",\n \"rust\",\n \"java\",\n \"ruby\",\n \"database\",\n \"prisma\",\n \"testing\",\n \"infra\",\n \"ci\",\n \"docs\",\n \"structural\",\n]);\n\nconst WALK_IGNORED = new Set([\n \"node_modules\",\n \".git\",\n \"dist\",\n \"build\",\n \".next\",\n \".turbo\",\n \"__pycache__\",\n \".venv\",\n \"venv\",\n \".mypy_cache\",\n \"target\",\n \".cache\",\n \"coverage\",\n]);\n\nfunction walkDir(dir: string, root: string, depth: number, maxDepth: number): string[] {\n if (depth > maxDepth) return [];\n let entries: string[] = [];\n try {\n entries = readdirSync(dir);\n } catch {\n return [];\n }\n const results: string[] = [];\n for (const entry of entries) {\n if (WALK_IGNORED.has(entry) || entry.startsWith(\".\")) continue;\n const full = join(dir, entry);\n const rel = full.slice(root.length + 1);\n results.push(rel);\n // Try to recurse (will just return [] if it's a file, not a dir)\n const children = walkDir(full, root, depth + 1, maxDepth);\n results.push(...children);\n }\n return results;\n}\n\n/**\n * Returns a list of all files in the repo (relative paths from cwd).\n * Uses `git ls-files` when available; falls back to directory walk.\n */\nexport function getRepoFiles(cwd: string): string[] {\n try {\n const out = execSync(\"git ls-files\", {\n cwd,\n encoding: \"utf8\",\n stdio: [\"pipe\", \"pipe\", \"ignore\"],\n });\n const files = out.trim().split(\"\\n\").filter(Boolean);\n if (files.length > 0) return files;\n } catch {\n // not a git repo or git not available\n }\n return walkDir(cwd, cwd, 0, 6);\n}\n\n/**\n * Try to extract a simple path hint from a regex pattern, for use as a\n * `file_exists` condition path.\n * e.g. \"^prisma/\" → \"prisma\", \"^checks\\\\.yaml$\" → \"checks.yaml\"\n */\nfunction extractPathFromRegex(pattern: string): string | undefined {\n const cleaned = pattern\n .replace(/^\\^/, \"\")\n .replace(/\\$$/, \"\")\n .replace(/\\\\\\./g, \".\")\n .replace(/\\(\\?:/g, \"\")\n .replace(/\\)/g, \"\")\n .replace(/[|*+?[\\]{}()]/g, \"\");\n const candidate = cleaned.replace(/\\/$/, \"\").trim();\n if (candidate.length > 0 && /^[\\w\\-./]+$/.test(candidate)) return candidate;\n return undefined;\n}\n\n/**\n * Detect checks whose `when:` regex pattern matches zero files in the repo.\n * Named scope whens (frontend, backend, structural, etc.) are never flagged as stale.\n * User-defined named patterns (from config.patterns) are resolved to their regex before checking.\n * Checks that already have a conditionId are skipped (already guarded).\n */\nexport function detectStaleChecks(config: HoldpointConfig, repoFiles: string[]): StaleCheck[] {\n const stale: StaleCheck[] = [];\n const userPatterns = config.patterns ?? {};\n\n for (const check of config.checks) {\n if (!check.when) continue;\n if (NAMED_SCOPES.has(check.when)) continue;\n if (check.conditionId) continue; // already guarded by a condition\n\n // Resolve user-defined named patterns to their regex value\n const patternAlias = check.when in userPatterns ? check.when : undefined;\n const regexStr = patternAlias ? userPatterns[patternAlias]! : check.when;\n\n let re: RegExp;\n try {\n re = new RegExp(regexStr);\n } catch {\n stale.push({ check, reason: `Invalid regex: '${regexStr}'` });\n continue;\n }\n\n const matches = repoFiles.filter((f) => re.test(f));\n if (matches.length === 0) {\n const label = patternAlias\n ? `Pattern '${patternAlias}' (= '${regexStr}')`\n : `Regex '${regexStr}'`;\n const suggestedConditionPath = extractPathFromRegex(regexStr);\n // Verify the suggested path doesn't actually exist either\n const pathGone =\n !suggestedConditionPath || !existsSync(join(process.cwd(), suggestedConditionPath));\n if (pathGone) {\n stale.push({\n check,\n reason: `${label} matches 0 files in the repo`,\n ...(suggestedConditionPath ? { suggestedConditionPath } : {}),\n });\n }\n }\n }\n\n return stale;\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport chalk from \"chalk\";\nimport { parseHoldpointYaml, validateConfig } from \"@holdpoint/yaml-core\";\n\nexport async function validateCommand(): Promise<void> {\n if (!existsSync(\"checks.yaml\")) {\n console.error(chalk.red(\"No checks.yaml found. Run `holdpoint init` first.\"));\n process.exit(1);\n }\n\n const text = readFileSync(\"checks.yaml\", \"utf8\");\n\n let config;\n try {\n config = parseHoldpointYaml(text);\n } catch (err: unknown) {\n console.error(chalk.red(\"Parse error:\"), (err as Error).message);\n process.exit(1);\n }\n\n const result = validateConfig(config);\n\n if (result.valid) {\n console.log(chalk.green(\"✓ checks.yaml is valid\"));\n console.log(\n chalk.dim(\n ` ${config.checks.filter((c) => c.cmd !== undefined).length} tasks, ${config.checks.filter((c) => c.prompt !== undefined).length} prompts, ${config.conditions.length} conditions`,\n ),\n );\n } else {\n console.error(chalk.red(\"✗ checks.yaml has errors:\"));\n for (const err of result.errors) {\n console.error(` ${chalk.yellow(err.path)}: ${err.message}`);\n }\n process.exit(1);\n }\n}\n","import { existsSync, readFileSync, writeFileSync, mkdirSync } from \"node:fs\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport { parseHoldpointYaml } from \"@holdpoint/yaml-core\";\nimport {\n buildHookJson,\n buildCheckScript,\n buildConfigJson,\n buildEngine,\n} from \"@holdpoint/engine-copilot\";\nimport { buildEngineJson as buildClaudeEngineJson } from \"@holdpoint/engine-claude\";\nimport { buildEngine as buildCursorEngine } from \"@holdpoint/engine-cursor\";\nimport {\n buildHooksJson as buildCodexHooksJson,\n buildCheckScript as buildCodexCheckScript,\n spliceAgentsMd,\n} from \"@holdpoint/engine-codex\";\nimport { detectInstalledAgents } from \"../detect.js\";\nimport type { AgentType } from \"@holdpoint/types\";\n\n/**\n * Regenerate all Holdpoint engine adapter files from the current `checks.yaml`.\n *\n * Detects which agents were previously installed via `detectInstalledAgents()` and\n * regenerates only their files. Falls back to all four agents if no engine files\n * are found (e.g. first run after a manual `checks.yaml` edit).\n */\nexport async function updateCommand(): Promise<void> {\n if (!existsSync(\"checks.yaml\")) {\n console.error(chalk.red(\"No checks.yaml found. Run `holdpoint init` first.\"));\n process.exit(1);\n }\n\n const spinner = ora(\"Updating Holdpoint engine files…\").start();\n const config = parseHoldpointYaml(readFileSync(\"checks.yaml\", \"utf8\"));\n\n // Regenerate for every agent that was previously installed.\n // Fall back to all four if no engine files exist yet (e.g. first run after manual checks.yaml edit).\n const detected = detectInstalledAgents();\n const agents: AgentType[] =\n detected.length > 0 ? detected : [\"copilot\", \"claude\", \"cursor\", \"codex\"];\n\n // Always write checks.immutable.json — read by holdpoint-check.mjs at runtime\n const generatedDir = \".github/holdpoint/generated\";\n mkdirSync(generatedDir, { recursive: true });\n writeFileSync(`${generatedDir}/checks.immutable.json`, buildConfigJson(config), \"utf8\");\n\n if (agents.includes(\"copilot\")) {\n const hooksDir = \".github/hooks\";\n mkdirSync(hooksDir, { recursive: true });\n writeFileSync(`${hooksDir}/holdpoint.json`, buildHookJson(config), \"utf8\");\n writeFileSync(`${hooksDir}/holdpoint-check.mjs`, buildCheckScript(config), \"utf8\");\n const extDir = \".github/extensions/holdpoint\";\n mkdirSync(extDir, { recursive: true });\n writeFileSync(`${extDir}/extension.mjs`, buildEngine(config), \"utf8\");\n }\n\n if (agents.includes(\"claude\")) {\n mkdirSync(\".claude\", { recursive: true });\n const settingsPath = \".claude/settings.json\";\n let existing: Record<string, unknown> = {};\n if (existsSync(settingsPath)) {\n try {\n existing = JSON.parse(readFileSync(settingsPath, \"utf8\")) as Record<string, unknown>;\n } catch {\n /* */\n }\n }\n const hooks = JSON.parse(buildClaudeEngineJson(config)) as Record<string, unknown>;\n writeFileSync(\n settingsPath,\n JSON.stringify({ ...existing, hooks: hooks.hooks }, null, 2) + \"\\n\",\n );\n }\n\n if (agents.includes(\"cursor\")) {\n const cursorRules = buildCursorEngine(config);\n const cursorPath = \".cursorrules\";\n if (existsSync(cursorPath)) {\n const content = readFileSync(cursorPath, \"utf8\");\n const start = content.indexOf(\"# ─── Holdpoint Rules\");\n const end = content.indexOf(\"# ─── End Holdpoint Rules ───\");\n if (start !== -1 && end !== -1) {\n // Slice past the end-marker line (find its newline to avoid hardcoded offsets)\n const afterEnd = content.indexOf(\"\\n\", end);\n const updated =\n content.slice(0, start) +\n cursorRules +\n content.slice(afterEnd === -1 ? end : afterEnd + 1);\n writeFileSync(cursorPath, updated);\n } else {\n writeFileSync(cursorPath, content + \"\\n\" + cursorRules);\n }\n }\n }\n\n if (agents.includes(\"codex\")) {\n mkdirSync(\".codex\", { recursive: true });\n // hooks.json is fully managed by Holdpoint; users who need additional Codex hooks\n // should add them in .codex/config.toml (Codex merges both sources).\n writeFileSync(\".codex/hooks.json\", buildCodexHooksJson(config), \"utf8\");\n writeFileSync(\".codex/holdpoint-check.mjs\", buildCodexCheckScript(), \"utf8\");\n const agentsMdPath = \"AGENTS.md\";\n const existing = existsSync(agentsMdPath) ? readFileSync(agentsMdPath, \"utf8\") : \"\";\n writeFileSync(agentsMdPath, spliceAgentsMd(existing, config), \"utf8\");\n }\n\n spinner.succeed(chalk.green(\"Engine files updated from current checks.yaml\"));\n}\n","import { createServer, type IncomingMessage, type ServerResponse } from \"node:http\";\nimport { createReadStream, existsSync } from \"node:fs\";\nimport { join, extname, dirname } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { execSync } from \"node:child_process\";\nimport chalk from \"chalk\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\nconst MIME: Record<string, string> = {\n \".html\": \"text/html; charset=utf-8\",\n \".js\": \"text/javascript\",\n \".mjs\": \"text/javascript\",\n \".css\": \"text/css\",\n \".svg\": \"image/svg+xml\",\n \".png\": \"image/png\",\n \".ico\": \"image/x-icon\",\n \".woff\": \"font/woff\",\n \".woff2\": \"font/woff2\",\n \".ttf\": \"font/ttf\",\n \".json\": \"application/json\",\n};\n\n/**\n * Serve a static file with the appropriate MIME type.\n */\nfunction serveFile(res: ServerResponse, filePath: string): void {\n const mime = MIME[extname(filePath)] ?? \"application/octet-stream\";\n res.writeHead(200, { \"Content-Type\": mime });\n createReadStream(filePath).pipe(res);\n}\n\n/**\n * Handle an incoming HTTP request: serve `/__holdpoint/initial-yaml` from the\n * user's `checks.yaml`, and all other paths as static files from `uiDir` with\n * a SPA fallback to `index.html`.\n */\nfunction handleRequest(req: IncomingMessage, res: ServerResponse, uiDir: string): void {\n const url = (req.url ?? \"/\").split(\"?\")[0] ?? \"/\";\n\n // Serve the user's checks.yaml for the builder UI to load\n if (url === \"/__holdpoint/initial-yaml\") {\n const checksPath = join(process.cwd(), \"checks.yaml\");\n if (existsSync(checksPath)) {\n res.writeHead(200, { \"Content-Type\": \"text/yaml; charset=utf-8\" });\n createReadStream(checksPath).pipe(res);\n } else {\n res.writeHead(404, { \"Content-Type\": \"text/plain\" });\n res.end(\"checks.yaml not found in current directory\");\n }\n return;\n }\n\n // Static files\n const candidate = join(uiDir, url === \"/\" ? \"index.html\" : url);\n const filePath = existsSync(candidate) ? candidate : join(uiDir, \"index.html\"); // SPA fallback\n serveFile(res, filePath);\n}\n\n/**\n * Start the Holdpoint visual builder on localhost:4321.\n *\n * Serves the pre-built React SPA from `dist/builder-ui/` (bundled into the CLI\n * package at publish time) and exposes a `/__holdpoint/initial-yaml` endpoint\n * that returns the user's `checks.yaml` so the builder can load it on startup.\n */\nexport async function buildCommand(): Promise<void> {\n const port = 4321;\n const uiDir = join(__dirname, \"builder-ui\");\n\n if (!existsSync(uiDir)) {\n console.error(chalk.red(\"✗ Builder UI not found.\\n\"));\n console.log(chalk.dim(\" This is unexpected for a published build of @holdpoint/cli.\"));\n console.log(chalk.dim(\" If you installed from source, rebuild with: pnpm turbo build\\n\"));\n process.exit(1);\n }\n\n const server = createServer((req, res) => handleRequest(req, res, uiDir));\n\n await new Promise<void>((resolve, reject) => {\n server.listen(port, () => {\n console.log(\n `\\n${chalk.green(\"✓\")} Holdpoint builder running at ${chalk.cyan(`http://localhost:${port}`)}`,\n );\n console.log(chalk.dim(\" Edit checks.yaml, then reload the page to see updates\"));\n console.log(chalk.dim(\" Press Ctrl+C to stop\\n\"));\n\n const openCmd =\n process.platform === \"darwin\"\n ? \"open\"\n : process.platform === \"win32\"\n ? \"start\"\n : \"xdg-open\";\n try {\n execSync(`${openCmd} http://localhost:${port}`, { stdio: \"ignore\" });\n } catch {\n /* non-fatal */\n }\n });\n\n server.on(\"error\", reject);\n\n process.on(\"SIGINT\", () => {\n console.log(chalk.dim(\"\\n Stopping builder…\"));\n server.close(() => resolve());\n });\n });\n}\n","import { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { execSync } from \"node:child_process\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport { parseHoldpointYaml, generateYaml } from \"@holdpoint/yaml-core\";\nimport type { HoldpointConfig, CheckDef, ConditionDef } from \"@holdpoint/types\";\nimport { scanProject } from \"../evolve/scanner.js\";\nimport { getRepoFiles, detectStaleChecks } from \"../evolve/dead-checker.js\";\nimport { getTemplates } from \"../evolve/templates.js\";\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\n/**\n * Strip leading comment lines from a checks.yaml so we can re-prepend them\n * after re-serialising — preserves the documentation header.\n */\nfunction extractHeader(yaml: string): string {\n const lines = yaml.split(\"\\n\");\n const commentLines: string[] = [];\n for (const line of lines) {\n if (line.startsWith(\"#\") || (commentLines.length > 0 && line.trim() === \"\")) {\n commentLines.push(line);\n } else {\n break;\n }\n }\n // Trim trailing blank lines\n while (commentLines.length > 0 && commentLines[commentLines.length - 1]?.trim() === \"\") {\n commentLines.pop();\n }\n return commentLines.join(\"\\n\");\n}\n\nfunction withHeader(header: string, newYaml: string): string {\n if (!header) return newYaml;\n return header + \"\\n\\n\" + newYaml;\n}\n\n// ── The command ───────────────────────────────────────────────────────────────\n\nexport async function evolveCommand(options: { apply?: boolean }): Promise<void> {\n if (!existsSync(\"checks.yaml\")) {\n console.error(chalk.red(\"No checks.yaml found. Run `holdpoint init` first.\"));\n process.exit(1);\n }\n\n const spinner = ora(\"Scanning project profile…\").start();\n const cwd = process.cwd();\n\n // 1. Scan project\n const profile = scanProject(cwd);\n const repoFiles = getRepoFiles(cwd);\n\n // 2. Parse checks.yaml\n const yamlContent = readFileSync(\"checks.yaml\", \"utf8\");\n let config: HoldpointConfig;\n try {\n config = parseHoldpointYaml(yamlContent);\n } catch (err: unknown) {\n spinner.fail(chalk.red(\"Invalid checks.yaml:\") + \" \" + (err as Error).message);\n process.exit(1);\n }\n\n spinner.stop();\n\n // 3. Compute proposals — templates whose trigger matches AND id not already in config\n const existingIds = new Set(config.checks.map((c) => c.id));\n const existingConditionIds = new Set(config.conditions.map((c) => c.id));\n const allTemplates = getTemplates(profile);\n const proposals = allTemplates.filter((t) => t.trigger(profile) && !existingIds.has(t.id));\n\n // 4. Detect stale checks\n const staleChecks = detectStaleChecks(config, repoFiles);\n\n // ── Print report ─────────────────────────────────────────────────────────\n\n // Profile summary — show detected items\n console.log(chalk.bold(\"\\n📋 Project profile:\"));\n const traits: [string, boolean, string][] = [\n [\"TypeScript\", profile.hasTypeScript, \"tsconfig.json\"],\n [\"ESLint\", profile.hasEslint, \"eslint.config.*\"],\n [\"Biome\", profile.hasBiome, \"biome.json\"],\n [\"Ruff\", profile.hasRuff, \"pyproject.toml / ruff\"],\n [\"Prettier\", profile.hasPrettier, \".prettierrc\"],\n [\"Vitest\", profile.hasVitest, \"devDependencies\"],\n [\"Jest\", profile.hasJest, \"devDependencies\"],\n [\"Python\", profile.hasPython, \"pyproject.toml\"],\n [\"Pytest\", profile.hasPytest, \"pytest.ini\"],\n [\"Go\", profile.hasGo, \"go.mod\"],\n [\"Rust\", profile.hasRust, \"Cargo.toml\"],\n [\"Next.js\", profile.hasNext, \"next.config.*\"],\n [\"React\", profile.hasReact, \"dependencies\"],\n [\"Prisma\", profile.hasPrisma, \"prisma/schema.prisma\"],\n [\"Drizzle\", profile.hasDrizzle, \"drizzle-orm\"],\n [\"Migrations\", profile.hasMigrations, \"migrations/\"],\n [\"Docker\", profile.hasDocker, \"Dockerfile\"],\n [\"Terraform\", profile.hasTerraform, \"*.tf\"],\n [\"Kubernetes\", profile.hasKubernetes, \"k8s/\"],\n [\"OpenAPI\", profile.hasOpenApi, \"openapi.yaml\"],\n [\"GitHub Actions\", profile.hasGithubActions, \".github/workflows/\"],\n ];\n const detected = traits.filter(([, yes]) => yes);\n if (detected.length === 0) {\n console.log(chalk.dim(\" (empty project — only universal checks apply)\"));\n } else {\n for (const [name, , hint] of detected) {\n console.log(` ${chalk.green(\"✓\")} ${name.padEnd(18)} ${chalk.dim(hint)}`);\n }\n }\n\n // Stale checks\n if (staleChecks.length > 0) {\n console.log(chalk.bold(`\\n⚠️ Stale checks (${staleChecks.length}):`));\n for (const { check, reason, suggestedConditionPath } of staleChecks) {\n const fix = suggestedConditionPath\n ? chalk.dim(` → will wrap with conditionId: file_exists: ${suggestedConditionPath}`)\n : chalk.dim(\" → no path inferred; review manually\");\n console.log(` ${chalk.yellow(\"◌\")} ${chalk.bold(check.id)} ${chalk.dim(reason)}${fix}`);\n }\n }\n\n // Proposals\n if (proposals.length === 0 && staleChecks.length === 0) {\n console.log(chalk.green(\"\\n✓ checks.yaml is fully in sync with the project profile.\"));\n return;\n }\n\n if (proposals.length > 0) {\n console.log(chalk.bold(`\\n💡 Proposed additions (${proposals.length}):`));\n for (const t of proposals) {\n const scope = t.when ? chalk.cyan(` when: ${t.when}`) : \"\";\n const type = t.cmd ? chalk.dim(\"cmd\") : chalk.dim(\"prompt\");\n const preview = t.cmd\n ? chalk.dim(` ${t.cmd.slice(0, 80)}${t.cmd.length > 80 ? \"…\" : \"\"}`)\n : chalk.dim(` ${(t.prompt ?? \"\").slice(0, 80)}${(t.prompt?.length ?? 0) > 80 ? \"…\" : \"\"}`);\n console.log(` ${chalk.green(\"+\")} ${chalk.bold(t.id.padEnd(24))} [${type}]${scope}`);\n console.log(` ${preview}`);\n }\n }\n\n if (!options.apply) {\n console.log(\n chalk.red(`\\n✗ checks.yaml is out of sync with the project profile.`) +\n `\\n Run ${chalk.bold(\"npx @holdpoint/cli@alpha evolve --apply\")} to apply these changes.`,\n );\n process.exit(1);\n }\n\n // ── Apply ───────────────────────────────────────────────────────────────\n\n const applySpinner = ora(\"Applying changes to checks.yaml…\").start();\n\n // Build updated conditions list\n const newConditions = [...config.conditions];\n\n // Collect conditions needed by proposals\n for (const t of proposals) {\n if (t.condition && !existingConditionIds.has(t.condition.id)) {\n newConditions.push(t.condition as ConditionDef);\n existingConditionIds.add(t.condition.id);\n }\n }\n\n // Wrap stale checks with file_exists conditions\n const updatedChecks: CheckDef[] = config.checks.map((check) => {\n const stale = staleChecks.find((s) => s.check.id === check.id);\n if (!stale || !stale.suggestedConditionPath) return check;\n\n const condId = `has-${check.id}`;\n if (!existingConditionIds.has(condId)) {\n newConditions.push({\n id: condId,\n operator: \"file_exists\",\n path: stale.suggestedConditionPath,\n });\n existingConditionIds.add(condId);\n }\n return { ...check, conditionId: condId };\n });\n\n // Append proposed checks\n const newChecks: CheckDef[] = proposals.map((t) => ({\n id: t.id,\n label: t.label,\n ...(t.when ? { when: t.when } : {}),\n ...(t.cmd ? { cmd: t.cmd } : {}),\n ...(t.prompt ? { prompt: t.prompt } : {}),\n ...(t.conditionId ? { conditionId: t.conditionId } : {}),\n }));\n\n const updatedConfig: HoldpointConfig = {\n ...config,\n conditions: newConditions,\n checks: [...updatedChecks, ...newChecks],\n };\n\n const header = extractHeader(yamlContent);\n const newYaml = withHeader(header, generateYaml(updatedConfig));\n writeFileSync(\"checks.yaml\", newYaml, \"utf8\");\n\n // Regenerate engine files\n applySpinner.text = \"Running holdpoint update…\";\n try {\n execSync(\"npx @holdpoint/cli@alpha update\", { stdio: \"pipe\" });\n } catch {\n // holdpoint update failure is non-fatal — checks.yaml is already written\n applySpinner.warn(\n chalk.yellow(\"checks.yaml updated, but `holdpoint update` failed — run it manually.\"),\n );\n printAppliedSummary(proposals.length, staleChecks.length);\n return;\n }\n\n applySpinner.succeed(chalk.green(\"checks.yaml updated and engine files regenerated.\"));\n printAppliedSummary(proposals.length, staleChecks.length);\n}\n\nfunction printAppliedSummary(added: number, wrapped: number): void {\n const parts: string[] = [];\n if (added > 0) parts.push(chalk.green(`${added} check${added === 1 ? \"\" : \"s\"} added`));\n if (wrapped > 0)\n parts.push(chalk.yellow(`${wrapped} stale check${wrapped === 1 ? \"\" : \"s\"} wrapped`));\n if (parts.length > 0) console.log(\" \" + parts.join(\" · \"));\n console.log(\n chalk.dim(\"\\n Review checks.yaml, then commit: \") +\n chalk.yellow(\"git add checks.yaml && git commit -m 'chore: evolve holdpoint checks'\"),\n );\n}\n"],"mappings":"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","names":["existsSync","readFileSync","existsSync","readFileSync","existsSync","readFileSync","writeFileSync","mkdirSync","join","chalk","ora","parseHoldpointYaml","execSync","existsSync","readFileSync","join","existsSync","join","execSync","readdirSync","existsSync","join","execSync","readFileSync","mkdirSync","join","writeFileSync","existsSync","chalk","parseHoldpointYaml","ora","existsSync","readFileSync","chalk","parseHoldpointYaml","existsSync","readFileSync","writeFileSync","mkdirSync","chalk","ora","parseHoldpointYaml","buildHookJson","buildCheckScript","buildConfigJson","buildEngine","buildClaudeEngineJson","buildCursorEngine","buildCodexHooksJson","buildCodexCheckScript","spliceAgentsMd","existsSync","chalk","ora","parseHoldpointYaml","readFileSync","mkdirSync","writeFileSync","buildConfigJson","buildHookJson","buildCheckScript","buildEngine","buildClaudeEngineJson","buildCursorEngine","buildCodexHooksJson","buildCodexCheckScript","spliceAgentsMd","existsSync","join","dirname","fileURLToPath","execSync","chalk","__dirname","existsSync","readFileSync","writeFileSync","execSync","chalk","ora","parseHoldpointYaml","existsSync","chalk","ora","readFileSync","parseHoldpointYaml","writeFileSync","execSync"]}
|
|
@@ -9,7 +9,7 @@ eval checkpoints. Before marking any task done, all checks must pass.
|
|
|
9
9
|
|
|
10
10
|
Before marking **any** task complete:
|
|
11
11
|
|
|
12
|
-
1. Run `npx holdpoint check` — all tasks must exit 0.
|
|
12
|
+
1. Run `npx @holdpoint/cli@alpha check` — all tasks must exit 0.
|
|
13
13
|
2. `holdpoint check` also prints every **prompt** check whose `when` matches the
|
|
14
14
|
files you changed. Read and act on each listed instruction before finishing.
|
|
15
15
|
|
|
@@ -19,12 +19,12 @@ Before marking **any** task complete:
|
|
|
19
19
|
|
|
20
20
|
`checks.yaml` is not static — it grows alongside the project automatically.
|
|
21
21
|
|
|
22
|
-
**`holdpoint-evolve` is a deterministic check** in `checks.yaml` that fires whenever you change a structural file (`package.json`, `pyproject.toml`, `go.mod`, `Dockerfile`, `tsconfig.json`, `vitest.config.*`, etc.). When it fires, `npx holdpoint evolve` runs and **exits 1 if `checks.yaml` is out of sync** — blocking task completion until you apply the proposals.
|
|
22
|
+
**`holdpoint-evolve` is a deterministic check** in `checks.yaml` that fires whenever you change a structural file (`package.json`, `pyproject.toml`, `go.mod`, `Dockerfile`, `tsconfig.json`, `vitest.config.*`, etc.). When it fires, `npx @holdpoint/cli@alpha evolve` runs and **exits 1 if `checks.yaml` is out of sync** — blocking task completion until you apply the proposals.
|
|
23
23
|
|
|
24
24
|
When blocked by `holdpoint-evolve`, run:
|
|
25
25
|
|
|
26
26
|
```
|
|
27
|
-
npx holdpoint evolve --apply # scan, apply proposals, regenerate engine files
|
|
27
|
+
npx @holdpoint/cli@alpha evolve --apply # scan, apply proposals, regenerate engine files
|
|
28
28
|
```
|
|
29
29
|
|
|
30
30
|
Then commit:
|
|
@@ -56,7 +56,7 @@ remove, or change checkpoints.
|
|
|
56
56
|
After every edit, regenerate the engine files and commit everything together:
|
|
57
57
|
|
|
58
58
|
```
|
|
59
|
-
npx holdpoint update
|
|
59
|
+
npx @holdpoint/cli@alpha update
|
|
60
60
|
git add checks.yaml .github/holdpoint/generated/ .github/hooks/
|
|
61
61
|
git commit -m "chore: update holdpoint checks"
|
|
62
62
|
```
|
|
@@ -200,7 +200,7 @@ context:
|
|
|
200
200
|
|
|
201
201
|
1. Open `checks.yaml`.
|
|
202
202
|
2. Add your entry under `checks:`.
|
|
203
|
-
3. Run `npx holdpoint update`.
|
|
203
|
+
3. Run `npx @holdpoint/cli@alpha update`.
|
|
204
204
|
4. Commit `checks.yaml` and the generated files.
|
|
205
205
|
|
|
206
206
|
**Add a task check (runs a shell command automatically):**
|
|
@@ -283,15 +283,15 @@ skipped.
|
|
|
283
283
|
|
|
284
284
|
## Commands
|
|
285
285
|
|
|
286
|
-
| Command
|
|
287
|
-
|
|
|
288
|
-
| `npx holdpoint check`
|
|
289
|
-
| `npx holdpoint check --staged`
|
|
290
|
-
| `npx holdpoint evolve`
|
|
291
|
-
| `npx holdpoint evolve --apply`
|
|
292
|
-
| `npx holdpoint update`
|
|
293
|
-
| `npx holdpoint validate`
|
|
294
|
-
| `npx @holdpoint/cli@alpha builder`
|
|
286
|
+
| Command | What it does |
|
|
287
|
+
| ----------------------------------------- | ------------------------------------------------------- |
|
|
288
|
+
| `npx @holdpoint/cli@alpha check` | Run checks against all files changed vs HEAD |
|
|
289
|
+
| `npx @holdpoint/cli@alpha check --staged` | Run checks against staged files only |
|
|
290
|
+
| `npx @holdpoint/cli@alpha evolve` | Scan project and show proposed additions to checks.yaml |
|
|
291
|
+
| `npx @holdpoint/cli@alpha evolve --apply` | Apply proposals and regenerate engine files |
|
|
292
|
+
| `npx @holdpoint/cli@alpha update` | Regenerate engine files from the current `checks.yaml` |
|
|
293
|
+
| `npx @holdpoint/cli@alpha validate` | Validate `checks.yaml` schema (no commands run) |
|
|
294
|
+
| `npx @holdpoint/cli@alpha builder` | Open the visual builder UI at localhost:4321 |
|
|
295
295
|
|
|
296
296
|
---
|
|
297
297
|
|
|
@@ -305,5 +305,5 @@ skipped.
|
|
|
305
305
|
| `.claude/settings.json` | Claude |
|
|
306
306
|
| `.cursorrules` (Holdpoint section) | Cursor |
|
|
307
307
|
|
|
308
|
-
All generated files are overwritten by `npx holdpoint update`. Edit `checks.yaml`,
|
|
308
|
+
All generated files are overwritten by `npx @holdpoint/cli@alpha update`. Edit `checks.yaml`,
|
|
309
309
|
then run `update` — never edit the generated files directly.
|
package/dist/templates/go.yaml
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@holdpoint/cli",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.3",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public",
|
|
6
6
|
"tag": "alpha"
|
|
@@ -49,18 +49,19 @@
|
|
|
49
49
|
"chalk": "^5.3.0",
|
|
50
50
|
"commander": "^12.1.0",
|
|
51
51
|
"ora": "^8.1.1",
|
|
52
|
-
"@holdpoint/engine-claude": "0.1.0-alpha.
|
|
53
|
-
"@holdpoint/engine-cursor": "0.1.0-alpha.
|
|
54
|
-
"@holdpoint/engine-
|
|
55
|
-
"@holdpoint/
|
|
56
|
-
"@holdpoint/
|
|
52
|
+
"@holdpoint/engine-claude": "0.1.0-alpha.3",
|
|
53
|
+
"@holdpoint/engine-cursor": "0.1.0-alpha.3",
|
|
54
|
+
"@holdpoint/engine-codex": "0.1.0-alpha.3",
|
|
55
|
+
"@holdpoint/types": "0.1.0-alpha.3",
|
|
56
|
+
"@holdpoint/engine-copilot": "0.1.0-alpha.3",
|
|
57
|
+
"@holdpoint/yaml-core": "0.1.0-alpha.3"
|
|
57
58
|
},
|
|
58
59
|
"devDependencies": {
|
|
59
60
|
"@types/node": "^22.10.2",
|
|
60
61
|
"tsup": "^8.3.5",
|
|
61
62
|
"typescript": "^5.7.2",
|
|
62
63
|
"vitest": "^2.1.8",
|
|
63
|
-
"@holdpoint/builder": "0.1.0"
|
|
64
|
+
"@holdpoint/builder": "0.1.1-alpha.0"
|
|
64
65
|
},
|
|
65
66
|
"scripts": {
|
|
66
67
|
"build": "tsup",
|