@wildorder/nightshift 0.17.0 → 0.18.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 (99) hide show
  1. package/README.md +269 -1
  2. package/dist/agent-runner.d.ts +41 -3
  3. package/dist/agent-runner.d.ts.map +1 -1
  4. package/dist/agent-runner.js +197 -12
  5. package/dist/agent-runner.js.map +1 -1
  6. package/dist/agent-session.d.ts +123 -0
  7. package/dist/agent-session.d.ts.map +1 -0
  8. package/dist/agent-session.js +114 -0
  9. package/dist/agent-session.js.map +1 -0
  10. package/dist/atomic-write.d.ts +18 -0
  11. package/dist/atomic-write.d.ts.map +1 -0
  12. package/dist/atomic-write.js +74 -0
  13. package/dist/atomic-write.js.map +1 -0
  14. package/dist/author.d.ts +112 -6
  15. package/dist/author.d.ts.map +1 -1
  16. package/dist/author.js +597 -137
  17. package/dist/author.js.map +1 -1
  18. package/dist/causal-analysis.d.ts +6 -2
  19. package/dist/causal-analysis.d.ts.map +1 -1
  20. package/dist/causal-analysis.js +55 -2
  21. package/dist/causal-analysis.js.map +1 -1
  22. package/dist/cli.js +22 -2
  23. package/dist/cli.js.map +1 -1
  24. package/dist/concurrency.d.ts +24 -0
  25. package/dist/concurrency.d.ts.map +1 -0
  26. package/dist/concurrency.js +28 -0
  27. package/dist/concurrency.js.map +1 -0
  28. package/dist/decider-review.d.ts +10 -3
  29. package/dist/decider-review.d.ts.map +1 -1
  30. package/dist/decider-review.js +6 -4
  31. package/dist/decider-review.js.map +1 -1
  32. package/dist/decision-ledger.d.ts +7 -0
  33. package/dist/decision-ledger.d.ts.map +1 -1
  34. package/dist/decision-ledger.js +25 -10
  35. package/dist/decision-ledger.js.map +1 -1
  36. package/dist/detect-package-manager.d.ts +10 -0
  37. package/dist/detect-package-manager.d.ts.map +1 -1
  38. package/dist/detect-package-manager.js +12 -0
  39. package/dist/detect-package-manager.js.map +1 -1
  40. package/dist/index.d.ts +3 -1
  41. package/dist/index.d.ts.map +1 -1
  42. package/dist/index.js +3 -1
  43. package/dist/index.js.map +1 -1
  44. package/dist/manifest.d.ts +24 -5
  45. package/dist/manifest.d.ts.map +1 -1
  46. package/dist/manifest.js +254 -108
  47. package/dist/manifest.js.map +1 -1
  48. package/dist/permits.d.ts +18 -0
  49. package/dist/permits.d.ts.map +1 -1
  50. package/dist/permits.js +155 -0
  51. package/dist/permits.js.map +1 -1
  52. package/dist/preflight.d.ts +2 -2
  53. package/dist/preflight.d.ts.map +1 -1
  54. package/dist/preflight.js.map +1 -1
  55. package/dist/review-pass.d.ts +52 -10
  56. package/dist/review-pass.d.ts.map +1 -1
  57. package/dist/review-pass.js +114 -30
  58. package/dist/review-pass.js.map +1 -1
  59. package/dist/run-analytics-report.d.ts +114 -1
  60. package/dist/run-analytics-report.d.ts.map +1 -1
  61. package/dist/run-analytics-report.js +606 -14
  62. package/dist/run-analytics-report.js.map +1 -1
  63. package/dist/run-analytics.d.ts +107 -1
  64. package/dist/run-analytics.d.ts.map +1 -1
  65. package/dist/run-analytics.js +257 -25
  66. package/dist/run-analytics.js.map +1 -1
  67. package/dist/run-log.d.ts +16 -0
  68. package/dist/run-log.d.ts.map +1 -0
  69. package/dist/run-log.js +32 -0
  70. package/dist/run-log.js.map +1 -0
  71. package/dist/run-program.d.ts +203 -7
  72. package/dist/run-program.d.ts.map +1 -1
  73. package/dist/run-program.js +1526 -320
  74. package/dist/run-program.js.map +1 -1
  75. package/dist/scheduler.d.ts +75 -0
  76. package/dist/scheduler.d.ts.map +1 -0
  77. package/dist/scheduler.js +126 -0
  78. package/dist/scheduler.js.map +1 -0
  79. package/dist/verify-cache.d.ts +64 -0
  80. package/dist/verify-cache.d.ts.map +1 -0
  81. package/dist/verify-cache.js +56 -0
  82. package/dist/verify-cache.js.map +1 -0
  83. package/dist/whole-program-review.d.ts +2 -2
  84. package/dist/whole-program-review.d.ts.map +1 -1
  85. package/dist/whole-program-review.js.map +1 -1
  86. package/dist/worktree.d.ts +124 -0
  87. package/dist/worktree.d.ts.map +1 -0
  88. package/dist/worktree.js +397 -0
  89. package/dist/worktree.js.map +1 -0
  90. package/dist/write-queue.d.ts +25 -0
  91. package/dist/write-queue.d.ts.map +1 -0
  92. package/dist/write-queue.js +52 -0
  93. package/dist/write-queue.js.map +1 -0
  94. package/package.json +2 -2
  95. package/skills/plan-program/SKILL.md +37 -5
  96. package/dist/worktree-guard.d.ts +0 -40
  97. package/dist/worktree-guard.d.ts.map +0 -1
  98. package/dist/worktree-guard.js +0 -91
  99. package/dist/worktree-guard.js.map +0 -1
