voidmachine 7.0.0 → 7.0.2

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.
@@ -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, spawn its worker |
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>`; 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 |
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. So start each worktree from
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. It is compared by the coordinator before it
208
- publishes, with `autopilot fingerprint --after <ticket>`, and again by the kernel before it arms a
209
- merge. A changed or missing baseline sends the ticket to a human, unpublished; only that person
210
- deletes the record.
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, and starts its mission with the ticket id as its
273
- `--title`, which is how a respawn finds it again. Before any context compaction it writes to the
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 fingerprint --after <ticket>`,
280
- pushes, and must mark the same pull request ready (create one only if absent), then move the ticket
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
 
@@ -338,7 +339,10 @@ its proofs and returns its commit for coordinator publication; `semantic` -- two
338
339
  sends the ticket to a human. A worker never picks a side of a semantic conflict to keep the loop
339
340
  moving.
340
341
 
341
- **Serial fallback.** Without a merge queue, merges run one at a time: the oldest ready pull request
342
+ **Serial fallback.** This path requires no queue service or paid plan.
343
+ For CI optimization, use [void-verify CI feedback](../void-verify/references/ci-feedback.md);
344
+ add neither a second scheduler nor a mandatory duration gate.
345
+ Without a merge queue, merges run one at a time: the oldest ready pull request
342
346
  (or the one already merging) holds the turn. The kernel reads whether the base moved past its head
343
347
  itself, since GitHub reports it only under a protection that requires it: a head behind gets
344
348
  `update-branch`, its new head is reviewed again, then merged, then the next. `merge` reads it once
@@ -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. Start with `mission start --ticket <ticket>` and follow `mission dispatch --id <mission>
59
- --json`. The frozen task and controller own routing, state and correction budget. Normal
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
@@ -1,12 +1,12 @@
1
1
  ---
2
2
  name: void-merge
3
- description: Vider la file des PR ouvertes sans casser le dépôt. Ordre par déblocage plutôt que par date, CI verte ET à jour, artefacts générés régénérés, conflits de contenu rendus à leur auteur. Use when merging pull requests.
3
+ description: Vider la file des PR ouvertes sans casser le dépôt. Fusions séquentielles, ordre stable et dépendances explicites, CI verte ET à jour, artefacts générés régénérés, conflits de contenu rendus à leur auteur. Use when merging pull requests.
4
4
  ---
5
5
 
6
6
  # merge — voidcorp craftsman edition
7
7
 
8
8
  `void-implement` s'arrête à la PR ouverte. `void-autopilot` laisse à une personne les PR qu'il ne peut
9
- pas armer. Personne ne dit comment vider la file. Ce geste a l'air trivial jusqu'au moment où il ne l'est pas.
9
+ pas fusionner dans son mandat. Personne ne dit comment vider la file. Ce geste a l'air trivial jusqu'au moment où il ne l'est pas.
10
10
 
11
11
  **Attribution**: see `.source`.
12
12
 
@@ -36,19 +36,26 @@ Sortent de la file, sans discussion :
36
36
 
37
37
  Une file vide est un résultat, pas un échec : le dire et s'arrêter.
38
38
 
