@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
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Mathias
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,183 @@
1
+ # osq
2
+
3
+ Strict spec queue. Spec-driven development with two kinds of agent and a human gate between them.
4
+
5
+ A smart model helps you write small, immutable task specs. A watcher hands each approved spec to a fresh, cheap coding agent that does the work, writes a result, and exits. Failures go to a dead letter queue you deal with next time you sit down. Nothing runs that you didn't approve, and nothing is marked done that the watcher didn't verify itself.
6
+
7
+ If a fresh agent could not pick up a task from the files in the repo alone, the files are wrong. Everything here follows from that.
8
+
9
+ ## Install
10
+
11
+ ```sh
12
+ npx @matteeh/osq init # scaffolds the folders below and configuration
13
+ pnpm add -D @matteeh/osq # adds osq as a devDependency (or npm i -D @matteeh/osq)
14
+ pnpm osq watch # start the watcher
15
+ ```
16
+
17
+ `init` is idempotent. Run it again after upgrading to refresh the managed block in AGENTS.md; it never touches anything else you've edited.
18
+
19
+ ## What it puts in your repo
20
+
21
+ ```
22
+ AGENTS.md your existing file, plus a managed block with the coding agent procedure
23
+ osq.config.ts limits, paths, max concurrency
24
+ specs/
25
+ _template/ copied by `osq new`
26
+ 042-order-cancellation/
27
+ spec.md goal, contract, non-goals, and the delta to apply to feature docs
28
+ tasks.md one checkbox per task, ticked by the watcher
29
+ tasks/1.md the unit of work: acceptance, verify, scope, entry
30
+ tasks/2.md
31
+ .run/ approved (hash), running/, done/, dead/, results/, events/
32
+ archive/ finished change folders, moved whole
33
+ features/ one doc per feature, describes current behavior, always true of main
34
+ decisions/ ADRs, superseded not edited
35
+ .env.example OSQ_HARNESS and API keys
36
+ ```
37
+
38
+ A change folder is a feature. A task is one unit of work for one agent. After approval the folder is read-only until every task is done or one is dead. State is which marker files exist under `.run/`, never a field in a document.
39
+
40
+ ## The loop
41
+
42
+ ```
43
+ you + smart model write change folder -> specs/042-x/ with spec.md and tasks/
44
+ you approve -> .run/approved
45
+ watcher spawn per task -> cheap agent, fresh context, one attempt
46
+ agent work, write result -> .run/results/1.md, exit
47
+ watcher verify, tick box -> .run/done/1 or .run/dead/1.md
48
+ watcher last task done -> apply delta to features/, archive folder
49
+ you next time -> osq status, look at dead
50
+ ```
51
+
52
+ Smart models author specs and never execute them. Cheap models execute specs and never author them.
53
+
54
+ ## Change folder
55
+
56
+ `spec.md` is written for humans and the smart model:
57
+
58
+ ```yaml
59
+ ---
60
+ title: Order cancellation
61
+ depends_on: [041]
62
+ features:
63
+ reads: [inventory-reservation]
64
+ writes: [order-state-machine]
65
+ ---
66
+ ## Goal
67
+ ## Contract
68
+ ## Non-goals
69
+ ## Delta
70
+ What changes in each doc under features.writes. Applied by the watcher when the last task is done.
71
+ ```
72
+
73
+ `tasks/<n>.md` is what a coding agent gets:
74
+
75
+ ```yaml
76
+ ---
77
+ title: When a PENDING order is cancelled, its reservation is released
78
+ verify: pnpm test -- orders/cancel
79
+ scope: [src/orders/**, tests/orders/**]
80
+ entry: [src/orders/service.ts]
81
+ skills: []
82
+ ---
83
+ ## Acceptance
84
+ - [ ] each line is a test in disguise, max 7
85
+ ```
86
+
87
+ Tasks run in order. The agent reads its task, the parent `spec.md`, the docs under `features.reads` and `features.writes`, AGENTS.md, and a previous result file for that task if there is one. Nothing else. The delta is applied by the watcher, so the agent never edits feature docs.
88
+
89
+ Lint, run by `osq approve`:
90
+
91
+ | Check | Result |
92
+ |---------------------------------------------|--------|
93
+ | task `scope` has more than 8 patterns | reject |
94
+ | `features.writes` has more than 2 entries | reject |
95
+ | more than one table under `## Contract` | reject |
96
+ | task `verify` empty or chains commands | reject |
97
+ | `depends_on` names a missing change | reject |
98
+ | task acceptance longer than 7 lines | reject |
99
+ | `## Delta` empty while `features.writes` is not | reject |
100
+ | task title contains " and " | warn |
101
+
102
+ Rules the lint can't check: title reads "when X, Y happens"; slice vertically so every spec leaves `main` green on its own; no "investigate" or "decide" in a spec (that's a spike, whose output is a paragraph in a feature doc or an ADR); default to a parent with children and approve the list before writing any child in full.
103
+
104
+ ## What the watcher guarantees
105
+
106
+ - State is rebuilt from `specs/` on every change. Kill it and restart it any time.
107
+ - One agent per spec: locks are created exclusively, stale locks (dead pid or timeout) are reaped to `dead/`.
108
+ - What runs is what was approved: `.run/approved` holds a hash of the folder minus `.run/` (with `tasks.md` checkbox state normalized), checked before every spawn.
109
+ - `done` means the watcher ran `verify` itself in a timeout-bounded process group after the agent exited. The agent's claim is not enough.
110
+ - Feature docs are only ever changed by the watcher applying an approved delta. Agents never touch `features/`.
111
+ - The agent prompt protocol restricts write paths to `.run/results/` and edits to `scope`. All markers and checkboxes are written by the watcher.
112
+ - An agent that exits without writing `.run/results/<n>.md` is not lost: if the adapter captured a final text message, the watcher synthesizes a result file (`synthesized: true`) from it and proceeds to verify. Only an exit with neither a result file nor final text is `dead` with `reason: no_result`. Nothing disappears silently.
113
+
114
+ Reasons emitted: `verify_red` (with `timed_out: true` if verify exceeded timeout), `spec_conflict`, `already_running`, `no_result` (no result file and no final text), `crashed`, `timeout`.
115
+
116
+ ## Harnesses
117
+
118
+ `OSQ_HARNESS` picks an adapter. An adapter does two things: spawn an agent for a tier (`coding` or `smart`) and write its harness's config files (`osq setup`). Adapters translate the harness's own event stream into six events (`started`, `tokens`, `file_changed`, `verify_ran`, `result_written`, `exited`), appended to the task's `.run/events/<n>.jsonl`. Hooks are optional shims that append to the same file. The loop works without them.
119
+
120
+ Available adapters:
121
+ - `agy`: Antigravity harness adapter
122
+ - `opencode`: OpenCode harness adapter running tasks via `opencode run`
123
+ - `mock`: In-memory deterministic simulation for tests
124
+
125
+ Configure `opencode` in `osq.config.ts`:
126
+
127
+ ```ts
128
+ import { defineConfig } from '@matteeh/osq';
129
+
130
+ export default defineConfig({
131
+ harness: 'opencode',
132
+ opencode: {
133
+ bin: 'opencode',
134
+ model: 'deepseek/deepseek-flash',
135
+ agent: 'osq-coder',
136
+ variant: 'thinking', // optional
137
+ },
138
+ });
139
+ ```
140
+
141
+ Running `osq setup` with the `opencode` harness scaffolds `.opencode/agent/osq-coder.md` with restricted permissions (denying `webfetch` and `websearch`) and the managed `AGENTS.md` execution procedure. Note that the `--auto` flag approves any action the agent file does not deny. The agent file must have mode `all` or `primary`; a subagent cannot be selected with --agent and OpenCode silently falls back to an unrestricted default. `webfetch` and `websearch` are denied at the tool level, but `bash` is allowed and unrestricted, so the agent can reach the network through the shell. Network isolation requires a sandbox and is listed under "Not yet".
142
+
143
+ ## Commands
144
+
145
+ ```
146
+ osq init scaffold
147
+ osq setup write harness config for OSQ_HARNESS
148
+ osq new <name> new change folder from the template
149
+ osq watch run the watcher
150
+ osq approve <id>.. lint, hash, approve. also re-approves after fixing a dead task
151
+ osq status every change and task with its state
152
+ osq show <id> spec, tasks, results, dead markers, event timeline
153
+ osq report completion rate, dead by reason, cost and time per task
154
+ ```
155
+
156
+ `osq report` renders completion rate, failures by reason, execution durations, token usage, and file changes. Reported cost sums the `cost` values carried by harness events. Reported cost reflects the harness's internal price table rather than the invoice.
157
+
158
+ ## Release Procedure
159
+
160
+ To release a new version of `osq`:
161
+ 1. Bump `"version"` in `package.json`.
162
+ 2. Add a corresponding release section in `CHANGELOG.md`.
163
+ 3. Commit the changes: `git commit -am "release: v<x.y.z>"`.
164
+ 4. Create and push the release tag: `git tag v<x.y.z> && git push --tags`.
165
+ 5. GitHub Actions (`release.yml`) verifies the build and publishes to npm with provenance via trusted publishing.
166
+
167
+ ## Not yet
168
+
169
+ Decided but deliberately unbuilt until the loop has closed on real work:
170
+
171
+ - Concurrency above 1, with a worktree per running task and merge on done (`reason: merge_conflict`).
172
+ - Hard OS/container sandbox confinement enforcing `scope` boundaries and filesystem write limits (`reason: scope_violation`).
173
+ - Pre-spawn dependency and context verification checks (`reason: missing_dep`, `reason: missing_context`).
174
+ - Deterministic section-level replacement for feature doc deltas (ADR 002).
175
+ - Containerized coding agents.
176
+ - A derived SQLite index under `~/.osq/` for `status` and `report` across projects. Files stay the source of truth; the index is gitignored and can be deleted at any time.
177
+ - Hook shims for harnesses, and `osq import` for OpenSpec change folders.
178
+
179
+ ## Status
180
+
181
+ Early. Written in TypeScript so `npx` is the whole install and the glue (spawning, JSON streams, file watching, git) stays short; the filesystem protocol means the watcher could be rewritten in another language later without consumers noticing. Numbers in `osq.config.ts` are guesses until `osq report` says otherwise. See `decisions/` for why things are the way they are.
182
+
183
+ MIT.
@@ -0,0 +1,6 @@
1
+ import { type OsqConfig } from '../core/config.js';
2
+ export declare function approveCommand(specIds: string[], options?: {
3
+ cwd?: string;
4
+ config?: OsqConfig;
5
+ }): Promise<void>;
6
+ //# sourceMappingURL=approve.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"approve.d.ts","sourceRoot":"","sources":["../../src/cli/approve.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,SAAS,EAAc,MAAM,mBAAmB,CAAC;AAE/D,wBAAsB,cAAc,CAClC,OAAO,EAAE,MAAM,EAAE,EACjB,OAAO,GAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,SAAS,CAAA;CAAO,GACjD,OAAO,CAAC,IAAI,CAAC,CAuBf"}
@@ -0,0 +1,26 @@
1
+ import { approveSpec } from '../core/approve.js';
2
+ import { loadConfig } from '../core/config.js';
3
+ export async function approveCommand(specIds, options = {}) {
4
+ const cwd = options.cwd || process.cwd();
5
+ const config = options.config || (await loadConfig(cwd));
6
+ if (!specIds || specIds.length === 0) {
7
+ console.error('Error: specify at least one spec ID to approve (e.g. osq approve 001)');
8
+ process.exit(1);
9
+ }
10
+ for (const specId of specIds) {
11
+ try {
12
+ const result = await approveSpec(cwd, specId, config);
13
+ console.log(`Approved ${result.specId} (${result.folderName})`);
14
+ console.log(` Hash: ${result.hash}`);
15
+ for (const warning of result.warnings) {
16
+ console.warn(` Warning: ${warning}`);
17
+ }
18
+ }
19
+ catch (error) {
20
+ const message = error instanceof Error ? error.message : String(error);
21
+ console.error(`Error approving ${specId}:\n ${message}`);
22
+ process.exit(1);
23
+ }
24
+ }
25
+ }
26
+ //# sourceMappingURL=approve.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"approve.js","sourceRoot":"","sources":["../../src/cli/approve.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAkB,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/D,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,OAAiB,EACjB,UAAgD,EAAE;IAElD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IACzC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,CAAC,MAAM,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;IAEzD,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrC,OAAO,CAAC,KAAK,CAAC,uEAAuE,CAAC,CAAC;QACvF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;YACtD,OAAO,CAAC,GAAG,CAAC,YAAY,MAAM,CAAC,MAAM,KAAK,MAAM,CAAC,UAAU,GAAG,CAAC,CAAC;YAChE,OAAO,CAAC,GAAG,CAAC,WAAW,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;YACtC,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;gBACtC,OAAO,CAAC,IAAI,CAAC,cAAc,OAAO,EAAE,CAAC,CAAC;YACxC,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACvE,OAAO,CAAC,KAAK,CAAC,mBAAmB,MAAM,QAAQ,OAAO,EAAE,CAAC,CAAC;YAC1D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=bin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bin.d.ts","sourceRoot":"","sources":["../../src/cli/bin.ts"],"names":[],"mappings":""}
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+ import { createProgram, resolvePackageVersion } from './index.js';
3
+ const program = createProgram(resolvePackageVersion());
4
+ await program.parseAsync(process.argv);
5
+ //# sourceMappingURL=bin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bin.js","sourceRoot":"","sources":["../../src/cli/bin.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAElE,MAAM,OAAO,GAAG,aAAa,CAAC,qBAAqB,EAAE,CAAC,CAAC;AACvD,MAAM,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { Command } from 'commander';
2
+ export declare function resolvePackageVersion(): string;
3
+ export declare function createProgram(version?: string): Command;
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAYpC,wBAAgB,qBAAqB,IAAI,MAAM,CAG9C;AAED,wBAAgB,aAAa,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAuEvD"}
@@ -0,0 +1,76 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { Command } from 'commander';
3
+ import { approveCommand } from './approve.js';
4
+ import { initCommand } from './init.js';
5
+ import { newCommand } from './new.js';
6
+ import { reportCommand } from './report.js';
7
+ import { setupCommand } from './setup.js';
8
+ import { showCommand } from './show.js';
9
+ import { statusCommand } from './status.js';
10
+ import { watchCommand } from './watch.js';
11
+ const PACKAGE_MANIFEST_URL = new URL('../../package.json', import.meta.url);
12
+ export function resolvePackageVersion() {
13
+ const manifest = JSON.parse(readFileSync(PACKAGE_MANIFEST_URL, 'utf8'));
14
+ return manifest.version ?? '0.0.0';
15
+ }
16
+ export function createProgram(version) {
17
+ const program = new Command();
18
+ program
19
+ .name('osq')
20
+ .description('Strict spec queue. Spec-driven development with two kinds of agent and a human gate.')
21
+ .version(version ?? resolvePackageVersion());
22
+ program
23
+ .command('init')
24
+ .description('scaffold osq folders and configuration')
25
+ .action(async () => {
26
+ await initCommand();
27
+ });
28
+ program
29
+ .command('new <name>')
30
+ .description('new change folder from template')
31
+ .action(async (name) => {
32
+ await newCommand(name);
33
+ });
34
+ program
35
+ .command('approve <ids...>')
36
+ .description('lint, hash, and approve change folders')
37
+ .action(async (ids) => {
38
+ await approveCommand(ids);
39
+ });
40
+ program
41
+ .command('watch')
42
+ .description('run the spec watcher loop')
43
+ .option('-o, --once', 'run pending tasks in queue and exit')
44
+ .option('--verbose', 'enable verbose logging')
45
+ .option('-q, --quiet', 'suppress info and verbose logging')
46
+ .action(async (options) => {
47
+ await watchCommand(options);
48
+ });
49
+ program
50
+ .command('setup')
51
+ .description('configure harness environment and configuration')
52
+ .action(async () => {
53
+ await setupCommand();
54
+ });
55
+ program
56
+ .command('status')
57
+ .description('show status overview of change folders and tasks')
58
+ .action(async () => {
59
+ await statusCommand();
60
+ });
61
+ program
62
+ .command('show <id>')
63
+ .description('show detailed change information, tasks, and event timeline')
64
+ .action(async (id) => {
65
+ await showCommand(id);
66
+ });
67
+ program
68
+ .command('report')
69
+ .description('display delivery metrics and task completion report')
70
+ .option('--json', 'output report as raw JSON')
71
+ .action(async (options) => {
72
+ await reportCommand(options);
73
+ });
74
+ return program;
75
+ }
76
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export declare function initCommand(options?: {
2
+ cwd?: string;
3
+ }): Promise<void>;
4
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"AAEA,wBAAsB,WAAW,CAAC,OAAO,GAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAiB/E"}
@@ -0,0 +1,19 @@
1
+ import { scaffoldProject } from '../core/init.js';
2
+ export async function initCommand(options = {}) {
3
+ const cwd = options.cwd || process.cwd();
4
+ const result = await scaffoldProject(cwd);
5
+ for (const dir of result.createdDirs) {
6
+ console.log(` created ${dir}/`);
7
+ }
8
+ for (const file of result.createdFiles) {
9
+ console.log(` created ${file}`);
10
+ }
11
+ for (const file of result.skippedFiles) {
12
+ console.log(` exists ${file}`);
13
+ }
14
+ if (result.updatedAgentsMd) {
15
+ console.log(' updated AGENTS.md (refreshed managed block)');
16
+ }
17
+ console.log('\nosq initialized successfully.');
18
+ }
19
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAElD,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,UAA4B,EAAE;IAC9D,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IACzC,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,GAAG,CAAC,CAAC;IAE1C,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;QACrC,OAAO,CAAC,GAAG,CAAC,cAAc,GAAG,GAAG,CAAC,CAAC;IACpC,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;QACvC,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,EAAE,CAAC,CAAC;IACpC,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;QACvC,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,EAAE,CAAC,CAAC;IACpC,CAAC;IACD,IAAI,MAAM,CAAC,eAAe,EAAE,CAAC;QAC3B,OAAO,CAAC,GAAG,CAAC,gDAAgD,CAAC,CAAC;IAChE,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC;AACjD,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare function newCommand(name: string, options?: {
2
+ cwd?: string;
3
+ }): Promise<void>;
4
+ //# sourceMappingURL=new.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"new.d.ts","sourceRoot":"","sources":["../../src/cli/new.ts"],"names":[],"mappings":"AAEA,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAW5F"}
@@ -0,0 +1,15 @@
1
+ import { createNewSpec } from '../core/new.js';
2
+ export async function newCommand(name, options = {}) {
3
+ const cwd = options.cwd || process.cwd();
4
+ try {
5
+ const result = await createNewSpec(cwd, name);
6
+ console.log(`Created spec ${result.specId}: ${result.folderName}`);
7
+ console.log(` Path: ${result.folderPath}`);
8
+ }
9
+ catch (error) {
10
+ const message = error instanceof Error ? error.message : String(error);
11
+ console.error(`Error: ${message}`);
12
+ process.exit(1);
13
+ }
14
+ }
15
+ //# sourceMappingURL=new.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"new.js","sourceRoot":"","sources":["../../src/cli/new.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE/C,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAY,EAAE,UAA4B,EAAE;IAC3E,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IACzC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC9C,OAAO,CAAC,GAAG,CAAC,gBAAgB,MAAM,CAAC,MAAM,KAAK,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC;QACnE,OAAO,CAAC,GAAG,CAAC,WAAW,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC;IAC9C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,OAAO,CAAC,KAAK,CAAC,UAAU,OAAO,EAAE,CAAC,CAAC;QACnC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { type OsqConfig } from '../core/config.js';
2
+ export interface ReportCommandOptions {
3
+ cwd?: string;
4
+ stdout?: (msg: string) => void;
5
+ config?: OsqConfig;
6
+ json?: boolean;
7
+ }
8
+ export declare function serializeSortedJson(data: unknown): string;
9
+ export declare function reportCommand(options?: ReportCommandOptions): Promise<string>;
10
+ //# sourceMappingURL=report.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../src/cli/report.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAc,MAAM,mBAAmB,CAAC;AAG/D,MAAM,WAAW,oBAAoB;IACnC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAkBD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAEzD;AA8CD,wBAAsB,aAAa,CAAC,OAAO,GAAE,oBAAyB,GAAG,OAAO,CAAC,MAAM,CAAC,CAqBvF"}
@@ -0,0 +1,84 @@
1
+ import { loadConfig } from '../core/config.js';
2
+ import { formatMetricsReport, getMetricsReport } from '../core/report.js';
3
+ /** Recursively sorts object keys so serialized output is deterministic on every platform. */
4
+ function sortKeysDeep(value) {
5
+ if (Array.isArray(value)) {
6
+ return value.map(sortKeysDeep);
7
+ }
8
+ if (value !== null && typeof value === 'object') {
9
+ const record = value;
10
+ const sorted = {};
11
+ for (const key of Object.keys(record).sort()) {
12
+ sorted[key] = sortKeysDeep(record[key]);
13
+ }
14
+ return sorted;
15
+ }
16
+ return value;
17
+ }
18
+ export function serializeSortedJson(data) {
19
+ return JSON.stringify(sortKeysDeep(data), null, 2);
20
+ }
21
+ /**
22
+ * Projects the report down to the stable {@link MetricsReport} shape, dropping
23
+ * backward-compatibility aliases so the machine-readable output stays fixed.
24
+ */
25
+ function toStableMetrics(report) {
26
+ const stable = {
27
+ completionRate: report.completionRate,
28
+ durations: {
29
+ totalMs: report.durations.totalMs,
30
+ totalSeconds: report.durations.totalSeconds,
31
+ avgMs: report.durations.avgMs,
32
+ avgSeconds: report.durations.avgSeconds,
33
+ formattedTotal: report.durations.formattedTotal,
34
+ formattedAvg: report.durations.formattedAvg,
35
+ },
36
+ failureBreakdown: { ...report.failureBreakdown },
37
+ fileChanges: {
38
+ totalChanges: report.fileChanges.totalChanges,
39
+ uniqueCount: report.fileChanges.uniqueCount,
40
+ uniqueFiles: [...report.fileChanges.uniqueFiles],
41
+ },
42
+ specs: { ...report.specs },
43
+ tasks: { ...report.tasks },
44
+ tokens: {
45
+ input: report.tokens.input,
46
+ cached_input: report.tokens.cached_input,
47
+ output: report.tokens.output,
48
+ reasoning: report.tokens.reasoning,
49
+ total: report.tokens.total,
50
+ cacheSharePercent: report.tokens.cacheSharePercent,
51
+ },
52
+ };
53
+ if (report.cost) {
54
+ stable.cost = {
55
+ total: report.cost.total,
56
+ perSpec: { ...report.cost.perSpec },
57
+ formattedTotal: report.cost.formattedTotal,
58
+ };
59
+ }
60
+ return stable;
61
+ }
62
+ export async function reportCommand(options = {}) {
63
+ const cwd = options.cwd || process.cwd();
64
+ const config = options.config || (await loadConfig(cwd));
65
+ try {
66
+ const report = await getMetricsReport(cwd, config);
67
+ const output = options.json
68
+ ? serializeSortedJson(toStableMetrics(report))
69
+ : formatMetricsReport(report);
70
+ if (options.stdout) {
71
+ options.stdout(output);
72
+ }
73
+ else {
74
+ console.log(output);
75
+ }
76
+ return output;
77
+ }
78
+ catch (err) {
79
+ const message = err instanceof Error ? err.message : String(err);
80
+ console.error(`Report error: ${message}`);
81
+ process.exit(1);
82
+ }
83
+ }
84
+ //# sourceMappingURL=report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.js","sourceRoot":"","sources":["../../src/cli/report.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function setupCommand(): Promise<void>;
2
+ //# sourceMappingURL=setup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/cli/setup.ts"],"names":[],"mappings":"AAGA,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAMlD"}
@@ -0,0 +1,10 @@
1
+ import { loadConfig } from '../core/config.js';
2
+ import { getHarnessAdapter } from '../harness/index.js';
3
+ export async function setupCommand() {
4
+ const cwd = process.cwd();
5
+ const config = await loadConfig(cwd);
6
+ const adapter = getHarnessAdapter(config.harness);
7
+ await adapter.setup(cwd, config);
8
+ console.log(`Harness '${config.harness}' setup completed successfully.`);
9
+ }
10
+ //# sourceMappingURL=setup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/cli/setup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAExD,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAC1B,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,GAAG,CAAC,CAAC;IACrC,MAAM,OAAO,GAAG,iBAAiB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAClD,MAAM,OAAO,CAAC,KAAK,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IACjC,OAAO,CAAC,GAAG,CAAC,YAAY,MAAM,CAAC,OAAO,iCAAiC,CAAC,CAAC;AAC3E,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { type OsqConfig } from '../core/config.js';
2
+ export declare function showCommand(specId: string, options?: {
3
+ cwd?: string;
4
+ stdout?: (msg: string) => void;
5
+ config?: OsqConfig;
6
+ }): Promise<string>;
7
+ //# sourceMappingURL=show.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"show.d.ts","sourceRoot":"","sources":["../../src/cli/show.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAc,MAAM,mBAAmB,CAAC;AAG/D,wBAAsB,WAAW,CAC/B,MAAM,EAAE,MAAM,EACd,OAAO,GAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAAC,MAAM,CAAC,EAAE,SAAS,CAAA;CAAO,GACjF,OAAO,CAAC,MAAM,CAAC,CAuBjB"}
@@ -0,0 +1,27 @@
1
+ import { loadConfig } from '../core/config.js';
2
+ import { formatSpecDetails, getSpecDetails } from '../core/show.js';
3
+ export async function showCommand(specId, options = {}) {
4
+ const cwd = options.cwd || process.cwd();
5
+ const config = options.config || (await loadConfig(cwd));
6
+ if (!specId || !specId.trim()) {
7
+ console.error('Error: specify a spec ID to show (e.g. osq show 001)');
8
+ process.exit(1);
9
+ }
10
+ try {
11
+ const details = await getSpecDetails(cwd, specId, config);
12
+ const formatted = formatSpecDetails(details);
13
+ if (options.stdout) {
14
+ options.stdout(formatted);
15
+ }
16
+ else {
17
+ console.log(formatted);
18
+ }
19
+ return formatted;
20
+ }
21
+ catch (err) {
22
+ const message = err instanceof Error ? err.message : String(err);
23
+ console.error(`Show error: ${message}`);
24
+ process.exit(1);
25
+ }
26
+ }
27
+ //# sourceMappingURL=show.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"show.js","sourceRoot":"","sources":["../../src/cli/show.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEpE,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,MAAc,EACd,UAAgF,EAAE;IAElF,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IACzC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,CAAC,MAAM,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;IAEzD,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;QAC9B,OAAO,CAAC,KAAK,CAAC,sDAAsD,CAAC,CAAC;QACtE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;QAC1D,MAAM,SAAS,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;QAC7C,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YACnB,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAC5B,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACzB,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACjE,OAAO,CAAC,KAAK,CAAC,eAAe,OAAO,EAAE,CAAC,CAAC;QACxC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { type OsqConfig } from '../core/config.js';
2
+ export declare function statusCommand(options?: {
3
+ cwd?: string;
4
+ stdout?: (msg: string) => void;
5
+ config?: OsqConfig;
6
+ }): Promise<string>;
7
+ //# sourceMappingURL=status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/cli/status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAc,MAAM,mBAAmB,CAAC;AAG/D,wBAAsB,aAAa,CACjC,OAAO,GAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAAC,MAAM,CAAC,EAAE,SAAS,CAAA;CAAO,GACjF,OAAO,CAAC,MAAM,CAAC,CAkBjB"}
@@ -0,0 +1,23 @@
1
+ import { loadConfig } from '../core/config.js';
2
+ import { formatStatusOverview, getStatusOverview } from '../core/status.js';
3
+ export async function statusCommand(options = {}) {
4
+ const cwd = options.cwd || process.cwd();
5
+ const config = options.config || (await loadConfig(cwd));
6
+ try {
7
+ const overview = await getStatusOverview(cwd, config);
8
+ const formatted = formatStatusOverview(overview);
9
+ if (options.stdout) {
10
+ options.stdout(formatted);
11
+ }
12
+ else {
13
+ console.log(formatted);
14
+ }
15
+ return formatted;
16
+ }
17
+ catch (err) {
18
+ const message = err instanceof Error ? err.message : String(err);
19
+ console.error(`Status error: ${message}`);
20
+ process.exit(1);
21
+ }
22
+ }
23
+ //# sourceMappingURL=status.js.map