@@ -0,0 +1,114 @@
1
+ import { resolveSummary } from "./agent-summary.js";
2
+ /**
3
+ * Opens a resumed revision brief (§3.7): a resumed agent must be told it is
4
+ * resuming, or it re-orients as if the brief were its first contact. Shared
5
+ * verbatim by the spec-critique writer and the test-critique fix brief so
6
+ * the two revision briefs never drift in wording.
7
+ */
8
+ export const SESSION_CONTINUATION_PREAMBLE = [
9
+ "## You are continuing your own session",
10
+ "",
11
+ "This is the same conversation in which you wrote this work. The findings",
12
+ "below came from an independent reviewer who read it afterwards. You do not",
13
+ "need to re-read what you already know; go straight to the findings.",
14
+ "",
15
+ ].join("\n");
16
+ /** Human sentences for each decline reason, one exported and exhaustively
17
+ * switched function so the wording lives in one place and fails to compile
18
+ * when a reason is added without a sentence. Never prints the session id
19
+ * itself — it is a machine-local handle with no meaning to the reader. */
20
+ export function describeSessionDecline(reason, detail) {
21
+ switch (reason) {
22
+ case "no-session-captured":
23
+ return "no session id was captured from the agent that wrote it";
24
+ case "provider-mismatch":
25
+ return detail?.producerCommand !== undefined && detail?.seatCommand !== undefined
26
+ ? `it ran \`${detail.producerCommand}\` and this seat runs \`${detail.seatCommand}\``
27
+ : "it ran under a different provider than this seat runs";
28
+ case "invocation-mismatch":
29
+ return "it ran under different flags than this seat uses";
30
+ case "cwd-mismatch":
31
+ return "it ran in a different directory";
32
+ case "operator-pinned-session-flag":
33
+ return "the configured agent manages its own sessions";
34
+ case "unsupported-resume-argv":
35
+ return detail?.token !== undefined
36
+ ? `its arguments cannot be translated to a resume (\`${detail.token}\`)`
37
+ : "its arguments cannot be translated to a resume";
38
+ case "resume-spawn-failed":
39
+ return "the resumed agent failed to start";
40
+ }
41
+ }
42
+ const NO_SESSION_CAPTURED = {
43
+ mode: "fresh",
44
+ declineReason: "no-session-captured",
45
+ };
46
+ function safeObserve(observeContinuity, continuity) {
47
+ try {
48
+ observeContinuity?.(continuity);
49
+ }
50
+ catch {
51
+ // An analytics defect must never flip a seat's outcome (SC-13).
52
+ }
53
+ }
54
+ /**
55
+ * The one fallback helper the three resuming seats share (§3.6): a resumed
56
+ * spawn that failed *before touching the artifact* falls back to exactly one
57
+ * fresh spawn; a resumed spawn that failed *after* changing the tree is
58
+ * never compounded with a second attempt — the existing verify-and-reset
59
+ * machinery handles it exactly as it would a fresh spawn's failure.
60
+ */
61
+ export async function spawnWithSessionContinuity(options) {
62
+ const { resume, spawn, untouched, log, observeContinuity } = options;
63
+ if (resume === undefined) {
64
+ const result = await spawn(undefined, false);
65
+ const continuity = result.continuity ?? NO_SESSION_CAPTURED;
66
+ safeObserve(observeContinuity, continuity);
67
+ return { result, continuity };
68
+ }
69
+ let first;
70
+ try {
71
+ first = await spawn(resume, true);
72
+ }
73
+ catch (error) {
74
+ const isUntouched = await safeUntouched(untouched);
75
+ if (!isUntouched) {
76
+ safeObserve(observeContinuity, { mode: "resumed" });
77
+ throw error;
78
+ }
79
+ log(`session continuity: the resumed spawn failed to start (${error.message}); ` +
80
+ "retrying fresh since nothing was touched");
81
+ const fallback = await spawn(undefined, false);
82
+ const continuity = { mode: "fresh", declineReason: "resume-spawn-failed" };
83
+ safeObserve(observeContinuity, continuity);
84
+ return { result: fallback, continuity };
85
+ }
86
+ const continuityFromFirst = first.continuity ?? NO_SESSION_CAPTURED;
87
+ if (continuityFromFirst.mode !== "resumed") {
88
+ // The resume was declined before the spawn even happened (invokeAgent's
89
+ // own checks) — nothing to fall back from, the spawn already ran fresh.
90
+ safeObserve(observeContinuity, continuityFromFirst);
91
+ return { result: first, continuity: continuityFromFirst };
92
+ }
93
+ if (first.exitCode !== 0 && !resolveSummary(first.output).available) {
94
+ const isUntouched = await safeUntouched(untouched);
95
+ if (isUntouched) {
96
+ log("session continuity: the resumed spawn exited non-zero with no reply; retrying fresh");
97
+ const fallback = await spawn(undefined, false);
98
+ const continuity = { mode: "fresh", declineReason: "resume-spawn-failed" };
99
+ safeObserve(observeContinuity, continuity);
100
+ return { result: fallback, continuity };
101
+ }
102
+ }
103
+ safeObserve(observeContinuity, { mode: "resumed" });
104
+ return { result: first, continuity: { mode: "resumed" } };
105
+ }
106
+ async function safeUntouched(untouched) {
107
+ try {
108
+ return await untouched();
109
+ }
110
+ catch {
111
+ return false;
112
+ }
113
+ }
114
+ //# sourceMappingURL=agent-session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-session.js","sourceRoot":"","sources":["../src/agent-session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEpD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAG;IAC3C,wCAAwC;IACxC,EAAE;IACF,0EAA0E;IAC1E,4EAA4E;IAC5E,qEAAqE;IACrE,EAAE;CACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAyEb;;;2EAG2E;AAC3E,MAAM,UAAU,sBAAsB,CACpC,MAA4B,EAC5B,MAIC;IAED,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,qBAAqB;YACxB,OAAO,yDAAyD,CAAC;QACnE,KAAK,mBAAmB;YACtB,OAAO,MAAM,EAAE,eAAe,KAAK,SAAS,IAAI,MAAM,EAAE,WAAW,KAAK,SAAS;gBAC/E,CAAC,CAAC,YAAY,MAAM,CAAC,eAAe,2BAA2B,MAAM,CAAC,WAAW,IAAI;gBACrF,CAAC,CAAC,uDAAuD,CAAC;QAC9D,KAAK,qBAAqB;YACxB,OAAO,kDAAkD,CAAC;QAC5D,KAAK,cAAc;YACjB,OAAO,iCAAiC,CAAC;QAC3C,KAAK,8BAA8B;YACjC,OAAO,+CAA+C,CAAC;QACzD,KAAK,yBAAyB;YAC5B,OAAO,MAAM,EAAE,KAAK,KAAK,SAAS;gBAChC,CAAC,CAAC,qDAAqD,MAAM,CAAC,KAAK,KAAK;gBACxE,CAAC,CAAC,gDAAgD,CAAC;QACvD,KAAK,qBAAqB;YACxB,OAAO,mCAAmC,CAAC;IAC/C,CAAC;AACH,CAAC;AA6CD,MAAM,mBAAmB,GAAsB;IAC7C,IAAI,EAAE,OAAO;IACb,aAAa,EAAE,qBAAqB;CACrC,CAAC;AAEF,SAAS,WAAW,CAClB,iBAAwE,EACxE,UAA6B;IAE7B,IAAI,CAAC;QACH,iBAAiB,EAAE,CAAC,UAAU,CAAC,CAAC;IAClC,CAAC;IAAC,MAAM,CAAC;QACP,gEAAgE;IAClE,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAC9C,OAAiC;IAEjC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,iBAAiB,EAAE,GAAG,OAAO,CAAC;IAErE,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QAC7C,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,IAAI,mBAAmB,CAAC;QAC5D,WAAW,CAAC,iBAAiB,EAAE,UAAU,CAAC,CAAC;QAC3C,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;IAChC,CAAC;IAED,IAAI,KAAQ,CAAC;IACb,IAAI,CAAC;QACH,KAAK,GAAG,MAAM,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACpC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,WAAW,GAAG,MAAM,aAAa,CAAC,SAAS,CAAC,CAAC;QACnD,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,WAAW,CAAC,iBAAiB,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;YACpD,MAAM,KAAK,CAAC;QACd,CAAC;QACD,GAAG,CACD,0DAA2D,KAAe,CAAC,OAAO,KAAK;YACrF,0CAA0C,CAC7C,CAAC;QACF,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QAC/C,MAAM,UAAU,GAAsB,EAAE,IAAI,EAAE,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,CAAC;QAC9F,WAAW,CAAC,iBAAiB,EAAE,UAAU,CAAC,CAAC;QAC3C,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC;IAC1C,CAAC;IAED,MAAM,mBAAmB,GAAG,KAAK,CAAC,UAAU,IAAI,mBAAmB,CAAC;IACpE,IAAI,mBAAmB,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC3C,wEAAwE;QACxE,wEAAwE;QACxE,WAAW,CAAC,iBAAiB,EAAE,mBAAmB,CAAC,CAAC;QACpD,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,mBAAmB,EAAE,CAAC;IAC5D,CAAC;IAED,IAAI,KAAK,CAAC,QAAQ,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,SAAS,EAAE,CAAC;QACpE,MAAM,WAAW,GAAG,MAAM,aAAa,CAAC,SAAS,CAAC,CAAC;QACnD,IAAI,WAAW,EAAE,CAAC;YAChB,GAAG,CAAC,qFAAqF,CAAC,CAAC;YAC3F,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;YAC/C,MAAM,UAAU,GAAsB,EAAE,IAAI,EAAE,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,CAAC;YAC9F,WAAW,CAAC,iBAAiB,EAAE,UAAU,CAAC,CAAC;YAC3C,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC;QAC1C,CAAC;IACH,CAAC;IAED,WAAW,CAAC,iBAAiB,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;IACpD,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,CAAC;AAC5D,CAAC;AAED,KAAK,UAAU,aAAa,CAAC,SAAiC;IAC5D,IAAI,CAAC;QACH,OAAO,MAAM,SAAS,EAAE,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Write-temp-then-rename, shared by every runner-owned durable write
3
+ * (manifest, analytics artifact). Same-directory rename is atomic on POSIX
4
+ * and, via libuv's `MOVEFILE_REPLACE_EXISTING`, replaces atomically on
5
+ * Windows too — a crash mid-write can never leave a half-written artifact; a
6
+ * reader sees either the old file or the new one.
7
+ *
8
+ * `tempDir`, when given, is where the temp file is written before the
9
+ * rename — out of any staged/committed prefix (see the `build-logs-temp`
10
+ * decision), so a concurrent commit can never sweep up a stray `.tmp-*`
11
+ * file. If the rename across `tempDir` → `path` fails with `EXDEV` (an
12
+ * exotic layout where they live on different filesystems), this falls back
13
+ * once to a same-directory temp file rather than failing the write.
14
+ */
15
+ export declare function atomicWriteFile(path: string, contents: string, options?: {
16
+ tempDir?: string;
17
+ }): Promise<void>;
18
+ //# sourceMappingURL=atomic-write.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"atomic-write.d.ts","sourceRoot":"","sources":["../src/atomic-write.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;GAaG;AACH,wBAAsB,eAAe,CACnC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7B,OAAO,CAAC,IAAI,CAAC,CAgCf"}
@@ -0,0 +1,74 @@
1
+ import { randomBytes } from "node:crypto";
2
+ import { mkdir, rename, rm, writeFile } from "node:fs/promises";
3
+ import { dirname, join } from "node:path";
4
+ /**
5
+ * Write-temp-then-rename, shared by every runner-owned durable write
6
+ * (manifest, analytics artifact). Same-directory rename is atomic on POSIX
7
+ * and, via libuv's `MOVEFILE_REPLACE_EXISTING`, replaces atomically on
8
+ * Windows too — a crash mid-write can never leave a half-written artifact; a
9
+ * reader sees either the old file or the new one.
10
+ *
11
+ * `tempDir`, when given, is where the temp file is written before the
12
+ * rename — out of any staged/committed prefix (see the `build-logs-temp`
13
+ * decision), so a concurrent commit can never sweep up a stray `.tmp-*`
14
+ * file. If the rename across `tempDir` → `path` fails with `EXDEV` (an
15
+ * exotic layout where they live on different filesystems), this falls back
16
+ * once to a same-directory temp file rather than failing the write.
17
+ */
18
+ export async function atomicWriteFile(path, contents, options) {
19
+ const targetDir = dirname(path);
20
+ await mkdir(targetDir, { recursive: true });
21
+ const primaryDir = options?.tempDir ?? targetDir;
22
+ if (primaryDir !== targetDir)
23
+ await mkdir(primaryDir, { recursive: true });
24
+ const tmp = join(primaryDir, `.${randomId()}.tmp-${randomId()}`);
25
+ await writeFile(tmp, contents, "utf8");
26
+ try {
27
+ await renameWithRetry(tmp, path);
28
+ }
29
+ catch (error) {
30
+ if (primaryDir !== targetDir &&
31
+ error.code === "EXDEV") {
32
+ await rm(tmp, { force: true }).catch(() => undefined);
33
+ const fallbackTmp = join(targetDir, `.${randomId()}.tmp-${randomId()}`);
34
+ await writeFile(fallbackTmp, contents, "utf8");
35
+ try {
36
+ await renameWithRetry(fallbackTmp, path);
37
+ }
38
+ catch (fallbackError) {
39
+ await rm(fallbackTmp, { force: true }).catch(() => undefined);
40
+ throw fallbackError;
41
+ }
42
+ return;
43
+ }
44
+ // A failed rename must never leave an orphaned temp file behind for a
45
+ // later staged commit to sweep up as an untracked artifact.
46
+ await rm(tmp, { force: true }).catch(() => undefined);
47
+ throw error;
48
+ }
49
+ }
50
+ /**
51
+ * Windows-only wrinkle: replacing a file a reader currently holds open (an
52
+ * agent reading the manifest) fails with `EPERM`/`EBUSY` for the moment the
53
+ * handle is held; POSIX never does. A few short retries cover that window
54
+ * without masking a genuine permission problem.
55
+ */
56
+ async function renameWithRetry(from, to) {
57
+ const maxAttempts = 6;
58
+ for (let attempt = 1;; attempt += 1) {
59
+ try {
60
+ await rename(from, to);
61
+ return;
62
+ }
63
+ catch (error) {
64
+ const code = error.code;
65
+ if ((code !== "EPERM" && code !== "EBUSY") || attempt >= maxAttempts)
66
+ throw error;
67
+ await new Promise((resolveDelay) => setTimeout(resolveDelay, 20 * attempt));
68
+ }
69
+ }
70
+ }
71
+ function randomId() {
72
+ return randomBytes(8).toString("hex");
73
+ }
74
+ //# sourceMappingURL=atomic-write.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"atomic-write.js","sourceRoot":"","sources":["../src/atomic-write.ts"],"names":[],"mappings":"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"}
package/dist/author.d.ts CHANGED
@@ -1,9 +1,11 @@
1
1
  import { type AgentRunner } from "./agent-runner.js";