39
- ## Étape 2 — Ordonner par déblocage, jamais par date
40
-
41
- L'ordre correct n'a aucun rapport avec le numéro ni l'ancienneté.
42
-
43
- 1. **Une PR dont le contenu supprime la cause du conflit d'une autre passe avant elle.** Le cas
44
- qui a motivé cette skill : la PR réparant le workflow de back-merge était en conflit
45
- précisément parce que ce back-merge n'avait jamais tourné. Sans le back-merge d'abord, elle
46
- restait bloquée pour toujours.
47
- 2. À défaut de relation, **le moindre conflit d'abord** : ce qui se merge sans rien toucher, puis
48
- ce qui demande une régénération.
49
-
50
- Chercher la relation explicitement : une PR en conflit avec la base, dont une autre PR ouverte (ou
51
- un geste manquant) explique le conflit, attend cette autre.
39
+ ## Étape 2 — Garder un ordre stable, identifier les dépendances
40
+
41
+ Une seule fusion à la fois suffit, sans service de file ni abonnement particulier.
42
+ Une file native déjà configurée reste compatible ; ses protections restent applicables.
43
+
44
+ 1. **Conserver le tour engagé.** Dans `void-autopilot`, le noyau choisit : une PR dont la
45
+ fusion est déjà armée garde son tour ; sinon, la plus ancienne PR ouverte non brouillon
46
+ parmi les tickets suivis passe d'abord. Utiliser ses actions, pas un script de fusion parallèle.
47
+ 2. **Hors autopilot, garder l'ordre des PR admissibles.** À défaut d'ordre explicite, partir
48
+ de la plus ancienne. Une PR dont la revue est acquise et dont seule la CI attendue tourne
49
+ conserve son tour ; une PR plus récente ne la dépasse pas simplement parce qu'elle est verte.
50
+ 3. **Un déblocage réel se traite explicitement.** Nommer la dépendance, le conflit ou le
51
+ blocage durable et son propriétaire. Hors autopilot, une PR préalable peut passer d'abord
52
+ avec cette raison. Sous autopilot, rendre ce blocage au coordinateur : ne pas contourner
53
+ le tour choisi par le noyau. Une PR rouge ou en conflit ne justifie pas une attente indéfinie.
54
+
55
+ Remettre à jour seulement la PR dont le tour arrive, puis attendre ses preuves avant de
56
+ fusionner. Ne pas remettre toutes les branches à jour après chaque fusion : la suivante
57
+ ferait immédiatement vieillir ce travail. Le temps déjà dépensé ne rend jamais valide
58
+ une preuve liée à un ancien commit ou à une ancienne base.
52
59
 
53
60
  ## Étape 3 — Trois conditions pour merger, toutes nécessaires
54
61
 
