dorfl 0.7.0 → 0.8.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 (71) hide show
  1. package/dist/advance-drivers.d.ts.map +1 -1
  2. package/dist/advance-drivers.js +11 -2
  3. package/dist/advance-drivers.js.map +1 -1
  4. package/dist/bootstrap-forward.d.ts +224 -0
  5. package/dist/bootstrap-forward.d.ts.map +1 -0
  6. package/dist/bootstrap-forward.js +247 -0
  7. package/dist/bootstrap-forward.js.map +1 -0
  8. package/dist/cli.d.ts +9 -0
  9. package/dist/cli.d.ts.map +1 -1
  10. package/dist/cli.js +21 -1
  11. package/dist/cli.js.map +1 -1
  12. package/dist/config.d.ts +50 -0
  13. package/dist/config.d.ts.map +1 -1
  14. package/dist/config.js +42 -0
  15. package/dist/config.js.map +1 -1
  16. package/dist/cwd-section.d.ts.map +1 -1
  17. package/dist/cwd-section.js +11 -2
  18. package/dist/cwd-section.js.map +1 -1
  19. package/dist/env-config.d.ts.map +1 -1
  20. package/dist/env-config.js +8 -0
  21. package/dist/env-config.js.map +1 -1
  22. package/dist/github.d.ts +32 -1
  23. package/dist/github.d.ts.map +1 -1
  24. package/dist/github.js +115 -0
  25. package/dist/github.js.map +1 -1
  26. package/dist/index.d.ts +2 -0
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +1 -0
  29. package/dist/index.js.map +1 -1
  30. package/dist/install-ci-core.d.ts.map +1 -1
  31. package/dist/install-ci-core.js +20 -48
  32. package/dist/install-ci-core.js.map +1 -1
  33. package/dist/integration-core.d.ts.map +1 -1
  34. package/dist/integration-core.js +9 -0
  35. package/dist/integration-core.js.map +1 -1
  36. package/dist/integrator.d.ts +48 -0
  37. package/dist/integrator.d.ts.map +1 -1
  38. package/dist/integrator.js +12 -0
  39. package/dist/integrator.js.map +1 -1
  40. package/dist/item-lock.d.ts +26 -0
  41. package/dist/item-lock.d.ts.map +1 -1
  42. package/dist/item-lock.js +39 -0
  43. package/dist/item-lock.js.map +1 -1
  44. package/dist/repo-config.d.ts +1 -1
  45. package/dist/repo-config.d.ts.map +1 -1
  46. package/dist/repo-config.js +20 -1
  47. package/dist/repo-config.js.map +1 -1
  48. package/dist/scan.d.ts +24 -2
  49. package/dist/scan.d.ts.map +1 -1
  50. package/dist/scan.js +28 -4
  51. package/dist/scan.js.map +1 -1
  52. package/dist/skills/setup/SKILL.md +3 -0
  53. package/dist/tasking.d.ts.map +1 -1
  54. package/dist/tasking.js +124 -65
  55. package/dist/tasking.js.map +1 -1
  56. package/package.json +1 -1
  57. package/src/advance-drivers.ts +17 -8
  58. package/src/bootstrap-forward.ts +359 -0
  59. package/src/cli.ts +21 -1
  60. package/src/config.ts +75 -0
  61. package/src/cwd-section.ts +21 -2
  62. package/src/env-config.ts +8 -0
  63. package/src/github.ts +149 -0
  64. package/src/index.ts +24 -0
  65. package/src/install-ci-core.ts +20 -48
  66. package/src/integration-core.ts +10 -0
  67. package/src/integrator.ts +62 -0
  68. package/src/item-lock.ts +50 -0
  69. package/src/repo-config.ts +20 -0
  70. package/src/scan.ts +32 -8
  71. package/src/tasking.ts +154 -68
