@holdpoint/cli 0.1.0-alpha.15 → 0.1.0-alpha.17

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.
@@ -0,0 +1,10 @@
1
+ # Holdpoint prerequisites
2
+
3
+ Holdpoint installed repo-local adapters for one or more AI coding agents. Before relying on them locally, review these setup notes:
4
+
5
+ - **GitHub Copilot CLI** — Holdpoint's `.github/extensions/holdpoint/extension.mjs` uses the Copilot CLI **EXTENSIONS** feature. Today that feature is gated behind experimental mode. In Copilot CLI, run `/experimental on` so **EXTENSIONS** appears in the enabled feature set before using Holdpoint locally.
6
+ - **Cursor** — project-level hooks run in trusted workspaces. After opening the repo in Cursor, confirm the workspace is trusted and review Settings → Hooks if hooks do not fire.
7
+ - **OpenAI Codex** — project-level hooks require trust approval. Run `codex trust` in the Codex TUI or review the hook with `/hooks`.
8
+ - **General** — Holdpoint expects Node.js 18+ and a git repository so `holdpoint init`, `holdpoint update`, and `holdpoint check` can run normally.
9
+
10
+ Docs: https://holdpoint.dev/docs
@@ -0,0 +1,341 @@
1
+ # Holdpoint — Eval Checkpoints
2
+
3
+ This project uses [Holdpoint](https://github.com/holdpoint-dev/holdpoint) to enforce
4
+ eval checkpoints. Before marking any task done, all checks must pass.
5
+
6
+ ---
7
+
8
+ ## The Rule
9
+
10
+ Before marking **any** task complete:
11
+
12
+ 1. Run `holdpoint check` — all tasks must exit 0.
13
+ 2. `holdpoint check` also prints every **prompt** check whose `when` matches the
14
+ files you changed. Read and act on each listed instruction before finishing.
15
+
16
+ ---
17
+
18
+ ## The Suggest Loop
19
+
20
+ `checks.yaml` is not static — it grows alongside the project automatically.
21
+
22
+ **`holdpoint-suggest` 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, `holdpoint suggest` runs and **exits 1 if `checks.yaml` is out of sync** — blocking task completion until you apply the proposals.
23
+
24
+ When blocked by `holdpoint-suggest`, run:
25
+
26
+ ```
27
+ holdpoint suggest --apply # scan, apply proposals, regenerate engine files
28
+ ```
29
+
30
+ Then commit:
31
+
32
+ ```
33
+ git add checks.yaml .github/holdpoint/generated/
34
+ git commit -m "chore: suggest holdpoint checks"
35
+ ```
36
+
37
+ `holdpoint suggest --apply` is idempotent — safe to re-run at any time. It only adds checks for tools/patterns detected in the project and wraps stale checks (whose `when:` pattern no longer matches any file) with `conditionId: file_exists` so they auto-skip instead of failing.
38
+
39
+ **What triggers evolution:**
40
+
41
+ - New dependency in `package.json` / `pyproject.toml` / `go.mod` / `Cargo.toml`
42
+ - New `Dockerfile`, `docker-compose.yml`, `*.tf`, `openapi.yaml`
43
+ - New test runner config (`vitest.config.*`, `jest.config.*`, `playwright.config.*`)
44
+ - New CI workflow in `.github/workflows/`
45
+ - New TypeScript setup (`tsconfig.json`)
46
+
47
+ **What does NOT trigger it:** `.ts` / `.py` / `.go` source files, docs, styles, tests — minor work proceeds without interruption.
48
+
49
+ ---
50
+
51
+ ## Git workflow best practices
52
+
53
+ Prefer the least-disruptive git workflow that still satisfies the task:
54
+
55
+ - Use a branch + PR when the user requests it, when work targets protected
56
+ `main`, or when remote CI/review is part of the task.
57
+ - For small local fixes, commit directly on the current branch and do not open a
58
+ PR unless the user asks.
59
+ - If already on a feature branch, keep committing there instead of creating
60
+ another branch.
61
+ - After committing, decide whether to push: push when a PR, remote review, CI
62
+ run, or handoff needs it; otherwise leave the commit local and report the
63
+ branch/commit.
64
+
65
+ ---
66
+
67
+ ## checks.yaml — Full Reference
68
+
69
+ `checks.yaml` at the project root is the single source of truth. Edit it to add,
70
+ remove, or change checkpoints.
71
+
72
+ After every edit, regenerate the engine files and commit everything together:
73
+
74
+ ```
75
+ holdpoint update
76
+ git add checks.yaml .github/holdpoint/generated/ .github/hooks/
77
+ git commit -m "chore: update holdpoint checks"
78
+ ```
79
+
80
+ ### Top-level structure
81
+
82
+ ```yaml
83
+ version: 1
84
+
85
+ context:
86
+ guides: # project notes shown when `holdpoint check` runs
87
+ setup: >
88
+ Use pnpm, not npm. Node 20+ required.
89
+
90
+ session_context_files:
91
+ - MASTER_PROMPT.md # injected into Copilot/Codex sessions when supported
92
+
93
+ conditions: # gate checks on file/env state
94
+ - id: dist-built
95
+ operator: file_exists
96
+ path: dist/index.js
97
+
98
+ checks: # list of all checks — each has on/when + cmd (task) or prompt
99
+ - ...
100
+ ```
101
+
102
+ ---
103
+
104
+ ### Deterministic check
105
+
106
+ ```yaml
107
+ - id: lint # unique slug, kebab-case
108
+ label: "ESLint — all packages" # human-readable label shown in output
109
+ # on: before_done # lifecycle hook (default; only value today)
110
+ # when: frontend # file filter — omit to run on every task
111
+ cmd: "pnpm turbo lint" # shell command; must exit 0 to pass
112
+ conditionId: dist-built # optional: skip if condition is not met
113
+ ```
114
+
115
+ ### Prompt check
116
+
117
+ ```yaml
118
+ - id: migration-review
119
+ label: "Review DB migration"
120
+ when: "^prisma/migrations/" # only fires when migration files change
121
+ prompt: >
122
+ Open the new migration file. Confirm it is backward-compatible
123
+ and does not drop or truncate data without a fallback.
124
+ ```
125
+
126
+ ---
127
+
128
+ ### `on` — lifecycle hooks
129
+
130
+ `on` specifies _when in the agent lifecycle_ a check fires. Omit it to use the default.
131
+
132
+ | Value | Fires |
133
+ | ------------- | ---------------------------------- |
134
+ | `before_done` | Before the agent marks a task done |
135
+
136
+ ---
137
+
138
+ ### `when` — file filters
139
+
140
+ `when` is an optional file filter. If omitted the check runs on every task.
141
+
142
+ | Value | Fires when changed files match |
143
+ | ----------- | -------------------------------------------------------------------------------------------------- |
144
+ | _(absent)_ | Every task — no file filter applied |
145
+ | `frontend` | `**/*.tsx`, `**/*.jsx`, `**/*.css`, `**/*.scss`, `**/tailwind.config.*`, `apps/**` |
146
+ | `backend` | `**/api/**`, `**/server/**`, `**/routes/**`, `**/controllers/**`, `packages/*/src/**` |
147
+ | `socket` | `**/socket/**`, `**/ws/**`, `**/websocket/**` |
148
+ | `visual` | `**/*.stories.{ts,tsx}`, `**/__screenshots__/**`, `**/*.snap` |
149
+ | `python` | `**/*.py`, `**/*.pyi`, `**/requirements*.txt`, `**/pyproject.toml`, `**/setup.py`, `**/pytest.ini` |
150
+ | `go` | `**/*.go`, `**/go.mod`, `**/go.sum` |
151
+ | `rust` | `**/*.rs`, `**/Cargo.toml`, `**/Cargo.lock` |
152
+ | `java` | `**/*.java`, `**/*.kt`, `**/*.gradle`, `**/*.gradle.kts`, `**/pom.xml` |
153
+ | `ruby` | `**/*.rb`, `**/Gemfile`, `**/Gemfile.lock`, `**/Rakefile` |
154
+ | `database` | `**/*.sql`, `**/migrations/**`, `**/db/**`, `**/database/**`, `**/prisma/**`, `**/*.prisma` |
155
+ | `prisma` | `**/prisma/**`, `**/*.prisma` — focused subset of `database` for Prisma-specific checks |
156
+ | `testing` | `**/*.test.*`, `**/*.spec.*`, `**/__tests__/**`, `**/test/**`, `**/tests/**`, `**/spec/**` |
157
+ | `infra` | `**/Dockerfile*`, `**/docker-compose.*`, `**/*.tf`, `**/*.tfvars`, `**/k8s/**`, `**/kubernetes/**` |
158
+ | `ci` | `**/.github/workflows/**`, `**/.circleci/**`, `**/Jenkinsfile`, `**/.gitlab-ci.yml` |
159
+ | `docs` | `**/*.mdx`, `**/*.rst`, `**/docs/**`, `**/documentation/**` |
160
+ | `"^src/.*"` | Any JavaScript regex tested against each changed file path |
161
+
162
+ Regex example — fires only when files under `src/api/` change:
163
+
164
+ ```yaml
165
+ when: "^src/api/" # new RegExp(when).test(filePath)
166
+ ```
167
+
168
+ > **Note:** Named scopes use glob matching; plain strings are treated as JavaScript regexes.
169
+
170
+ ---
171
+
172
+ ### Conditions
173
+
174
+ Conditions let you skip a check when a prerequisite is not yet met (e.g. a build
175
+ artefact doesn't exist yet).
176
+
177
+ | Operator | What it checks |
178
+ | ----------------- | ------------------------------------------------- |
179
+ | `file_exists` | A file or directory exists at `path` |
180
+ | `file_contains` | The file at `path` contains the substring `value` |
181
+ | `env_var_set` | The environment variable named `value` is set |
182
+ | `shell_returns_0` | The shell command in `cmd` exits with code 0 |
183
+
184
+ ```yaml
185
+ conditions:
186
+ - id: packages-built
187
+ operator: file_exists
188
+ path: packages/yaml-core/dist/index.js
189
+
190
+ checks:
191
+ - id: validate-templates
192
+ label: "Templates parse against schema"
193
+ conditionId: packages-built # skipped (◌) when dist is absent
194
+ cmd: "node dist/validate.js templates/"
195
+ ```
196
+
197
+ ---
198
+
199
+ ### Context guides
200
+
201
+ `context.guides` is a freeform key → multiline-string map. Guides are printed
202
+ at the start of `holdpoint check` output as project-level reminders to whoever
203
+ (or whatever) is running the checks.
204
+
205
+ ```yaml
206
+ context:
207
+ guides:
208
+ setup: >
209
+ This project requires Node 20 and pnpm 9+.
210
+ Run `pnpm install` from the repo root before any other command.
211
+ architecture: >
212
+ API routes live in src/api/. Models live in src/models/.
213
+ Client code must never import from server modules.
214
+ ```
215
+
216
+ ---
217
+
218
+ ## Adding a New Check
219
+
220
+ 1. Open `checks.yaml`.
221
+ 2. Add your entry under `checks:`.
222
+ 3. Run `holdpoint update`.
223
+ 4. Commit `checks.yaml` and the generated files.
224
+
225
+ **Add a task check (runs a shell command automatically):**
226
+
227
+ ```yaml
228
+ checks:
229
+ - id: vitest
230
+ label: "Vitest — unit tests"
231
+ cmd: "pnpm vitest run"
232
+ ```
233
+
234
+ **Add a scoped task (fires only on matching file changes):**
235
+
236
+ ```yaml
237
+ checks:
238
+ - id: openapi-sync
239
+ label: "OpenAPI types are up to date"
240
+ when: "^src/api/"
241
+ cmd: "pnpm generate:types && git diff --exit-code src/generated/"
242
+ ```
243
+
244
+ **Add an agent prompt checkpoint:**
245
+
246
+ ```yaml
247
+ checks:
248
+ - id: jsdoc
249
+ label: "JSDoc on changed public functions"
250
+ prompt: >
251
+ For every public function or export you modified, ensure there is an
252
+ accurate JSDoc comment: description, @param, and @returns.
253
+ ```
254
+
255
+ **Enforce changelog and git commit on every task (recommended):**
256
+
257
+ ```yaml
258
+ checks:
259
+ - id: changelog-update
260
+ label: "Add a CHANGELOG.md entry for this session"
261
+ prompt: >
262
+ Before committing, add an entry to CHANGELOG.md describing what was done.
263
+ Use Keep a Changelog format — add under ## [Unreleased] (create the file
264
+ and that section if absent). Group entries as Added, Changed, Fixed, or Removed.
265
+ Be concise but specific. The entry text will serve as the commit message.
266
+
267
+ - id: readme-sync
268
+ label: "Update README.md if user-facing changes were made"
269
+ prompt: >
270
+ If you added, changed, or removed user-facing functionality — CLI commands,
271
+ configuration options, public APIs, or significant new features — update
272
+ README.md to reflect those changes.
273
+
274
+ - id: git-workflow
275
+ label: "Use the right git workflow"
276
+ prompt: >
277
+ Choose the least-disruptive git workflow: use branch + PR for requested
278
+ feature branches or protected-main work; for small local fixes, commit on
279
+ the current branch without opening a PR unless asked; if already on a
280
+ feature branch, keep committing there instead of creating another branch.
281
+ Push only when a PR, remote review, CI run, or handoff needs it; otherwise
282
+ leave the commit local and report the branch/commit.
283
+
284
+ - id: git-commit
285
+ label: "Commit all changes before finishing"
286
+ cmd: 'git rev-parse --is-inside-work-tree >/dev/null 2>&1 || exit 0; [ -z "$(git status --porcelain)" ] && exit 0; git status --short; exit 1'
287
+ ```
288
+
289
+ When the `git-commit` check fails (uncommitted changes remain), the agent will also see
290
+ the `changelog-update` and `readme-sync` prompt reminders inline — ensuring it updates
291
+ the changelog, syncs docs, _then_ commits before it can mark the task done.
292
+
293
+ ---
294
+
295
+ ## `session_context_files`
296
+
297
+ `session_context_files` is an optional list of project files that Holdpoint injects
298
+ as context at the start of every Copilot session. Use it for files the agent should
299
+ always read before starting work.
300
+
301
+ ```yaml
302
+ session_context_files:
303
+ - MASTER_PROMPT.md
304
+ - AGENT_CONTEXT.md
305
+ ```
306
+
307
+ Files are resolved relative to the repo root and must stay inside it (traversal
308
+ paths like `../../etc/passwd` are rejected). If a file doesn't exist it is silently
309
+ skipped.
310
+
311
+ ---
312
+
313
+ ## Commands
314
+
315
+ | Command | What it does |
316
+ | ----------------------------- | ------------------------------------------------------- |
317
+ | `holdpoint check` | Run checks against all files changed vs HEAD |
318
+ | `holdpoint check --staged` | Run checks against staged files only |
319
+ | `holdpoint suggest` | Scan project and show proposed additions to checks.yaml |
320
+ | `holdpoint suggest --apply` | Apply proposals and regenerate engine files |
321
+ | `holdpoint require-changeset` | Require `.changeset/*.md` for package changes |
322
+ | `holdpoint update` | Regenerate engine files from the current `checks.yaml` |
323
+ | `holdpoint validate` | Validate `checks.yaml` schema (no commands run) |
324
+ | `holdpoint builder` | Open the daemon-served visual builder UI |
325
+
326
+ ---
327
+
328
+ ## Generated files (do not edit directly)
329
+
330
+ | File | Agent |
331
+ | --------------------------------------------------- | ------- |
332
+ | `.github/holdpoint/generated/checks.immutable.json` | all |
333
+ | `.github/hooks/holdpoint.json` | Copilot |
334
+ | `.github/hooks/holdpoint-check.mjs` | Copilot |
335
+ | `.claude/settings.json` | Claude |
336
+ | `.cursor/hooks.json` | Cursor |
337
+ | `.cursor/holdpoint-hook.mjs` | Cursor |
338
+ | `.cursorrules` (Holdpoint section) | Cursor |
339
+
340
+ All generated files are overwritten by `holdpoint update`. Edit `checks.yaml`,
341
+ then run `update` — never edit the generated files directly.
@@ -1,309 +1,39 @@
1
1
  # Holdpoint — Eval Checkpoints
2
2
 
3
- This project uses [Holdpoint](https://github.com/holdpoint-dev/holdpoint) to enforce
4
- eval checkpoints. Before marking any task done, all checks must pass.
5
-
6
- ---
3
+ This repo uses [Holdpoint](https://holdpoint.dev) to enforce eval
4
+ checkpoints. Before marking any task done, all checks must pass.
7
5
 
8
6
  ## The Rule
9
7
 
10
8
  Before marking **any** task complete:
11
9
 
12
- 1. Run `holdpoint check` — all tasks must exit 0.
13
- 2. `holdpoint check` also prints every **prompt** check whose `when` matches the
14
- files you changed. Read and act on each listed instruction before finishing.
15
-
16
- ---
17
-
18
- ## The Evolve Loop
19
-
20
- `checks.yaml` is not static — it grows alongside the project automatically.
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, `holdpoint evolve` runs and **exits 1 if `checks.yaml` is out of sync** — blocking task completion until you apply the proposals.
23
-
24
- When blocked by `holdpoint-evolve`, run:
25
-
26
- ```
27
- holdpoint evolve --apply # scan, apply proposals, regenerate engine files
28
- ```
29
-
30
- Then commit:
31
-
32
- ```
33
- git add checks.yaml .github/holdpoint/generated/
34
- git commit -m "chore: evolve holdpoint checks"
35
- ```
36
-
37
- `holdpoint evolve --apply` is idempotent — safe to re-run at any time. It only adds checks for tools/patterns detected in the project and wraps stale checks (whose `when:` pattern no longer matches any file) with `conditionId: file_exists` so they auto-skip instead of failing.
38
-
39
- **What triggers evolution:**
40
-
41
- - New dependency in `package.json` / `pyproject.toml` / `go.mod` / `Cargo.toml`
42
- - New `Dockerfile`, `docker-compose.yml`, `*.tf`, `openapi.yaml`
43
- - New test runner config (`vitest.config.*`, `jest.config.*`, `playwright.config.*`)
44
- - New CI workflow in `.github/workflows/`
45
- - New TypeScript setup (`tsconfig.json`)
46
-
47
- **What does NOT trigger it:** `.ts` / `.py` / `.go` source files, docs, styles, tests — minor work proceeds without interruption.
48
-
49
- ---
50
-
51
- ## checks.yaml — Full Reference
52
-
53
- `checks.yaml` at the project root is the single source of truth. Edit it to add,
54
- remove, or change checkpoints.
55
-
56
- After every edit, regenerate the engine files and commit everything together:
57
-
58
- ```
59
- holdpoint update
60
- git add checks.yaml .github/holdpoint/generated/ .github/hooks/
61
- git commit -m "chore: update holdpoint checks"
62
- ```
63
-
64
- ### Top-level structure
65
-
66
- ```yaml
67
- version: 1
68
-
69
- context:
70
- guides: # project notes shown when `holdpoint check` runs
71
- setup: >
72
- Use pnpm, not npm. Node 20+ required.
73
-
74
- conditions: # gate checks on file/env state
75
- - id: dist-built
76
- operator: file_exists
77
- path: dist/index.js
78
-
79
- checks: # list of all checks — each has on/when + cmd (task) or prompt
80
- - ...
81
- ```
82
-
83
- ---
84
-
85
- ### Deterministic check
86
-
87
- ```yaml
88
- - id: lint # unique slug, kebab-case
89
- label: "ESLint — all packages" # human-readable label shown in output
90
- # on: before_done # lifecycle hook (default; only value today)
91
- # when: frontend # file filter — omit to run on every task
92
- cmd: "pnpm turbo lint" # shell command; must exit 0 to pass
93
- conditionId: dist-built # optional: skip if condition is not met
94
- ```
95
-
96
- ### Prompt check
97
-
98
- ```yaml
99
- - id: migration-review
100
- label: "Review DB migration"
101
- when: "^prisma/migrations/" # only fires when migration files change
102
- prompt: >
103
- Open the new migration file. Confirm it is backward-compatible
104
- and does not drop or truncate data without a fallback.
105
- ```
106
-
107
- ---
108
-
109
- ### `on` — lifecycle hooks
110
-
111
- `on` specifies _when in the agent lifecycle_ a check fires. Omit it to use the default.
112
-
113
- | Value | Fires |
114
- | ------------- | ---------------------------------- |
115
- | `before_done` | Before the agent marks a task done |
116
-
117
- ---
118
-
119
- ### `when` — file filters
120
-
121
- `when` is an optional file filter. If omitted the check runs on every task.
122
-
123
- | Value | Fires when changed files match |
124
- | ----------- | -------------------------------------------------------------------------------------------------- |
125
- | _(absent)_ | Every task — no file filter applied |
126
- | `frontend` | `**/*.tsx`, `**/*.jsx`, `**/*.css`, `**/*.scss`, `**/tailwind.config.*`, `apps/**` |
127
- | `backend` | `**/api/**`, `**/server/**`, `**/routes/**`, `**/controllers/**`, `packages/*/src/**` |
128
- | `socket` | `**/socket/**`, `**/ws/**`, `**/websocket/**` |
129
- | `visual` | `**/*.stories.{ts,tsx}`, `**/__screenshots__/**`, `**/*.snap` |
130
- | `python` | `**/*.py`, `**/*.pyi`, `**/requirements*.txt`, `**/pyproject.toml`, `**/setup.py`, `**/pytest.ini` |
131
- | `go` | `**/*.go`, `**/go.mod`, `**/go.sum` |
132
- | `rust` | `**/*.rs`, `**/Cargo.toml`, `**/Cargo.lock` |
133
- | `java` | `**/*.java`, `**/*.kt`, `**/*.gradle`, `**/*.gradle.kts`, `**/pom.xml` |
134
- | `ruby` | `**/*.rb`, `**/Gemfile`, `**/Gemfile.lock`, `**/Rakefile` |
135
- | `database` | `**/*.sql`, `**/migrations/**`, `**/db/**`, `**/database/**`, `**/prisma/**`, `**/*.prisma` |
136
- | `prisma` | `**/prisma/**`, `**/*.prisma` — focused subset of `database` for Prisma-specific checks |
137
- | `testing` | `**/*.test.*`, `**/*.spec.*`, `**/__tests__/**`, `**/test/**`, `**/tests/**`, `**/spec/**` |
138
- | `infra` | `**/Dockerfile*`, `**/docker-compose.*`, `**/*.tf`, `**/*.tfvars`, `**/k8s/**`, `**/kubernetes/**` |
139
- | `ci` | `**/.github/workflows/**`, `**/.circleci/**`, `**/Jenkinsfile`, `**/.gitlab-ci.yml` |
140
- | `docs` | `**/*.mdx`, `**/*.rst`, `**/docs/**`, `**/documentation/**` |
141
- | `"^src/.*"` | Any JavaScript regex tested against each changed file path |
142
-
143
- Regex example — fires only when files under `src/api/` change:
144
-
145
- ```yaml
146
- when: "^src/api/" # new RegExp(when).test(filePath)
147
- ```
148
-
149
- > **Note:** Named scopes use glob matching; plain strings are treated as JavaScript regexes.
150
-
151
- ---
152
-
153
- ### Conditions
154
-
155
- Conditions let you skip a check when a prerequisite is not yet met (e.g. a build
156
- artefact doesn't exist yet).
157
-
158
- | Operator | What it checks |
159
- | ----------------- | ------------------------------------------------- |
160
- | `file_exists` | A file or directory exists at `path` |
161
- | `file_contains` | The file at `path` contains the substring `value` |
162
- | `env_var_set` | The environment variable named `value` is set |
163
- | `shell_returns_0` | The shell command in `cmd` exits with code 0 |
164
-
165
- ```yaml
166
- conditions:
167
- - id: packages-built
168
- operator: file_exists
169
- path: packages/yaml-core/dist/index.js
170
-
171
- checks:
172
- - id: validate-templates
173
- label: "Templates parse against schema"
174
- conditionId: packages-built # skipped (◌) when dist is absent
175
- cmd: "node dist/validate.js templates/"
176
- ```
177
-
178
- ---
179
-
180
- ### Context guides
181
-
182
- `context.guides` is a freeform key → multiline-string map. Guides are printed
183
- at the start of `holdpoint check` output as project-level reminders to whoever
184
- (or whatever) is running the checks.
185
-
186
- ```yaml
187
- context:
188
- guides:
189
- setup: >
190
- This project requires Node 20 and pnpm 9+.
191
- Run `pnpm install` from the repo root before any other command.
192
- architecture: >
193
- API routes live in src/api/. Models live in src/models/.
194
- Client code must never import from server modules.
195
- ```
196
-
197
- ---
198
-
199
- ## Adding a New Check
200
-
201
- 1. Open `checks.yaml`.
202
- 2. Add your entry under `checks:`.
203
- 3. Run `holdpoint update`.
204
- 4. Commit `checks.yaml` and the generated files.
205
-
206
- **Add a task check (runs a shell command automatically):**
207
-
208
- ```yaml
209
- checks:
210
- - id: vitest
211
- label: "Vitest — unit tests"
212
- cmd: "pnpm vitest run"
213
- ```
214
-
215
- **Add a scoped task (fires only on matching file changes):**
216
-
217
- ```yaml
218
- checks:
219
- - id: openapi-sync
220
- label: "OpenAPI types are up to date"
221
- when: "^src/api/"
222
- cmd: "pnpm generate:types && git diff --exit-code src/generated/"
223
- ```
224
-
225
- **Add an agent prompt checkpoint:**
226
-
227
- ```yaml
228
- checks:
229
- - id: jsdoc
230
- label: "JSDoc on changed public functions"
231
- prompt: >
232
- For every public function or export you modified, ensure there is an
233
- accurate JSDoc comment: description, @param, and @returns.
234
- ```
235
-
236
- **Enforce changelog and git commit on every task (recommended):**
237
-
238
- ```yaml
239
- checks:
240
- - id: changelog-update
241
- label: "Add a CHANGELOG.md entry for this session"
242
- prompt: >
243
- Before committing, add an entry to CHANGELOG.md describing what was done.
244
- Use Keep a Changelog format — add under ## [Unreleased] (create the file
245
- and that section if absent). Group entries as Added, Changed, Fixed, or Removed.
246
- Be concise but specific. The entry text will serve as the commit message.
247
-
248
- - id: readme-sync
249
- label: "Update README.md if user-facing changes were made"
250
- prompt: >
251
- If you added, changed, or removed user-facing functionality — CLI commands,
252
- configuration options, public APIs, or significant new features — update
253
- README.md to reflect those changes.
254
-
255
- - id: git-commit
256
- label: "Commit all changes before finishing"
257
- cmd: 'git rev-parse --is-inside-work-tree >/dev/null 2>&1 || exit 0; [ -z "$(git status --porcelain)" ] && exit 0; git status --short; exit 1'
258
- ```
259
-
260
- When the `git-commit` check fails (uncommitted changes remain), the agent will also see
261
- the `changelog-update` and `readme-sync` prompt reminders inline — ensuring it updates
262
- the changelog, syncs docs, _then_ commits before it can mark the task done.
263
-
264
- ---
265
-
266
- ## `session_context_files`
267
-
268
- `session_context_files` is an optional list of project files that Holdpoint injects
269
- as context at the start of every Copilot session. Use it for files the agent should
270
- always read before starting work.
271
-
272
- ```yaml
273
- session_context_files:
274
- - MASTER_PROMPT.md
275
- - AGENT_CONTEXT.md
276
- ```
277
-
278
- Files are resolved relative to the repo root and must stay inside it (traversal
279
- paths like `../../etc/passwd` are rejected). If a file doesn't exist it is silently
280
- skipped.
10
+ 1. Run `holdpoint check` — all checks must exit 0.
11
+ 2. `holdpoint check` also prints every **prompt** check whose `when`
12
+ matches the files you changed. Read and act on each listed
13
+ instruction before finishing.
14
+ 3. Never bypass via `git commit --no-verify` or by skipping a stop
15
+ hook. If a check is wrong, fix the check in `checks.yaml`, don't
16
+ route around it.
281
17
 
282
- ---
18
+ ## The Suggest Loop
283
19
 
284
- ## Commands
20
+ `checks.yaml` grows with the project. `holdpoint-suggest` is a check
21
+ that fires whenever structural files change (`package.json`,
22
+ `pyproject.toml`, `go.mod`, `Dockerfile`, `tsconfig.json`,
23
+ `vitest.config.*`, etc.). When it fires, `holdpoint suggest` runs and
24
+ **exits 1 if `checks.yaml` is out of sync** — blocking task completion
25
+ until you apply the proposals.
285
26
 
286
- | Command | What it does |
287
- | -------------------------- | ------------------------------------------------------- |
288
- | `holdpoint check` | Run checks against all files changed vs HEAD |
289
- | `holdpoint check --staged` | Run checks against staged files only |
290
- | `holdpoint evolve` | Scan project and show proposed additions to checks.yaml |
291
- | `holdpoint evolve --apply` | Apply proposals and regenerate engine files |
292
- | `holdpoint update` | Regenerate engine files from the current `checks.yaml` |
293
- | `holdpoint validate` | Validate `checks.yaml` schema (no commands run) |
294
- | `holdpoint builder` | Open the visual builder UI at localhost:4321 |
27
+ When blocked, run:
295
28
 
296
- ---
29
+ holdpoint suggest --apply
297
30
 
298
- ## Generated files (do not edit directly)
31
+ then commit the changes and continue.
299
32
 
300
- | File | Agent |
301
- | --------------------------------------------------- | ------- |
302
- | `.github/holdpoint/generated/checks.immutable.json` | all |
303
- | `.github/hooks/holdpoint.json` | Copilot |
304
- | `.github/hooks/holdpoint-check.mjs` | Copilot |
305
- | `.claude/settings.json` | Claude |
306
- | `.cursorrules` (Holdpoint section) | Cursor |
33
+ ## Going deeper
307
34
 
308
- All generated files are overwritten by `holdpoint update`. Edit `checks.yaml`,
309
- then run `update`never edit the generated files directly.
35
+ For the full reference every built-in check, every `when:` scope,
36
+ per-engine details, troubleshootingread
37
+ [`HOLDPOINT_REFERENCE.md`](./HOLDPOINT_REFERENCE.md). The file is on
38
+ disk; you can `cat` it when you need detail. It is intentionally not
39
+ auto-injected because it's reference, not directive.