rcf-lite 0.9.0 → 0.11.0

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.
Files changed (105) hide show
  1. package/CHANGELOG.md +95 -54
  2. package/README.md +8 -4
  3. package/bin/rcf.js +145 -57
  4. package/fixtures/canary-manifest.json +9 -9
  5. package/guidance/README.md +1 -1
  6. package/guidance/build-cycle-playbook.md +108 -51
  7. package/guidance/build-cycle.md +7 -7
  8. package/guidance/document-model.md +1 -1
  9. package/guidance/elicitation-playbook.md +29 -29
  10. package/guidance/harness-template.md +52 -10
  11. package/guidance/managed/README.md +1 -1
  12. package/guidance/managed/agent-instructions-block.hash +1 -1
  13. package/guidance/managed/agent-instructions-block.md +51 -9
  14. package/guidance/manifest.json +1 -1
  15. package/guidance/overview.md +4 -4
  16. package/package.json +4 -6
  17. package/rcf/adrs/adr-008.json +1 -1
  18. package/rcf/adrs/adr-009.json +4 -4
  19. package/rcf/code-nodes/cn-016.json +1 -1
  20. package/rcf/code-nodes/cn-019.json +1 -1
  21. package/rcf/code-nodes/cn-020.json +1 -1
  22. package/rcf/code-nodes/cn-021.json +1 -1
  23. package/rcf/code-nodes/cn-022.json +1 -1
  24. package/rcf/code-nodes/cn-049.json +1 -1
  25. package/rcf/code-nodes/cn-055.json +1 -1
  26. package/rcf/code-nodes/cn-057.json +5 -5
  27. package/rcf/code-nodes/cn-061.json +1 -1
  28. package/rcf/code-nodes/cn-066.json +1 -1
  29. package/rcf/code-nodes/cn-069.json +1 -1
  30. package/rcf/fbs/fbs-005.json +1 -1
  31. package/rcf/fbs/fbs-006.json +2 -2
  32. package/rcf/fbs/fbs-007.json +1 -1
  33. package/rcf/fbs/fbs-014.json +1 -1
  34. package/rcf/fbs/fbs-015.json +9 -8
  35. package/rcf/fbs/fbs-016.json +1 -1
  36. package/rcf/fbs/fbs-017.json +1 -1
  37. package/rcf/fbs/fbs-018.json +2 -2
  38. package/rcf/requirements/req-008.json +1 -1
  39. package/rcf/requirements/req-009.json +2 -2
  40. package/rcf/requirements/req-010.json +1 -1
  41. package/rcf/test-suites/PENDING.md +2 -2
  42. package/rcf/test-suites/ts-004.json +1 -1
  43. package/rcf/test-suites/ts-006.json +3 -3
  44. package/rcf/test-suites/ts-008.json +2 -2
  45. package/rcf/test-suites/ts-009.json +2 -2
  46. package/rcf/test-suites/ts-017.json +1 -1
  47. package/rcf/test-suites/ts-024.json +1 -1
  48. package/rcf/test-suites/ts-025.json +32 -18
  49. package/rcf/test-suites/ts-026.json +1 -1
  50. package/rcf/test-suites/ts-027.json +7 -7
  51. package/rcf/test-suites/ts-028.json +1 -1
  52. package/rcf/user-stories/us-1001.json +10 -10
  53. package/rcf/user-stories/us-1002.json +12 -12
  54. package/rcf/user-stories/us-1003.json +6 -6
  55. package/rcf/user-stories/us-805.json +2 -2
  56. package/rcf/user-stories/us-901.json +13 -13
  57. package/src/blueprint/conflicts.js +15 -15
  58. package/src/blueprint/supersede.js +6 -6
  59. package/src/build/bundle.js +3 -3
  60. package/src/build/formatters/markdown.js +9 -9
  61. package/src/build/mark.js +3 -3
  62. package/src/build/queue.js +1 -1
  63. package/src/cli/blueprint.js +3 -3
  64. package/src/cli/browser-verify.js +1 -1
  65. package/src/cli/build.js +139 -69
  66. package/src/cli/coverage.js +1 -1
  67. package/src/cli/create.js +3 -3
  68. package/src/cli/delete.js +2 -2
  69. package/src/cli/design.js +10 -10
  70. package/src/cli/fbs.js +1 -1
  71. package/src/cli/finalise.js +22 -20
  72. package/src/cli/help.js +267 -95
  73. package/src/cli/impact.js +1 -1
  74. package/src/cli/intake.js +3 -3
  75. package/src/cli/link.js +3 -3
  76. package/src/cli/preflight.js +2 -2
  77. package/src/cli/read.js +1 -1
  78. package/src/cli/req-baseline.js +2 -2
  79. package/src/cli/req-classify.js +3 -3
  80. package/src/cli/review.js +1 -1
  81. package/src/cli/standards.js +1 -1
  82. package/src/cli/test-suite.js +1 -1
  83. package/src/cli/trace.js +1 -1
  84. package/src/cli/ui-baseline.js +3 -3
  85. package/src/cli/ui-classify.js +4 -4
  86. package/src/cli/update.js +2 -2
  87. package/src/cli/validate.js +2 -2
  88. package/src/cli/view.js +12 -10
  89. package/src/core/store/writer.js +1 -1
  90. package/src/design/writer.js +3 -3
  91. package/src/finalise/detect.js +32 -38
  92. package/src/finalise/index.js +0 -1
  93. package/src/finalise/install.js +9 -8
  94. package/src/finalise/spawn.js +14 -10
  95. package/src/mcp/tools.js +1 -1
  96. package/src/req-baseline/gate.js +1 -1
  97. package/src/ui-baseline/manifest-writer.js +2 -2
  98. package/src/verify/cli/cleanup.js +1 -1
  99. package/src/verify/cli/mcp.js +1 -1
  100. package/src/verify/cli/provision.js +1 -1
  101. package/src/verify/cli/report.js +1 -1
  102. package/src/verify/cli/run.js +1 -1
  103. package/src/view-supervisor/manifest-writer.js +2 -2
  104. package/bin/rcf-verify.js +0 -122
  105. package/src/verify/cli/help.js +0 -56
