dorfl 0.8.0 → 0.10.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 (44) hide show
  1. package/dist/cli.d.ts.map +1 -1
  2. package/dist/cli.js +63 -25
  3. package/dist/cli.js.map +1 -1
  4. package/dist/config.d.ts +82 -7
  5. package/dist/config.d.ts.map +1 -1
  6. package/dist/config.js +14 -2
  7. package/dist/config.js.map +1 -1
  8. package/dist/do.d.ts +16 -1
  9. package/dist/do.d.ts.map +1 -1
  10. package/dist/do.js +14 -9
  11. package/dist/do.js.map +1 -1
  12. package/dist/env-config.d.ts.map +1 -1
  13. package/dist/env-config.js +25 -3
  14. package/dist/env-config.js.map +1 -1
  15. package/dist/intake-trigger-template.d.ts +91 -53
  16. package/dist/intake-trigger-template.d.ts.map +1 -1
  17. package/dist/intake-trigger-template.js +213 -114
  18. package/dist/intake-trigger-template.js.map +1 -1
  19. package/dist/intake.d.ts +53 -4
  20. package/dist/intake.d.ts.map +1 -1
  21. package/dist/intake.js +59 -15
  22. package/dist/intake.js.map +1 -1
  23. package/dist/placement.d.ts +42 -33
  24. package/dist/placement.d.ts.map +1 -1
  25. package/dist/placement.js +20 -17
  26. package/dist/placement.js.map +1 -1
  27. package/dist/repo-config.d.ts +1 -1
  28. package/dist/repo-config.d.ts.map +1 -1
  29. package/dist/repo-config.js +35 -0
  30. package/dist/repo-config.js.map +1 -1
  31. package/dist/tasking.d.ts +46 -1
  32. package/dist/tasking.d.ts.map +1 -1
  33. package/dist/tasking.js +48 -21
  34. package/dist/tasking.js.map +1 -1
  35. package/package.json +1 -1
  36. package/src/cli.ts +75 -28
  37. package/src/config.ts +96 -9
  38. package/src/do.ts +30 -10
  39. package/src/env-config.ts +25 -3
  40. package/src/intake-trigger-template.ts +263 -143
  41. package/src/intake.ts +136 -18
  42. package/src/placement.ts +42 -36
  43. package/src/repo-config.ts +35 -0
  44. package/src/tasking.ts +75 -43
package/src/config.ts CHANGED
@@ -44,21 +44,23 @@ export type TasksLandIn = 'backlog' | 'ready';
44
44
  * `pre-prd-staging-pool-split-and-untrusted-prd-placement`, governing ADR
45
45
  * `placement-is-runner-deterministic-humanonly-is-agent-judgement`). Which
46
46
  * folder the runner lands `intake`-authored spec files in BY DEFAULT —
