@matteeh/osq 0.1.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 (140) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +183 -0
  3. package/dist/cli/approve.d.ts +6 -0
  4. package/dist/cli/approve.d.ts.map +1 -0
  5. package/dist/cli/approve.js +26 -0
  6. package/dist/cli/approve.js.map +1 -0
  7. package/dist/cli/bin.d.ts +3 -0
  8. package/dist/cli/bin.d.ts.map +1 -0
  9. package/dist/cli/bin.js +5 -0
  10. package/dist/cli/bin.js.map +1 -0
  11. package/dist/cli/index.d.ts +4 -0
  12. package/dist/cli/index.d.ts.map +1 -0
  13. package/dist/cli/index.js +76 -0
  14. package/dist/cli/index.js.map +1 -0
  15. package/dist/cli/init.d.ts +4 -0
  16. package/dist/cli/init.d.ts.map +1 -0
  17. package/dist/cli/init.js +19 -0
  18. package/dist/cli/init.js.map +1 -0
  19. package/dist/cli/new.d.ts +4 -0
  20. package/dist/cli/new.d.ts.map +1 -0
  21. package/dist/cli/new.js +15 -0
  22. package/dist/cli/new.js.map +1 -0
  23. package/dist/cli/report.d.ts +10 -0
  24. package/dist/cli/report.d.ts.map +1 -0
  25. package/dist/cli/report.js +84 -0
  26. package/dist/cli/report.js.map +1 -0
  27. package/dist/cli/setup.d.ts +2 -0
  28. package/dist/cli/setup.d.ts.map +1 -0
  29. package/dist/cli/setup.js +10 -0
  30. package/dist/cli/setup.js.map +1 -0
  31. package/dist/cli/show.d.ts +7 -0
  32. package/dist/cli/show.d.ts.map +1 -0
  33. package/dist/cli/show.js +27 -0
  34. package/dist/cli/show.js.map +1 -0
  35. package/dist/cli/status.d.ts +7 -0
  36. package/dist/cli/status.d.ts.map +1 -0
  37. package/dist/cli/status.js +23 -0
  38. package/dist/cli/status.js.map +1 -0
  39. package/dist/cli/watch.d.ts +9 -0
  40. package/dist/cli/watch.d.ts.map +1 -0
  41. package/dist/cli/watch.js +20 -0
  42. package/dist/cli/watch.js.map +1 -0
  43. package/dist/core/approve.d.ts +11 -0
  44. package/dist/core/approve.d.ts.map +1 -0
  45. package/dist/core/approve.js +52 -0
  46. package/dist/core/approve.js.map +1 -0
  47. package/dist/core/config.d.ts +53 -0
  48. package/dist/core/config.d.ts.map +1 -0
  49. package/dist/core/config.js +124 -0
  50. package/dist/core/config.js.map +1 -0
  51. package/dist/core/hasher.d.ts +4 -0
  52. package/dist/core/hasher.d.ts.map +1 -0
  53. package/dist/core/hasher.js +49 -0
  54. package/dist/core/hasher.js.map +1 -0
  55. package/dist/core/init.d.ts +12 -0
  56. package/dist/core/init.d.ts.map +1 -0
  57. package/dist/core/init.js +151 -0
  58. package/dist/core/init.js.map +1 -0
  59. package/dist/core/linter.d.ts +8 -0
  60. package/dist/core/linter.d.ts.map +1 -0
  61. package/dist/core/linter.js +100 -0
  62. package/dist/core/linter.js.map +1 -0
  63. package/dist/core/lock.d.ts +17 -0
  64. package/dist/core/lock.d.ts.map +1 -0
  65. package/dist/core/lock.js +104 -0
  66. package/dist/core/lock.js.map +1 -0
  67. package/dist/core/logger.d.ts +32 -0
  68. package/dist/core/logger.d.ts.map +1 -0
  69. package/dist/core/logger.js +106 -0
  70. package/dist/core/logger.js.map +1 -0
  71. package/dist/core/new.d.ts +11 -0
  72. package/dist/core/new.d.ts.map +1 -0
  73. package/dist/core/new.js +79 -0
  74. package/dist/core/new.js.map +1 -0
  75. package/dist/core/parser.d.ts +32 -0
  76. package/dist/core/parser.d.ts.map +1 -0
  77. package/dist/core/parser.js +87 -0
  78. package/dist/core/parser.js.map +1 -0
  79. package/dist/core/report.d.ts +54 -0
  80. package/dist/core/report.d.ts.map +1 -0
  81. package/dist/core/report.js +475 -0
  82. package/dist/core/report.js.map +1 -0
  83. package/dist/core/show.d.ts +50 -0
  84. package/dist/core/show.d.ts.map +1 -0
  85. package/dist/core/show.js +374 -0
  86. package/dist/core/show.js.map +1 -0
  87. package/dist/core/state.d.ts +25 -0
  88. package/dist/core/state.d.ts.map +1 -0
  89. package/dist/core/state.js +180 -0
  90. package/dist/core/state.js.map +1 -0
  91. package/dist/core/status.d.ts +10 -0
  92. package/dist/core/status.d.ts.map +1 -0
  93. package/dist/core/status.js +106 -0
  94. package/dist/core/status.js.map +1 -0
  95. package/dist/harness/agy.d.ts +31 -0
  96. package/dist/harness/agy.d.ts.map +1 -0
  97. package/dist/harness/agy.js +251 -0
  98. package/dist/harness/agy.js.map +1 -0
  99. package/dist/harness/index.d.ts +7 -0
  100. package/dist/harness/index.d.ts.map +1 -0
  101. package/dist/harness/index.js +20 -0
  102. package/dist/harness/index.js.map +1 -0
  103. package/dist/harness/mock.d.ts +19 -0
  104. package/dist/harness/mock.d.ts.map +1 -0
  105. package/dist/harness/mock.js +62 -0
  106. package/dist/harness/mock.js.map +1 -0
  107. package/dist/harness/opencode.d.ts +39 -0
  108. package/dist/harness/opencode.d.ts.map +1 -0
  109. package/dist/harness/opencode.js +394 -0
  110. package/dist/harness/opencode.js.map +1 -0
  111. package/dist/harness/process.d.ts +26 -0
  112. package/dist/harness/process.d.ts.map +1 -0
  113. package/dist/harness/process.js +99 -0
  114. package/dist/harness/process.js.map +1 -0
  115. package/dist/harness/stream.d.ts +34 -0
  116. package/dist/harness/stream.d.ts.map +1 -0
  117. package/dist/harness/stream.js +75 -0
  118. package/dist/harness/stream.js.map +1 -0
  119. package/dist/harness/types.d.ts +53 -0
  120. package/dist/harness/types.d.ts.map +1 -0
  121. package/dist/harness/types.js +10 -0
  122. package/dist/harness/types.js.map +1 -0
  123. package/dist/index.d.ts +3 -0
  124. package/dist/index.d.ts.map +1 -0
  125. package/dist/index.js +2 -0
  126. package/dist/index.js.map +1 -0
  127. package/dist/watcher/archiver.d.ts +5 -0
  128. package/dist/watcher/archiver.d.ts.map +1 -0
  129. package/dist/watcher/archiver.js +66 -0
  130. package/dist/watcher/archiver.js.map +1 -0
  131. package/dist/watcher/loop.d.ts +34 -0
  132. package/dist/watcher/loop.d.ts.map +1 -0
  133. package/dist/watcher/loop.js +235 -0
  134. package/dist/watcher/loop.js.map +1 -0
  135. package/dist/watcher/runner.d.ts +70 -0
  136. package/dist/watcher/runner.d.ts.map +1 -0
  137. package/dist/watcher/runner.js +604 -0
  138. package/dist/watcher/runner.js.map +1 -0
  139. package/package.json +66 -0
  140. package/templates/.env.example +3 -0
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Shared harness stream helpers. Harness adapters translate an unbounded stdout
3
+ * stream of JSON lines into `events.jsonl`; the record coercion, string picking,
4
+ * timestamp resolution, and line buffering are identical across adapters and
5
+ * live here so each adapter only owns its event translation.
6
+ */
7
+ /** Coerce an unknown JSON value into a plain object, or `undefined` for arrays and primitives. */
8
+ export function asRecord(value) {
9
+ return value && typeof value === 'object' && !Array.isArray(value)
10
+ ? value
11
+ : undefined;
12
+ }
13
+ /** Return the first candidate that is a non-empty string, skipping every other type. */
14
+ export function firstNonEmptyString(...values) {
15
+ for (const value of values) {
16
+ if (typeof value === 'string' && value.length > 0) {
17
+ return value;
18
+ }
19
+ }
20
+ return undefined;
21
+ }
22
+ /**
23
+ * Resolve an event timestamp to ISO form. Harnesses report either a top-level
24
+ * `timestamp` or, for Antigravity step updates, a nested `step_update.timestamp`.
25
+ * Invalid or missing timestamps fall back to the current time so an event is
26
+ * never written without one.
27
+ */
28
+ export function resolveEventTimestamp(eventObj) {
29
+ const stepUpdate = asRecord(eventObj.step_update);
30
+ const candidate = eventObj.timestamp ?? stepUpdate?.timestamp;
31
+ if (typeof candidate === 'number' || typeof candidate === 'string') {
32
+ const date = new Date(candidate);
33
+ if (!Number.isNaN(date.getTime())) {
34
+ return date.toISOString();
35
+ }
36
+ }
37
+ return new Date().toISOString();
38
+ }
39
+ /**
40
+ * Buffers arbitrarily chunked stdout and delivers complete, non-blank lines to
41
+ * an async handler one at a time in arrival order. A handler rejection is
42
+ * swallowed so a single malformed line can never abort the rest of the stream;
43
+ * `flush` drains whatever partial line remains and resolves after every queued
44
+ * handler has settled.
45
+ */
46
+ export class EventStreamParser {
47
+ onLine;
48
+ buffer = '';
49
+ pending = Promise.resolve();
50
+ constructor(onLine) {
51
+ this.onLine = onLine;
52
+ }
53
+ feed(chunk) {
54
+ this.buffer += chunk;
55
+ const lines = this.buffer.split('\n');
56
+ this.buffer = lines.pop() ?? '';
57
+ for (const line of lines) {
58
+ this.enqueue(line);
59
+ }
60
+ }
61
+ async flush() {
62
+ if (this.buffer.trim()) {
63
+ this.enqueue(this.buffer);
64
+ }
65
+ this.buffer = '';
66
+ await this.pending;
67
+ }
68
+ enqueue(line) {
69
+ if (!line.trim()) {
70
+ return;
71
+ }
72
+ this.pending = this.pending.then(() => this.onLine(line).catch(() => { }));
73
+ }
74
+ }
75
+ //# sourceMappingURL=stream.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream.js","sourceRoot":"","sources":["../../src/harness/stream.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,kGAAkG;AAClG,MAAM,UAAU,QAAQ,CAAC,KAAc;IACrC,OAAO,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAChE,CAAC,CAAE,KAAiC;QACpC,CAAC,CAAC,SAAS,CAAC;AAChB,CAAC;AAED,wFAAwF;AACxF,MAAM,UAAU,mBAAmB,CAAC,GAAG,MAAiB;IACtD,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAClD,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB,CAAC,QAAiC;IACrE,MAAM,UAAU,GAAG,QAAQ,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IAClD,MAAM,SAAS,GAAG,QAAQ,CAAC,SAAS,IAAI,UAAU,EAAE,SAAS,CAAC;IAC9D,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,OAAO,SAAS,KAAK,QAAQ,EAAE,CAAC;QACnE,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC;QACjC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC;YAClC,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC;QAC5B,CAAC;IACH,CAAC;IACD,OAAO,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AAClC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,OAAO,iBAAiB;IAIC;IAHrB,MAAM,GAAG,EAAE,CAAC;IACZ,OAAO,GAAkB,OAAO,CAAC,OAAO,EAAE,CAAC;IAEnD,YAA6B,MAAuC;QAAvC,WAAM,GAAN,MAAM,CAAiC;IAAG,CAAC;IAExE,IAAI,CAAC,KAAa;QAChB,IAAI,CAAC,MAAM,IAAI,KAAK,CAAC;QACrB,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACtC,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;QAEhC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACrB,CAAC;IACH,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;YACvB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC5B,CAAC;QACD,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC;QACjB,MAAM,IAAI,CAAC,OAAO,CAAC;IACrB,CAAC;IAEO,OAAO,CAAC,IAAY;QAC1B,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;YACjB,OAAO;QACT,CAAC;QACD,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC,CAAC;IAC5E,CAAC;CACF"}
@@ -0,0 +1,53 @@
1
+ import type { OsqConfig } from '../core/config.js';
2
+ import type { Logger } from '../core/logger.js';
3
+ export type HarnessEventType = 'started' | 'tokens' | 'tool' | 'text' | 'file_changed' | 'verify_ran' | 'result_written' | 'exited' | 'done' | 'dead';
4
+ export interface ToolEventData {
5
+ tool: string;
6
+ summary: string;
7
+ }
8
+ export interface TextEventData {
9
+ readonly text: string;
10
+ }
11
+ export interface DoneEventData {
12
+ readonly task: string;
13
+ }
14
+ export interface DeadEventData {
15
+ readonly task: string;
16
+ readonly reason: string;
17
+ }
18
+ export interface HarnessEvent {
19
+ type: HarnessEventType;
20
+ timestamp: string;
21
+ data?: Record<string, unknown>;
22
+ }
23
+ export interface SpawnTaskOptions {
24
+ projectRoot: string;
25
+ specFolderPath: string;
26
+ taskNumber: string;
27
+ taskTitle: string;
28
+ verifyCommand: string;
29
+ scope: string[];
30
+ entry: string[];
31
+ skills: string[];
32
+ tier: 'coding' | 'smart';
33
+ timeoutSeconds?: number;
34
+ config?: OsqConfig;
35
+ logger?: Logger;
36
+ onSpawn?: (pid: number) => Promise<void> | void;
37
+ }
38
+ export interface SpawnResult {
39
+ exitCode: number;
40
+ error?: string;
41
+ timedOut?: boolean;
42
+ signal?: NodeJS.Signals | string | null;
43
+ pid?: number;
44
+ elapsedMs?: number;
45
+ }
46
+ export interface HarnessAdapter {
47
+ readonly name: string;
48
+ setup(projectRoot: string, config: OsqConfig): Promise<void>;
49
+ spawn(options: SpawnTaskOptions): Promise<SpawnResult>;
50
+ preflight?(projectRoot: string, config: OsqConfig): Promise<void>;
51
+ }
52
+ export declare function appendHarnessEvent(specFolderPath: string, taskNumber: string, event: HarnessEvent): Promise<void>;
53
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/harness/types.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAEhD,MAAM,MAAM,gBAAgB,GACxB,SAAS,GACT,QAAQ,GACR,MAAM,GACN,MAAM,GACN,cAAc,GACd,YAAY,GACZ,gBAAgB,GAChB,QAAQ,GACR,MAAM,GACN,MAAM,CAAC;AAEX,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,gBAAgB,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CACjD;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC,OAAO,GAAG,MAAM,GAAG,IAAI,CAAC;IACxC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7D,KAAK,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IACvD,SAAS,CAAC,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACnE;AAED,wBAAsB,kBAAkB,CACtC,cAAc,EAAE,MAAM,EACtB,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,YAAY,GAClB,OAAO,CAAC,IAAI,CAAC,CAOf"}
@@ -0,0 +1,10 @@
1
+ import fs from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ export async function appendHarnessEvent(specFolderPath, taskNumber, event) {
4
+ const eventsDir = path.join(specFolderPath, '.run', 'events');
5
+ await fs.mkdir(eventsDir, { recursive: true });
6
+ const eventFilePath = path.join(eventsDir, `${taskNumber}.jsonl`);
7
+ const line = `${JSON.stringify(event)}\n`;
8
+ await fs.appendFile(eventFilePath, line, 'utf8');
9
+ }
10
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/harness/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAwE7B,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,cAAsB,EACtB,UAAkB,EAClB,KAAmB;IAEnB,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC9D,MAAM,EAAE,CAAC,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE/C,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,UAAU,QAAQ,CAAC,CAAC;IAClE,MAAM,IAAI,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC;IAC1C,MAAM,EAAE,CAAC,UAAU,CAAC,aAAa,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;AACnD,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { DEFAULT_CONFIG, defineConfig, loadConfig } from './core/config.js';
2
+ export type { AgyConfig, LogConfig, OpencodeConfig, OsqConfig, OsqLimits, OsqPaths, OsqTimeouts, OsqUserConfig, } from './core/config.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC5E,YAAY,EACV,SAAS,EACT,SAAS,EACT,cAAc,EACd,SAAS,EACT,SAAS,EACT,QAAQ,EACR,WAAW,EACX,aAAa,GACd,MAAM,kBAAkB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export { DEFAULT_CONFIG, defineConfig, loadConfig } from './core/config.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { OsqConfig } from '../core/config.js';
2
+ export declare function applyDelta(projectRoot: string, specFolderPath: string, config: OsqConfig): Promise<void>;
3
+ export declare function archiveSpecFolder(projectRoot: string, specFolderPath: string, config: OsqConfig): Promise<string>;
4
+ export declare function checkAndArchiveSpec(projectRoot: string, specFolderPath: string, config: OsqConfig): Promise<boolean>;
5
+ //# sourceMappingURL=archiver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"archiver.d.ts","sourceRoot":"","sources":["../../src/watcher/archiver.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAInD,wBAAsB,UAAU,CAC9B,WAAW,EAAE,MAAM,EACnB,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,SAAS,GAChB,OAAO,CAAC,IAAI,CAAC,CAqCf;AAED,wBAAsB,iBAAiB,CACrC,WAAW,EAAE,MAAM,EACnB,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,SAAS,GAChB,OAAO,CAAC,MAAM,CAAC,CAoBjB;AAED,wBAAsB,mBAAmB,CACvC,WAAW,EAAE,MAAM,EACnB,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,SAAS,GAChB,OAAO,CAAC,OAAO,CAAC,CASlB"}
@@ -0,0 +1,66 @@
1
+ import fs from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { parseSpecMd } from '../core/parser.js';
4
+ import { deriveSpecState } from '../core/state.js';
5
+ export async function applyDelta(projectRoot, specFolderPath, config) {
6
+ const specMdPath = path.join(specFolderPath, 'spec.md');
7
+ let specContent = '';
8
+ try {
9
+ specContent = await fs.readFile(specMdPath, 'utf8');
10
+ }
11
+ catch {
12
+ return;
13
+ }
14
+ const specData = parseSpecMd(specContent);
15
+ if (!specData.delta.trim() || specData.features.writes.length === 0) {
16
+ return;
17
+ }
18
+ const featuresDir = path.join(projectRoot, config.paths.features);
19
+ await fs.mkdir(featuresDir, { recursive: true });
20
+ for (const featureName of specData.features.writes) {
21
+ const featurePath = path.join(featuresDir, `${featureName}.md`);
22
+ let existing = '';
23
+ try {
24
+ existing = await fs.readFile(featurePath, 'utf8');
25
+ }
26
+ catch { }
27
+ let updatedContent = '';
28
+ if (!existing.trim()) {
29
+ const titleWords = featureName
30
+ .split('-')
31
+ .map((w) => w.charAt(0).toUpperCase() + w.slice(1))
32
+ .join(' ');
33
+ updatedContent = `# ${titleWords}\n\n${specData.delta}\n`;
34
+ }
35
+ else {
36
+ updatedContent = `${existing.trim()}\n\n## Delta from ${specData.title}\n\n${specData.delta}\n`;
37
+ }
38
+ await fs.writeFile(featurePath, updatedContent, 'utf8');
39
+ }
40
+ }
41
+ export async function archiveSpecFolder(projectRoot, specFolderPath, config) {
42
+ const archiveDir = path.join(projectRoot, config.paths.archive);
43
+ await fs.mkdir(archiveDir, { recursive: true });
44
+ const folderName = path.basename(specFolderPath);
45
+ let targetPath = path.join(archiveDir, folderName);
46
+ let counter = 1;
47
+ while (await fs
48
+ .stat(targetPath)
49
+ .then(() => true)
50
+ .catch(() => false)) {
51
+ targetPath = path.join(archiveDir, `${folderName}-${counter}`);
52
+ counter++;
53
+ }
54
+ await fs.rename(specFolderPath, targetPath);
55
+ return targetPath;
56
+ }
57
+ export async function checkAndArchiveSpec(projectRoot, specFolderPath, config) {
58
+ const specState = await deriveSpecState(projectRoot, specFolderPath);
59
+ if (specState.status !== 'done') {
60
+ return false;
61
+ }
62
+ await applyDelta(projectRoot, specFolderPath, config);
63
+ await archiveSpecFolder(projectRoot, specFolderPath, config);
64
+ return true;
65
+ }
66
+ //# sourceMappingURL=archiver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"archiver.js","sourceRoot":"","sources":["../../src/watcher/archiver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ import type { OsqConfig } from '../core/config.js';
2
+ import { type Logger } from '../core/logger.js';
3
+ import type { HarnessAdapter } from '../harness/types.js';
4
+ export interface WatcherSummary {
5
+ tasksRun: number;
6
+ specsArchived: number;
7
+ }
8
+ export interface StartWatcherOptions {
9
+ once?: boolean;
10
+ pollIntervalMs?: number;
11
+ signal?: AbortSignal;
12
+ logger?: Logger;
13
+ }
14
+ export interface ArchivedSpecSummary {
15
+ id: string;
16
+ folder: string;
17
+ archivedAt: number;
18
+ }
19
+ export declare function formatAgo(ms: number): string;
20
+ /**
21
+ * Single idle status line: the watched spec directory, how many approved specs
22
+ * are still waiting, and when the last spec was archived. Pure so the exact
23
+ * shape is testable without a watcher.
24
+ */
25
+ export declare function formatIdleStatus(specsDir: string, approvedWaiting: number, lastArchived?: ArchivedSpecSummary, now?: number): string;
26
+ /**
27
+ * Most recently archived spec folder, derived from the archive directory's
28
+ * modification times so the idle status survives a watcher restart.
29
+ */
30
+ export declare function findLatestArchivedSpec(projectRoot: string, config: OsqConfig): Promise<ArchivedSpecSummary | undefined>;
31
+ export declare function runWatcherCycle(projectRoot: string, config: OsqConfig, adapter: HarnessAdapter, logger?: Logger): Promise<WatcherSummary>;
32
+ export declare function runWatcherOnce(projectRoot: string, config: OsqConfig, adapter: HarnessAdapter, logger?: Logger): Promise<WatcherSummary>;
33
+ export declare function startWatcher(projectRoot: string, config: OsqConfig, adapter: HarnessAdapter, options?: StartWatcherOptions): Promise<void>;
34
+ //# sourceMappingURL=loop.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loop.d.ts","sourceRoot":"","sources":["../../src/watcher/loop.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAEnD,OAAO,EAAE,KAAK,MAAM,EAAiB,MAAM,mBAAmB,CAAC;AAG/D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAO1D,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAS5C;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,MAAM,EAChB,eAAe,EAAE,MAAM,EACvB,YAAY,CAAC,EAAE,mBAAmB,EAClC,GAAG,GAAE,MAAmB,GACvB,MAAM,CAKR;AAED;;;GAGG;AACH,wBAAsB,sBAAsB,CAC1C,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,SAAS,GAChB,OAAO,CAAC,mBAAmB,GAAG,SAAS,CAAC,CAyB1C;AAUD,wBAAsB,eAAe,CACnC,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,cAAc,EACvB,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,cAAc,CAAC,CAmFzB;AAED,wBAAsB,cAAc,CAClC,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,cAAc,EACvB,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,cAAc,CAAC,CAezB;AAED,wBAAsB,YAAY,CAChC,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,cAAc,EACvB,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,IAAI,CAAC,CAuFf"}
@@ -0,0 +1,235 @@
1
+ import fs from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { watch } from 'chokidar';
4
+ import { reapStaleLocks } from '../core/lock.js';
5
+ import { resolveSymbol } from '../core/logger.js';
6
+ import { compareNumericPrefix, deriveSpecState } from '../core/state.js';
7
+ import { preflightOpencode } from '../harness/opencode.js';
8
+ import { checkAndArchiveSpec } from './archiver.js';
9
+ import { runTask } from './runner.js';
10
+ const SHOW_CURSOR = '\x1b[?25h';
11
+ const EXIT_SIGINT = 130;
12
+ export function formatAgo(ms) {
13
+ const seconds = Math.max(0, Math.floor(ms / 1000));
14
+ if (seconds < 60)
15
+ return `${seconds}s ago`;
16
+ const minutes = Math.floor(seconds / 60);
17
+ if (minutes < 60)
18
+ return `${minutes}m ago`;
19
+ const hours = Math.floor(minutes / 60);
20
+ if (hours < 24)
21
+ return `${hours}h ago`;
22
+ const days = Math.floor(hours / 24);
23
+ return `${days}d ago`;
24
+ }
25
+ /**
26
+ * Single idle status line: the watched spec directory, how many approved specs
27
+ * are still waiting, and when the last spec was archived. Pure so the exact
28
+ * shape is testable without a watcher.
29
+ */
30
+ export function formatIdleStatus(specsDir, approvedWaiting, lastArchived, now = Date.now()) {
31
+ const last = lastArchived
32
+ ? `last: ${lastArchived.id} archived ${formatAgo(now - lastArchived.archivedAt)}`
33
+ : 'last: none';
34
+ return `watching ${specsDir} · ${approvedWaiting} approved waiting · ${last}`;
35
+ }
36
+ /**
37
+ * Most recently archived spec folder, derived from the archive directory's
38
+ * modification times so the idle status survives a watcher restart.
39
+ */
40
+ export async function findLatestArchivedSpec(projectRoot, config) {
41
+ const archiveDir = path.join(projectRoot, config.paths.archive);
42
+ let entries = [];
43
+ try {
44
+ entries = await fs.readdir(archiveDir, { withFileTypes: true });
45
+ }
46
+ catch {
47
+ return undefined;
48
+ }
49
+ let latest;
50
+ for (const entry of entries) {
51
+ if (!entry.isDirectory())
52
+ continue;
53
+ const stat = await fs.stat(path.join(archiveDir, entry.name)).catch(() => null);
54
+ if (!stat)
55
+ continue;
56
+ const summary = {
57
+ id: entry.name.match(/^(\d+)/)?.[1] ?? entry.name,
58
+ folder: entry.name,
59
+ archivedAt: stat.mtimeMs,
60
+ };
61
+ if (!latest || summary.archivedAt > latest.archivedAt) {
62
+ latest = summary;
63
+ }
64
+ }
65
+ return latest;
66
+ }
67
+ function errorMessage(err) {
68
+ return err instanceof Error ? err.message : String(err);
69
+ }
70
+ function logWatcherError(logger, useSymbols, err) {
71
+ logger?.error(`${resolveSymbol('✗', '[error]', useSymbols)} watcher error: ${errorMessage(err)}`);
72
+ }
73
+ export async function runWatcherCycle(projectRoot, config, adapter, logger) {
74
+ const useSymbols = logger?.symbols === true;
75
+ const tag = (symbol, word) => resolveSymbol(symbol, word, useSymbols);
76
+ const specsDir = path.join(projectRoot, config.paths.specs);
77
+ let entries = [];
78
+ try {
79
+ entries = await fs.readdir(specsDir);
80
+ }
81
+ catch {
82
+ logger?.status(formatIdleStatus(config.paths.specs, 0));
83
+ return { tasksRun: 0, specsArchived: 0 };
84
+ }
85
+ const specFolders = entries
86
+ .filter((e) => !e.startsWith('_') && e !== 'archive')
87
+ .sort(compareNumericPrefix);
88
+ let tasksRun = 0;
89
+ let specsArchived = 0;
90
+ let approvedWaiting = 0;
91
+ for (const folder of specFolders) {
92
+ const folderPath = path.join(specsDir, folder);
93
+ try {
94
+ const stat = await fs.stat(folderPath).catch(() => null);
95
+ if (!stat || !stat.isDirectory())
96
+ continue;
97
+ await reapStaleLocks(folderPath, config.timeouts.staleLockSeconds);
98
+ const specState = await deriveSpecState(projectRoot, folderPath);
99
+ if (specState.approvedHash &&
100
+ (specState.status === 'pending' ||
101
+ specState.status === 'running' ||
102
+ specState.status === 'blocked')) {
103
+ approvedWaiting++;
104
+ }
105
+ if (specState.status === 'pending' && specState.nextTask) {
106
+ const taskNumber = specState.nextTask.taskNumber;
107
+ logger?.info(`${tag('▶ spec', '[spec]')} ${specState.id} picked up (${folder})`);
108
+ const taskResult = await runTask(projectRoot, folderPath, taskNumber, config, adapter, logger);
109
+ tasksRun++;
110
+ if (taskResult.success) {
111
+ const archived = await checkAndArchiveSpec(projectRoot, folderPath, config);
112
+ if (archived) {
113
+ specsArchived++;
114
+ logger?.info(`${tag('✓ spec', '[archived]')} ${specState.id} archived (${folder})`);
115
+ }
116
+ }
117
+ else {
118
+ logger?.info(`${tag('■ spec', '[halted]')} ${specState.id} halted (task ${taskNumber} dead)`);
119
+ }
120
+ }
121
+ else if (specState.status === 'done') {
122
+ const archived = await checkAndArchiveSpec(projectRoot, folderPath, config);
123
+ if (archived) {
124
+ specsArchived++;
125
+ logger?.info(`${tag('✓ spec', '[archived]')} ${specState.id} archived (${folder})`);
126
+ }
127
+ }
128
+ }
129
+ catch (err) {
130
+ logWatcherError(logger, useSymbols, err);
131
+ }
132
+ }
133
+ if (tasksRun === 0) {
134
+ const lastArchived = await findLatestArchivedSpec(projectRoot, config).catch(() => undefined);
135
+ logger?.status(formatIdleStatus(config.paths.specs, approvedWaiting, lastArchived));
136
+ }
137
+ return { tasksRun, specsArchived };
138
+ }
139
+ export async function runWatcherOnce(projectRoot, config, adapter, logger) {
140
+ let totalTasksRun = 0;
141
+ let totalSpecsArchived = 0;
142
+ while (true) {
143
+ const cycle = await runWatcherCycle(projectRoot, config, adapter, logger);
144
+ totalTasksRun += cycle.tasksRun;
145
+ totalSpecsArchived += cycle.specsArchived;
146
+ if (cycle.tasksRun === 0) {
147
+ break;
148
+ }
149
+ }
150
+ return { tasksRun: totalTasksRun, specsArchived: totalSpecsArchived };
151
+ }
152
+ export async function startWatcher(projectRoot, config, adapter, options = {}) {
153
+ const logger = options.logger;
154
+ if (adapter.name === 'opencode' || config.harness === 'opencode') {
155
+ if (adapter.preflight) {
156
+ await adapter.preflight(projectRoot, config);
157
+ }
158
+ else {
159
+ await preflightOpencode(projectRoot, config);
160
+ }
161
+ }
162
+ if (options.once) {
163
+ await runWatcherOnce(projectRoot, config, adapter, logger);
164
+ return;
165
+ }
166
+ const useSymbols = logger?.symbols === true;
167
+ let interrupted = false;
168
+ let stopped = false;
169
+ let isRunningCycle = false;
170
+ let intervalId = null;
171
+ let watcher = null;
172
+ let onSigint = () => { };
173
+ const stop = () => {
174
+ if (stopped)
175
+ return;
176
+ stopped = true;
177
+ if (intervalId)
178
+ clearInterval(intervalId);
179
+ watcher?.close().catch(() => { });
180
+ process.removeListener('SIGINT', onSigint);
181
+ };
182
+ onSigint = () => {
183
+ if (interrupted) {
184
+ process.exit(EXIT_SIGINT);
185
+ }
186
+ interrupted = true;
187
+ logger?.clearStatus();
188
+ if (logger?.interactive) {
189
+ process.stderr.write(SHOW_CURSOR);
190
+ }
191
+ logger?.info('waiting for running task to exit (press Ctrl+C again to kill)');
192
+ if (!isRunningCycle) {
193
+ stop();
194
+ }
195
+ };
196
+ process.on('SIGINT', onSigint);
197
+ const cycleHandler = async () => {
198
+ if (interrupted || stopped || isRunningCycle)
199
+ return;
200
+ isRunningCycle = true;
201
+ try {
202
+ await runWatcherCycle(projectRoot, config, adapter, logger);
203
+ }
204
+ catch (err) {
205
+ logWatcherError(logger, useSymbols, err);
206
+ }
207
+ finally {
208
+ isRunningCycle = false;
209
+ if (interrupted)
210
+ stop();
211
+ }
212
+ };
213
+ if (options.signal) {
214
+ if (options.signal.aborted) {
215
+ stop();
216
+ return;
217
+ }
218
+ options.signal.addEventListener('abort', stop);
219
+ }
220
+ await cycleHandler();
221
+ if (interrupted || stopped)
222
+ return;
223
+ const specsDir = path.join(projectRoot, config.paths.specs);
224
+ watcher = watch(specsDir, {
225
+ ignoreInitial: true,
226
+ depth: 3,
227
+ });
228
+ watcher.on('all', () => {
229
+ cycleHandler().catch(() => { });
230
+ });
231
+ intervalId = setInterval(() => {
232
+ cycleHandler().catch(() => { });
233
+ }, options.pollIntervalMs || 1000);
234
+ }
235
+ //# sourceMappingURL=loop.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loop.js","sourceRoot":"","sources":["../../src/watcher/loop.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAEjC,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAe,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACzE,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAEtC,MAAM,WAAW,GAAG,WAAW,CAAC;AAChC,MAAM,WAAW,GAAG,GAAG,CAAC;AAoBxB,MAAM,UAAU,SAAS,CAAC,EAAU;IAClC,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC;IACnD,IAAI,OAAO,GAAG,EAAE;QAAE,OAAO,GAAG,OAAO,OAAO,CAAC;IAC3C,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;IACzC,IAAI,OAAO,GAAG,EAAE;QAAE,OAAO,GAAG,OAAO,OAAO,CAAC;IAC3C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;IACvC,IAAI,KAAK,GAAG,EAAE;QAAE,OAAO,GAAG,KAAK,OAAO,CAAC;IACvC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC;IACpC,OAAO,GAAG,IAAI,OAAO,CAAC;AACxB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAC9B,QAAgB,EAChB,eAAuB,EACvB,YAAkC,EAClC,MAAc,IAAI,CAAC,GAAG,EAAE;IAExB,MAAM,IAAI,GAAG,YAAY;QACvB,CAAC,CAAC,SAAS,YAAY,CAAC,EAAE,aAAa,SAAS,CAAC,GAAG,GAAG,YAAY,CAAC,UAAU,CAAC,EAAE;QACjF,CAAC,CAAC,YAAY,CAAC;IACjB,OAAO,YAAY,QAAQ,MAAM,eAAe,uBAAuB,IAAI,EAAE,CAAC;AAChF,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,WAAmB,EACnB,MAAiB;IAEjB,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAEhE,IAAI,OAAO,GAAa,EAAE,CAAC;IAC3B,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAClE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,MAAuC,CAAC;IAC5C,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE;YAAE,SAAS;QACnC,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;QAChF,IAAI,CAAC,IAAI;YAAE,SAAS;QACpB,MAAM,OAAO,GAAwB;YACnC,EAAE,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,IAAI;YACjD,MAAM,EAAE,KAAK,CAAC,IAAI;YAClB,UAAU,EAAE,IAAI,CAAC,OAAO;SACzB,CAAC;QACF,IAAI,CAAC,MAAM,IAAI,OAAO,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;YACtD,MAAM,GAAG,OAAO,CAAC;QACnB,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,YAAY,CAAC,GAAY;IAChC,OAAO,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;AAC1D,CAAC;AAED,SAAS,eAAe,CAAC,MAA0B,EAAE,UAAmB,EAAE,GAAY;IACpF,MAAM,EAAE,KAAK,CAAC,GAAG,aAAa,CAAC,GAAG,EAAE,SAAS,EAAE,UAAU,CAAC,mBAAmB,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AACpG,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,WAAmB,EACnB,MAAiB,EACjB,OAAuB,EACvB,MAAe;IAEf,MAAM,UAAU,GAAG,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IAC5C,MAAM,GAAG,GAAG,CAAC,MAAc,EAAE,IAAY,EAAU,EAAE,CAAC,aAAa,CAAC,MAAM,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;IAE9F,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC5D,IAAI,OAAO,GAAa,EAAE,CAAC;IAC3B,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACvC,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,EAAE,MAAM,CAAC,gBAAgB,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;QACxD,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,CAAC;IAC3C,CAAC;IAED,MAAM,WAAW,GAAG,OAAO;SACxB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,SAAS,CAAC;SACpD,IAAI,CAAC,oBAAoB,CAAC,CAAC;IAE9B,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,IAAI,aAAa,GAAG,CAAC,CAAC;IACtB,IAAI,eAAe,GAAG,CAAC,CAAC;IAExB,KAAK,MAAM,MAAM,IAAI,WAAW,EAAE,CAAC;QACjC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAC/C,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;YACzD,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE;gBAAE,SAAS;YAE3C,MAAM,cAAc,CAAC,UAAU,EAAE,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC;YAEnE,MAAM,SAAS,GAAG,MAAM,eAAe,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;YAEjE,IACE,SAAS,CAAC,YAAY;gBACtB,CAAC,SAAS,CAAC,MAAM,KAAK,SAAS;oBAC7B,SAAS,CAAC,MAAM,KAAK,SAAS;oBAC9B,SAAS,CAAC,MAAM,KAAK,SAAS,CAAC,EACjC,CAAC;gBACD,eAAe,EAAE,CAAC;YACpB,CAAC;YAED,IAAI,SAAS,CAAC,MAAM,KAAK,SAAS,IAAI,SAAS,CAAC,QAAQ,EAAE,CAAC;gBACzD,MAAM,UAAU,GAAG,SAAS,CAAC,QAAQ,CAAC,UAAU,CAAC;gBACjD,MAAM,EAAE,IAAI,CAAC,GAAG,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,IAAI,SAAS,CAAC,EAAE,eAAe,MAAM,GAAG,CAAC,CAAC;gBAEjF,MAAM,UAAU,GAAG,MAAM,OAAO,CAC9B,WAAW,EACX,UAAU,EACV,UAAU,EACV,MAAM,EACN,OAAO,EACP,MAAM,CACP,CAAC;gBACF,QAAQ,EAAE,CAAC;gBAEX,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC;oBACvB,MAAM,QAAQ,GAAG,MAAM,mBAAmB,CAAC,WAAW,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;oBAC5E,IAAI,QAAQ,EAAE,CAAC;wBACb,aAAa,EAAE,CAAC;wBAChB,MAAM,EAAE,IAAI,CAAC,GAAG,GAAG,CAAC,QAAQ,EAAE,YAAY,CAAC,IAAI,SAAS,CAAC,EAAE,cAAc,MAAM,GAAG,CAAC,CAAC;oBACtF,CAAC;gBACH,CAAC;qBAAM,CAAC;oBACN,MAAM,EAAE,IAAI,CACV,GAAG,GAAG,CAAC,QAAQ,EAAE,UAAU,CAAC,IAAI,SAAS,CAAC,EAAE,iBAAiB,UAAU,QAAQ,CAChF,CAAC;gBACJ,CAAC;YACH,CAAC;iBAAM,IAAI,SAAS,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;gBACvC,MAAM,QAAQ,GAAG,MAAM,mBAAmB,CAAC,WAAW,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;gBAC5E,IAAI,QAAQ,EAAE,CAAC;oBACb,aAAa,EAAE,CAAC;oBAChB,MAAM,EAAE,IAAI,CAAC,GAAG,GAAG,CAAC,QAAQ,EAAE,YAAY,CAAC,IAAI,SAAS,CAAC,EAAE,cAAc,MAAM,GAAG,CAAC,CAAC;gBACtF,CAAC;YACH,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,eAAe,CAAC,MAAM,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC;QAC3C,CAAC;IACH,CAAC;IAED,IAAI,QAAQ,KAAK,CAAC,EAAE,CAAC;QACnB,MAAM,YAAY,GAAG,MAAM,sBAAsB,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAC9F,MAAM,EAAE,MAAM,CAAC,gBAAgB,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,eAAe,EAAE,YAAY,CAAC,CAAC,CAAC;IACtF,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,CAAC;AACrC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,WAAmB,EACnB,MAAiB,EACjB,OAAuB,EACvB,MAAe;IAEf,IAAI,aAAa,GAAG,CAAC,CAAC;IACtB,IAAI,kBAAkB,GAAG,CAAC,CAAC;IAE3B,OAAO,IAAI,EAAE,CAAC;QACZ,MAAM,KAAK,GAAG,MAAM,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;QAC1E,aAAa,IAAI,KAAK,CAAC,QAAQ,CAAC;QAChC,kBAAkB,IAAI,KAAK,CAAC,aAAa,CAAC;QAE1C,IAAI,KAAK,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;YACzB,MAAM;QACR,CAAC;IACH,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,aAAa,EAAE,kBAAkB,EAAE,CAAC;AACxE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,WAAmB,EACnB,MAAiB,EACjB,OAAuB,EACvB,UAA+B,EAAE;IAEjC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAE9B,IAAI,OAAO,CAAC,IAAI,KAAK,UAAU,IAAI,MAAM,CAAC,OAAO,KAAK,UAAU,EAAE,CAAC;QACjE,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;YACtB,MAAM,OAAO,CAAC,SAAS,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;QAC/C,CAAC;aAAM,CAAC;YACN,MAAM,iBAAiB,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC;IAED,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,MAAM,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;QAC3D,OAAO;IACT,CAAC;IAED,MAAM,UAAU,GAAG,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IAC5C,IAAI,WAAW,GAAG,KAAK,CAAC;IACxB,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,IAAI,cAAc,GAAG,KAAK,CAAC;IAC3B,IAAI,UAAU,GAA0B,IAAI,CAAC;IAC7C,IAAI,OAAO,GAAoC,IAAI,CAAC;IAEpD,IAAI,QAAQ,GAAe,GAAG,EAAE,GAAE,CAAC,CAAC;IAEpC,MAAM,IAAI,GAAG,GAAS,EAAE;QACtB,IAAI,OAAO;YAAE,OAAO;QACpB,OAAO,GAAG,IAAI,CAAC;QACf,IAAI,UAAU;YAAE,aAAa,CAAC,UAAU,CAAC,CAAC;QAC1C,OAAO,EAAE,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QACjC,OAAO,CAAC,cAAc,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAC7C,CAAC,CAAC;IAEF,QAAQ,GAAG,GAAG,EAAE;QACd,IAAI,WAAW,EAAE,CAAC;YAChB,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC5B,CAAC;QACD,WAAW,GAAG,IAAI,CAAC;QACnB,MAAM,EAAE,WAAW,EAAE,CAAC;QACtB,IAAI,MAAM,EAAE,WAAW,EAAE,CAAC;YACxB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QACpC,CAAC;QACD,MAAM,EAAE,IAAI,CAAC,+DAA+D,CAAC,CAAC;QAC9E,IAAI,CAAC,cAAc,EAAE,CAAC;YACpB,IAAI,EAAE,CAAC;QACT,CAAC;IACH,CAAC,CAAC;IAEF,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAE/B,MAAM,YAAY,GAAG,KAAK,IAAmB,EAAE;QAC7C,IAAI,WAAW,IAAI,OAAO,IAAI,cAAc;YAAE,OAAO;QACrD,cAAc,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC;YACH,MAAM,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;QAC9D,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,eAAe,CAAC,MAAM,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC;QAC3C,CAAC;gBAAS,CAAC;YACT,cAAc,GAAG,KAAK,CAAC;YACvB,IAAI,WAAW;gBAAE,IAAI,EAAE,CAAC;QAC1B,CAAC;IACH,CAAC,CAAC;IAEF,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACnB,IAAI,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YAC3B,IAAI,EAAE,CAAC;YACP,OAAO;QACT,CAAC;QACD,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IACjD,CAAC;IAED,MAAM,YAAY,EAAE,CAAC;IACrB,IAAI,WAAW,IAAI,OAAO;QAAE,OAAO;IAEnC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC5D,OAAO,GAAG,KAAK,CAAC,QAAQ,EAAE;QACxB,aAAa,EAAE,IAAI;QACnB,KAAK,EAAE,CAAC;KACT,CAAC,CAAC;IAEH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;QACrB,YAAY,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;IAEH,UAAU,GAAG,WAAW,CAAC,GAAG,EAAE;QAC5B,YAAY,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IACjC,CAAC,EAAE,OAAO,CAAC,cAAc,IAAI,IAAI,CAAC,CAAC;AACrC,CAAC"}
@@ -0,0 +1,70 @@
1
+ import type { OsqConfig } from '../core/config.js';
2
+ import { type Logger } from '../core/logger.js';
3
+ import { type HarnessAdapter } from '../harness/types.js';
4
+ export type RunTaskFailureReason = 'spec_conflict' | 'already_running' | 'no_result' | 'verify_red' | 'crashed' | 'timeout';
5
+ export interface RunTaskResult {
6
+ success: boolean;
7
+ reason?: RunTaskFailureReason;
8
+ error?: string;
9
+ }
10
+ /**
11
+ * Single-line, human-readable summary of a task outcome. Kept pure so the exact
12
+ * shape can be tested without running the runner, and used directly beside every
13
+ * marker write (`done/<n>` or `dead/<n>.md`) so the log and the marker agree.
14
+ */
15
+ export declare function formatTaskOutcomeSummary(taskNumber: string, success: boolean, reason?: RunTaskFailureReason, extra?: string): string;
16
+ export declare function tickTaskCheckbox(specFolderPath: string, taskNumber: string): Promise<void>;
17
+ export interface TaskHeartbeatStats {
18
+ elapsedSeconds: number;
19
+ eventCount: number;
20
+ totalTokens: number;
21
+ toolCount: number;
22
+ cost?: number;
23
+ lastToolSummary?: string;
24
+ }
25
+ /**
26
+ * Snapshot of task progress. Counters are maintained in memory and advanced
27
+ * with only the bytes appended since the previous poll; the event file may not
28
+ * exist yet, in which case counters are zero.
29
+ */
30
+ export declare function computeTaskHeartbeatStats(specFolderPath: string, taskNumber: string, startTime: number): Promise<TaskHeartbeatStats>;
31
+ /**
32
+ * Drop the in-memory counters for a finished task so the map does not grow
33
+ * across watcher cycles.
34
+ */
35
+ export declare function clearTaskHeartbeatStats(specFolderPath: string, taskNumber: string): void;
36
+ /**
37
+ * Single-line running status row. The logger owns the animated spinner and
38
+ * prepends `<frame> `, so this text is truncated to leave room for that prefix
39
+ * while fitting `terminalWidth` columns.
40
+ */
41
+ export declare function formatTaskStatusRow(taskNumber: string, stats: TaskHeartbeatStats, terminalWidth?: number): string;
42
+ /** Periodic heartbeat line shared by the 1s TTY row and the non-TTY log. */
43
+ export declare function formatTaskHeartbeatLine(taskNumber: string, stats: TaskHeartbeatStats): string;
44
+ /**
45
+ * Curated task-started line: a single info line carrying the task title
46
+ * truncated so the whole line fits the terminal width. The lifecycle details
47
+ * (pid, timeout) travel with it so the marker and the log line stay in sync.
48
+ */
49
+ export declare function formatTaskStartedLine(taskNumber: string, title: string, pid: number | undefined, timeoutSeconds: number, symbols: boolean, terminalWidth?: number): string;
50
+ /**
51
+ * Curated task-outcome line: verified or dead with the failure reason and the
52
+ * elapsed seconds since the task began.
53
+ */
54
+ export declare function formatTaskOutcomeLine(taskNumber: string, success: boolean, reason: RunTaskFailureReason | undefined, elapsedSeconds: number, symbols: boolean): string;
55
+ /**
56
+ * Return the last text message emitted on the agent's event stream, or null
57
+ * when the stream has no text at all. Synthesis reads exclusively from
58
+ * first-class `text` events carrying the completed assistant message; raw
59
+ * harness payload shapes are never inspected. The stream is the append-only
60
+ * `.run/events/<n>.jsonl` file, so this survives a watcher restart.
61
+ */
62
+ export declare function extractFinalTextFromStream(specFolderPath: string, taskNumber: string): Promise<string | null>;
63
+ /**
64
+ * Write a result file synthesized from the agent's final stream message. The
65
+ * frontmatter flags it as `synthesized: true` and a comment attributes it to
66
+ * the watcher so a reader never mistakes it for an agent-authored result.
67
+ */
68
+ export declare function synthesizeResultFile(resultsDir: string, taskNumber: string, finalText: string): Promise<string>;
69
+ export declare function runTask(projectRoot: string, specFolderPath: string, taskNumber: string, config: OsqConfig, adapter: HarnessAdapter, logger?: Logger): Promise<RunTaskResult>;
70
+ //# sourceMappingURL=runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/watcher/runner.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAGnD,OAAO,EAAE,KAAK,MAAM,EAAiB,MAAM,mBAAmB,CAAC;AAG/D,OAAO,EAGL,KAAK,cAAc,EAGpB,MAAM,qBAAqB,CAAC;AAE7B,MAAM,MAAM,oBAAoB,GAC5B,eAAe,GACf,iBAAiB,GACjB,WAAW,GACX,YAAY,GACZ,SAAS,GACT,SAAS,CAAC;AAEd,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,oBAAoB,CAAC;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,OAAO,EAChB,MAAM,CAAC,EAAE,oBAAoB,EAC7B,KAAK,CAAC,EAAE,MAAM,GACb,MAAM,CAOR;AAED,wBAAsB,gBAAgB,CAAC,cAAc,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAehG;AAmDD,MAAM,WAAW,kBAAkB;IACjC,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAuBD;;;;GAIG;AACH,wBAAsB,yBAAyB,CAC7C,cAAc,EAAE,MAAM,EACtB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,kBAAkB,CAAC,CA0E7B;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,cAAc,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAGxF;AAkBD;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,kBAAkB,EACzB,aAAa,GAAE,MAA0E,GACxF,MAAM,CAwBR;AAED,4EAA4E;AAC5E,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,kBAAkB,GAAG,MAAM,CAE7F;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,GAAG,SAAS,EACvB,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE,OAAO,EAChB,aAAa,GAAE,MAA0E,GACxF,MAAM,CAKR;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,oBAAoB,GAAG,SAAS,EACxC,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE,OAAO,GACf,MAAM,CAKR;AAED;;;;;;GAMG;AACH,wBAAsB,0BAA0B,CAC9C,cAAc,EAAE,MAAM,EACtB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAgCxB;AAED;;;;GAIG;AACH,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,CAAC,CAgBjB;AAED,wBAAsB,OAAO,CAC3B,WAAW,EAAE,MAAM,EACnB,cAAc,EAAE,MAAM,EACtB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,cAAc,EACvB,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,aAAa,CAAC,CAmYxB"}