verifika 0.0.2 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/runner.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { constants } from "node:os";
2
2
  import path from "node:path";
3
3
  import { formatSeconds } from "./format.js";
4
+ import { LastLine } from "./preview.js";
4
5
  import { execCheck } from "./process.js";
5
6
  import { createRun, logPath, pruneRuns, readLatest, releaseRun, writeRunResult } from "./runs.js";
6
7
  import { schedule } from "./scheduler.js";
@@ -47,6 +48,7 @@ export async function runVerification(options) {
47
48
  selection,
48
49
  selected: selected.map((check) => check.name),
49
50
  concurrency: options.concurrency,
51
+ dependsOn: Object.fromEntries(selected.map((check) => [check.name, check.dependsOn])),
50
52
  });
51
53
  const env = { ...(options.env ?? process.env), VERIFIKA: "1", VERIFIKA_RUN_ID: runId };
52
54
  let firstFailure = null;
@@ -54,6 +56,11 @@ export async function runVerification(options) {
54
56
  const check = byName.get(task.name);
55
57
  reporter.onCheckStart?.(check.name);
56
58
  const log = logPath(runId, check.name);
59
+ const onCheckOutput = reporter.onCheckOutput?.bind(reporter);
60
+ const followers = onCheckOutput && {
61
+ stdout: new LastLine((line) => onCheckOutput(check.name, line)),
62
+ stderr: new LastLine((line) => onCheckOutput(check.name, line)),
63
+ };
57
64
  const outcome = await execCheck({
58
65
  command: check.command,
59
66
  cwd: root,
@@ -62,6 +69,7 @@ export async function runVerification(options) {
62
69
  logFile: path.join(root, log),
63
70
  previewLines: options.previewLines,
64
71
  signal,
72
+ ...(followers ? { onOutput: (stream, text) => followers[stream].write(text) } : {}),
65
73
  });
66
74
  const checkResult = completedResult(results.get(check.name), check, outcome, log);
67
75
  results.set(check.name, checkResult);
@@ -172,7 +180,12 @@ function completedResult(base, check, outcome, log) {
172
180
  }
173
181
  function notRunResult(base, outcome, interrupted, firstFailure) {
174
182
  if (outcome.state === "blocked") {
175
- return { ...base, status: "blocked", reason: `dependency ${outcome.dependency} did not pass` };
183
+ return {
184
+ ...base,
185
+ status: "blocked",
186
+ reason: `dependency ${outcome.dependency} did not pass`,
187
+ blockedBy: outcome.dependency,
188
+ };
176
189
  }
177
190
  if (outcome.state !== "not_started")
178
191
  return null;
package/dist/runs.js CHANGED
@@ -155,6 +155,45 @@ function isProcessAlive(pid) {
155
155
  return error.code === "EPERM";
156
156
  }
157
157
  }
158
+ /**
159
+ * Estimates the time saved by skipping `names`: each check's duration in the most
160
+ * recent retained run where it ran to completion (passed or failed).
161
+ */
162
+ export async function estimateSkipped(root, names) {
163
+ const found = new Map();
164
+ let runs = [];
165
+ try {
166
+ runs = (await readdir(path.join(root, STATE_DIR, RUNS_DIR)))
167
+ .filter((name) => RUN_ID_PATTERN.test(name))
168
+ .sort()
169
+ .reverse();
170
+ }
171
+ catch {
172
+ // No runs yet: nothing is known.
173
+ }
174
+ const wanted = new Set(names);
175
+ for (const id of runs) {
176
+ if (found.size === wanted.size)
177
+ break;
178
+ let run;
179
+ try {
180
+ run = JSON.parse(await readFile(path.join(runDirectory(root, id), RESULT_FILE), "utf8"));
181
+ }
182
+ catch {
183
+ continue;
184
+ }
185
+ for (const check of run.checks ?? []) {
186
+ if (wanted.has(check.name) &&
187
+ !found.has(check.name) &&
188
+ (check.status === "passed" || check.status === "failed") &&
189
+ typeof check.durationMs === "number") {
190
+ found.set(check.name, check.durationMs);
191
+ }
192
+ }
193
+ }
194
+ const knownMs = [...found.values()].reduce((total, ms) => total + ms, 0);
195
+ return { knownMs, unknown: wanted.size - found.size };
196
+ }
158
197
  export async function readRun(root, runId) {
159
198
  const id = runId ?? (await readLatest(root));
160
199
  if (id === null) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "verifika",
3
- "version": "0.0.2",
3
+ "version": "0.0.3",
4
4
  "description": "Deterministic, agent-friendly repository verification: run the checks your changes need, concurrently, with minimal output.",
5
5
  "keywords": [
6
6
  "verify",
@@ -51,8 +51,8 @@
51
51
  "test": "vitest run",
52
52
  "test:pack": "node scripts/pack-smoke.mjs",
53
53
  "check:skill": "node scripts/check-skill.mjs",
54
- "verifika": "node src/cli.ts",
55
- "verify": "node src/cli.ts --all",
54
+ "verify": "node src/cli.ts",
55
+ "verify:ci": "node src/cli.ts --all",
56
56
  "prepack": "npm run build"
57
57
  },
58
58
  "dependencies": {
@@ -10,7 +10,7 @@ Verifika runs a repository's configured checks (lint, typecheck, tests, build, .
10
10
 
11
11
  ## Is it set up here?
12
12
 
13
- Look for `verifika.config.json` in the repository root (or the package directory in a monorepo). Its `checks` object lists every check name and command. Run the CLI the way the repository does: `npx vfk` when it is a devDependency, `vfk` when installed globally, or a documented wrapper script such as `npm run verify`. `vfk` is short for `verifika`; both commands are identical. The examples below write `vfk`.
13
+ Look for `verifika.config.json` in the repository root (or the package directory in a monorepo). Its `checks` object lists every check name and command. Run the CLI the way the repository does: `npx vfk` when it is a devDependency, `vfk` when installed globally, or the repository's scripts. Projects set up with the init command have `npm run verify` (runs `vfk`: selective) and `npm run verify:ci` (runs `vfk --all`: the full gate). `npm run verify` is not the full gate. `vfk` is short for `verifika`; both commands are identical. The examples below write `vfk`.
14
14
 
15
15
  ## Workflow
16
16
 
@@ -34,7 +34,7 @@ Look for `verifika.config.json` in the repository root (or the package directory
34
34
  vfk --check typecheck
35
35
  ```
36
36
 
37
- 4. **Before claiming the task is complete, committing, or opening a pull request**, always run the full suite:
37
+ 4. **Before claiming the task is complete, committing, or opening a pull request**, always run the full suite (`npm run verify:ci` where that script exists):
38
38
 
39
39
  ```sh
40
40
  vfk --all
@@ -59,7 +59,22 @@ On failure, one line per problem, a short preview, and the command for full logs
59
59
  FAIL 3/4 (3.2s) full run (--all)
60
60
  typecheck: exit 2
61
61
  src/cart.ts(14,7): error TS2322: Type 'string' is not assignable to type 'number'.
62
- Run: verifika logs typecheck
62
+ Run: vfk logs typecheck
63
+ ```
64
+
65
+ Previews are shown for at most three failed checks. Any further failed check says where its output is instead:
66
+
67
+ ```text
68
+ FAIL 1/5 (9.8s) full run (--all)
69
+ format: exit 1
70
+ [warn] src/cart.ts
71
+ lint: exit 1
72
+ /repo/src/cart.ts
73
+ 12:9 error 'total' is assigned a value but never used no-unused-vars
74
+ typecheck: exit 2
75
+ src/cart.ts(14,7): error TS2322: Type 'string' is not assignable to type 'number'.
76
+ test: exit 1 (preview omitted: vfk logs test)
77
+ Run: vfk logs --failed
63
78
  ```
64
79
 
65
80
  | Exit code | Meaning |
@@ -83,7 +98,7 @@ Check statuses: `passed`, `failed`, `timed_out`, `error` (could not start, or le
83
98
  ## Rules
84
99
 
85
100
  - Do not claim success unless you saw `PASS` and exit code 0 from a finished run. Say what ran: "selective verification passed (2 checks)" is not "all checks pass".
86
- - A selective `PASS` only covers the checks it selected. Skipped checks were not verified. Run `vfk --all` before delivery, every time.
101
+ - A selective `PASS` only covers the checks it selected. Skipped checks were not verified. Run `vfk --all` (or `npm run verify:ci`) before delivery, every time; `npm run verify` is selective and does not count.
87
102
  - `PASS 0/0` means nothing matched your changes and nothing was verified.
88
103
  - Do not read logs of passing checks or use `vfk logs` after a `PASS`; there is nothing to diagnose.
89
104
  - Do not edit `verifika.config.json`, remove checks, narrow `paths`, raise timeouts, or pass `--check` to dodge a failing check, unless the user asked for that change.