47
- * `'pre-proposed'` (staging — durable + readable but NOT in the auto-tasking
47
+ * `'proposed'` (staging — durable + readable but NOT in the auto-tasking
48
48
  * POOL; a runner/human promotion is needed to make the spec auto-taskable; the
49
49
  * on-disk folder for this value is `work/specs/proposed/`) or `'ready'` (the
50
50
  * auto-tasking POOL — the trusted fast-path landing, on-disk
51
51
  * `work/specs/ready/`). The same runner-deterministic placement RESOLVER
52
52
  * (`src/placement.ts`) layers on top:
53
- * `explicit operator flag > untrusted-origin ⇒ pre-proposed > specsLandIn
54
- * default > built-in (pre-proposed)`. An untrusted-origin intake spec is FORCED
55
- * to staging even in a `'ready'` repo (the positional analogue of the existing
56
- * `untrusted-origin-forces-build-propose` rule). The SPEC twin of
53
+ * `explicit operator flag > configured default > built-in (proposed)`.
54
+ * Author-trust is NO LONGER a rung in the resolver (ADR
55
+ * `untrusted-origin-carries-via-stamp-not-forced-staging`): the CALLER reads the
56
+ * `originTrust:` stamp and selects the untrusted twin `untrustedSpecsLandIn`
57
+ * (default `'proposed'`; opt-in `'ready'`) as the configured default for an
58
+ * untrusted intake spec. The SPEC twin of
57
59
  * {@link TasksLandIn}; the SAME shape, the SAME precedence chain. The value
58
60
  * spellings mirror the live spec folders (`specs/proposed/` staging,
59
61
  * `specs/ready/` pool), exactly as {@link TasksLandIn} mirrors the task folders.
60
62
  */
61
- export type SpecsLandIn = 'pre-proposed' | 'ready';
63
+ export type SpecsLandIn = 'proposed' | 'ready';
62
64
 
63
65
  /**
64
66
  * The observation-triage gate (ADR `ci-config-policy-and-gate-family` §2): a
@@ -357,6 +359,37 @@ export interface Config {
357
359
  * per-LIFECYCLE-TRANSITION knob, inside the trust boundary, operator/config-only.
358
360
  */
359
361
  taskingIntegration?: IntegrationMode;
362
+ /**
363
+ * **Per-TRANSITION override for the INTAKE DOCUMENT emit only** — the twin of
364
+ * {@link taskingIntegration} for the intake front door. When set, an
365
+ * `intake`-emitted DOCUMENT (a task file `work/tasks/*` OR a spec file
366
+ * `work/specs/*`) integrates with THIS mode instead of the flat
367
+ * {@link integration}; the task-BUILD transition is unaffected (it always reads
368
+ * {@link integration}), and neither is the tasking transition (it reads
369
+ * {@link taskingIntegration}). UNSET (the default) ⇒ intake falls back to
370
+ * {@link integration} — byte-for-byte today's behaviour for any repo that does
371
+ * not set it, so a single `integration: 'merge'` merges documents across BOTH
372
+ * the tasking and intake transitions with no extra key.
373
+ *
374
+ * A SINGLE value applies to both the task AND the spec document (spec
375
+ * `intake-integration-knob-and-specs-land-in-proposed-rename` US #1 chose a
376
+ * single knob, NOT a per-type `{task, spec}` split). Decoupled from the
377
+ * AUTONOMY GATES (`autoBuild`/`autoTask`): the intake document PR-mode is now an
378
+ * operator/config choice, NOT a function of "may an agent act autonomously" —
379
+ * so a repo can have `autoBuild: true`/`autoTask: true` (autonomy) AND intake
380
+ * documents merging to `main` at the same time (ADR
381
+ * `untrusted-origin-carries-via-stamp-not-forced-staging`). Untrusted safety is
382
+ * unchanged: it rests entirely on placement (`untrusted*LandIn`) + the
383
+ * build-time `originTrust: untrusted` stamp (the code PR), never a forced
384
+ * document PR. Resolved per-repo like {@link taskingIntegration}: flag
385
+ * (`--merge`/`--propose`) > env (`DORFL_INTAKE_INTEGRATION`) > per-repo >
386
+ * global > (fall back to) `integration` > default `propose`. The intake CLI's
387
+ * explicit `--merge-task`/`--merge-spec`/`--merge`/`--propose` flags still win
388
+ * (operator-present, top of precedence). DISTINCT from `taskingIntegration` (a
389
+ * DIFFERENT lifecycle transition) — each is its own `merge|propose` mode that
390
+ * falls back to `integration`, none tied to an autonomy gate.
391
+ */
392
+ intakeIntegration?: IntegrationMode;
360
393
  /**
361
394
  * **Per-repo DEFAULT landing for the TASKER's emitted tasks** (spec
362
395
  * `staging-pool-position-gate-and-trust-model` US #5, task
@@ -377,7 +410,7 @@ export interface Config {
377
410
  * `staging-pool-position-gate-and-trust-model` US #2/#5/#6/#12). The SPEC twin
378
411
  * of {@link tasksLandIn}: resolved per-repo EXACTLY like it (flag
379
412
  * `--specs-land-in` > env `DORFL_SPECS_LAND_IN` > per-repo > global >
380
- * built-in `'pre-proposed'`). `intake`'s spec dispatch reads it and passes it as
413
+ * built-in `'proposed'`). `intake`'s spec dispatch reads it and passes it as
381
414
  * the CONFIGURED-DEFAULT rung into the shared placement resolver
382
415
  * (`src/placement.ts`); the resolver overlays an EXPLICIT operator flag
383
416
  * (top) and the UNTRUSTED-ORIGIN force (staging) on top, in that order.
@@ -391,6 +424,48 @@ export interface Config {
391
424
  * `prdsLandIn` config key + `--prds-land-in` flag are GONE (clean break).
392
425
  */
393
426
  specsLandIn: SpecsLandIn;
427
+ /**
428
+ * **Per-repo DEFAULT landing for an UNTRUSTED-origin TASK** (spec
429
+ * `untrusted-origin-carries-via-stamp-intake-placement-symmetry-and-ci-gate-resolution`
430
+ * US #5/#6, governing ADR
431
+ * `untrusted-origin-carries-via-stamp-not-forced-staging`). The exact TWIN of
432
+ * {@link tasksLandIn} for items whose `originTrust` stamp is `untrusted`:
433
+ * SAME value shape ({@link TasksLandIn}), SAME resolution chain (flag
434
+ * `--untrusted-tasks-land-in` > env `DORFL_UNTRUSTED_TASKS_LAND_IN` >
435
+ * per-repo > global > built-in `'backlog'`). The ADR removes the
436
+ * untrusted-forces-staging RUNG from the placement resolver; instead the
437
+ * CALLER reads the stamp and selects THIS key (vs the trusted
438
+ * {@link tasksLandIn}) as the configured-default rung. Governs EVERY
439
+ * untrusted-stamped task — intake-authored directly from an issue OR emitted
440
+ * by the tasker from an untrusted-origin spec (decision X: one policy, both
441
+ * call sites; no third knob). DEFAULTS to STAGING (`'backlog'`), the
442
+ * conservative human-admission landing: safety for an untrusted item that
443
+ * opts into the pool (`'ready'`) is then the carried build STAMP (a code PR),
444
+ * not the folder. CONSUMED at both task call sites: the tasker
445
+ * (`performTask`) selects it for an untrusted-origin spec's emitted tasks, and
446
+ * intake's direct task emit (`dispatchTask`, a sibling task) selects it for a
447
+ * task born straight from an issue.
448
+ */
449
+ untrustedTasksLandIn: TasksLandIn;
450
+ /**
451
+ * **Per-repo DEFAULT landing for an UNTRUSTED-origin intake SPEC** (spec
452
+ * `untrusted-origin-carries-via-stamp-intake-placement-symmetry-and-ci-gate-resolution`
453
+ * US #7, governing ADR
454
+ * `untrusted-origin-carries-via-stamp-not-forced-staging`). The exact TWIN of
455
+ * {@link specsLandIn} for untrusted-stamped intake specs: SAME value shape
456
+ * ({@link SpecsLandIn} — `proposed` staging vs `ready` pool), SAME
457
+ * resolution chain (flag `--untrusted-specs-land-in` > env
458
+ * `DORFL_UNTRUSTED_SPECS_LAND_IN` > per-repo > global > built-in
459
+ * `'proposed'`). The caller reads the `originTrust` stamp and selects THIS
460
+ * key (vs the trusted {@link specsLandIn}) as the placement resolver's
461
+ * configured-default rung. DEFAULTS to STAGING (`'proposed'`) — the
462
+ * conservative human-admission landing, preserving today's effective
463
+ * behaviour for a repo that configures nothing; a repo opts an untrusted spec
464
+ * into the pool (`'ready'`) explicitly, safety then via the carried stamp.
465
+ * CONSUMED at the intake SPEC call site (`dispatchSpec`), which selects it
466
+ * over {@link specsLandIn} when the intake stamp is `originTrust: untrusted`.
467
+ */
468
+ untrustedSpecsLandIn: SpecsLandIn;
394
469
  /**
395
470
  * **The PR-INTENT axis** (ADR §6): on the `propose` path, do NOT open a review
396
471
  * request even on a GitHub arbiter with auth — push the branch (the
@@ -825,14 +900,26 @@ export const DEFAULT_CONFIG: Config = {
825
900
  // The runner-deterministic resolver overlays explicit-flag + untrusted-origin
826
901
  // force on top of this default (`src/placement.ts`).
827
902
  tasksLandIn: 'backlog',
828
- // `intake`-authored specs land STAGED (`pre-proposed/`) by default — the
903
+ // `intake`-authored specs land STAGED (`proposed/`) by default — the
829
904
  // conservative landing that mirrors `tasksLandIn`'s built-in floor: a spec is
830
905
  // durable + readable but NOT in the auto-tasking POOL until a human/runner
831
906
  // promotes it. A repo opts into the trusted fast-path with `specsLandIn: 'ready'`
832
907
  // (or `--specs-land-in ready` / `DORFL_SPECS_LAND_IN=ready`). The same
833
908
  // runner-deterministic resolver overlays explicit-flag + untrusted-origin
834
909
  // force on top of this default (`src/placement.ts`).
835
- specsLandIn: 'pre-proposed',
910
+ specsLandIn: 'proposed',
911
+ // The untrusted-side placement TWINS default to STAGING (`backlog` /
912
+ // `proposed`) — the conservative human-admission landing (ADR
913
+ // `untrusted-origin-carries-via-stamp-not-forced-staging`). A repo that trusts
914
+ // its stamp-based pipeline opts an untrusted item into the pool (`ready`)
915
+ // explicitly; safety is then the carried build STAMP (a code PR), not the
916
+ // folder. Unset ⇒ both resolve to staging, so a repo configuring nothing keeps
917
+ // today's effective behaviour. NO call site consumes these yet (resolver +
918
+ // intake/tasker wiring are later tasks); resolved flag > env
919
+ // (`DORFL_UNTRUSTED_TASKS_LAND_IN` / `DORFL_UNTRUSTED_SPECS_LAND_IN`) > per-repo
920
+ // > global > built-in, exactly like their trusted twins.
921
+ untrustedTasksLandIn: 'backlog',
922
+ untrustedSpecsLandIn: 'proposed',
836
923
  agentCmd: '',
837
924
  // Gate 2 (PR/code review) defaults OFF — it puts a model on the merge path, so
838
925
  // it is opt-in (ADR §8). On an `approve` a resolved `merge` lands automatically
package/src/do.ts CHANGED
@@ -416,11 +416,21 @@ export interface DoOptions {
416
416
  * lifecycle concern).
417
417
  */
418
418
  tasksLandIn?: 'backlog' | 'ready';
419
+ /**
420
+ * **The per-repo UNTRUSTED-side TASK-PLACEMENT default** (spec
421
+ * `untrusted-origin-carries-via-stamp-intake-placement-symmetry-and-ci-gate-resolution`,
422
+ * ADR `untrusted-origin-carries-via-stamp-not-forced-staging`). Threaded into
423
+ * {@link performTask}, which selects it (over {@link tasksLandIn}) as the
424
+ * configured-default rung when the tasked spec carries an
425
+ * `originTrust: untrusted` stamp. See {@link performTask}'s
426
+ * `untrustedTasksLandIn`.
427
+ */
428
+ untrustedTasksLandIn?: 'backlog' | 'ready';
419
429
  /**
420
430
  * **The OPERATOR's EXPLICIT task-placement override** (the TOP precedence
421
431
  * rung in the placement resolver). Set ONLY when the operator typed
422
432
  * `--tasks-land-in <where>` on this invocation; never when the value came
423
- * from config. Wins over `originTrust: untrusted` (the operator is present;
433
+ * from config. Wins over the configured default (the operator is present;
424
434
  * CLI always wins, no special force-key) — the positional analogue of
425
435
  * `explicitMerge` overriding the untrusted-origin build-propose rule.
426
436
  */
@@ -704,6 +714,11 @@ export interface DoRemoteOptions extends DoAgentLaunchOptions {
704
714
  * configured-default rung. See {@link DoOptions.tasksLandIn}.
705
715
  */
706
716
  tasksLandIn?: 'backlog' | 'ready';
717
+ /**
718
+ * **The per-repo UNTRUSTED-side TASK-PLACEMENT default** on the `do --remote
719
+ * spec:` path. See {@link DoOptions.untrustedTasksLandIn}.
720
+ */
721
+ untrustedTasksLandIn?: 'backlog' | 'ready';
707
722
  /**
708
723
  * **The OPERATOR's EXPLICIT task-placement override** on the `do --remote
709
724
  * spec:` path. See {@link DoOptions.explicitTasksLandIn}.
@@ -942,13 +957,16 @@ export async function performDo(options: DoOptions): Promise<DoResult> {
942
957
  // same per-repo cap the build path uses (task
943
958
  // `thread-merge-retries-cross-task-and-ratify-default`).
944
959
  mergeRetries: options.mergeRetries,
945
- // The per-repo TASK-PLACEMENT default + the operator's explicit
946
- // override (task `runner-deterministic-slice-placement-policy-and-
947
- // precedence`). The tasker reads them as the configured-default + the
948
- // top rung of the runner-deterministic placement resolver; the
949
- // `originTrust: untrusted` force is read inside the tasker from the
950
- // spec's stamped frontmatter.
960
+ // The per-repo TASK-PLACEMENT defaults (trusted + untrusted twin) + the
961
+ // operator's explicit override (task `runner-deterministic-slice-
962
+ // placement-policy-and-precedence`; ADR `untrusted-origin-carries-via-
963
+ // stamp-not-forced-staging`). The tasker reads the spec's stamped
964
+ // `originTrust:` to SELECT the trusted-vs-untrusted configured default,
965
+ // then feeds it (with the explicit override on top) into the
966
+ // runner-deterministic placement resolver (which no longer has a trust
967
+ // rung).
951
968
  tasksLandIn: options.tasksLandIn,
969
+ untrustedTasksLandIn: options.untrustedTasksLandIn,
952
970
  explicitTasksLandIn: options.explicitTasksLandIn,
953
971
  noPR: options.noPR,
954
972
  providerInstance: options.providerInstance,
@@ -2372,10 +2390,12 @@ export async function performDoRemote(
2372
2390
  // threaded on the no-checkout `do --remote spec:` tasking path too,
2373
2391
  // mirroring the in-place site above.
2374
2392
  mergeRetries: options.mergeRetries,
2375
- // The per-repo TASK-PLACEMENT default + the operator's explicit
2376
- // override (task `runner-deterministic-slice-placement-policy-and-
2377
- // precedence`). Same threading as the in-place `do spec:` path.
2393
+ // The per-repo TASK-PLACEMENT defaults (trusted + untrusted twin) + the
2394
+ // operator's explicit override. Same stamp-selected threading as the
2395
+ // in-place `do spec:` path (ADR `untrusted-origin-carries-via-stamp-
2396
+ // not-forced-staging`).
2378
2397
  tasksLandIn: options.tasksLandIn,
2398
+ untrustedTasksLandIn: options.untrustedTasksLandIn,
2379
2399
  explicitTasksLandIn: options.explicitTasksLandIn,
2380
2400
  noPR: options.noPR,
2381
2401
  providerInstance: options.providerInstance,
package/src/env-config.ts CHANGED
@@ -98,6 +98,14 @@ const KEY_COERCIONS: {[K in keyof Config]?: Coercion} = {
98
98
  // works and a typo FAILS LOUDLY. Unset ⇒ the tasking transition falls back to
99
99
  // `integration` (the flat value). It NEVER touches the build transition or intake.
100
100
  taskingIntegration: {enum: ['propose', 'merge']},
101
+ // `intakeIntegration` (the per-TRANSITION INTAKE-DOCUMENT override — the twin of
102
+ // `taskingIntegration` for the intake front door) coerces as the SAME
103
+ // `propose`/`merge` enum as `integration`, so `DORFL_INTAKE_INTEGRATION`
104
+ // works and a typo FAILS LOUDLY. Unset ⇒ the intake document emit falls back to
105
+ // `integration` (the flat value). Decoupled from the autonomy gates
106
+ // (`autoBuild`/`autoTask`) — the intake document PR-mode is operator/config, not
107
+ // a function of autonomy (ADR untrusted-origin-carries-via-stamp-not-forced-staging).
108
+ intakeIntegration: {enum: ['propose', 'merge']},
101
109
  // `tasksLandIn` (the per-repo TASK-PLACEMENT default — spec
102
110
  // `staging-pool-position-gate-and-trust-model` US #5) coerces as the
103
111
  // `backlog`/`ready` enum, so `DORFL_TASKS_LAND_IN=ready` works and a
@@ -108,13 +116,27 @@ const KEY_COERCIONS: {[K in keyof Config]?: Coercion} = {
108
116
  tasksLandIn: {enum: ['backlog', 'ready']},
109
117
  // `specsLandIn` (the per-repo SPEC-PLACEMENT default — spec
110
118
  // `staging-pool-position-gate-and-trust-model` US #2/#5) coerces as the
111
- // `pre-proposed`/`ready` enum, so `DORFL_SPECS_LAND_IN=ready` works and a typo
119
+ // `proposed`/`ready` enum, so `DORFL_SPECS_LAND_IN=ready` works and a typo
112
120
  // FAILS LOUDLY. Same precedence chain as `tasksLandIn` (flag > env > per-repo
113
- // > global > built-in `pre-proposed`); fed into the shared placement resolver
121
+ // > global > built-in `proposed`); fed into the shared placement resolver
114
122
  // (`src/placement.ts`) as the configured-default rung for the spec lifecycle.
115
123
  // The legacy `prdsLandIn` key / `DORFL_PRDS_LAND_IN` env are GONE after the
116
124
  // ''prd'' → `spec` hard cutover (clean break).
117
- specsLandIn: {enum: ['pre-proposed', 'ready']},
125
+ specsLandIn: {enum: ['proposed', 'ready']},
126
+ // `untrustedTasksLandIn` (the UNTRUSTED-side TWIN of `tasksLandIn` — spec
127
+ // `untrusted-origin-carries-via-stamp-intake-placement-symmetry-and-ci-gate-resolution`
128
+ // US #5/#6, ADR `untrusted-origin-carries-via-stamp-not-forced-staging`)
129
+ // coerces as the SAME `backlog`/`ready` enum as `tasksLandIn`, so
130
+ // `DORFL_UNTRUSTED_TASKS_LAND_IN=ready` works and a typo FAILS LOUDLY. Same
131
+ // precedence chain (flag > env > per-repo > global > built-in `backlog`); the
132
+ // caller selects it (over the trusted `tasksLandIn`) by reading the
133
+ // `originTrust` stamp before feeding the placement resolver.
134
+ untrustedTasksLandIn: {enum: ['backlog', 'ready']},
135
+ // `untrustedSpecsLandIn` (the UNTRUSTED-side TWIN of `specsLandIn` — same spec
136
+ // US #7) coerces as the SAME `proposed`/`ready` enum as `specsLandIn`, so
137
+ // `DORFL_UNTRUSTED_SPECS_LAND_IN=ready` works and a typo FAILS LOUDLY. Same
138
+ // precedence chain (flag > env > per-repo > global > built-in `proposed`).
139
+ untrustedSpecsLandIn: {enum: ['proposed', 'ready']},
118
140
  // `noPR` (the PR-INTENT axis) is a BOOLEAN coercion (like `review`), so
119
141
  // `DORFL_NO_PR=true|false` works and a typo FAILS LOUDLY. The removed
120
142
  // `provider` override has NO env var (a stale `DORFL_PROVIDER` is ignored