2
2
  import type { NightshiftConfig } from "./config.js";
3
3
  import { type PermitsContext } from "./permits.js";
4
+ import { type ProgramManifest, type Workstream } from "./manifest.js";
4
5
  import { type ReviewPassOutcome } from "./review-pass.js";
5
6
  import { type GitOps } from "./run-program.js";
6
- import { type RunRecorder } from "./run-analytics.js";
7
+ import { type SpanHandle, type SpanScope } from "./run-analytics.js";
8
+ import { type Mutex } from "./concurrency.js";
7
9
  export interface AuthorOptions {
8
10
  cwd: string;
9
11
  programId: string;
@@ -19,6 +21,23 @@ export interface AuthorOptions {
19
21
  * stage never builds its own. */
20
22
  permits?: PermitsContext;
21
23
  git?: GitOps;
24
+ /**
25
+ * The run's manifest object. When supplied, authoring mutates and persists
26
+ * *this* object rather than loading its own — so there is exactly one
27
+ * in-memory manifest per run and the build scheduler sees discovered
28
+ * dependency edges and `specStatus` transitions the instant an author makes
29
+ * them (WS-05 §3.4). Omitted by the standalone `author` CLI, which loads
30
+ * its own.
31
+ */
32
+ manifest?: ProgramManifest;
33
+ /**
34
+ * The run-scoped mutex guarding every operation that takes
35
+ * `.git/index.lock` in the root checkout (WS-05 §3.7). Supplied by
36
+ * `runProgram` so authoring's spec commits and WS-02's integration commits
37
+ * share one serializer. Omitted, authoring creates its own — correct for
38
+ * the standalone CLI, where nothing else commits.
39
+ */
40
+ rootIndexMutex?: Mutex;
22
41
  log?: (line: string) => void;
23
42
  now?: () => Date;
24
43
  /**
@@ -40,7 +59,34 @@ export interface AuthorOptions {
40
59
  * under the same run. A caller with no run-scoped recorder (a standalone
41
60
  * `author` CLI invocation, tests) gets a shared no-op default.
42
61
  */
43
- recorder?: RunRecorder;
62
+ recorder?: SpanScope;
63
+ /**
64
+ * Maximum authoring flows in flight at once. `undefined` or anything below
65
+ * 1 means unbounded — the dependency graph is the only serializer. `1`
66
+ * reproduces the pre-WS-03 serial behaviour exactly, including dispatch
67
+ * order and the absence of any deferred re-author (§3.3 of the spec).
68
+ * Filled from `run --max-parallel` by WS-04; this module never reads a CLI
69
+ * flag.
70
+ */
71
+ maxParallel?: number;
72
+ /**
73
+ * The run's `run` span (WS-01). When present, each authoring flow opens
74
+ * its spans through `runSpan.scope({ workstream })`, so a span is parented
75
+ * because the code said so and is stamped with its workstream even when
76
+ * the call site did not name one — never by whichever span happened to be
77
+ * open at that microsecond. Absent (the standalone `author` CLI, tests),
78
+ * spans go through `recorder` exactly as they do today.
79
+ */
80
+ runSpan?: SpanHandle;
81
+ /**
82
+ * Injectable monotonic clock; defaults to `performance.now()`. Measures
83
+ * the §3.3 dependency wait for `workstream-waiting`'s `waitedMs`.
84
+ * Deliberately separate from `now`, which is wall-clock and therefore not
85
+ * monotonic. `runProgram` passes the same `monotonic` it built its
86
+ * recorder's `RunClock` from, so a run's authoring waits and its span
87
+ * offsets are measured on one timebase; tests inject a counter.
88
+ */
89
+ monotonic?: () => number;
44
90
  }
45
91
  export type AuthorOutcome = {
46
92
  status: "authored";
@@ -90,10 +136,70 @@ export interface AuthorStageResult {
90
136
  borrowedImplementer: boolean;
91
137
  }
92
138
  /**
93
- * The authoring stage: writes every missing workstream spec, one clean agent
94
- * at a time, in dependency-level order. Shaped like `runProgram` plain
95
- * inputs, injected boundaries, a structured result the CLI and `run` both
96
- * consume.
139
+ * Everything `authorProgram` does *around* its per-workstream loop: agent
140
+ * resolution and its three stage-level log lines, the cycle check, `--from`
141
+ * validation into the selected set, the repository check, and the run-scoped
142
+ * state WS-03 shares across flows (the settled/dispatched sets and their
143
+ * deferreds, the graph mutex, the flow scopes). See WS-05 §3.3.
144
+ */
145
+ export interface AuthoringPipeline {
146
+ /** True when no `authorAgent` was configured and the implementer stood in. */
147
+ readonly borrowedImplementer: boolean;
148
+ /**
149
+ * The manifest object this pipeline authors against — `options.manifest`
150
+ * when supplied, otherwise the one this call loaded itself. Exposed so a
151
+ * caller driving its own scheduler (this module's own `authorProgram`, or
152
+ * `runProgram`'s unified one) reads `dependencies` off the exact same live
153
+ * objects `authorWorkstream` mutates.
154
+ */
155
+ readonly manifest: ProgramManifest;
156
+ /**
157
+ * One workstream's authoring flow: WS-03's `handle`, wrapped in WS-03's
158
+ * dispatch/settle bookkeeping so the deferred re-author (WS-03 §3.3) keeps
159
+ * working. Call exactly once per workstream in the roster — including
160
+ * out-of-selection keeps and cone-parked ones, whose `handle`
161
+ * short-circuits in microseconds. Never throws for a workstream-level
162
+ * failure; it returns an `AuthorResult`. A throw is an unexpected error
163
+ * and drains the run, exactly as it does today.
164
+ */
165
+ authorWorkstream(workstream: Workstream): Promise<AuthorResult>;
166
+ /**
167
+ * Records a workstream's authoring flow as settled without running it —
168
+ * the environmental-halt branch (WS-05 §3.6): `handle` never runs, so
169
+ * nothing is spawned and `specStatus` is left exactly as it stood before
170
+ * this run (no manifest write on this branch, mirroring WS-04's own halt
171
+ * branch for a build item). Marks the workstream dispatched and settled
172
+ * exactly like `authorWorkstream`, resolving its settle deferred, so a
173
+ * sibling's deferred re-author waiting on it is released with the same
174
+ * not-final answer a parked dependency already gives `specFinal`.
175
+ * Deliberately synchronous and side-effect-free beyond that bookkeeping —
176
+ * the caller decides `reason`, since only it knows why the run halted.
177
+ */
178
+ haltAuthorWorkstream(workstream: Workstream, reason: string): AuthorResult;
179
+ /**
180
+ * The stage result, assembled from every recorded `AuthorResult` in
181
+ * `stableTopologicalOrder` of the final roster (WS-03 §3.8). Call once,
182
+ * after every workstream has been through `authorWorkstream` or
183
+ * `haltAuthorWorkstream`.
184
+ */
185
+ finish(): AuthorStageResult;
186
+ }
187
+ /**
188
+ * Throws for exactly the reasons `authorProgram` throws today — no author
189
+ * agent configured, a cyclic manifest, an unknown `--from` id — and throws
190
+ * them before any agent spawns, so a caller that never reaches the scheduler
191
+ * fails identically to today.
192
+ */
193
+ export declare function prepareAuthoring(options: AuthorOptions): Promise<AuthoringPipeline>;
194
+ /**
195
+ * The authoring stage, standalone: writes every missing workstream spec, one
196
+ * clean agent at a time, in dependency order, at `--max-parallel`'s cap —
197
+ * `runReadySet` over `manifest.workstreams` directly, the same scheduler
198
+ * `runProgram`'s unified pipeline (WS-05 §3.1) drives, just with only one
199
+ * kind of item. `--max-parallel 1` reproduces the pre-WS-03 serial behaviour
200
+ * exactly, including dispatch order and the absence of any deferred
201
+ * re-author. This module no longer contains a hand-written scheduler of its
202
+ * own (WS-04 §8, WS-05 §3.3): one implementation, two callers.
97
203
  */
98
204
  export declare function authorProgram(options: AuthorOptions): Promise<AuthorStageResult>;
99
205
  //# sourceMappingURL=author.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"author.d.ts","sourceRoot":"","sources":["../src/author.ts"],"names":[],"mappings":"AAEA,OAAO,EAOL,KAAK,WAAW,EAEjB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,KAAK,EAAe,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,EAAwB,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AAkBzE,OAAO,EASL,KAAK,iBAAiB,EAEvB,MAAM,kBAAkB,CAAC;AAO1B,OAAO,EAAwD,KAAK,MAAM,EAAE,MAAM,kBAAkB,CAAC;AACrG,OAAO,EAAqB,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAezE,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,gBAAgB,CAAC;IACzB;iFAC6E;IAC7E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,iFAAiF;IACjF,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B;;sCAEkC;IAClC,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7B,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;IACjB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACvB;;;;OAIG;IACH,OAAO,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACtB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,WAAW,CAAC;CACxB;AAED,MAAM,MAAM,aAAa,GACrB;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GACvC;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,GAClB;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACpC;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzC,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,aAAa,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,gEAAgE;IAChE,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,+EAA+E;IAC/E,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,qEAAqE;IACrE,oBAAoB,EAAE,MAAM,EAAE,CAAC;IAC/B,uEAAuE;IACvE,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,8FAA8F;IAC9F,UAAU,EAAE,OAAO,CAAC;IACpB,gFAAgF;IAChF,YAAY,CAAC,EAAE,iBAAiB,CAAC;IACjC;;sDAEkD;IAClD,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB;;kEAE8D;IAC9D,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,kEAAkE;IAClE,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,8EAA8E;IAC9E,mBAAmB,EAAE,OAAO,CAAC;CAC9B;AAyvBD;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,iBAAiB,CAAC,CA2nB5B"}
1
+ {"version":3,"file":"author.d.ts","sourceRoot":"","sources":["../src/author.ts"],"names":[],"mappings":"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"}