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.
- package/dist/advance-drivers.d.ts.map +1 -1
- package/dist/advance-drivers.js +11 -2
- package/dist/advance-drivers.js.map +1 -1
- package/dist/bootstrap-forward.d.ts +224 -0
- package/dist/bootstrap-forward.d.ts.map +1 -0
- package/dist/bootstrap-forward.js +247 -0
- package/dist/bootstrap-forward.js.map +1 -0
- package/dist/cli.d.ts +9 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +21 -1
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +50 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +42 -0
- package/dist/config.js.map +1 -1
- package/dist/cwd-section.d.ts.map +1 -1
- package/dist/cwd-section.js +11 -2
- package/dist/cwd-section.js.map +1 -1
- package/dist/env-config.d.ts.map +1 -1
- package/dist/env-config.js +8 -0
- package/dist/env-config.js.map +1 -1
- package/dist/github.d.ts +32 -1
- package/dist/github.d.ts.map +1 -1
- package/dist/github.js +115 -0
- package/dist/github.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/install-ci-core.d.ts.map +1 -1
- package/dist/install-ci-core.js +20 -48
- package/dist/install-ci-core.js.map +1 -1
- package/dist/integration-core.d.ts.map +1 -1
- package/dist/integration-core.js +9 -0
- package/dist/integration-core.js.map +1 -1
- package/dist/integrator.d.ts +48 -0
- package/dist/integrator.d.ts.map +1 -1
- package/dist/integrator.js +12 -0
- package/dist/integrator.js.map +1 -1
- package/dist/item-lock.d.ts +26 -0
- package/dist/item-lock.d.ts.map +1 -1
- package/dist/item-lock.js +39 -0
- package/dist/item-lock.js.map +1 -1
- package/dist/repo-config.d.ts +1 -1
- package/dist/repo-config.d.ts.map +1 -1
- package/dist/repo-config.js +20 -1
- package/dist/repo-config.js.map +1 -1
- package/dist/scan.d.ts +24 -2
- package/dist/scan.d.ts.map +1 -1
- package/dist/scan.js +28 -4
- package/dist/scan.js.map +1 -1
- package/dist/skills/setup/SKILL.md +3 -0
- package/dist/tasking.d.ts.map +1 -1
- package/dist/tasking.js +124 -65
- package/dist/tasking.js.map +1 -1
- package/package.json +1 -1
- package/src/advance-drivers.ts +17 -8
- package/src/bootstrap-forward.ts +359 -0
- package/src/cli.ts +21 -1
- package/src/config.ts +75 -0
- package/src/cwd-section.ts +21 -2
- package/src/env-config.ts +8 -0
- package/src/github.ts +149 -0
- package/src/index.ts +24 -0
- package/src/install-ci-core.ts +20 -48
- package/src/integration-core.ts +10 -0
- package/src/integrator.ts +62 -0
- package/src/item-lock.ts +50 -0
- package/src/repo-config.ts +20 -0
- package/src/scan.ts +32 -8
- 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,
|
|
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"}
|
package/dist/advance-drivers.js
CHANGED
|
@@ -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
|
|
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":"AAAA,OAAO,EACN,cAAc,GAKd,MAAM,cAAc,CAAC;AACtB,OAAO,EACN,kBAAkB,EAClB,cAAc,GACd,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAC,aAAa,EAAC,MAAM,WAAW,CAAC;AACxC,OAAO,EAAC,aAAa,EAAC,MAAM,gBAAgB,CAAC;
|
|
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;
|
|
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));
|