@@ -1 +1 @@
1
- {"version":3,"file":"advance-drivers.d.ts","sourceRoot":"","sources":["../src/advance-drivers.ts"],"names":[],"mappings":"AAAA,OAAO,EAEN,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,MAAM,cAAc,CAAC;AAOtB,OAAO,EAAa,KAAK,kBAAkB,EAAC,MAAM,kBAAkB,CAAC;AAQrE,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,sBAAsB,CAAC;AAC7D,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,aAAa,CAAC;AACxC,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,sBAAsB,CAAC;AAE5D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAEH,6EAA6E;AAC7E,MAAM,MAAM,iBAAiB,GAAG,CAC/B,OAAO,EAAE,kBAAkB,KACvB,OAAO,CAAC,aAAa,CAAC,CAAC;AAE5B,yEAAyE;AACzE,MAAM,WAAW,kBAAmB,SAAQ,cAAc;IACzD,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,kBAAkB,CAAC;CAC1B;AAED,sEAAsE;AACtE,KAAK,oBAAoB,GAAG,cAAc,CAAC;AAE3C,MAAM,WAAW,0BAA2B,SAAQ,oBAAoB;IACvE;;;;;;OAMG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,iBAAiB,CAAC;IAC7B;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iGAAiG;IACjG,GAAG,CAAC,EAAE,iBAAiB,CAAC;IACxB,qFAAqF;IACrF,IAAI,CAAC,EAAE,kBAAkB,CAAC;IAC1B;;;;;;;;;;OAUG;IACH,cAAc,CAAC,EAAE,kBAAkB,CAAC;CACpC;AAED,iEAAiE;AACjE,MAAM,WAAW,kBAAkB;IAClC,kEAAkE;IAClE,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB;;;;;OAKG;IACH,QAAQ,EAAE,eAAe,CAAC;IAC1B,mDAAmD;IACnD,OAAO,EAAE,MAAM,CAAC;CAChB;AAUD;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,kBAAkB,CACvC,OAAO,EAAE,0BAA0B,GACjC,OAAO,CAAC,kBAAkB,CAAC,CAmF7B;AAED;;;;;;;GAOG;AACH,wBAAsB,kBAAkB,CACvC,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,EAAE,0BAA0B,GACjC,OAAO,CAAC,kBAAkB,CAAC,CAU7B;AAqCD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAsB,iCAAiC,CACtD,OAAO,EAAE,kBAAkB,EAC3B,GAAG,EAAE,iBAAiB,GACpB,OAAO,CAAC,aAAa,CAAC,CAqBxB;AA+CD;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAIhE;AAED,YAAY,EAAC,cAAc,EAAC,CAAC"}
1
+ {"version":3,"file":"advance-drivers.d.ts","sourceRoot":"","sources":["../src/advance-drivers.ts"],"names":[],"mappings":"AAAA,OAAO,EAEN,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,MAAM,cAAc,CAAC;AAOtB,OAAO,EAAa,KAAK,kBAAkB,EAAC,MAAM,kBAAkB,CAAC;AAQrE,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,sBAAsB,CAAC;AAC7D,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,aAAa,CAAC;AACxC,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,sBAAsB,CAAC;AAE5D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAEH,6EAA6E;AAC7E,MAAM,MAAM,iBAAiB,GAAG,CAC/B,OAAO,EAAE,kBAAkB,KACvB,OAAO,CAAC,aAAa,CAAC,CAAC;AAE5B,yEAAyE;AACzE,MAAM,WAAW,kBAAmB,SAAQ,cAAc;IACzD,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,kBAAkB,CAAC;CAC1B;AAED,sEAAsE;AACtE,KAAK,oBAAoB,GAAG,cAAc,CAAC;AAE3C,MAAM,WAAW,0BAA2B,SAAQ,oBAAoB;IACvE;;;;;;OAMG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,iBAAiB,CAAC;IAC7B;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iGAAiG;IACjG,GAAG,CAAC,EAAE,iBAAiB,CAAC;IACxB,qFAAqF;IACrF,IAAI,CAAC,EAAE,kBAAkB,CAAC;IAC1B;;;;;;;;;;OAUG;IACH,cAAc,CAAC,EAAE,kBAAkB,CAAC;CACpC;AAED,iEAAiE;AACjE,MAAM,WAAW,kBAAkB;IAClC,kEAAkE;IAClE,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB;;;;;OAKG;IACH,QAAQ,EAAE,eAAe,CAAC;IAC1B,mDAAmD;IACnD,OAAO,EAAE,MAAM,CAAC;CAChB;AAUD;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,kBAAkB,CACvC,OAAO,EAAE,0BAA0B,GACjC,OAAO,CAAC,kBAAkB,CAAC,CA4F7B;AAED;;;;;;;GAOG;AACH,wBAAsB,kBAAkB,CACvC,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,EAAE,0BAA0B,GACjC,OAAO,CAAC,kBAAkB,CAAC,CAU7B;AAqCD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAsB,iCAAiC,CACtD,OAAO,EAAE,kBAAkB,EAC3B,GAAG,EAAE,iBAAiB,GACpB,OAAO,CAAC,aAAa,CAAC,CAqBxB;AA+CD;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAIhE;AAED,YAAY,EAAC,cAAc,EAAC,CAAC"}
@@ -1,7 +1,7 @@
1
1
  import { performAdvance, } from './advance.js';
2
2
  import { pushTreelessResult, TREELESS_RUNGS, } from './advance-treeless-publish.js';
3
3
  import { scanRepoPaths } from './scan.js';
4
- import { heldTaskSlugs } from './item-lock.js';
4
+ import { heldTaskSlugs, heldSpecSlugs } from './item-lock.js';
5
5
  import { ledgerRead } from './ledger-read.js';
6
6
  import { selectPrioritised, taskableSpecs, } from './select-priority.js';
7
7
  import { gatherLifecycleInPlace } from './lifecycle-gather.js';
