voidmachine 7.0.0 → 7.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/core-assets/.claude-plugin/plugin.json +1 -1
- package/core-assets/data/catalog.v3.json +7 -7
- package/core-assets/data/certification.json +1 -1
- package/core-assets/data/model.json +6 -6
- package/core-assets/skills/void-autopilot/SKILL.md +13 -12
- package/core-assets/skills/void-autopilot/references/publication.md +82 -0
- package/core-assets/skills/void-implement/SKILL.md +4 -2
- package/core-assets/skills/void-orchestrate/SKILL.md +9 -4
- package/core-assets/skills/void-verify/references/ci-admission.mjs +1 -1
- package/core-assets/skills/void-verify/references/ci-feedback.md +33 -4
- package/core-assets/templates/github/void-dependency-audit.yml +18 -2
- package/dist/main.js +2135 -1377
- package/package.json +2 -2
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "harness",
|
|
3
|
-
"version": "7.0.
|
|
3
|
+
"version": "7.0.1",
|
|
4
4
|
"description": "VoidCorp universal craftsman skills (void-tdd, void-typescript-strict, void-hexagonal-architecture, void-domain-driven-design, void-functional, void-code-review, void-api-and-interface-design, void-source-driven-development, void-context, void-learn, void-decide, void-claude-md, void-observability, void-security-guidance, ...) plus 12 PreToolUse enforcement hooks (tdd-guard, no-any, protect-sensitive-files, block-dangerous-bash, no-ai-design-slop, ...) and PostToolUse/SessionStart lifecycle hooks (incl. trim-large-output token frugality), five read-only critics including doctrine-critic, native architecture/security/QA specialists, and the void-graph, void-doctor and void-audit gestures, which are skills like everything else.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "VoidCorp",
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"source": {
|
|
6
6
|
"kind": "adapter",
|
|
7
7
|
"version": "3.0.0-alpha.1",
|
|
8
|
-
"rootHash": "sha256:
|
|
8
|
+
"rootHash": "sha256:f1fe033cd7785501f43276bf1cb9e971d71928c082c836d0cd9c04db90efaa95"
|
|
9
9
|
},
|
|
10
10
|
"nodes": [
|
|
11
11
|
{
|
|
@@ -3523,7 +3523,7 @@
|
|
|
3523
3523
|
}
|
|
3524
3524
|
],
|
|
3525
3525
|
"id": "skill:void-autopilot",
|
|
3526
|
-
"lines":
|
|
3526
|
+
"lines": 397,
|
|
3527
3527
|
"name": "void-autopilot",
|
|
3528
3528
|
"owner": "folpe",
|
|
3529
3529
|
"pack": null,
|
|
@@ -3532,7 +3532,7 @@
|
|
|
3532
3532
|
"codex"
|
|
3533
3533
|
],
|
|
3534
3534
|
"source": "packages/core/skills/void-autopilot/SKILL.md",
|
|
3535
|
-
"staticTokens":
|
|
3535
|
+
"staticTokens": 7165,
|
|
3536
3536
|
"type": "skill"
|
|
3537
3537
|
}
|
|
3538
3538
|
},
|
|
@@ -4303,7 +4303,7 @@
|
|
|
4303
4303
|
}
|
|
4304
4304
|
],
|
|
4305
4305
|
"id": "skill:void-implement",
|
|
4306
|
-
"lines":
|
|
4306
|
+
"lines": 236,
|
|
4307
4307
|
"name": "void-implement",
|
|
4308
4308
|
"owner": "folpe",
|
|
4309
4309
|
"pack": null,
|
|
@@ -4312,7 +4312,7 @@
|
|
|
4312
4312
|
"codex"
|
|
4313
4313
|
],
|
|
4314
4314
|
"source": "packages/core/skills/void-implement/SKILL.md",
|
|
4315
|
-
"staticTokens":
|
|
4315
|
+
"staticTokens": 6683,
|
|
4316
4316
|
"type": "skill"
|
|
4317
4317
|
}
|
|
4318
4318
|
},
|
|
@@ -4649,7 +4649,7 @@
|
|
|
4649
4649
|
}
|
|
4650
4650
|
],
|
|
4651
4651
|
"id": "skill:void-orchestrate",
|
|
4652
|
-
"lines":
|
|
4652
|
+
"lines": 203,
|
|
4653
4653
|
"name": "void-orchestrate",
|
|
4654
4654
|
"owner": "folpe",
|
|
4655
4655
|
"pack": null,
|
|
@@ -4658,7 +4658,7 @@
|
|
|
4658
4658
|
"codex"
|
|
4659
4659
|
],
|
|
4660
4660
|
"source": "packages/core/skills/void-orchestrate/SKILL.md",
|
|
4661
|
-
"staticTokens":
|
|
4661
|
+
"staticTokens": 3363,
|
|
4662
4662
|
"type": "skill"
|
|
4663
4663
|
}
|
|
4664
4664
|
},
|
|
@@ -1693,7 +1693,7 @@
|
|
|
1693
1693
|
}
|
|
1694
1694
|
],
|
|
1695
1695
|
"id": "skill:void-autopilot",
|
|
1696
|
-
"lines":
|
|
1696
|
+
"lines": 397,
|
|
1697
1697
|
"name": "void-autopilot",
|
|
1698
1698
|
"owner": "folpe",
|
|
1699
1699
|
"pack": null,
|
|
@@ -1702,7 +1702,7 @@
|
|
|
1702
1702
|
"codex"
|
|
1703
1703
|
],
|
|
1704
1704
|
"source": "packages/core/skills/void-autopilot/SKILL.md",
|
|
1705
|
-
"staticTokens":
|
|
1705
|
+
"staticTokens": 7165,
|
|
1706
1706
|
"type": "skill"
|
|
1707
1707
|
},
|
|
1708
1708
|
{
|
|
@@ -2185,7 +2185,7 @@
|
|
|
2185
2185
|
}
|
|
2186
2186
|
],
|
|
2187
2187
|
"id": "skill:void-implement",
|
|
2188
|
-
"lines":
|
|
2188
|
+
"lines": 236,
|
|
2189
2189
|
"name": "void-implement",
|
|
2190
2190
|
"owner": "folpe",
|
|
2191
2191
|
"pack": null,
|
|
@@ -2194,7 +2194,7 @@
|
|
|
2194
2194
|
"codex"
|
|
2195
2195
|
],
|
|
2196
2196
|
"source": "packages/core/skills/void-implement/SKILL.md",
|
|
2197
|
-
"staticTokens":
|
|
2197
|
+
"staticTokens": 6683,
|
|
2198
2198
|
"type": "skill"
|
|
2199
2199
|
},
|
|
2200
2200
|
{
|
|
@@ -2405,7 +2405,7 @@
|
|
|
2405
2405
|
}
|
|
2406
2406
|
],
|
|
2407
2407
|
"id": "skill:void-orchestrate",
|
|
2408
|
-
"lines":
|
|
2408
|
+
"lines": 203,
|
|
2409
2409
|
"name": "void-orchestrate",
|
|
2410
2410
|
"owner": "folpe",
|
|
2411
2411
|
"pack": null,
|
|
@@ -2414,7 +2414,7 @@
|
|
|
2414
2414
|
"codex"
|
|
2415
2415
|
],
|
|
2416
2416
|
"source": "packages/core/skills/void-orchestrate/SKILL.md",
|
|
2417
|
-
"staticTokens":
|
|
2417
|
+
"staticTokens": 3363,
|
|
2418
2418
|
"type": "skill"
|
|
2419
2419
|
},
|
|
2420
2420
|
{
|
|
@@ -151,7 +151,7 @@ Act on each returned action, then ask again:
|
|
|
151
151
|
|
|
152
152
|
| Action | What you do |
|
|
153
153
|
|---|---|
|
|
154
|
-
| `assign` | claim the ticket (In Progress, assigned), run `autopilot fingerprint --before <ticket>`, create or reuse its worktree,
|
|
154
|
+
| `assign` | claim the ticket (In Progress, assigned), run `autopilot fingerprint --before <ticket>`, create or reuse its worktree, create the controlled mission there with title and full frozen ticket via `void-orchestrate`, hand its ID to the worker |
|
|
155
155
|
| `wait` | nothing; the reason says who is working |
|
|
156
156
|
| `hand-back-to-worker` | give the ticket back to its worker, alive or respawned in the same worktree, with the reason and the pull request; a respawned worker resumes its mission (see Respawning) |
|
|
157
157
|
| `mark-human-wait` | record it in `recent` with its `reason`, which `recent` requires and the recap repeats, put the decision's `humanWaitLabel` on the ticket, comment the reason and detail, free the slot; keep reporting its pull request and footprint, which hold its ground until that pull request merges or closes |
|
|
@@ -159,7 +159,7 @@ Act on each returned action, then ask again:
|
|
|
159
159
|
| `update-branch` | `void-machine autopilot update-branch --pr <n> --head <headSha>`: GitHub merges the base into the branch if its head is still that one; the new head is reviewed before anything merges it |
|
|
160
160
|
| `enable-auto-merge` | `void-machine autopilot arm --ticket <id> --pr <n> --head <headSha>`, on a base with a merge queue: the same guards, then it records the head, arms on exactly that head and reads GitHub back; never `gh pr merge --auto` by hand, never `--admin` |
|
|
161
161
|
| `disable-auto-merge` | `void-machine autopilot disarm --pr <n>`, before the action that follows it for the same ticket; it turns its auto-merge off, then takes it out of the merge queue, and fails while GitHub still shows either; never `gh pr merge --disable-auto` alone, which leaves a queued pull request in the queue |
|
|
162
|
-
| `review` | `void-machine autopilot review --ticket <id> --pr <n> --head <headSha> --round <round> --mission <canonical-id
|
|
162
|
+
| `review` | `void-machine autopilot review --ticket <id> --pr <n> --head <headSha> --round <round> --mission <canonical-id> --worktree <assigned-path>` from the coordinator checkout; on awaiting-native-review use `void-orchestrate` for the actual reviewer, record canonical receipts, then repeat to collect. The same attempt keeps its 30 minute deadline; failures retain the existing budget |
|
|
163
163
|
| `requeue` | the same command, to put an ejected head back in the queue; the kernel bounds how often |
|
|
164
164
|
| `drain` | take nothing new; keep acting on the tickets in flight |
|
|
165
165
|
| `freeze` | stop acting, once the disarms before it succeeded |
|
|
@@ -201,13 +201,13 @@ the local config and the files it includes, the stash, tags, notes, remotes, the
|
|
|
201
201
|
deploy branches, replace refs, `hooks/` and `info/` are one set for every worktree. The upstream
|
|
202
202
|
(`remote`, `merge`) of every branch but the bases and the one that deploys is left out, since units
|
|
203
203
|
in flight set it when they create or push their branch and drop it with a merged one; the bases'
|
|
204
|
-
own settings still count.
|
|
204
|
+
own settings still count; only regular root `info/refs`, Git’s generated transport cache, is exempt. Start each worktree from
|
|
205
205
|
`origin/<base>` and never move a local base branch while units are in flight. The baseline
|
|
206
206
|
recorded at `assign` is written once: a second `--before` for the same ticket is refused, so a unit
|
|
207
|
-
cannot re-record the state it left as the state it found.
|
|
208
|
-
publishes
|
|
209
|
-
|
|
210
|
-
|
|
207
|
+
cannot re-record the state it left as the state it found. `autopilot fingerprint --after <ticket>`
|
|
208
|
+
checks it; the coordinator publishes only through `autopilot publish --ticket <ticket> --head <sha>
|
|
209
|
+
--remote <remote> --branch <branch>`, which couples that guard to the literal SHA push. Never follow
|
|
210
|
+
refusal with direct Git. Human renewal retains evidence; see [publication and recovery](references/publication.md).
|
|
211
211
|
|
|
212
212
|
**Disarming.** Armed means GitHub merges without anyone acting again: an auto-merge request, or,
|
|
213
213
|
once the checks pass on a base with a merge queue, an entry in that queue and no request at all.
|
|
@@ -266,18 +266,19 @@ neither, so a restart loses nothing.
|
|
|
266
266
|
|
|
267
267
|
## Workers
|
|
268
268
|
|
|
269
|
-
Given: one ticket id, its worktree, its branch, the programme's plan and spec. The worker re-fetches
|
|
269
|
+
Given: one ticket id, its worktree, its branch, its canonical mission ID, the programme's plan and spec. The worker re-fetches
|
|
270
270
|
the complete ticket itself; it never works from a summary.
|
|
271
271
|
|
|
272
|
-
It runs `void-implement` whole in that worktree,
|
|
273
|
-
|
|
272
|
+
It runs `void-implement` whole and `mission dispatch` in that worktree, reusing the mission
|
|
273
|
+
the coordinator created once with `--title <ticket-id> --ticket <full-frozen-ticket>`.
|
|
274
|
+
A respawn retains that identity and its budgets. Before any context compaction it writes to the
|
|
274
275
|
mission what it has done: each specialist result through `mission specialist-event`, each proof
|
|
275
276
|
through `mission verify`, a committed candidate through `mission writer-event`. The journal accepts
|
|
276
277
|
only these typed events, no free note; what is not yet one of them does not survive a respawn, and
|
|
277
278
|
uncommitted edits survive only in the worktree. During development, the coordinator may create or reuse a draft pull request
|
|
278
279
|
for the branch; drafts are permitted for development, never for merge admission. After the worker
|
|
279
|
-
returns its commit and green proofs, the coordinator runs `autopilot
|
|
280
|
-
|
|
280
|
+
returns its commit and green proofs, the coordinator runs the guarded `autopilot publish` command
|
|
281
|
+
and must mark the same pull request ready (create one only if absent), then move the ticket
|
|
281
282
|
to In Review. The independent reviewer examines ready pull requests only; an unfinished draft waits.
|
|
282
283
|
Blocking findings come back as a hand-back and are corrected as a batch, per `void-implement`.
|
|
283
284
|
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# Guarded publication and human recovery
|
|
2
|
+
|
|
3
|
+
The coordinator runs from the checkout containing the ticket's original baseline.
|
|
4
|
+
The local candidate branch can belong to another worktree; no checkout movement
|
|
5
|
+
or evidence copy is needed. Workers remain commit-only.
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
void-machine autopilot publish --ticket DEV-42 --head <full-sha> --remote origin --branch fix/dev-42 --json
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
This checks the explicit local branch against the full SHA and the shared Git
|
|
12
|
+
guard, then pushes that literal SHA to the named remote branch in the same
|
|
13
|
+
command. A base or deploy branch is refused. It does not force push, disable
|
|
14
|
+
hooks, set an upstream, grant review or merge permission, or remove a merge hold.
|
|
15
|
+
Missing, invalid, unreadable and changed fingerprints launch zero pushes. A
|
|
16
|
+
transport error can follow a remote success: inspect the named remote branch
|
|
17
|
+
before a deliberate retry. Never automatically follow a refusal with direct Git.
|
|
18
|
+
|
|
19
|
+
## Coverage
|
|
20
|
+
|
|
21
|
+
Policy v4 excludes only a regular file exactly at common-Git-directory `info/refs`.
|
|
22
|
+
Git documents it as generated transport information, rebuilt by
|
|
23
|
+
[`git update-server-info`](https://git-scm.com/docs/git-update-server-info).
|
|
24
|
+
Its creation, update and removal are harmless to this guard. This does not identify
|
|
25
|
+
who created an incident file from its timestamp. `objects/info/packs` is Git's
|
|
26
|
+
other generated output; it is outside the existing fingerprint. `info/packs` is
|
|
27
|
+
not that output and stays guarded. Symlinks, nested `refs`, `info/exclude`,
|
|
28
|
+
`info/attributes`, hooks and their checksums, config/includes, bases, stash, tags,
|
|
29
|
+
notes, remotes and replace refs retain their previous coverage.
|
|
30
|
+
|
|
31
|
+
Version 3 aggregates the whole info directory, including regular root `info/refs`.
|
|
32
|
+
A retained v3 record is compared against a current reading using that same complete
|
|
33
|
+
v3 policy at both publication checks and in `autopilot next` merge decisions. All nine digests and retained protected branches
|
|
34
|
+
stay authoritative; any drift refuses. No conversion, renewal or baseline write is
|
|
35
|
+
needed for an unchanged v3 state. Versions 1 and 2 remain unsupported.
|
|
36
|
+
|
|
37
|
+
A v3 aggregate cannot be converted to v4 without historical file contents. Relaxing
|
|
38
|
+
its policy or accepting actual drift still requires the explicit human renewal below.
|
|
39
|
+
`fingerprint --record` reports the current v4 reading for that renewal inspection;
|
|
40
|
+
`fingerprint --after` and publication use the retained policy for comparison.
|
|
41
|
+
|
|
42
|
+
## Explicit human renewal
|
|
43
|
+
|
|
44
|
+
Stop publication. Inspect the failure and the actual shared-state changes. A
|
|
45
|
+
person must authorize the exact repair or policy transition and affected candidate;
|
|
46
|
+
the ticket's implementation mandate alone is not that authorization.
|
|
47
|
+
|
|
48
|
+
```sh
|
|
49
|
+
void-machine autopilot fingerprint --record DEV-42 --json
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Retain the output, including `recordDigest`, `currentDigest`, old fingerprint and
|
|
53
|
+
current fingerprint. After the human decision, use those exact digest values:
|
|
54
|
+
|
|
55
|
+
```sh
|
|
56
|
+
void-machine autopilot fingerprint --renew DEV-42 --head <full-sha> --branch fix/dev-42 \
|
|
57
|
+
--previous <recordDigest> --expected <currentDigest> \
|
|
58
|
+
--cause 'Reviewed authorized repair or v3 policy transition' \
|
|
59
|
+
--decision '<reference to the explicit human decision>' --json
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
The original `fingerprints/DEV-42.json` remains byte-for-byte intact. The complete
|
|
63
|
+
renewal under `fingerprints/DEV-42.renewals/` retains both fingerprints, predecessor
|
|
64
|
+
digest, branch/SHA, cause and decision. Its atomic creation is the transition;
|
|
65
|
+
there is no separate baseline replacement. Identical replay returns the retained
|
|
66
|
+
record. Conflicting or stale replay and changed observations refuse. Preserve
|
|
67
|
+
all those files: deleting history is not recovery. Renewal changes no review,
|
|
68
|
+
merge hold, merge authorization or deployment permission.
|
|
69
|
+
|
|
70
|
+
Publication and renewal share `fingerprints/DEV-42.lock`. A competing operation
|
|
71
|
+
refuses immediately. A crashed process may leave that directory: a person must
|
|
72
|
+
establish the owning process ended and inspect retained evidence before removing
|
|
73
|
+
only that abandoned lock. An incomplete canonical record remains blocked and
|
|
74
|
+
must be recovered from retained evidence, never ignored. Unlinked unique temporary
|
|
75
|
+
files are not committed records; retain them for diagnosis after an interrupted write.
|
|
76
|
+
|
|
77
|
+
The lock coordinates these supported commands in this state directory. It cannot
|
|
78
|
+
serialize direct Git, hooks or other processes, nor prevent malicious edits to
|
|
79
|
+
local evidence. The command rechecks immediately before its side effect and uses
|
|
80
|
+
an immutable commit refspec, but does not claim an atomic snapshot of all Git state
|
|
81
|
+
through network completion. See [Git push](https://git-scm.com/docs/git-push) for
|
|
82
|
+
refspec and hook semantics. Direct Git is outside this guarantee.
|
|
@@ -55,8 +55,10 @@ materializes its runtime-neutral specialist envelopes from the current plan.
|
|
|
55
55
|
|
|
56
56
|
1. Keep one `leadWriterId` for implementation and every correction. The implementer owns
|
|
57
57
|
the worktree and code; specialists and the independent reviewer never edit.
|
|
58
|
-
2.
|
|
59
|
-
|
|
58
|
+
2. Reuse the mission ID the coordinator supplied. The coordinator creates it once from the
|
|
59
|
+
assigned worktree with `mission start --title <unit> --ticket <full-frozen-ticket> --json`.
|
|
60
|
+
Run `mission dispatch --id <mission> --json` from that worktree. Never start another mission
|
|
61
|
+
to repair a refusal. The frozen task and controller own routing, state and correction budget. Normal
|
|
60
62
|
dispatch starts the writer without a compulsory preparation panel. The writer still obtains
|
|
61
63
|
the primary domain specialist advice required by pass 5 before production edits.
|
|
62
64
|
For canonical `invoke-specialists` actions, pass each envelope unchanged through
|
|
@@ -131,8 +131,11 @@ Missing required native capability is reported with cause and next action.
|
|
|
131
131
|
## Publish worker observations
|
|
132
132
|
|
|
133
133
|
For each mission worker or reviewer, keep one `run_<opaque-id>` for its assignment.
|
|
134
|
-
|
|
135
|
-
`void-machine mission start --title <unit>
|
|
134
|
+
The coordinator reuses the unit's open canonical mission. If none exists for controlled
|
|
135
|
+
implementation, it creates one from the assigned worktree with `void-machine mission start --title <unit>
|
|
136
|
+
--ticket <full-frozen-ticket> --json` and hands the returned ID to the writer.
|
|
137
|
+
The writer reuses that ID and runs `mission dispatch` from the assigned worktree.
|
|
138
|
+
Title-only missions remain valid for simple work without controlled dispatch or review.
|
|
136
139
|
Do not recreate a mission to evade a refusal. This publication never substitutes
|
|
137
140
|
for the mission's implementation, verification or independent review receipts.
|
|
138
141
|
|
|
@@ -189,8 +192,10 @@ stays within the existing project boundary and must match its digest and invocat
|
|
|
189
192
|
A central report marked done is never a review receipt. Preserve limitations honestly.
|
|
190
193
|
|
|
191
194
|
For autopilot, `autopilot review --ticket <id> --pr <n> --head <sha> --round <1|2>
|
|
192
|
-
--mission <canonical-id
|
|
193
|
-
and
|
|
195
|
+
--mission <canonical-id> --worktree <assigned-path>` runs from the coordinator checkout,
|
|
196
|
+
retains its programme and local verdicts there, and checks the target ticket against the existing bounded ticket reader (filename identity
|
|
197
|
+
and frozen content hash) in the assigned checkout, reading the journal from its resolved
|
|
198
|
+
installation root. Missing plans and mismatched subjects refuse before spending an attempt. It then prepares the exact review subject/worktree and, when
|
|
194
199
|
pending, returns awaiting-native-review. ORCH performs the native invocation and
|
|
195
200
|
records its real receipts, then repeats the same command to collect. Do not start a
|
|
196
201
|
new mission to repair a pending attempt. Budgets, protected paths, HEAD drift checks,
|
|
@@ -6,7 +6,7 @@ import { readFileSync } from 'node:fs';
|
|
|
6
6
|
|
|
7
7
|
try {
|
|
8
8
|
const name = process.env.GITHUB_EVENT_NAME;
|
|
9
|
-
if (!['pull_request', 'merge_group', 'push', 'workflow_dispatch'].includes(name)) {
|
|
9
|
+
if (!['pull_request', 'merge_group', 'push', 'workflow_dispatch', 'schedule'].includes(name)) {
|
|
10
10
|
throw new Error('CI_INVALID_EVENT: unsupported or missing GitHub event.');
|
|
11
11
|
}
|
|
12
12
|
const event = JSON.parse(readFileSync(process.env.GITHUB_EVENT_PATH, 'utf8'));
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
# Fast local feedback, real integration checks
|
|
2
2
|
|
|
3
3
|
The sibling files are shipped with this skill and copied by `init` into the selected
|
|
4
|
-
runtime's skill directory.
|
|
4
|
+
runtime's skill directory. `update` refreshes owned references; adopted workflows
|
|
5
|
+
remain project-owned and are never overwritten by that reference refresh. Resolve them relative to the SKILL.md you actually loaded,
|
|
5
6
|
not from a developer checkout or a global installation.
|
|
6
7
|
|
|
7
8
|
On an explicit CI configuration request:
|
|
@@ -14,7 +15,9 @@ On an explicit CI configuration request:
|
|
|
14
15
|
inside an existing **required** quality job, before dependency installation, without
|
|
15
16
|
`continue-on-error`, `always()` on later quality steps, or a job-level draft skip.
|
|
16
17
|
3. Set up the project's actual package manager and immutable lockfile installation.
|
|
17
|
-
The example uses npm
|
|
18
|
+
The example uses npm and an illustrative Node version; preserve the project's
|
|
19
|
+
supported Node version owner (for example `.node-version`). For pnpm/Bun use
|
|
20
|
+
their pinned setup and frozen install. Do not introduce another package manager.
|
|
18
21
|
Define `ci:verify` in package.json to run the actual complete lint, typecheck, build,
|
|
19
22
|
and test commands appropriate to the project. Do not equate `testUnit` with the
|
|
20
23
|
whole integration suite; discover the project's existing CI contract. Missing
|
|
@@ -24,9 +27,11 @@ On an explicit CI configuration request:
|
|
|
24
27
|
this template alone does not configure GitHub protection. Retain the separate
|
|
25
28
|
`void-enforce` floor and independent review. This template does not replace either.
|
|
26
29
|
5. Test draft, ready without another commit, new head, return to draft, merge group,
|
|
27
|
-
and manual run.
|
|
30
|
+
and manual run. A deliberately added schedule is supported by the guard and
|
|
31
|
+
runs real checks; it does not prove a separate PR candidate. `CI_DEFERRED_DRAFT` is expected non-admission during preparation,
|
|
28
32
|
not a failed test: tests have not run. Readiness runs the full suite even at the
|
|
29
|
-
same SHA.
|
|
33
|
+
same SHA. Continue focused local work during draft non-admission, without
|
|
34
|
+
retrying the remote refusal. Never treat a skipped required job as test evidence.
|
|
30
35
|
|
|
31
36
|
Development runs configured local tests for the changed behavior and affected types.
|
|
32
37
|
There is no network hook or mandatory remote wait per edit. Only obsolete PR runs are
|
|
@@ -40,6 +45,28 @@ post-merge run only after checking that no release, promotion or artifact consum
|
|
|
40
45
|
needs it, and that the protected integration path proves the merged result. The
|
|
41
46
|
example has no push trigger; add one where it provides distinct release evidence.
|
|
42
47
|
|
|
48
|
+
For reusable enforcement, the caller must also declare `ready_for_review`,
|
|
49
|
+
`converted_to_draft` and `merge_group: checks_requested`, keeping its existing
|
|
50
|
+
check names. Put concurrency only in that caller; the called workflow inherits
|
|
51
|
+
`github.workflow` and must not cancel the same group. Its admission guard runs
|
|
52
|
+
from the immutable harness checkout before Node setup and floor execution.
|
|
53
|
+
GitHub-hosted runner usage belongs to the caller, even when the reusable workflow
|
|
54
|
+
is public and the caller private. Compare latency and job-minutes before making
|
|
55
|
+
any billing claim.
|
|
56
|
+
|
|
57
|
+
Dependency audit is a separate project-owned job, without a `needs` edge that
|
|
58
|
+
prevents lint/tests/build from running during an advisory-service outage. Preserve
|
|
59
|
+
its actual package-manager/lockfile contract and severity policy: installing Bun
|
|
60
|
+
is not an audit solution for npm or pnpm consumers. `npm ci` advisory output alone
|
|
61
|
+
is not a complete audit gate. Bun consumers can adopt the packaged
|
|
62
|
+
`core-assets/templates/github/void-dependency-audit.yml` and `dependency-audit.mjs`,
|
|
63
|
+
plus this sibling `ci-admission.mjs`; the audit guide is `docs/DEPENDENCY-AUDIT.md`
|
|
64
|
+
in a matching source checkout. Its ready-PR and merge-group runs judge their own
|
|
65
|
+
revision; a weekly scheduled run catches new advisories without a lockfile change
|
|
66
|
+
and is surveillance, not a substitute for a required candidate check. Unavailable
|
|
67
|
+
or malformed evidence stays non-green. No workflow path filter may hide required
|
|
68
|
+
checks or prevent scheduled registry refresh.
|
|
69
|
+
|
|
43
70
|
Rollback: restore the prior workflow triggers and admission step together. Restoring
|
|
44
71
|
full draft CI costs runner time but does not weaken the floor. Leave protection and
|
|
45
72
|
review evidence unchanged. Existing missions and receipts are not migrated.
|
|
@@ -49,3 +76,5 @@ Sources read for GitHub Actions (hosted service):
|
|
|
49
76
|
- https://docs.github.com/en/actions/how-tos/write-workflows/choose-when-workflows-run/control-workflow-concurrency
|
|
50
77
|
- https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/configuring-pull-request-merges/managing-a-merge-queue
|
|
51
78
|
- https://docs.github.com/en/actions/how-tos/write-workflows/choose-when-workflows-run/control-jobs-with-conditions
|
|
79
|
+
|
|
80
|
+
- https://docs.github.com/en/actions/reference/workflows-and-actions/reusing-workflow-configurations
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Bun consumer template: adopt with dependency-audit.mjs and ci-admission.mjs.
|
|
2
2
|
# See docs/DEPENDENCY-AUDIT.md before adopting; no consumer CI is overwritten.
|
|
3
3
|
name: void-dependency-audit
|
|
4
4
|
|
|
@@ -6,17 +6,33 @@ on:
|
|
|
6
6
|
push:
|
|
7
7
|
branches: [main]
|
|
8
8
|
pull_request:
|
|
9
|
+
types: [opened, synchronize, reopened, ready_for_review, converted_to_draft]
|
|
10
|
+
merge_group:
|
|
11
|
+
types: [checks_requested]
|
|
12
|
+
# New advisories can affect an unchanged lockfile. Surveillance is not PR proof.
|
|
13
|
+
schedule:
|
|
14
|
+
- cron: '17 4 * * 1'
|
|
9
15
|
workflow_dispatch:
|
|
10
16
|
|
|
11
17
|
permissions:
|
|
12
18
|
contents: read
|
|
13
19
|
|
|
20
|
+
concurrency:
|
|
21
|
+
group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.event.pull_request.number || github.run_id }}
|
|
22
|
+
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
|
23
|
+
|
|
14
24
|
jobs:
|
|
15
25
|
dependency-audit:
|
|
16
26
|
runs-on: ubuntu-latest
|
|
17
27
|
timeout-minutes: 10
|
|
18
28
|
steps:
|
|
19
29
|
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
|
|
30
|
+
with:
|
|
31
|
+
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
|
32
|
+
persist-credentials: false
|
|
33
|
+
- name: Admit dependency audit
|
|
34
|
+
id: admission
|
|
35
|
+
run: node .github/scripts/ci-admission.mjs
|
|
20
36
|
- uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6
|
|
21
37
|
with:
|
|
22
38
|
node-version: 24
|
|
@@ -26,7 +42,7 @@ jobs:
|
|
|
26
42
|
- name: Classify dependency audit
|
|
27
43
|
run: node .github/scripts/dependency-audit.mjs "$RUNNER_TEMP/dependency-audit"
|
|
28
44
|
- name: Preserve audit report
|
|
29
|
-
if: always()
|
|
45
|
+
if: ${{ always() && steps.admission.outcome == 'success' }}
|
|
30
46
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
|
|
31
47
|
with:
|
|
32
48
|
name: dependency-audit
|