@@ -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
- Reuse the unit's open canonical mission; if it has none, create it with
135
- `void-machine mission start --title <unit> --json` and retain its returned ID.
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>` checks the target ticket against the existing bounded ticket reader (filename identity
193
- and frozen content hash), then prepares the exact review subject/worktree and, when
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. Resolve them relative to the SKILL.md you actually loaded,
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. For pnpm/Bun use their pinned setup and frozen install.
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. `CI_DEFERRED_DRAFT` is expected non-admission during preparation,
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. Never treat a skipped required job as successful test evidence.
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
@@ -35,17 +40,80 @@ concurrency keys: `cancel-in-progress: false` alone still replaces pending runs
35
40
  shared group. Keep integration checks before entry to the protected branch; checking
36
41
  only after merge permits broken integration.
37
42
 
38
- GitHub couples required PR and merge queue checks. Preserve both. Remove a redundant
39
- post-merge run only after checking that no release, promotion or artifact consumer
43
+ Where a repository already uses a merge queue, preserve both its required PR and
44
+ merge-group checks. A queue is optional; sequential merging needs no queue setup.
45
+ Remove a redundant post-merge run only after checking that no release, promotion or artifact consumer
40
46
  needs it, and that the protected integration path proves the merged result. The
41
47
  example has no push trigger; add one where it provides distinct release evidence.
42
48
 
49
+ For reusable enforcement, the caller must also declare `ready_for_review` and
50
+ `converted_to_draft`, keeping its existing check names. Preserve
51
+ `merge_group: checks_requested` where a queue is configured. Put concurrency only
52
+ in that caller; the called workflow inherits `github.workflow` and must not cancel the same group. Its admission guard runs
53
+ from the immutable harness checkout before Node setup and floor execution.
54
+ GitHub-hosted runner usage belongs to the caller, even when the reusable workflow
55
+ is public and the caller private. Compare latency and job-minutes before making
56
+ any billing claim.
57
+
58
+ Dependency audit is a separate project-owned job, without a `needs` edge that
59
+ prevents lint/tests/build from running during an advisory-service outage. Preserve
60
+ its actual package-manager/lockfile contract and severity policy: installing Bun
61
+ is not an audit solution for npm or pnpm consumers. `npm ci` advisory output alone
62
+ is not a complete audit gate. Bun consumers can adopt the packaged
63
+ `core-assets/templates/github/void-dependency-audit.yml` and `dependency-audit.mjs`,
64
+ plus this sibling `ci-admission.mjs`; the audit guide is `docs/DEPENDENCY-AUDIT.md`
65
+ in a matching source checkout. Its ready-PR and merge-group runs judge their own
66
+ revision; a weekly scheduled run catches new advisories without a lockfile change
67
+ and is surveillance, not a substitute for a required candidate check. Unavailable
68
+ or malformed evidence stays non-green. No workflow path filter may hide required
69
+ checks or prevent scheduled registry refresh.
70
+
43
71
  Rollback: restore the prior workflow triggers and admission step together. Restoring
44
72
  full draft CI costs runner time but does not weaken the floor. Leave protection and
45
73
  review evidence unchanged. Existing missions and receipts are not migrated.
46
74
 
75
+ ## Measure feedback before changing CI
76
+
77
+ On a CI optimization request, use existing run history to agree a project-specific
78
+ feedback target, separately for ordinary changes and documentation changes. Around ten
79
+ minutes for a complete PR and a few minutes for documentation can start the discussion;
80
+ they are advisory targets, not timeouts, required checks or permission to omit tests.
81
+ Report the sample size, median and p95 when the sample supports it. A missed target
82
+ calls for diagnosis of the critical path, not a retry or another reporting service.
83
+
84
+ Record separately: time waiting for execution, elapsed time until all required results
85
+ are available, and summed job execution minutes across parallel jobs and all attempts.
86
+ Include cancelled work and runs invalidated by branch updates. A later PR overtaking an
87
+ older one only wastes CI when that change actually invalidates work; do not assume a
88
+ saving from ordering alone. Use provider billing data for money: job-minutes are not
89
+ billed minutes. Missing runner-wait timestamps mean unknown, not zero; dependency waits
90
+ are not automatically runner waits. A run update timestamp is not its completion time.
91
+
92
+ For GitHub, inspect a concrete run and repeat for earlier attempts when present:
93
+
94
+ ```sh
95
+ gh run view RUN_ID --repo OWNER/REPO --attempt ATTEMPT --json attempt,event,headSha,createdAt,startedAt,jobs
96
+ ```
97
+
98
+ Job start/completion times describe execution intervals; inspect the workflow dependencies
99
+ and every required workflow before deriving the feedback delay. Another CI provider's
100
+ native run/job view supplies the same evidence; this is no GitHub prerequisite.
101
+
102
+ Investigate a full build/test cache miss on a documentation-only diff by tracing actual
103
+ inputs and cache keys. Markdown may feed generated assets, executable skills or contract
104
+ tests; the extension alone proves nothing. Optimize unaffected work only when dependencies
105
+ are proven; otherwise keep the complete suite above. Preserve exact-candidate checks,
106
+ release artifacts and integration evidence. Reuse local evidence with unchanged inputs
107
+ instead of asking every agent to repeat the same full suite. Adopt workflow changes in
108
+ the consumer's existing configuration; updating these references does not rewrite it.
109
+
47
110
  Sources read for GitHub Actions (hosted service):
48
111
  - https://docs.github.com/en/actions/reference/workflows-and-actions/events-that-trigger-workflows#pull_request
49
112
  - https://docs.github.com/en/actions/how-tos/write-workflows/choose-when-workflows-run/control-workflow-concurrency
50
113
  - https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/configuring-pull-request-merges/managing-a-merge-queue
51
114
  - https://docs.github.com/en/actions/how-tos/write-workflows/choose-when-workflows-run/control-jobs-with-conditions
115
+
116
+ - https://docs.github.com/en/actions/reference/workflows-and-actions/reusing-workflow-configurations
117
+
118
+ - https://cli.github.com/manual/gh_run_view
119
+ - https://docs.github.com/en/rest/actions/workflow-jobs
@@ -1,4 +1,4 @@
1
- # Manual consumer template: copy this workflow and its companion script.
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