@orc-brain/core 1.0.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 (126) hide show
  1. package/LICENSE +21 -0
  2. package/dist/autoLoop.d.ts +70 -0
  3. package/dist/autoLoop.d.ts.map +1 -0
  4. package/dist/autoLoop.js +178 -0
  5. package/dist/autoLoop.js.map +1 -0
  6. package/dist/backpressure.d.ts +38 -0
  7. package/dist/backpressure.d.ts.map +1 -0
  8. package/dist/backpressure.js +103 -0
  9. package/dist/backpressure.js.map +1 -0
  10. package/dist/budgetTracker.d.ts +53 -0
  11. package/dist/budgetTracker.d.ts.map +1 -0
  12. package/dist/budgetTracker.js +93 -0
  13. package/dist/budgetTracker.js.map +1 -0
  14. package/dist/config.d.ts +9 -0
  15. package/dist/config.d.ts.map +1 -0
  16. package/dist/config.js +107 -0
  17. package/dist/config.js.map +1 -0
  18. package/dist/escalation.d.ts +43 -0
  19. package/dist/escalation.d.ts.map +1 -0
  20. package/dist/escalation.js +81 -0
  21. package/dist/escalation.js.map +1 -0
  22. package/dist/eventBus.d.ts +30 -0
  23. package/dist/eventBus.d.ts.map +1 -0
  24. package/dist/eventBus.js +42 -0
  25. package/dist/eventBus.js.map +1 -0
  26. package/dist/goalJudge.d.ts +92 -0
  27. package/dist/goalJudge.d.ts.map +1 -0
  28. package/dist/goalJudge.js +254 -0
  29. package/dist/goalJudge.js.map +1 -0
  30. package/dist/index.d.ts +30 -0
  31. package/dist/index.d.ts.map +1 -0
  32. package/dist/index.js +30 -0
  33. package/dist/index.js.map +1 -0
  34. package/dist/modelRouter.d.ts +40 -0
  35. package/dist/modelRouter.d.ts.map +1 -0
  36. package/dist/modelRouter.js +114 -0
  37. package/dist/modelRouter.js.map +1 -0
  38. package/dist/orchestrator.d.ts +242 -0
  39. package/dist/orchestrator.d.ts.map +1 -0
  40. package/dist/orchestrator.js +975 -0
  41. package/dist/orchestrator.js.map +1 -0
  42. package/dist/pacing.d.ts +34 -0
  43. package/dist/pacing.d.ts.map +1 -0
  44. package/dist/pacing.js +49 -0
  45. package/dist/pacing.js.map +1 -0
  46. package/dist/planValidation.d.ts +24 -0
  47. package/dist/planValidation.d.ts.map +1 -0
  48. package/dist/planValidation.js +134 -0
  49. package/dist/planValidation.js.map +1 -0
  50. package/dist/planner.d.ts +70 -0
  51. package/dist/planner.d.ts.map +1 -0
  52. package/dist/planner.js +210 -0
  53. package/dist/planner.js.map +1 -0
  54. package/dist/plugins/host.d.ts +39 -0
  55. package/dist/plugins/host.d.ts.map +1 -0
  56. package/dist/plugins/host.js +109 -0
  57. package/dist/plugins/host.js.map +1 -0
  58. package/dist/plugins/registry.d.ts +71 -0
  59. package/dist/plugins/registry.d.ts.map +1 -0
  60. package/dist/plugins/registry.js +269 -0
  61. package/dist/plugins/registry.js.map +1 -0
  62. package/dist/plugins/secrets.d.ts +30 -0
  63. package/dist/plugins/secrets.d.ts.map +1 -0
  64. package/dist/plugins/secrets.js +99 -0
  65. package/dist/plugins/secrets.js.map +1 -0
  66. package/dist/preflight.d.ts +38 -0
  67. package/dist/preflight.d.ts.map +1 -0
  68. package/dist/preflight.js +108 -0
  69. package/dist/preflight.js.map +1 -0
  70. package/dist/reporting.d.ts +41 -0
  71. package/dist/reporting.d.ts.map +1 -0
  72. package/dist/reporting.js +229 -0
  73. package/dist/reporting.js.map +1 -0
  74. package/dist/safety/denyRules.d.ts +57 -0
  75. package/dist/safety/denyRules.d.ts.map +1 -0
  76. package/dist/safety/denyRules.js +498 -0
  77. package/dist/safety/denyRules.js.map +1 -0
  78. package/dist/safety/envClassifier.d.ts +45 -0
  79. package/dist/safety/envClassifier.d.ts.map +1 -0
  80. package/dist/safety/envClassifier.js +99 -0
  81. package/dist/safety/envClassifier.js.map +1 -0
  82. package/dist/safety/index.d.ts +83 -0
  83. package/dist/safety/index.d.ts.map +1 -0
  84. package/dist/safety/index.js +184 -0
  85. package/dist/safety/index.js.map +1 -0
  86. package/dist/safety/limitSignals.d.ts +36 -0
  87. package/dist/safety/limitSignals.d.ts.map +1 -0
  88. package/dist/safety/limitSignals.js +79 -0
  89. package/dist/safety/limitSignals.js.map +1 -0
  90. package/dist/safety/paths.d.ts +32 -0
  91. package/dist/safety/paths.d.ts.map +1 -0
  92. package/dist/safety/paths.js +102 -0
  93. package/dist/safety/paths.js.map +1 -0
  94. package/dist/safety/redact.d.ts +17 -0
  95. package/dist/safety/redact.d.ts.map +1 -0
  96. package/dist/safety/redact.js +85 -0
  97. package/dist/safety/redact.js.map +1 -0
  98. package/dist/spawnEnv.d.ts +18 -0
  99. package/dist/spawnEnv.d.ts.map +1 -0
  100. package/dist/spawnEnv.js +43 -0
  101. package/dist/spawnEnv.js.map +1 -0
  102. package/dist/store/auditLog.d.ts +28 -0
  103. package/dist/store/auditLog.d.ts.map +1 -0
  104. package/dist/store/auditLog.js +48 -0
  105. package/dist/store/auditLog.js.map +1 -0
  106. package/dist/store/index.d.ts +140 -0
  107. package/dist/store/index.d.ts.map +1 -0
  108. package/dist/store/index.js +648 -0
  109. package/dist/store/index.js.map +1 -0
  110. package/dist/store/schema.d.ts +17 -0
  111. package/dist/store/schema.d.ts.map +1 -0
  112. package/dist/store/schema.js +197 -0
  113. package/dist/store/schema.js.map +1 -0
  114. package/dist/system.d.ts +69 -0
  115. package/dist/system.d.ts.map +1 -0
  116. package/dist/system.js +135 -0
  117. package/dist/system.js.map +1 -0
  118. package/dist/workerManager.d.ts +80 -0
  119. package/dist/workerManager.d.ts.map +1 -0
  120. package/dist/workerManager.js +280 -0
  121. package/dist/workerManager.js.map +1 -0
  122. package/dist/worktrees.d.ts +74 -0
  123. package/dist/worktrees.d.ts.map +1 -0
  124. package/dist/worktrees.js +210 -0
  125. package/dist/worktrees.js.map +1 -0
  126. package/package.json +48 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secrets.js","sourceRoot":"","sources":["../../src/plugins/secrets.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Startup preflight & doctor checks (§2, §13.3). The cardinal rule: billing