@@ -18,7 +18,7 @@ const OPTION_SPEC = {
18
18
  'no-code': { type: 'boolean' },
19
19
  };
20
20
 
21
- export const HELP = `Usage: rcf validate [options]
21
+ export const HELP = `Usage: rcf define validate [options]
22
22
 
23
23
  Walk the rcf/ tree and report schema-validation and broken-reference
24
24
  issues. Exits 0 when clean, 3 on issues.
@@ -140,7 +140,7 @@ export async function main(argv, deps = {}) {
140
140
  }
141
141
  if (errors.length === 0) {
142
142
  if (!flags.quiet) {
143
- stdout.write('rcf validate: tree is clean.\n');
143
+ stdout.write('rcf define validate: tree is clean.\n');
144
144
  // B4 (E2E matrix 2026-07-06-003): scaffold TODO placeholders were
145
145
  // surviving to otherwise-valid trees unflagged. Non-blocking notice
146
146
  // only - the exit code is unchanged.
package/src/cli/view.js CHANGED
@@ -24,7 +24,7 @@ import { parsePersistUntil } from '../view-supervisor/persist-until.js';
24
24
  export const DEFAULT_PORT = 4373;
25
25
  export const SHUTDOWN_BUDGET_MS = 2000;
26
26
 
27
- export const HELP = `Usage: rcf view [subverb] [options]
27
+ export const HELP = `Usage: rcf audit view [subverb] [options]
28
28
 
29
29
  Serve the on-disk RCF tree as a live HTML review surface. Runs a
30
30
  long-running HTTP + SSE server on 127.0.0.1 that watches rcf/ and pushes
@@ -32,10 +32,10 @@ tree updates to the connected browser tab. No on-disk output; no static
32
32
  files are written.
33
33
 
34
34
  Subverbs (spec §9.2):
35
- rcf view Foreground server (default; lifetime tied to
35
+ rcf audit view Foreground server (default; lifetime tied to
36
36
  the invoking session). Backward-compatible
37
37
  with pre-0.7.0 callers.
38
- rcf view start [--detach|--foreground] [--persist-until <duration|iso>]
38
+ rcf audit view start [--detach|--foreground] [--persist-until <duration|iso>]
39
39
  Start the server. --detach forks a supervised
40
40
  background process that persists across the
41
41
  parent session's death; the manifest carries
@@ -50,12 +50,14 @@ Subverbs (spec §9.2):
50
50
  --detach; non-interactive callers keep
51
51
  --foreground so a script does not orphan a
52
52
  process.
53
- rcf view status [--json] Print the supervisor state:
53
+ rcf audit view status [--json]
54
+ Print the supervisor state:
54
55
  running | stale | not-started.
55
- rcf view stop Send SIGTERM to the supervised process, wait
56
+ rcf audit view stop Send SIGTERM to the supervised process, wait
56
57
  for a clean shutdown, and clear the manifest
57
58
  record.
58
- rcf view logs [--tail <n>] Print the supervisor log tail (default 200).
59
+ rcf audit view logs [--tail <n>]
60
+ Print the supervisor log tail (default 200).
59
61
 
60
62
  Options:
61
63
  --port <n> Bind the HTTP server on the given port.
@@ -83,7 +85,7 @@ Security posture:
83
85
  Shutdown:
84
86
  Ctrl-C (SIGINT) or SIGTERM triggers a clean shutdown: watcher
85
87
  closed, SSE connections drained with a shutdown event, port
86
- released, 2s force-exit budget. Detached: rcf view stop sends
88
+ released, 2s force-exit budget. Detached: rcf audit view stop sends
87
89
  SIGTERM to the supervisor and waits for a clean unwind.
88
90
 
89
91
  Exit codes:
@@ -213,7 +215,7 @@ export function maybeAutoOpen({ target, noOpen, stream, env, stderr, spawnFn = s
213
215
  }
214
216
 
215
217
  /**
216
- * Main entry for the `rcf view` subcommand. Mirrors the shape of the
218
+ * Main entry for the `rcf audit view` subcommand. Mirrors the shape of the
217
219
  * old bin/rcf-view.js main().
218
220
  *
219
221
  * @param {string[]} argv - the argv slice *after* the "view" positional
@@ -278,7 +280,7 @@ export async function main(argv, deps = {}) {
278
280
  });
279
281
  } catch (err) {
280
282
  if (/** @type {NodeJS.ErrnoException} */ (err).code === 'EADDRINUSE') {
281
- stderr.write(`[error] usage port ${resolvedPort} is in use (another rcf view process, or a different service).\n`);
283
+ stderr.write(`[error] usage port ${resolvedPort} is in use (another rcf audit view process, or a different service).\n`);
282
284
  stderr.write('Pass --port <n> or set RCF_VIEW_PORT to pick a free port.\n');
283
285
  return 2;
284
286
  }
@@ -286,7 +288,7 @@ export async function main(argv, deps = {}) {
286
288
  return 1;
287
289
  }
288
290
 
289
- stdout.write(`rcf view server listening at ${server.url}\n`);
291
+ stdout.write(`rcf audit view server listening at ${server.url}\n`);
290
292
  stdout.write('watching rcf/ - Ctrl-C to shut down\n');
291
293
 
292
294
  maybeAutoOpen({
@@ -1286,7 +1286,7 @@ export async function deleteDocument({ projectRoot, tree, id, options = {}, walk
1286
1286
  if (rootKinds.has(kind)) {
1287
1287
  return rcfError({
1288
1288
  kind: 'usage',
1289
- message: `delete: root singleton ${id} cannot be deleted via rcf delete`,
1289
+ message: `delete: root singleton ${id} cannot be deleted via rcf define delete`,
1290
1290
  documentId: id,
1291
1291
  });
1292
1292
  }
@@ -180,7 +180,7 @@ export async function writeMarkComplete({
180
180
  return rcfError({
181
181
  kind: 'usage',
182
182
  message: `design --mark-complete: refused - ${fbsId} designStage is missing: ${missing.join(', ')}. `
183
- + 'Author the missing artefacts first via `rcf design ' + fbsId + ' journeys add ...`, `nav set ...`, or `theme-a11y set ...`.',
183
+ + 'Author the missing artefacts first via `rcf define design ' + fbsId + ' journeys add ...`, `nav set ...`, or `theme-a11y set ...`.',
184
184
  documentId: fbsId,
185
185
  });
186
186
  }
@@ -189,8 +189,8 @@ export async function writeMarkComplete({
189
189
  return rcfError({
190
190
  kind: 'usage',
191
191
  message: `design --mark-complete: refused - ${fbsId} designStage.${disagreement.designStagePath} = ${JSON.stringify(disagreement.designValue)} conflicts with uiBaseline.defaults.${disagreement.path} = ${JSON.stringify(disagreement.baselineValue)} and there is no operatorOptOuts entry. `
192
- + 'Options: (1) change designStage to match, (2) rcf ui-baseline opt-out --field '
193
- + disagreement.path + ' --reason "..." (project override), (3) rcf update '
192
+ + 'Options: (1) change designStage to match, (2) rcf discover ui-baseline opt-out --field '
193
+ + disagreement.path + ' --reason "..." (project override), (3) rcf define update '
194
194
  + fbsId + ' --set designStage.' + disagreement.designStagePath + '=... (per-FBS override).',
195
195
  documentId: fbsId,
196
196
  });
@@ -1,36 +1,35 @@
1
- // rcf-verify install detection (spec §8.3, amendment 5 - install-together
2
- // posture). The finalise gate MUST detect whether `rcf-verify` is resolvable
3
- // and, when it is absent, prompt to install it - NEVER silently skip the ship
4
- // gate (the one behaviour §8.3 explicitly forbids).
1
+ // rcf verify install detection (spec §8.3, amendment 5 - install-together
2
+ // posture). The finalise gate MUST detect whether the `rcf` bin (which
3
+ // carries the `verify` group) is resolvable and, when it is absent,
4
+ // prompt to install rcf-lite - NEVER silently skip the ship gate (the
5
+ // one behaviour §8.3 explicitly forbids).
5
6
  //
6
- // Two detection routes, in order, matching how the CLI is actually installed:
7
- // 1. The `rcf-verify` bin on PATH - the umbrella install exposes both `rcf`
8
- // and `rcf-verify` as global bins (`npm i -g rcf-lite`).
9
- // 2. Package resolution from the project dir - the local-project install
10
- // (`npm i rcf-lite` in a repo's node_modules). Two package specifiers
11
- // are tried in order: the current umbrella `rcf-lite`, then the legacy
12
- // `@stravica-ai/rcf-verify-lite` name (deprecated at 0.7.1 but still
13
- // resolvable in lockfiles that pinned it). Either resolves to the same
14
- // `bin/rcf-verify.js` entry point.
15
- // Either route yields a concrete invocation the finalise spawn (spawn.js)
16
- // uses verbatim. A miss returns { installed:false } and the caller enters
17
- // the prompt-or-explicit-flag path.
7
+ // The 0.10.0 CLI reorganisation folded the standalone `rcf-verify` bin
8
+ // into the umbrella `rcf` CLI as the `verify` group. Detection now
9
+ // resolves the `rcf` bin exclusively; there is no legacy fallback.
10
+ //
11
+ // Two detection routes, in order:
12
+ // 1. The `rcf` bin on PATH - the umbrella install exposes `rcf` as a
13
+ // global bin (`npm i -g rcf-lite`).
14
+ // 2. Package resolution from the project dir - the local-project
15
+ // install (`npm i rcf-lite` in a repo's node_modules) resolves the
16
+ // `rcf-lite` package and its `bin/rcf.js` entry point.
17
+ // Either route yields a concrete invocation the finalise spawn
18
+ // (spawn.js) uses verbatim. A miss returns { installed:false } and the
19
+ // caller enters the prompt-or-explicit-flag path.
18
20
 
19
21
  import { access, constants } from 'node:fs/promises';
20
22
  import { createRequire } from 'node:module';
21
23
  import { delimiter, dirname, join, resolve } from 'node:path';
22
24
 
23
- // VERIFY_PACKAGE is the current install target and the name shown to
24
- // operators in absent-verify messaging. VERIFY_PACKAGE_LEGACY is only used
25
- // as a resolution fallback for lockfiles still pinning the pre-0.7.1 scoped
26
- // name; it is never displayed as an install target.
25
+ // VERIFY_PACKAGE is the install target and the name shown to operators
26
+ // in absent-verify messaging.
27
27
  const VERIFY_PACKAGE = 'rcf-lite';
28
- const VERIFY_PACKAGE_LEGACY = '@stravica-ai/rcf-verify-lite';
29
- const VERIFY_PACKAGE_CANDIDATES = [VERIFY_PACKAGE, VERIFY_PACKAGE_LEGACY];
30
- const VERIFY_BIN = 'rcf-verify';
28
+ const VERIFY_PACKAGE_CANDIDATES = [VERIFY_PACKAGE];
29
+ const VERIFY_BIN = 'rcf';
31
30
 
32
31
  /**
33
- * The concrete way to launch rcf-verify as a fresh subprocess.
32
+ * The concrete way to launch the `rcf` bin as a fresh subprocess.
34
33
  * - `{ command: '<abs-bin>', prefixArgs: [] }` for a PATH / shim bin
35
34
  * (its own shebang runs it).
36
35
  * - `{ command: process.execPath, prefixArgs: ['<abs-entry.js>'] }` for a
@@ -43,8 +42,8 @@ const VERIFY_BIN = 'rcf-verify';
43
42
  */
44
43
 
45
44
  /**
46
- * Scan PATH for an executable named `rcf-verify` (plus the Windows
47
- * `.cmd`/`.exe` shim variants). Returns the first absolute path that exists
45
+ * Scan PATH for an executable named `rcf` (plus the Windows `.cmd` /
46
+ * `.exe` shim variants). Returns the first absolute path that exists
48
47
  * and is executable, or null.
49
48
  *
50
49
  * @param {string} name
@@ -78,16 +77,11 @@ export async function findOnPath(name, { env = process.env } = {}) {
78
77
  }
79
78
 
80
79
  /**
81
- * Resolve the rcf-verify bin entry point from a starting directory, following
82
- * the normal node_modules resolution the caller's project sees. Returns the
83
- * absolute path to `bin/rcf-verify.js`, or null if no candidate package is
80
+ * Resolve the `rcf` bin entry point from a starting directory, following
81
+ * the normal node_modules resolution the caller's project sees. Returns
82
+ * the absolute path to `bin/rcf.js`, or null if the package is not
84
83
  * installed / resolvable from there.
85
84
  *
86
- * Candidates are tried in the order defined by VERIFY_PACKAGE_CANDIDATES: the
87
- * current umbrella (`rcf-lite`) first, then the deprecated scoped name
88
- * (`@stravica-ai/rcf-verify-lite`) as a fallback for lockfiles pinned to it.
89
- * The first candidate whose bin resolves and exists on disk wins.
90
- *
91
85
  * @param {string} fromDir - directory to resolve from (the project root / cwd)
92
86
  * @returns {Promise<string|null>}
93
87
  */
@@ -119,9 +113,9 @@ export async function resolvePackageBin(fromDir) {
119
113
  }
120
114
 
121
115
  /**
122
- * Detect whether rcf-verify is resolvable and, if so, how to launch it.
123
- * Deps are injectable so the finalise gate can be exercised without a real
124
- * rcf-verify on the test machine.
116
+ * Detect whether the `rcf` bin (carrying the `verify` group) is
117
+ * resolvable and, if so, how to launch it. Deps are injectable so the
118
+ * finalise gate can be exercised without a real installed rcf-lite.
125
119
  *
126
120
  * @param {object} [deps]
127
121
  * @param {string} [deps.cwd] - project dir to resolve a local install from
@@ -148,4 +142,4 @@ export async function detectVerify(deps = {}) {
148
142
  return { installed: false, invocation: null };
149
143
  }
150
144
 
151
- export { VERIFY_PACKAGE, VERIFY_PACKAGE_LEGACY, VERIFY_PACKAGE_CANDIDATES, VERIFY_BIN };
145
+ export { VERIFY_PACKAGE, VERIFY_PACKAGE_CANDIDATES, VERIFY_BIN };
@@ -11,7 +11,6 @@ export {
11
11
  findOnPath,
12
12
  resolvePackageBin,
13
13
  VERIFY_PACKAGE,
14
- VERIFY_PACKAGE_LEGACY,
15
14
  VERIFY_PACKAGE_CANDIDATES,
16
15
  VERIFY_BIN,
17
16
  } from './detect.js';
@@ -1,5 +1,6 @@
1
- // Absent-verify handling (spec §8.3, amendment 5). When `rcf-verify` is not
2
- // resolvable, the finalise gate MUST NOT silently skip - that recreates the
1
+ // Absent-verify handling (spec §8.3, amendment 5). When the `rcf` bin
2
+ // (which now carries the `verify` group post-0.10.0) is not resolvable,
3
+ // the finalise gate MUST NOT silently skip - that recreates the
3
4
  // false-confidence failure the whole programme exists to prevent. The
4
5
  // sanctioned paths are exactly two, and nothing else:
5
6
  // - interactive TTY -> prompt the operator to install now (y/N);
@@ -35,8 +36,8 @@ export function promptYesNo(question, { input = process.stdin, output = process.
35
36
  }
36
37
 
37
38
  /**
38
- * Install rcf-verify globally (matches the install-together default of two
39
- * global bins). Streams npm's output to the operator. Returns the install
39
+ * Install rcf-lite globally so the `rcf verify` group becomes
40
+ * resolvable. Streams npm's output to the operator. Returns the install
40
41
  * process exit code.
41
42
  *
42
43
  * @param {object} [deps]
@@ -77,11 +78,11 @@ export async function resolveAbsentVerify({ installFlag, isTty }, io, deps = {})
77
78
  let wantsInstall = false;
78
79
  if (installFlag) {
79
80
  // Explicit flag: the sanctioned non-interactive install path.
80
- io.stdout.write(`[finalise] rcf-verify not found; installing ${VERIFY_PACKAGE} (--install-verify)...\n`);
81
+ io.stdout.write(`[finalise] the rcf CLI (with verify) not found; installing ${VERIFY_PACKAGE} (--install-verify)...\n`);
81
82
  wantsInstall = true;
82
83
  } else if (isTty) {
83
84
  // Interactive: prompt. Declining aborts (never a silent skip).
84
- io.stderr.write(`[finalise] rcf-verify is not installed. The ship gate cannot run without it.\n`);
85
+ io.stderr.write(`[finalise] rcf-lite is not installed. The ship gate cannot run without it.\n`);
85
86
  wantsInstall = await prompt(`Install ${VERIFY_PACKAGE} now? [y/N]`, {
86
87
  input: io.input, output: io.output,
87
88
  });
@@ -89,7 +90,7 @@ export async function resolveAbsentVerify({ installFlag, isTty }, io, deps = {})
89
90
  return {
90
91
  action: 'abort',
91
92
  code: 4,
92
- reason: `finalise refused: rcf-verify is required and install was declined. `
93
+ reason: `finalise refused: rcf-lite is required and install was declined. `
93
94
  + `Install it (npm i -g ${VERIFY_PACKAGE}) or re-run with --install-verify. `
94
95
  + `The ship gate is never skipped.`,
95
96
  };
@@ -100,7 +101,7 @@ export async function resolveAbsentVerify({ installFlag, isTty }, io, deps = {})
100
101
  return {
101
102
  action: 'abort',
102
103
  code: 4,
103
- reason: `finalise refused: rcf-verify is not installed and no TTY is available to prompt. `
104
+ reason: `finalise refused: rcf-lite is not installed and no TTY is available to prompt. `
104
105
  + `Install it (npm i -g ${VERIFY_PACKAGE}) or re-run with --install-verify. `
105
106
  + `The ship gate is never silently skipped.`,
106
107
  };
@@ -1,9 +1,10 @@
1
- // Fresh-subprocess invocation of `rcf-verify run` (spec §8.2). This is the
2
- // load-bearing independence guarantee: build-lite's finalise step launches
3
- // verify as a SEPARATE OS PROCESS with the isolation env - it MUST NOT import
4
- // verify's engine in-process, because the verifier agent must start from a
5
- // cold session with zero build context (§9). The subprocess exit code is the
6
- // gate; findings flow back via the --out report file, never stdout scraping.
1
+ // Fresh-subprocess invocation of `rcf verify run` (spec §8.2). This is
2
+ // the load-bearing independence guarantee: build-lite's finalise step
3
+ // launches verify as a SEPARATE OS PROCESS with the isolation env - it
4
+ // MUST NOT import verify's engine in-process, because the verifier
5
+ // agent must start from a cold session with zero build context (§9).
6
+ // The subprocess exit code is the gate; findings flow back via the
7
+ // --out report file, never stdout scraping.
7
8
  //
8
9
  // The isolation env (core's ISOLATION_RECIPE, §7.3) is layered onto the child
9
10
  // env here so the recipe travels with the process boundary exactly as §8.2
@@ -14,9 +15,11 @@ import { spawn } from 'node:child_process';
14
15
  import { isolationEnv } from '#core/isolation';
15
16
 
16
17
  /**
17
- * Assemble the `rcf-verify run` argument vector from finalise options.
18
- * Deterministic and pure so it is directly unit-testable; the exact shape is
19
- * the §8.2 invocation contract.
18
+ * Assemble the `rcf verify run` argument vector from finalise options.
19
+ * Deterministic and pure so it is directly unit-testable; the exact
20
+ * shape is the §8.2 invocation contract. The 0.10.0 CLI reorganisation
21
+ * prepends the `verify` group token; the run-verb arguments below are
22
+ * otherwise unchanged.
20
23
  *
21
24
  * @param {object} opts
22
25
  * @param {string} opts.repo - RCF chain source (the project root)
@@ -32,6 +35,7 @@ import { isolationEnv } from '#core/isolation';
32
35
  */
33
36
  export function buildVerifyArgs(opts) {
34
37
  const args = [
38
+ 'verify',
35
39
  'run',
36
40
  '--repo', opts.repo,
37
41
  '--profile', opts.profile,
@@ -47,7 +51,7 @@ export function buildVerifyArgs(opts) {
47
51
  }
48
52
 
49
53
  /**
50
- * Spawn rcf-verify as a fresh subprocess and resolve with its exit code.
54
+ * Spawn `rcf verify run` as a fresh subprocess and resolve with its exit code.
51
55
  * stdio is inherited by default so the operator sees verify's live progress
52
56
  * and its verdict line; the report artifact is read separately by the caller.
53
57
  *
package/src/mcp/tools.js CHANGED
@@ -69,7 +69,7 @@ const ISSUE_SCHEMA = {
69
69
  // success branch stays the verbatim envelope transcription (D8/D9).
70
70
  const ERROR_PAYLOAD_SCHEMA = {
71
71
  type: 'object',
72
- description: 'Tool execution error payload (accompanies isError: true): the same issue shape rcf validate --json ships',
72
+ description: 'Tool execution error payload (accompanies isError: true): the same issue shape rcf define validate --json ships',
73
73
  properties: {
74
74
  ok: { const: false },
75
75
  errors: { type: 'array', items: ISSUE_SCHEMA },
@@ -73,7 +73,7 @@ export function formatStage1RefusalMessage({ fbsId, usId, reqId, openCandidates
73
73
  const short = shortDescription(c.canonicalText);
74
74
  lines.push(` ${c.baselineKey}: ${short}`);
75
75
  }
76
- lines.push(` Resolve: rcf req-baseline sweep --req ${reqId}`);
76
+ lines.push(` Resolve: rcf discover req-baseline sweep --req ${reqId}`);
77
77
  return lines.join('\n');
78
78
  }
79
79
 
@@ -210,14 +210,14 @@ export async function writeUiBaselineOptOut({
210
210
  if (!priorBaseline) {
211
211
  return rcfError({
212
212
  kind: 'usage',
213
- message: 'ui-baseline opt-out: no uiBaseline record exists yet; run \'rcf ui-baseline init\' first.',
213
+ message: 'ui-baseline opt-out: no uiBaseline record exists yet; run \'rcf discover ui-baseline init\' first.',
214
214
  });
215
215
  }
216
216
  const normalisedField = String(field).startsWith('defaults.') ? String(field).slice('defaults.'.length) : String(field);
217
217
  if (typeof isKnownField === 'function' && !isKnownField(normalisedField)) {
218
218
  return rcfError({
219
219
  kind: 'usage',
220
- message: `ui-baseline opt-out: unknown baseline field '${normalisedField}' (see 'rcf ui-baseline show' for the field list).`,
220
+ message: `ui-baseline opt-out: unknown baseline field '${normalisedField}' (see 'rcf discover ui-baseline show' for the field list).`,
221
221
  });
222
222
  }
223
223
  const isoNow = now.toISOString();
@@ -9,7 +9,7 @@ import { formatError, isRcfError } from '#core/errors';
9
9
 
10
10
  import { readProvisionFile, cleanup } from '../provision/index.js';
11
11
 
12
- export const HELP = `Usage: rcf-verify cleanup --provision <file> [--url <app-url>]
12
+ export const HELP = `Usage: rcf verify cleanup --provision <file> [--url <app-url>]
13
13
 
14
14
  Tear down artefacts recorded in the --provision file (all prefixed
15
15
  'zzverify-'). Reports what was removed and what could not be.
@@ -14,7 +14,7 @@ import { createToolRegistry } from '../mcp/tools.js';
14
14
 
15
15
  const here = dirname(fileURLToPath(import.meta.url));
16
16
 
17
- export const HELP = `Usage: rcf-verify mcp [options]
17
+ export const HELP = `Usage: rcf verify mcp [options]
18
18
 
19
19
  Serve verify over the Model Context Protocol (local stdio). Exposes one tool,
20
20
  rcf_verify_run, over the same in-process engine the CLI uses. stdout carries
@@ -11,7 +11,7 @@ import { formatError, isRcfError } from '#core/errors';
11
11
  import { readChain } from '../chain/index.js';
12
12
  import { runProvisioning } from '../provision/index.js';
13
13
 
14
- export const HELP = `Usage: rcf-verify provision --repo <path> --url <app-url> --provision <file>
14
+ export const HELP = `Usage: rcf verify provision --repo <path> --url <app-url> --provision <file>
15
15
 
16
16
  Stand up prerequisite accounts / sandboxes / seed data for a later run.
17
17
  Credentials are written to the --provision FILE only, never echoed.
@@ -11,7 +11,7 @@ import { formatError, isRcfError } from '#core/errors';
11
11
  import { parseReport } from '../report/index.js';
12
12
  import { renderReport } from '../report/renderer.js';
13
13
 
14
- export const HELP = `Usage: rcf-verify report <report-path> [--json]
14
+ export const HELP = `Usage: rcf verify report <report-path> [--json]
15
15
 
16
16
  Re-render a prior report artifact. Default output is the human-readable
17
17
  summary; --json re-emits the parsed artifact as JSON.
@@ -29,7 +29,7 @@ const OPTION_SPEC = {
29
29
  help: { type: 'boolean' },
30
30
  };
31
31
 
32
- export const HELP = `Usage: rcf-verify run [options]
32
+ export const HELP = `Usage: rcf verify run [options]
33
33
 
34
34
  Launch a fresh-context adversarial verifier against a running app and emit a
35
35
  structured verdict stamped with the runtime it ran against.
@@ -19,13 +19,13 @@ export const DEFAULT_PID_PATH = '.rcf/view-server.pid';
19
19
  */
20
20
  export const viewServerGitignoreEntry = Object.freeze({
21
21
  path: '.rcf/view-server.pid',
22
- owner: 'rcf view --detach (view-server pid file)',
22
+ owner: 'rcf audit view --detach (view-server pid file)',
23
23
  since: '0.7.0',
24
24
  });
25
25
 
26
26
  export const viewServerLogGitignoreEntry = Object.freeze({
27
27
  path: '.rcf/view-server.log',
28
- owner: 'rcf view --detach (supervisor log)',
28
+ owner: 'rcf audit view --detach (supervisor log)',
29
29
  since: '0.7.0',
30
30
  });
31
31
 
package/bin/rcf-verify.js DELETED
@@ -1,122 +0,0 @@
1
- #!/usr/bin/env node
2
- // The `rcf-verify` alias bin. Post 0.7.1 packaging consolidation the
3
- // unified `rcf` CLI grew a `verify` subcommand that dispatches to the
4
- // same handlers this file wires up; `rcf-verify` remains as a
5
- // transition-grace alias (see docs/2026-08-06_packaging-consolidation-
6
- // proposal.md R3). When run directly (as `rcf-verify <verb>` rather
7
- // than through the routing `rcf verify <verb>`), the entrypoint emits
8
- // a one-line stderr deprecation notice; behaviour is otherwise
9
- // unchanged.
10
- //
11
- // Argv layout: `rcf-verify <subcommand> [args...]`. The first positional
12
- // selects the subcommand handler; global --version / --help short-circuit
13
- // before dispatch. The `main` export is also imported by bin/rcf.js as
14
- // the `verify` subcommand handler, so the dispatcher lives in one place.
15
-
16
- import { realpathSync } from 'node:fs';
17
- import { readFile } from 'node:fs/promises';
18
- import { dirname, resolve } from 'node:path';
19
- import process from 'node:process';
20
- import { fileURLToPath, pathToFileURL } from 'node:url';
21
-
22
- import { main as runMain } from '../src/verify/cli/run.js';
23
- import { main as reportMain } from '../src/verify/cli/report.js';
24
- import { main as provisionMain } from '../src/verify/cli/provision.js';
25
- import { main as cleanupMain } from '../src/verify/cli/cleanup.js';
26
- import { main as mcpMain } from '../src/verify/cli/mcp.js';
27
- import { main as helpMain, TOP_LEVEL_HELP } from '../src/verify/cli/help.js';
28
-
29
- const here = dirname(fileURLToPath(import.meta.url));
30
-
31
- const SUBCOMMANDS = {
32
- run: runMain,
33
- report: reportMain,
34
- provision: provisionMain,
35
- cleanup: cleanupMain,
36
- mcp: mcpMain,
37
- help: helpMain,
38
- };
39
-
40
- /**
41
- * @param {string[]} argv - argv minus node + script
42
- * @param {object} [deps]
43
- * @returns {Promise<number>}
44
- */
45
- export async function main(argv, deps = {}) {
46
- const stdout = deps.stdout ?? process.stdout;
47
- const stderr = deps.stderr ?? process.stderr;
48
-
49
- if (argv.length === 0) {
50
- stdout.write(TOP_LEVEL_HELP);
51
- return 0;
52
- }
53
- const first = argv[0];
54
- if (first === '--version' || first === '-v') {
55
- stdout.write(`rcf-verify ${await readPackageVersion()}\n`);
56
- return 0;
57
- }
58
- if (first === '--help' || first === '-h') {
59
- stdout.write(TOP_LEVEL_HELP);
60
- return 0;
61
- }
62
- const handler = SUBCOMMANDS[first];
63
- if (!handler) {
64
- stderr.write(`[error] usage unknown subcommand: ${first}\n`);
65
- stderr.write(TOP_LEVEL_HELP);
66
- return 2;
67
- }
68
- return await handler(argv.slice(1), deps);
69
- }
70
-
71
- async function readPackageVersion() {
72
- try {
73
- const pkgPath = resolve(here, '..', 'package.json');
74
- const pkg = JSON.parse(await readFile(pkgPath, 'utf8'));
75
- return pkg.version ?? '0.0.0';
76
- } catch {
77
- return '0.0.0';
78
- }
79
- }
80
-
81
- /**
82
- * Symlink-safe entry-point compare (mirrors build's bin/rcf.js). macOS `/tmp`
83
- * is a symlink to `/private/tmp` and every `pnpm link` shim is a symlink;
84
- * without realpath the isMain gate breaks and main() never runs.
85
- *
86
- * @param {string} metaUrl
87
- * @param {string} argvPath
88
- * @returns {boolean}
89
- */
90
- export function isSameEntryPoint(metaUrl, argvPath) {
91
- try {
92
- const metaPath = fileURLToPath(metaUrl);
93
- return realpathSync(metaPath) === realpathSync(argvPath);
94
- } catch {
95
- try {
96
- return metaUrl === pathToFileURL(argvPath).href;
97
- } catch {
98
- return false;
99
- }
100
- }
101
- }
102
-
103
- const isMain = process.argv[1] && isSameEntryPoint(import.meta.url, process.argv[1]);
104
- if (isMain) {
105
- // Transition-grace deprecation notice per proposal R3. Only fires when
106
- // the alias bin is invoked directly (not when bin/rcf.js routes the
107
- // `verify` subcommand through the exported `main`, since the isMain
108
- // guard is false in that case). Suppressible via RCF_QUIET=1 for
109
- // scripted callers who cannot tolerate stderr chatter.
110
- if (!process.env.RCF_QUIET) {
111
- process.stderr.write(
112
- '[rcf-verify] deprecation: prefer `rcf verify` (the umbrella CLI subcommand). ' +
113
- 'The `rcf-verify` alias will be removed in a future major. Set RCF_QUIET=1 to silence.\n',
114
- );
115
- }
116
- main(process.argv.slice(2))
117
- .then((code) => process.exit(code))
118
- .catch((err) => {
119
- process.stderr.write(`[rcf-verify] unexpected failure: ${err.message}\n${err.stack}\n`);
120
- process.exit(1);
121
- });
122
- }
@@ -1,56 +0,0 @@
1
- // Top-level and per-subcommand help (mirrors build's cli/help.js). British
2
- // English, ASCII hyphens only.
3
-
4
- import { HELP as RUN_HELP } from './run.js';
5
- import { HELP as REPORT_HELP } from './report.js';
6
- import { HELP as PROVISION_HELP } from './provision.js';
7
- import { HELP as CLEANUP_HELP } from './cleanup.js';
8
- import { HELP as MCP_HELP } from './mcp.js';
9
-
10
- export const TOP_LEVEL_HELP = `Usage: rcf-verify <command> [options]
11
-
12
- A fresh-context adversarial verifier. Given an RCF chain (the acceptance
13
- contract) and a running app under a declared runtime profile, it launches an
14
- isolated verifier agent that walks real user journeys adversarially and emits a
15
- structured verdict stamped with the runtime it ran against.
16
-
17
- This is an independent ship-readiness signal, not a correctness guarantee.
18
-
19
- Commands:
20
- run Run adversarial verification and emit a report artifact
21
- report <path> Re-render a prior report artifact
22
- provision Stand up prerequisite accounts/sandboxes/data standalone
23
- cleanup Tear down provisioned artefacts (all prefixed 'zzverify-')
24
- mcp Serve verify over MCP (local stdio)
25
- help [command] Print help for a command
26
-
27
- Options:
28
- --version Print the package version and exit
29
- --help Print this help and exit
30
-
31
- Run 'rcf-verify help <command>' for command-specific help.
32
- `;
33
-
34
- const SUB_HELP = {
35
- run: RUN_HELP,
36
- report: REPORT_HELP,
37
- provision: PROVISION_HELP,
38
- cleanup: CLEANUP_HELP,
39
- mcp: MCP_HELP,
40
- };
41
-
42
- /**
43
- * @param {string[]} argv
44
- * @param {object} [deps]
45
- * @returns {Promise<number>}
46
- */
47
- export async function main(argv, deps = {}) {
48
- const stdout = deps.stdout ?? process.stdout;
49
- const topic = argv[0];
50
- if (topic && SUB_HELP[topic]) {
51
- stdout.write(SUB_HELP[topic]);
52
- return 0;
53
- }
54
- stdout.write(TOP_LEVEL_HELP);
55
- return 0;
56
- }