@@ -41,6 +41,13 @@ export async function performAdvanceAuto(options) {
41
41
  // runs. `heldTaskSlugs` is the GRACEFUL variant (empty set on any read fault):
42
42
  // the follow-on claim CAS is still the load-bearing safety net locally.
43
43
  const heldSlugs = await heldTaskSlugs(cwd, options.arbiter);
44
+ // The held-SPEC set (fix
45
+ // `propose-tasking-releases-lock-so-spec-is-retasked-and-pr-force-pushed-every-tick`):
46
+ // a spec whose `spec-<slug>` lock is held has an in-flight tasking PR (propose keeps
47
+ // the lock across the open PR), so it must NOT be re-selected into the task rung.
48
+ // GRACEFUL variant (empty on read fault) — the tasking-lock CAS is the local safety
49
+ // net, matching `heldTaskSlugs` above.
50
+ const heldSpecs = await heldSpecSlugs(cwd, options.arbiter);
44
51
  // Pool 1 — eligible TASKS via the EXISTING scan/select path. `scoreItems`
45
52
  // inside `scanRepoPaths` gates eligibility on `autoBuild` (the build gate), so
46
53
  // with `autoBuild` off NO task is selected — the build rung is never reached
@@ -50,7 +57,9 @@ export async function performAdvanceAuto(options) {
50
57
  // `autoTask`). With `autoTask` off NO spec is selected — the task rung is
51
58
  // never reached by the bare/`-n` selection.
52
59
  const pool = read.resolveSpecPool({ repoPath: cwd });
53
- const specCandidates = pool.specs.map((spec) => ({
60
+ const specCandidates = pool.specs
61
+ .filter((spec) => !heldSpecs.has(spec.slug))
62
+ .map((spec) => ({
54
63
  repoPath: cwd,
55
64
  slug: spec.slug,
56
65
  humanOnly: spec.humanOnly,
@@ -1 +1 @@
1
- {"version":3,"file":"advance-drivers.js","sourceRoot":"","sources":["../src/advance-drivers.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"advance-drivers.js","sourceRoot":"","sources":["../src/advance-drivers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,224 @@
1
+ /**
2
+ * The bootstrap self-forward (spec `dorfl-self-version-pinning-and-bootstrap-forward`
3
+ * §2/§4; task `dorfl-bootstrap-self-forward`, stories 1/4/5).
4
+ *
5
+ * The globally-installed `dorfl` is a thin BOOTSTRAP. On startup, BEFORE any
6
+ * command dispatch, it reads the nearest repo `dorfl.json`; if that repo declares
7
+ * a `dorflCmd` (and we are not already the forwarded process), it `exec`s that
8
+ * command with the ORIGINAL argv + env inherited, after a one-line STDERR notice,
9
+ * and returns the child's exit code (transparent passthrough).
10
+ *
11
+ * This module is the INJECTABLE seam: {@link decideForward} makes the pure
12
+ * decision (run-self / forward / error / opt-out) from argv + env + a config
13
+ * reader, and {@link performForward} does the exec through an injected spawn
14
+ * function — so the whole path is unit-testable WITHOUT re-execing a real second
15
+ * dorfl or hitting the network (mirroring how git/agent seams are injected in
16
+ * tests). {@link maybeForward} wires the two for the CLI entry point.
17
+ *
18
+ * Load-bearing safety fact (spec §2, task): the forward decision fires ONCE, at
19
+ * bare-`dorfl` startup, in the CHECKOUT ROOT — it is NOT recursive. The gate
20
+ * worktree that runs `prepare`/`verify` is created + prepared by the
21
+ * ALREADY-RUNNING dorfl, which runs the repo's commands via
22
+ * `spawn('bash', ['-c', cmd], {cwd: worktreeDir})` (`prepare.ts`/`verify.ts`) —
23
+ * it never launches a new `dorfl`, so a fresh worktree's empty `node_modules`
24
+ * never re-triggers the forward. Therefore a declared-but-ABSENT `dorflCmd` at
25
+ * the top level is almost always a MISCONFIGURATION (the repo's install did not
26
+ * run), and we FAIL LOUD (decision 2026-07-21, option B) rather than silently
27
+ * degrade to the global and run the WRONG version.
28
+ */
29
+ /**
30
+ * The env marker set on the FORWARDED child so it does not forward AGAIN forever
31
+ * (loop-safe). The forwarded dorfl reads the SAME `dorfl.json` (same `dorflCmd`);
32
+ * seeing this marker it runs in-process instead of re-execing. `DORFL_` prefixed
33
+ * from the single brand identity so a rename flips it in lockstep.
34
+ */
35
+ export declare const FORWARDED_ENV_MARKER: string;
36
+ /**
37
+ * The opt-out env var (spec §4). `DORFL_NO_FORWARD=1` (or any truthy value)
38
+ * DISABLES forwarding AND suppresses the notice — the bootstrap/global runs
39
+ * as-is, so a user can always reach the bootstrap dorfl directly.
40
+ */
41
+ export declare const NO_FORWARD_ENV: string;
42
+ /**
43
+ * The opt-out CLI flag (spec §4). `--no-forward` DISABLES forwarding AND
44
+ * suppresses the notice, exactly like {@link NO_FORWARD_ENV}. It is honoured
45
+ * BEFORE command dispatch and STRIPPED from the argv commander parses (commander
46
+ * never sees it — it is a bootstrap-level flag, not a per-command option).
47
+ */
48
+ export declare const NO_FORWARD_FLAG = "--no-forward";
49
+ /** The pure forward DECISION — what the bootstrap should do at startup. */
50
+ export type ForwardDecision = {
51
+ kind: 'run-self';
52
+ reason: 'no-cmd' | 'already-forwarded' | 'opted-out';
53
+ } | {
54
+ kind: 'forward';
55
+ cmd: string;
56
+ configPath: string;
57
+ } | {
58
+ kind: 'error';
59
+ message: string;
60
+ };
61
+ /**
62
+ * Read the nearest repo's declared `dorflCmd` for `cwd`. Returns the resolved
63
+ * command (trimmed / empty⇒undefined via the config layer) and the `dorfl.json`
64
+ * path it was read from. A missing/config-less repo ⇒ `{cmd: undefined}`. The
65
+ * default reader; tests inject a stub instead of touching the filesystem.
66
+ */
67
+ export interface RepoCmdReader {
68
+ (cwd: string): {
69
+ cmd: string | undefined;
70
+ configPath: string;
71
+ };
72
+ }
73
+ /** The default {@link RepoCmdReader}: read the cwd's `dorfl.json` `dorflCmd`. */
74
+ export declare function defaultRepoCmdReader(cwd: string): {
75
+ cmd: string | undefined;
76
+ configPath: string;
77
+ };
78
+ /**
79
+ * True iff the ORIGINAL argv carries the {@link NO_FORWARD_FLAG} opt-out. Read
80
+ * from raw argv BEFORE commander parses (commander never sees this bootstrap
81
+ * flag). Only the exact `--no-forward` token counts.
82
+ */
83
+ export declare function argvHasNoForward(argv: readonly string[]): boolean;
84
+ /** True iff the env carries a truthy {@link NO_FORWARD_ENV} opt-out. */
85
+ export declare function envHasNoForward(env: NodeJS.ProcessEnv): boolean;
86
+ /** True iff the env carries the {@link FORWARDED_ENV_MARKER} (we ARE the child). */
87
+ export declare function envIsForwarded(env: NodeJS.ProcessEnv): boolean;
88
+ /**
89
+ * Return `argv` with EVERY {@link NO_FORWARD_FLAG} token removed, so commander
90
+ * (which does not declare `--no-forward` as an option) never sees it. Preserves
91
+ * order + all other tokens. Used to hand a clean argv to the in-process run when
92
+ * the opt-out is set.
93
+ */
94
+ export declare function stripNoForwardFlag(argv: readonly string[]): string[];
95
+ /**
96
+ * The PURE forward decision (no I/O beyond the injected `readRepoCmd`). Given the
97
+ * original argv + env + cwd, decide whether the bootstrap should run itself,
98
+ * forward to a `dorflCmd`, or (a declared-but-unusable command) surface an error.
99
+ * The forward is fired ONCE here at startup; the returned decision is acted on by
100
+ * {@link performForward}.
101
+ *
102
+ * Order of precedence:
103
+ * 1. OPT-OUT (`--no-forward` OR `DORFL_NO_FORWARD`) ⇒ run-self, silent.
104
+ * 2. ALREADY-FORWARDED (the child's env marker) ⇒ run-self, silent (loop-safe).
105
+ * 3. NO `dorflCmd` declared ⇒ run-self (onboarding-safe; never chicken-and-egg).
106
+ * 4. A `dorflCmd` is declared ⇒ forward to it.
107
+ *
108
+ * NOTE: this decision never itself resolves whether the target BINARY exists —
109
+ * that is the exec's job ({@link performForward}), which FAILS LOUD on a spawn
110
+ * error (the absent / present-but-broken pin). Keeping the decision pure lets a
111
+ * test drive every branch without a filesystem probe.
112
+ */
113
+ export declare function decideForward(options: {
114
+ argv: readonly string[];
115
+ env: NodeJS.ProcessEnv;
116
+ cwd: string;
117
+ readRepoCmd: RepoCmdReader;
118
+ }): ForwardDecision;
119
+ /**
120
+ * The injected exec seam. Runs `cmd` (through the shell so `npx dorfl@x` /
121
+ * `mise exec dorfl@x --` / `node_modules/.bin/dorfl` all behave as written) with
122
+ * the given argv appended, the given env (which carries the
123
+ * {@link FORWARDED_ENV_MARKER} so the child does not forward again), inheriting
124
+ * stdio. Returns the child's exit code, or a spawn ERROR (target absent / not
125
+ * executable) which {@link performForward} turns into the loud, actionable error.
126
+ *
127
+ * Tests inject a stub that never touches a real process; the default
128
+ * ({@link defaultForwardSpawn}) uses `spawnSync('bash', ['-c', ...])`.
129
+ */
130
+ export interface ForwardSpawn {
131
+ (options: {
132
+ cmd: string;
133
+ forwardedArgs: readonly string[];
134
+ env: NodeJS.ProcessEnv;
135
+ }): ForwardSpawnResult;
136
+ }
137
+ /** The result of the injected {@link ForwardSpawn}. */
138
+ export type ForwardSpawnResult = {
139
+ kind: 'exited';
140
+ code: number;
141
+ } | {
142
+ kind: 'spawn-error';
143
+ message: string;
144
+ };
145
+ /**
146
+ * The default {@link ForwardSpawn}: run `<cmd> <forwardedArgs...>` via
147
+ * `bash -c "<cmd> \"$@\"" bash <args...>` with inherited stdio, returning the
148
+ * child's exit code. A spawn error (`error` set — e.g. bash missing) or a shell
149
+ * "command not found" (exit 127) is reported as `spawn-error` so an absent /
150
+ * broken `dorflCmd` fails loud rather than silently degrading.
151
+ */
152
+ export declare function defaultForwardSpawn(options: {
153
+ cmd: string;
154
+ forwardedArgs: readonly string[];
155
+ env: NodeJS.ProcessEnv;
156
+ }): ForwardSpawnResult;
157
+ /** The one-line STDERR notice announcing a forward (never stdout — must not
158
+ * corrupt `--json`). Shape per spec §4. */
159
+ export declare function forwardNotice(cmd: string, configPath: string): string;
160
+ /**
161
+ * The loud, actionable error for a declared-but-unusable `dorflCmd` (absent
162
+ * target, or a present binary that spawn-errors). Names the `dorflCmd` value +
163
+ * the `dorfl.json` path + the FIX (run the dependency install first) + the
164
+ * `--no-forward` / `DORFL_NO_FORWARD` bypass — so it is never a silent degrade to
165
+ * the global (which would run the WRONG version and defeat the pin).
166
+ */
167
+ export declare function forwardFailureMessage(options: {
168
+ cmd: string;
169
+ configPath: string;
170
+ detail: string;
171
+ }): string;
172
+ /** What {@link performForward} tells the caller to do next. */
173
+ export type ForwardOutcome =
174
+ /** A forward happened; exit the process with this code (transparent passthrough). */
175
+ {
176
+ kind: 'forwarded';
177
+ exitCode: number;
178
+ }
179
+ /** The forward could not run; print `message` to stderr and exit non-zero. */
180
+ | {
181
+ kind: 'error';
182
+ message: string;
183
+ exitCode: number;
184
+ }
185
+ /** No forward — the caller runs the bootstrap itself with `argv`. */
186
+ | {
187
+ kind: 'run-self';
188
+ argv: string[];
189
+ };
190
+ /**
191
+ * Act on a {@link ForwardDecision}: for a `forward`, print the notice to STDERR,
192
+ * spawn the child (via the injected `spawn`) with the {@link FORWARDED_ENV_MARKER}
193
+ * set + the ORIGINAL argv appended, and return the child's exit code — or, on a
194
+ * spawn error, the loud actionable failure. For `run-self`, return the (opt-out-
195
+ * stripped) argv for the caller to parse in-process.
196
+ *
197
+ * `argv` here is the FULL process argv (`[node, script, ...userArgs]`); only the
198
+ * USER args (index 2+) are forwarded to the child, since the child provides its
199
+ * own node + script.
200
+ */
201
+ export declare function performForward(options: {
202
+ decision: ForwardDecision;
203
+ argv: readonly string[];
204
+ env: NodeJS.ProcessEnv;
205
+ spawn: ForwardSpawn;
206
+ writeNotice: (line: string) => void;
207
+ }): ForwardOutcome;
208
+ /**
209
+ * The CLI-entry wiring: decide + (if forwarding) exec, all through the default
210
+ * seams. Returns the {@link ForwardOutcome} the entry point acts on — a
211
+ * `forwarded`/`error` outcome means "exit with this code now"; a `run-self`
212
+ * outcome means "continue into commander with this argv". Kept thin so the entry
213
+ * point stays a two-line hook; the testable logic lives in {@link decideForward}
214
+ * + {@link performForward}.
215
+ */
216
+ export declare function maybeForward(options: {
217
+ argv?: readonly string[];
218
+ env?: NodeJS.ProcessEnv;
219
+ cwd?: string;
220
+ readRepoCmd?: RepoCmdReader;
221
+ spawn?: ForwardSpawn;
222
+ writeNotice?: (line: string) => void;
223
+ }): ForwardOutcome;
224
+ //# sourceMappingURL=bootstrap-forward.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bootstrap-forward.d.ts","sourceRoot":"","sources":["../src/bootstrap-forward.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,247 @@
1
+ import { spawnSync } from 'node:child_process';
2
+ import { brand } from './brand.js';
3
+ import { resolveRepoConfigPath, loadRepoConfig, REPO_CONFIG_FILENAME, } from './repo-config.js';
4
+ /**
5
+ * The bootstrap self-forward (spec `dorfl-self-version-pinning-and-bootstrap-forward`
6
+ * §2/§4; task `dorfl-bootstrap-self-forward`, stories 1/4/5).
7
+ *
8
+ * The globally-installed `dorfl` is a thin BOOTSTRAP. On startup, BEFORE any
9
+ * command dispatch, it reads the nearest repo `dorfl.json`; if that repo declares
10
+ * a `dorflCmd` (and we are not already the forwarded process), it `exec`s that
11
+ * command with the ORIGINAL argv + env inherited, after a one-line STDERR notice,
12
+ * and returns the child's exit code (transparent passthrough).
13
+ *
14
+ * This module is the INJECTABLE seam: {@link decideForward} makes the pure
15
+ * decision (run-self / forward / error / opt-out) from argv + env + a config
16
+ * reader, and {@link performForward} does the exec through an injected spawn
17
+ * function — so the whole path is unit-testable WITHOUT re-execing a real second
18
+ * dorfl or hitting the network (mirroring how git/agent seams are injected in
19
+ * tests). {@link maybeForward} wires the two for the CLI entry point.
20
+ *
21
+ * Load-bearing safety fact (spec §2, task): the forward decision fires ONCE, at
22
+ * bare-`dorfl` startup, in the CHECKOUT ROOT — it is NOT recursive. The gate
23
+ * worktree that runs `prepare`/`verify` is created + prepared by the
24
+ * ALREADY-RUNNING dorfl, which runs the repo's commands via
25
+ * `spawn('bash', ['-c', cmd], {cwd: worktreeDir})` (`prepare.ts`/`verify.ts`) —
26
+ * it never launches a new `dorfl`, so a fresh worktree's empty `node_modules`
27
+ * never re-triggers the forward. Therefore a declared-but-ABSENT `dorflCmd` at
28
+ * the top level is almost always a MISCONFIGURATION (the repo's install did not
29
+ * run), and we FAIL LOUD (decision 2026-07-21, option B) rather than silently
30
+ * degrade to the global and run the WRONG version.
31
+ */
32
+ /**
33
+ * The env marker set on the FORWARDED child so it does not forward AGAIN forever
34
+ * (loop-safe). The forwarded dorfl reads the SAME `dorfl.json` (same `dorflCmd`);
35
+ * seeing this marker it runs in-process instead of re-execing. `DORFL_` prefixed
36
+ * from the single brand identity so a rename flips it in lockstep.
37
+ */
38
+ export const FORWARDED_ENV_MARKER = `${brand.envPrefix}FORWARDED`;
39
+ /**
40
+ * The opt-out env var (spec §4). `DORFL_NO_FORWARD=1` (or any truthy value)
41
+ * DISABLES forwarding AND suppresses the notice — the bootstrap/global runs
42
+ * as-is, so a user can always reach the bootstrap dorfl directly.
43
+ */
44
+ export const NO_FORWARD_ENV = `${brand.envPrefix}NO_FORWARD`;
45
+ /**
46
+ * The opt-out CLI flag (spec §4). `--no-forward` DISABLES forwarding AND
47
+ * suppresses the notice, exactly like {@link NO_FORWARD_ENV}. It is honoured
48
+ * BEFORE command dispatch and STRIPPED from the argv commander parses (commander
49
+ * never sees it — it is a bootstrap-level flag, not a per-command option).
50
+ */
51
+ export const NO_FORWARD_FLAG = '--no-forward';
52
+ /** The default {@link RepoCmdReader}: read the cwd's `dorfl.json` `dorflCmd`. */
53
+ export function defaultRepoCmdReader(cwd) {
54
+ const configPath = resolveRepoConfigPath(cwd);
55
+ const loaded = loadRepoConfig(cwd);
56
+ // `loadRepoConfig` carries `dorflCmd` verbatim from the file; the config-layer
57
+ // trim/empty⇒unset normalisation runs at full resolution, but for the bootstrap
58
+ // decision we only need the raw presence + trimmed value, so normalise here too.
59
+ const raw = loaded.config.dorflCmd;
60
+ const cmd = typeof raw === 'string' && raw.trim() !== '' ? raw.trim() : undefined;
61
+ return { cmd, configPath: loaded.path ?? configPath };
62
+ }
63
+ /**
64
+ * True iff the ORIGINAL argv carries the {@link NO_FORWARD_FLAG} opt-out. Read
65
+ * from raw argv BEFORE commander parses (commander never sees this bootstrap
66
+ * flag). Only the exact `--no-forward` token counts.
67
+ */
68
+ export function argvHasNoForward(argv) {
69
+ return argv.includes(NO_FORWARD_FLAG);
70
+ }
71
+ /** True iff the env carries a truthy {@link NO_FORWARD_ENV} opt-out. */
72
+ export function envHasNoForward(env) {
73
+ const value = env[NO_FORWARD_ENV];
74
+ return value !== undefined && value !== '' && value !== '0';
75
+ }
76
+ /** True iff the env carries the {@link FORWARDED_ENV_MARKER} (we ARE the child). */
77
+ export function envIsForwarded(env) {
78
+ const value = env[FORWARDED_ENV_MARKER];
79
+ return value !== undefined && value !== '' && value !== '0';
80
+ }
81
+ /**
82
+ * Return `argv` with EVERY {@link NO_FORWARD_FLAG} token removed, so commander
83
+ * (which does not declare `--no-forward` as an option) never sees it. Preserves
84
+ * order + all other tokens. Used to hand a clean argv to the in-process run when
85
+ * the opt-out is set.
86
+ */
87
+ export function stripNoForwardFlag(argv) {
88
+ return argv.filter((token) => token !== NO_FORWARD_FLAG);
89
+ }
90
+ /**
91
+ * The PURE forward decision (no I/O beyond the injected `readRepoCmd`). Given the
92
+ * original argv + env + cwd, decide whether the bootstrap should run itself,
93
+ * forward to a `dorflCmd`, or (a declared-but-unusable command) surface an error.
94
+ * The forward is fired ONCE here at startup; the returned decision is acted on by
95
+ * {@link performForward}.
96
+ *
97
+ * Order of precedence:
98
+ * 1. OPT-OUT (`--no-forward` OR `DORFL_NO_FORWARD`) ⇒ run-self, silent.
99
+ * 2. ALREADY-FORWARDED (the child's env marker) ⇒ run-self, silent (loop-safe).
100
+ * 3. NO `dorflCmd` declared ⇒ run-self (onboarding-safe; never chicken-and-egg).
101
+ * 4. A `dorflCmd` is declared ⇒ forward to it.
102
+ *
103
+ * NOTE: this decision never itself resolves whether the target BINARY exists —
104
+ * that is the exec's job ({@link performForward}), which FAILS LOUD on a spawn
105
+ * error (the absent / present-but-broken pin). Keeping the decision pure lets a
106
+ * test drive every branch without a filesystem probe.
107
+ */
108
+ export function decideForward(options) {
109
+ const { argv, env, cwd, readRepoCmd } = options;
110
+ if (argvHasNoForward(argv) || envHasNoForward(env)) {
111
+ return { kind: 'run-self', reason: 'opted-out' };
112
+ }
113
+ if (envIsForwarded(env)) {
114
+ return { kind: 'run-self', reason: 'already-forwarded' };
115
+ }
116
+ const { cmd, configPath } = readRepoCmd(cwd);
117
+ if (cmd === undefined) {
118
+ return { kind: 'run-self', reason: 'no-cmd' };
119
+ }
120
+ return { kind: 'forward', cmd, configPath };
121
+ }
122
+ /**
123
+ * The default {@link ForwardSpawn}: run `<cmd> <forwardedArgs...>` via
124
+ * `bash -c "<cmd> \"$@\"" bash <args...>` with inherited stdio, returning the
125
+ * child's exit code. A spawn error (`error` set — e.g. bash missing) or a shell
126
+ * "command not found" (exit 127) is reported as `spawn-error` so an absent /
127
+ * broken `dorflCmd` fails loud rather than silently degrading.
128
+ */
129
+ export function defaultForwardSpawn(options) {
130
+ // `bash -c '<cmd> "$@"' bash <forwardedArgs...>` passes the ORIGINAL argv
131
+ // through as positional params (quoting-safe) AFTER the (possibly multi-token)
132
+ // dorflCmd — so `npx dorfl@x <args>` and `./bin/dorfl <args>` both work.
133
+ const result = spawnSync('bash', ['-c', `${options.cmd} "$@"`, 'bash', ...options.forwardedArgs], { env: options.env, stdio: 'inherit' });
134
+ if (result.error) {
135
+ return { kind: 'spawn-error', message: result.error.message };
136
+ }
137
+ // 127 is the shell's "command not found" — the ABSENT-target case (e.g.
138
+ // `node_modules/.bin/dorfl` before install). Surface it as a spawn error so it
139
+ // fails loud, NOT a silent passthrough of a misleading exit code.
140
+ if (result.status === 127) {
141
+ return { kind: 'spawn-error', message: `command not found: ${options.cmd}` };
142
+ }
143
+ if (result.signal) {
144
+ return {
145
+ kind: 'spawn-error',
146
+ message: `terminated by signal ${result.signal}`,
147
+ };
148
+ }
149
+ return { kind: 'exited', code: result.status ?? 1 };
150
+ }
151
+ /** The one-line STDERR notice announcing a forward (never stdout — must not
152
+ * corrupt `--json`). Shape per spec §4. */
153
+ export function forwardNotice(cmd, configPath) {
154
+ return `${brand.bin}: forwarding to \`${cmd}\` (from ${configPath})`;
155
+ }
156
+ /**
157
+ * The loud, actionable error for a declared-but-unusable `dorflCmd` (absent
158
+ * target, or a present binary that spawn-errors). Names the `dorflCmd` value +
159
+ * the `dorfl.json` path + the FIX (run the dependency install first) + the
160
+ * `--no-forward` / `DORFL_NO_FORWARD` bypass — so it is never a silent degrade to
161
+ * the global (which would run the WRONG version and defeat the pin).
162
+ */
163
+ export function forwardFailureMessage(options) {
164
+ const { cmd, configPath, detail } = options;
165
+ return (`${brand.bin}: could NOT run the repo-declared dorflCmd \`${cmd}\` ` +
166
+ `(from ${configPath}): ${detail}.\n` +
167
+ `This usually means the repo's dependencies are not installed yet ` +
168
+ `(e.g. \`${cmd}\` points at node_modules/.bin/dorfl before install). ` +
169
+ `Run the repo's dependency install first (e.g. \`pnpm install\`, or the ` +
170
+ `CI project-setup hook), then re-run.\n` +
171
+ `To bypass the forward and run the bootstrap ${brand.bin} directly, pass ` +
172
+ `${NO_FORWARD_FLAG} or set ${NO_FORWARD_ENV}=1 ` +
173
+ `(this runs whatever ${brand.bin} is on PATH — NOT the pinned version).`);
174
+ }
175
+ /**
176
+ * Act on a {@link ForwardDecision}: for a `forward`, print the notice to STDERR,
177
+ * spawn the child (via the injected `spawn`) with the {@link FORWARDED_ENV_MARKER}
178
+ * set + the ORIGINAL argv appended, and return the child's exit code — or, on a
179
+ * spawn error, the loud actionable failure. For `run-self`, return the (opt-out-
180
+ * stripped) argv for the caller to parse in-process.
181
+ *
182
+ * `argv` here is the FULL process argv (`[node, script, ...userArgs]`); only the
183
+ * USER args (index 2+) are forwarded to the child, since the child provides its
184
+ * own node + script.
185
+ */
186
+ export function performForward(options) {
187
+ const { decision, argv, env, spawn, writeNotice } = options;
188
+ if (decision.kind === 'run-self') {
189
+ return { kind: 'run-self', argv: stripNoForwardFlag(argv) };
190
+ }
191
+ if (decision.kind === 'error') {
192
+ return { kind: 'error', message: decision.message, exitCode: 1 };
193
+ }
194
+ // A forward. The user args are everything after `[node, script]`.
195
+ const forwardedArgs = argv.slice(2);
196
+ writeNotice(forwardNotice(decision.cmd, decision.configPath));
197
+ const childEnv = { ...env, [FORWARDED_ENV_MARKER]: '1' };
198
+ const result = spawn({ cmd: decision.cmd, forwardedArgs, env: childEnv });
199
+ if (result.kind === 'spawn-error') {
200
+ return {
201
+ kind: 'error',
202
+ message: forwardFailureMessage({
203
+ cmd: decision.cmd,
204
+ configPath: decision.configPath,
205
+ detail: result.message,
206
+ }),
207
+ exitCode: 1,
208
+ };
209
+ }
210
+ return { kind: 'forwarded', exitCode: result.code };
211
+ }
212
+ /**
213
+ * The CLI-entry wiring: decide + (if forwarding) exec, all through the default
214
+ * seams. Returns the {@link ForwardOutcome} the entry point acts on — a
215
+ * `forwarded`/`error` outcome means "exit with this code now"; a `run-self`
216
+ * outcome means "continue into commander with this argv". Kept thin so the entry
217
+ * point stays a two-line hook; the testable logic lives in {@link decideForward}
218
+ * + {@link performForward}.
219
+ */
220
+ export function maybeForward(options) {
221
+ const argv = options.argv ?? process.argv;
222
+ const env = options.env ?? process.env;
223
+ const cwd = options.cwd ?? process.cwd();
224
+ const readRepoCmd = options.readRepoCmd ?? defaultRepoCmdReader;
225
+ const spawn = options.spawn ?? defaultForwardSpawn;
226
+ const writeNotice = options.writeNotice ??
227
+ ((line) => process.stderr.write(line + '\n'));
228
+ let decision;
229
+ try {
230
+ decision = decideForward({ argv, env, cwd, readRepoCmd });
231
+ }
232
+ catch (err) {
233
+ // A malformed `dorfl.json` (invalid JSON / non-string dorflCmd) surfaces as
234
+ // a loud error rather than a silent run-self, so a broken pin config is never
235
+ // masked. `REPO_CONFIG_FILENAME` names the file in the message.
236
+ return {
237
+ kind: 'error',
238
+ message: `${brand.bin}: could not read ${REPO_CONFIG_FILENAME} to decide the ` +
239
+ `bootstrap forward: ${err instanceof Error ? err.message : String(err)}. ` +
240
+ `Fix ${REPO_CONFIG_FILENAME}, or pass ${NO_FORWARD_FLAG} / set ` +
241
+ `${NO_FORWARD_ENV}=1 to run the bootstrap ${brand.bin} directly.`,
242
+ exitCode: 1,
243
+ };
244
+ }
245
+ return performForward({ decision, argv, env, spawn, writeNotice });
246
+ }
247
+ //# sourceMappingURL=bootstrap-forward.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bootstrap-forward.js","sourceRoot":"","sources":["../src/bootstrap-forward.ts"],"names":[],"mappings":"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"}
package/dist/cli.d.ts CHANGED
@@ -25,6 +25,15 @@ export declare function formatSkillsAddReport(result: InstallSkillsResult, local
25
25
  * so tests can build + introspect/parse the program WITHOUT triggering a real
26
26
  * argv parse + `process.exit` on import (the module-level bootstrap below only
27
27
  * fires when this file is the process entry point).
28
+ *
29
+ * BEFORE any command dispatch it runs the bootstrap SELF-FORWARD hook
30
+ * ({@link maybeForward}): if the nearest repo `dorfl.json` declares a `dorflCmd`
31
+ * (and we are not already the forwarded child / opted out), it execs that command
32
+ * with the ORIGINAL argv + env inherited and exits with the child's code
33
+ * (transparent passthrough). A declared-but-unusable `dorflCmd` FAILS LOUD. On
34
+ * the run-self branch (no `dorflCmd`, opted out, or the forwarded child) it parses
35
+ * the (opt-out-stripped) argv in-process, exactly as before. See
36
+ * `bootstrap-forward.ts` for the full model + the injectable seam.
28
37
  */
29
38
  export declare function runCli(argv?: string[]): Promise<void>;
30
39
  //# sourceMappingURL=cli.d.ts.map
package/dist/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAC,OAAO,EAAS,MAAM,WAAW,CAAC;AAmH1C,OAAO,EAAiB,KAAK,YAAY,EAAC,MAAM,sBAAsB,CAAC;AAuCvE,OAAO,EAAgB,KAAK,mBAAmB,EAAC,MAAM,qBAAqB,CAAC;AA2xB5E;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC/B,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,OAAO,GACb,MAAM,CAoCR;AA6RD,wBAAgB,YAAY,IAAI,OAAO,CA04GtC;AAaD;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACpC,MAAM,EAAE,mBAAmB,EAC3B,KAAK,EAAE,OAAO,GACZ,MAAM,CAyBR;AA+FD;;;;;GAKG;AACH,wBAAsB,MAAM,CAAC,IAAI,GAAE,MAAM,EAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAQzE"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAC,OAAO,EAAS,MAAM,WAAW,CAAC;AAmH1C,OAAO,EAAiB,KAAK,YAAY,EAAC,MAAM,sBAAsB,CAAC;AAwCvE,OAAO,EAAgB,KAAK,mBAAmB,EAAC,MAAM,qBAAqB,CAAC;AA2xB5E;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC/B,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,OAAO,GACb,MAAM,CAoCR;AA6RD,wBAAgB,YAAY,IAAI,OAAO,CA04GtC;AAaD;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACpC,MAAM,EAAE,mBAAmB,EAC3B,KAAK,EAAE,OAAO,GACZ,MAAM,CAyBR;AA+FD;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,MAAM,CAAC,IAAI,GAAE,MAAM,EAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAkBzE"}
package/dist/cli.js CHANGED
@@ -60,6 +60,7 @@ import { dropSource } from './drop-source.js';
60
60
  import { arbiterStatus, DEFAULT_ARBITER_REMOTE } from './arbiter.js';
61
61
  import { resolveTaskOnlyArg, workBranchRef, SlugResolutionError, } from './slug-namespace.js';
62
62
  import { brand } from './brand.js';
63
+ import { maybeForward } from './bootstrap-forward.js';
63
64
  import { installCI } from './install-ci.js';
64
65
  import { GitHubCIContext } from './install-ci-github.js';
65
66
  import { loadCapabilityRegistry } from './install-ci-core.js';
@@ -3485,11 +3486,30 @@ function promptMultiSelect(repos) {
3485
3486
  * so tests can build + introspect/parse the program WITHOUT triggering a real
3486
3487
  * argv parse + `process.exit` on import (the module-level bootstrap below only
3487
3488
  * fires when this file is the process entry point).
3489
+ *
3490
+ * BEFORE any command dispatch it runs the bootstrap SELF-FORWARD hook
3491
+ * ({@link maybeForward}): if the nearest repo `dorfl.json` declares a `dorflCmd`
3492
+ * (and we are not already the forwarded child / opted out), it execs that command
3493
+ * with the ORIGINAL argv + env inherited and exits with the child's code
3494
+ * (transparent passthrough). A declared-but-unusable `dorflCmd` FAILS LOUD. On
3495
+ * the run-self branch (no `dorflCmd`, opted out, or the forwarded child) it parses
3496
+ * the (opt-out-stripped) argv in-process, exactly as before. See
3497
+ * `bootstrap-forward.ts` for the full model + the injectable seam.
3488
3498
  */
3489
3499
  export async function runCli(argv = process.argv) {
3500
+ const outcome = maybeForward({ argv });
3501
+ if (outcome.kind === 'forwarded') {
3502
+ process.exit(outcome.exitCode);
3503
+ }
3504
+ if (outcome.kind === 'error') {
3505
+ console.error(outcome.message);
3506
+ process.exit(outcome.exitCode);
3507
+ }
3508
+ // run-self: parse the argv commander sees (with any `--no-forward` stripped,
3509
+ // since commander does not declare that bootstrap-level flag).
3490
3510
  const program = buildProgram();
3491
3511
  try {
3492
- await program.parseAsync(argv);
3512
+ await program.parseAsync(outcome.argv);
3493
3513
  }
3494
3514
  catch (err) {
3495
3515
  console.error(err instanceof Error ? err.message : String(err));