3
+ * must stay on the Max subscription, never pay-as-you-go API. `ANTHROPIC_API_KEY`
4
+ * (and the provider-routing flags) must not be set; if they are, we refuse.
5
+ */
6
+ /** Result of the provider-env check. */
7
+ export interface ProviderEnvCheck {
8
+ ok: boolean;
9
+ /** Offending environment variables that must be unset before running. */
10
+ offenders: string[];
11
+ }
12
+ /**
13
+ * Fails if any provider credential / routing override is present in the current
14
+ * environment (§2, §13.3). These override subscription auth and switch billing.
15
+ */
16
+ export declare function checkProviderEnv(env?: NodeJS.ProcessEnv): ProviderEnvCheck;
17
+ /** A single doctor check line. */
18
+ export interface DoctorCheck {
19
+ name: string;
20
+ ok: boolean;
21
+ detail: string;
22
+ }
23
+ /** Result of the live subscription/auth probe. */
24
+ export interface LiveAuthResult {
25
+ ok: boolean;
26
+ apiKeySource?: string;
27
+ model?: string;
28
+ error?: string;
29
+ }
30
+ /**
31
+ * Runs a trivial SDK query and reads the init message to confirm the CLI can
32
+ * start without an API key, surfacing the reported auth source (§2 preflight).
33
+ * Best-effort: bounded by `timeoutMs`, then aborted.
34
+ */
35
+ export declare function liveAuthCheck(timeoutMs?: number): Promise<LiveAuthResult>;
36
+ /** Runs the synchronous portion of `orc doctor` (§9). */
37
+ export declare function runDoctorSync(): DoctorCheck[];
38
+ //# sourceMappingURL=preflight.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preflight.d.ts","sourceRoot":"","sources":["../src/preflight.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,wCAAwC;AACxC,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,OAAO,CAAC;IACZ,yEAAyE;IACzE,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,gBAAgB,CAGlB;AAED,kCAAkC;AAClC,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,kDAAkD;AAClD,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,OAAO,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,wBAAsB,aAAa,CACjC,SAAS,SAAS,GACjB,OAAO,CAAC,cAAc,CAAC,CAwCzB;AAED,yDAAyD;AACzD,wBAAgB,aAAa,IAAI,WAAW,EAAE,CAmD7C"}
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Startup preflight & doctor checks (§2, §13.3). The cardinal rule: billing
3
+ * must stay on the Max subscription, never pay-as-you-go API. `ANTHROPIC_API_KEY`
4
+ * (and the provider-routing flags) must not be set; if they are, we refuse.
5
+ */
6
+ import { execFileSync } from "node:child_process";
7
+ import { statfsSync } from "node:fs";
8
+ import { query as sdkQuery } from "@anthropic-ai/claude-agent-sdk";
9
+ import { STRIPPED_ENV_KEYS } from "./spawnEnv.js";
10
+ /**
11
+ * Fails if any provider credential / routing override is present in the current
12
+ * environment (§2, §13.3). These override subscription auth and switch billing.
13
+ */
14
+ export function checkProviderEnv(env = process.env) {
15
+ const offenders = STRIPPED_ENV_KEYS.filter((k) => env[k] !== undefined);
16
+ return { ok: offenders.length === 0, offenders };
17
+ }
18
+ /**
19
+ * Runs a trivial SDK query and reads the init message to confirm the CLI can
20
+ * start without an API key, surfacing the reported auth source (§2 preflight).
21
+ * Best-effort: bounded by `timeoutMs`, then aborted.
22
+ */
23
+ export async function liveAuthCheck(timeoutMs = 20_000) {
24
+ const controller = new AbortController();
25
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
26
+ try {
27
+ const q = sdkQuery({
28
+ prompt: "Reply with the single word: ok",
29
+ options: {
30
+ maxTurns: 1,
31
+ abortController: controller,
32
+ env: Object.fromEntries(Object.entries(process.env).filter(([k]) => !STRIPPED_ENV_KEYS.includes(k))),
33
+ },
34
+ });
35
+ for await (const message of q) {
36
+ if (message.type === "system" && message.subtype === "init") {
37
+ return {
38
+ ok: true,
39
+ apiKeySource: message.apiKeySource,
40
+ model: message.model,
41
+ };
42
+ }
43
+ if (message.type === "result")
44
+ break;
45
+ }
46
+ return { ok: true };
47
+ }
48
+ catch (err) {
49
+ return {
50
+ ok: false,
51
+ error: err instanceof Error ? err.message : String(err),
52
+ };
53
+ }
54
+ finally {
55
+ clearTimeout(timer);
56
+ }
57
+ }
58
+ /** Runs the synchronous portion of `orc doctor` (§9). */
59
+ export function runDoctorSync() {
60
+ const checks = [];
61
+ const env = checkProviderEnv();
62
+ checks.push({
63
+ name: "subscription billing (no API key)",
64
+ ok: env.ok,
65
+ detail: env.ok
66
+ ? "no provider credentials in environment"
67
+ : `unset before running: ${env.offenders.join(", ")}`,
68
+ });
69
+ const [major] = process.versions.node.split(".").map(Number);
70
+ checks.push({
71
+ name: "node >= 22",
72
+ ok: (major ?? 0) >= 22,
73
+ detail: `node ${process.versions.node}`,
74
+ });
75
+ try {
76
+ const gitVersion = execFileSync("git", ["--version"], {
77
+ encoding: "utf8",
78
+ }).trim();
79
+ checks.push({ name: "git available", ok: true, detail: gitVersion });
80
+ }
81
+ catch {
82
+ checks.push({
83
+ name: "git available",
84
+ ok: false,
85
+ detail: "git not found on PATH",
86
+ });
87
+ }
88
+ // Disk headroom for SQLite + audit JSONL + reports (§13.9).
89
+ try {
90
+ const fs = statfsSync(process.cwd());
91
+ const freeBytes = fs.bfree * fs.bsize;
92
+ const freeGb = freeBytes / 1024 ** 3;
93
+ checks.push({
94
+ name: "disk space",
95
+ ok: freeGb >= 1,
96
+ detail: `${freeGb.toFixed(1)} GiB free`,
97
+ });
98
+ }
99
+ catch {
100
+ checks.push({
101
+ name: "disk space",
102
+ ok: true,
103
+ detail: "unavailable (skipped)",
104
+ });
105
+ }
106
+ return checks;
107
+ }
108
+ //# sourceMappingURL=preflight.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preflight.js","sourceRoot":"","sources":["../src/preflight.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Reporting engine (§11). Renders Markdown status reports from the store — not
3
+ * from an LLM — on interval, milestones, manual request, and run end. Each
4
+ * report is persisted as a {@link Report} row, written to
5
+ * `reports/<run>/<timestamp>.md` (plus `latest.md` for easy tailing), and
6
+ * announced on the bus as `report.new` for the UI. The same body goes to every
7
+ * sink (UI, CLI, files).
8
+ */
9
+ import type { OrchestratorConfig, Report, ReportTrigger, Run } from "@orc-brain/shared";
10
+ import type { Store } from "./store/index.js";
11
+ import type { EventBus } from "./eventBus.js";
12
+ /** Resolves the reports directory under a repo's `.orc` state dir. */
13
+ export declare function reportsDirFor(stateDir: string): string;
14
+ /** Generates and distributes reports for runs. */
15
+ export declare class ReportingEngine {
16
+ private readonly store;
17
+ private readonly bus;
18
+ private readonly config;
19
+ private readonly reportsDir;
20
+ /** Injected clock keeps burn-rate math testable. */
21
+ private readonly now;
22
+ private readonly timers;
23
+ constructor(store: Store, bus: EventBus, config: OrchestratorConfig, reportsDir: string,
24
+ /** Injected clock keeps burn-rate math testable. */
25
+ now?: () => Date);
26
+ /** Starts the interval-report timer for a run (§11). Idempotent. */
27
+ startInterval(runId: string): void;
28
+ /** Stops the interval timer for a run. */
29
+ stopInterval(runId: string): void;
30
+ /** Stops all timers (called on shutdown). */
31
+ stopAll(): void;
32
+ /**
33
+ * Generates a report for a run, persists it, writes the Markdown files, and
34
+ * emits `report.new`. Returns the stored {@link Report} (or null if the run
35
+ * is unknown).
36
+ */
37
+ generate(runId: string, trigger: ReportTrigger): Report | null;
38
+ /** Renders the Markdown body from the store (§11 contents). */
39
+ renderMarkdown(run: Run, trigger: ReportTrigger): string;
40
+ }
41
+ //# sourceMappingURL=reporting.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reporting.d.ts","sourceRoot":"","sources":["../src/reporting.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EACV,kBAAkB,EAClB,MAAM,EACN,aAAa,EACb,GAAG,EAEJ,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C,sEAAsE;AACtE,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEtD;AAwBD,kDAAkD;AAClD,qBAAa,eAAe;IAIxB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,oDAAoD;IACpD,OAAO,CAAC,QAAQ,CAAC,GAAG;IARtB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqD;gBAGzD,KAAK,EAAE,KAAK,EACZ,GAAG,EAAE,QAAQ,EACb,MAAM,EAAE,kBAAkB,EAC1B,UAAU,EAAE,MAAM;IACnC,oDAAoD;IACnC,GAAG,GAAE,MAAM,IAAuB;IAGrD,oEAAoE;IACpE,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAalC,0CAA0C;IAC1C,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAQjC,6CAA6C;IAC7C,OAAO,IAAI,IAAI;IAKf;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,MAAM,GAAG,IAAI;IA+B9D,+DAA+D;IAC/D,cAAc,CAAC,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,aAAa,GAAG,MAAM;CA4HzD"}
@@ -0,0 +1,229 @@
1
+ /**
2
+ * Reporting engine (§11). Renders Markdown status reports from the store — not
3
+ * from an LLM — on interval, milestones, manual request, and run end. Each
4
+ * report is persisted as a {@link Report} row, written to
5
+ * `reports/<run>/<timestamp>.md` (plus `latest.md` for easy tailing), and
6
+ * announced on the bus as `report.new` for the UI. The same body goes to every
7
+ * sink (UI, CLI, files).
8
+ */
9
+ import { mkdirSync, writeFileSync } from "node:fs";
10
+ import { join } from "node:path";
11
+ /** Resolves the reports directory under a repo's `.orc` state dir. */
12
+ export function reportsDirFor(stateDir) {
13
+ return join(stateDir, "reports");
14
+ }
15
+ const STATUS_ORDER = [
16
+ "done",
17
+ "running",
18
+ "queued",
19
+ "pending",
20
+ "paused",
21
+ "blocked",
22
+ "failed",
23
+ "skipped",
24
+ "cancelled",
25
+ ];
26
+ function pct(n, d) {
27
+ if (d <= 0)
28
+ return "0%";
29
+ return `${Math.round((100 * n) / d)}%`;
30
+ }
31
+ function minutesBetween(a, b) {
32
+ if (!a)
33
+ return 0;
34
+ return (new Date(b).getTime() - new Date(a).getTime()) / 60_000;
35
+ }
36
+ /** Generates and distributes reports for runs. */
37
+ export class ReportingEngine {
38
+ store;
39
+ bus;
40
+ config;
41
+ reportsDir;
42
+ now;
43
+ timers = new Map();
44
+ constructor(store, bus, config, reportsDir,
45
+ /** Injected clock keeps burn-rate math testable. */
46
+ now = () => new Date()) {
47
+ this.store = store;
48
+ this.bus = bus;
49
+ this.config = config;
50
+ this.reportsDir = reportsDir;
51
+ this.now = now;
52
+ }
53
+ /** Starts the interval-report timer for a run (§11). Idempotent. */
54
+ startInterval(runId) {
55
+ if (this.timers.has(runId))
56
+ return;
57
+ const ms = Math.max(1, this.config.reporting.interval_minutes) * 60_000;
58
+ const timer = setInterval(() => {
59
+ const run = this.store.getRun(runId);
60
+ if (!run || run.state !== "running")
61
+ return;
62
+ this.generate(runId, "interval");
63
+ }, ms);
64
+ // Do not keep the process alive solely for reporting.
65
+ if (typeof timer.unref === "function")
66
+ timer.unref();
67
+ this.timers.set(runId, timer);
68
+ }
69
+ /** Stops the interval timer for a run. */
70
+ stopInterval(runId) {
71
+ const timer = this.timers.get(runId);
72
+ if (timer) {
73
+ clearInterval(timer);
74
+ this.timers.delete(runId);
75
+ }
76
+ }
77
+ /** Stops all timers (called on shutdown). */
78
+ stopAll() {
79
+ for (const t of this.timers.values())
80
+ clearInterval(t);
81
+ this.timers.clear();
82
+ }
83
+ /**
84
+ * Generates a report for a run, persists it, writes the Markdown files, and
85
+ * emits `report.new`. Returns the stored {@link Report} (or null if the run
86
+ * is unknown).
87
+ */
88
+ generate(runId, trigger) {
89
+ const run = this.store.getRun(runId);
90
+ if (!run)
91
+ return null;
92
+ const content = this.renderMarkdown(run, trigger);
93
+ const dir = join(this.reportsDir, runId);
94
+ let path = null;
95
+ try {
96
+ mkdirSync(dir, { recursive: true });
97
+ const stamp = this.now().toISOString().replace(/[:.]/g, "-");
98
+ path = join(dir, `${stamp}.md`);
99
+ writeFileSync(path, content);
100
+ writeFileSync(join(dir, "latest.md"), content);
101
+ }
102
+ catch {
103
+ path = null; // File sink is best-effort; the DB row is the source of truth.
104
+ }
105
+ const report = this.store.insertReport({
106
+ run_id: runId,
107
+ trigger,
108
+ content_md: content,
109
+ path,
110
+ });
111
+ this.bus.publish({
112
+ type: "report.new",
113
+ run_id: runId,
114
+ payload: { report_id: report.id, trigger, path },
115
+ });
116
+ return report;
117
+ }
118
+ /** Renders the Markdown body from the store (§11 contents). */
119
+ renderMarkdown(run, trigger) {
120
+ const goal = this.store.getGoal(run.goal_id);
121
+ const tasks = this.store.listTasksByGoal(run.goal_id);
122
+ const scopes = this.store.listScopesByGoal(run.goal_id);
123
+ const counts = this.store.countTasksByStatus(run.goal_id);
124
+ const total = tasks.length;
125
+ const done = counts.done ?? 0;
126
+ const nowIso = this.now().toISOString();
127
+ const wallMin = minutesBetween(run.started_at, run.finished_at ?? nowIso);
128
+ const spent = this.store.sumCostForRun(run.id);
129
+ const burnPerMin = wallMin > 0 ? spent / wallMin : 0;
130
+ const fracDone = total > 0 ? done / total : 0;
131
+ const projected = fracDone > 0 ? spent / fracDone : spent;
132
+ const L = [];
133
+ L.push(`# Report — ${goal?.title ?? run.goal_id}`);
134
+ L.push("");
135
+ L.push(`- **Trigger:** ${trigger}`);
136
+ L.push(`- **Generated:** ${nowIso}`);
137
+ L.push(`- **Run state:** \`${run.state}\``);
138
+ L.push(`- **Wall-clock:** ${wallMin.toFixed(1)} min`);
139
+ L.push(`- **Tasks done:** ${done}/${total} (${pct(done, total)})`);
140
+ L.push("");
141
+ // Progress vs success criteria (Planner checklist).
142
+ if (goal && goal.success_criteria.length) {
143
+ L.push("## Success criteria");
144
+ for (const c of goal.success_criteria) {
145
+ L.push(`- [${run.state === "done" ? "x" : " "}] ${c.description}`);
146
+ }
147
+ L.push("");
148
+ }
149
+ // Task table by status.
150
+ L.push("## Tasks");
151
+ L.push("| status | count |");
152
+ L.push("| --- | --- |");
153
+ for (const status of STATUS_ORDER) {
154
+ const n = counts[status];
155
+ if (n)
156
+ L.push(`| ${status} | ${n} |`);
157
+ }
158
+ L.push("");
159
+ // Budget.
160
+ L.push("## Budget");
161
+ L.push(`- Spent (est.): $${spent.toFixed(4)} / $${run.budget_usd.toFixed(2)} (${run.budget_state})`);
162
+ L.push(`- Burn rate: $${burnPerMin.toFixed(4)}/min`);
163
+ L.push(`- Projected completion (est.): $${projected.toFixed(4)}`);
164
+ L.push("");
165
+ // Currently running subagents.
166
+ const running = tasks.filter((t) => t.status === "running");
167
+ if (running.length) {
168
+ L.push("## Running now");
169
+ for (const t of running) {
170
+ const sub = this.store.listSubagentsByTask(t.id).at(-1);
171
+ const tool = sub?.last_tool_call &&
172
+ typeof sub.last_tool_call === "object" &&
173
+ "name" in sub.last_tool_call
174
+ ? sub.last_tool_call.name
175
+ : "—";
176
+ L.push(`- ${t.title} [${t.model_used ?? "?"}] · ${tool}`);
177
+ }
178
+ L.push("");
179
+ }
180
+ // Scope branches (spec 002 §R8): settled worktree scopes leave a branch
181
+ // for manual merge; failed scopes also keep their worktree for debugging.
182
+ const withBranches = scopes.filter((s) => s.branch_name);
183
+ if (withBranches.length) {
184
+ L.push("## Scope branches");
185
+ for (const s of withBranches) {
186
+ const note = s.status === "done"
187
+ ? "ready to merge"
188
+ : s.worktree_path
189
+ ? `worktree kept at ${s.worktree_path}`
190
+ : s.status;
191
+ L.push(`- \`${s.branch_name}\` — ${s.name} (${note})`);
192
+ }
193
+ L.push("");
194
+ }
195
+ // Blockers & escalations needing the operator.
196
+ const escalations = this.store.listOpenEscalations(run.id);
197
+ if (escalations.length) {
198
+ L.push("## Blockers & escalations");
199
+ for (const e of escalations) {
200
+ L.push(`- **${e.rule_id}** on \`${e.tool_name}\` — ${e.input_summary}`);
201
+ }
202
+ L.push("");
203
+ }
204
+ // Deviations: retries (attempt>0), dirty pauses, degraded routing.
205
+ const retried = tasks.filter((t) => t.attempt > 0);
206
+ const dirty = tasks.filter((t) => t.dirty);
207
+ if (retried.length || dirty.length) {
208
+ L.push("## Deviations");
209
+ for (const t of retried)
210
+ L.push(`- retry: ${t.title} (attempt ${t.attempt})`);
211
+ for (const t of dirty)
212
+ L.push(`- dirty pause: ${t.title} (verify workspace on resume)`);
213
+ L.push("");
214
+ }
215
+ // Next planned dispatches: pending/queued tasks whose deps are met-ish.
216
+ const next = tasks
217
+ .filter((t) => t.status === "pending" || t.status === "queued")
218
+ .slice(0, 8);
219
+ if (next.length) {
220
+ L.push("## Next planned dispatches");
221
+ for (const t of next)
222
+ L.push(`- ${t.title} (${t.task_type})`);
223
+ L.push("");
224
+ }
225
+ L.push(`_Scopes: ${scopes.length}. Report generated from the store (§11)._`);
226
+ return L.join("\n");
227
+ }
228
+ }
229
+ //# sourceMappingURL=reporting.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reporting.js","sourceRoot":"","sources":["../src/reporting.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Destructive-command interception (§8.2). Bash input is parsed with a real
3
+ * shell tokenizer (not regex-only) to unwrap `sh -c`, `xargs`, `env`, `sudo`,
4
+ * command substitution, and `&&` chains, then each resolved command is matched
5
+ * against rule classes. A regex backstop covers unparseable input and
6
+ * substitution-hidden binaries; unparseable input denies in production scopes.
7
+ */
8
+ import type { DevPosture, Environment } from "@orc-brain/shared";
9
+ /** Destructive rule classes (§8.2). Keys align with `SafetyConfig.dev_posture`. */
10
+ export type RuleClass = "filesystem" | "vcs" | "database" | "infra" | "publish" | "credential" | "network";
11
+ /** Verdict severity, most severe first. */
12
+ export type Verdict = "deny" | "require_approval" | "allow_with_audit" | "allow";
13
+ /** A rule that fired against a command. */
14
+ export interface RuleMatch {
15
+ rule_id: string;
16
+ rule_class: RuleClass;
17
+ reason: string;
18
+ }
19
+ /** Final decision for a tool call after applying environment posture. */
20
+ export interface DenyDecision {
21
+ verdict: Verdict;
22
+ match: RuleMatch | null;
23
+ }
24
+ /** Context needed to evaluate a tool call against the deny rules. */
25
+ export interface DenyContext {
26
+ environment: Environment;
27
+ cwd: string;
28
+ path_allowlist: string[];
29
+ path_denylist: string[];
30
+ dev_posture: Record<string, DevPosture>;
31
+ }
32
+ interface ParsedCommand {
33
+ /** Command name + arguments (no operators/redirections). */
34
+ args: string[];
35
+ /** Redirection targets (e.g. the `x` in `> x`). */
36
+ redirects: string[];
37
+ /** Operator that immediately follows this command in the pipeline, if any. */
38
+ nextOp?: string;
39
+ }
40
+ /** Detects destructive SQL inside a string (DROP/TRUNCATE, unqualified DML). */
41
+ export declare function matchSql(sql: string): RuleMatch | null;
42
+ /** Matches a single resolved command against every rule class (§8.2). */
43
+ export declare function matchCommand(cmd: ParsedCommand, ctx: DenyContext): RuleMatch | null;
44
+ /**
45
+ * Evaluates a Bash command string (§8.2). Recursively unwraps shells, xargs,
46
+ * env, and command substitution; on parse failure denies in production scopes.
47
+ */
48
+ export declare function evaluateBash(command: string, ctx: DenyContext): DenyDecision;
49
+ /**
50
+ * Evaluates a Write/Edit file target against the scope allowlist (§8.2, §8.3).
51
+ * A write outside the allowlist (or inside the denylist) is filesystem-class.
52
+ */
53
+ export declare function evaluatePathWrite(filePath: string, ctx: DenyContext): DenyDecision;
54
+ /** Evaluates a Read file target — blocks credential/dotenv reads (§8.2). */
55
+ export declare function evaluatePathRead(filePath: string, ctx: DenyContext): DenyDecision;
56
+ export {};
57
+ //# sourceMappingURL=denyRules.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"denyRules.d.ts","sourceRoot":"","sources":["../../src/safety/denyRules.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AASjE,mFAAmF;AACnF,MAAM,MAAM,SAAS,GACjB,YAAY,GACZ,KAAK,GACL,UAAU,GACV,OAAO,GACP,SAAS,GACT,YAAY,GACZ,SAAS,CAAC;AAEd,2CAA2C;AAC3C,MAAM,MAAM,OAAO,GACjB,MAAM,GAAG,kBAAkB,GAAG,kBAAkB,GAAG,OAAO,CAAC;AAS7D,2CAA2C;AAC3C,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,SAAS,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,yEAAyE;AACzE,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;CACzB;AAED,qEAAqE;AACrE,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,WAAW,CAAC;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;CACzC;AA4BD,UAAU,aAAa;IACrB,4DAA4D;IAC5D,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,mDAAmD;IACnD,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,8EAA8E;IAC9E,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAuID,gFAAgF;AAChF,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAwBtD;AAgBD,yEAAyE;AACzE,wBAAgB,YAAY,CAC1B,GAAG,EAAE,aAAa,EAClB,GAAG,EAAE,WAAW,GACf,SAAS,GAAG,IAAI,CAiMlB;AAcD;;;GAGG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,GAAG,YAAY,CAiF5E;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,WAAW,GACf,YAAY,CAuBd;AAED,4EAA4E;AAC5E,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,WAAW,GACf,YAAY,CA0Bd"}