@mclawnet/swarm 0.1.13 → 0.1.15
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.
- package/dist/__tests__/always-on-activity-reader.test.d.ts +2 -0
- package/dist/__tests__/always-on-activity-reader.test.d.ts.map +1 -0
- package/dist/__tests__/always-on-activity-reader.test.js +193 -0
- package/dist/__tests__/always-on-activity-reader.test.js.map +1 -0
- package/dist/__tests__/always-on-config.test.d.ts +2 -0
- package/dist/__tests__/always-on-config.test.d.ts.map +1 -0
- package/dist/__tests__/always-on-config.test.js +285 -0
- package/dist/__tests__/always-on-config.test.js.map +1 -0
- package/dist/__tests__/always-on-manager.test.d.ts +2 -0
- package/dist/__tests__/always-on-manager.test.d.ts.map +1 -0
- package/dist/__tests__/always-on-manager.test.js +797 -0
- package/dist/__tests__/always-on-manager.test.js.map +1 -0
- package/dist/__tests__/always-on-parity.test.d.ts +2 -0
- package/dist/__tests__/always-on-parity.test.d.ts.map +1 -0
- package/dist/__tests__/always-on-parity.test.js +20 -0
- package/dist/__tests__/always-on-parity.test.js.map +1 -0
- package/dist/__tests__/cascade-picker.test.d.ts +2 -0
- package/dist/__tests__/cascade-picker.test.d.ts.map +1 -0
- package/dist/__tests__/cascade-picker.test.js +122 -0
- package/dist/__tests__/cascade-picker.test.js.map +1 -0
- package/dist/__tests__/coordinator-shipment.test.d.ts +2 -0
- package/dist/__tests__/coordinator-shipment.test.d.ts.map +1 -0
- package/dist/__tests__/coordinator-shipment.test.js +280 -0
- package/dist/__tests__/coordinator-shipment.test.js.map +1 -0
- package/dist/__tests__/coordinator-workspace-recover.test.d.ts +2 -0
- package/dist/__tests__/coordinator-workspace-recover.test.d.ts.map +1 -0
- package/dist/__tests__/coordinator-workspace-recover.test.js +140 -0
- package/dist/__tests__/coordinator-workspace-recover.test.js.map +1 -0
- package/dist/__tests__/coordinator-workspace.test.d.ts +2 -0
- package/dist/__tests__/coordinator-workspace.test.d.ts.map +1 -0
- package/dist/__tests__/coordinator-workspace.test.js +135 -0
- package/dist/__tests__/coordinator-workspace.test.js.map +1 -0
- package/dist/__tests__/default-runner-epipe.test.d.ts +2 -0
- package/dist/__tests__/default-runner-epipe.test.d.ts.map +1 -0
- package/dist/__tests__/default-runner-epipe.test.js +43 -0
- package/dist/__tests__/default-runner-epipe.test.js.map +1 -0
- package/dist/__tests__/discovery-scheduler.test.d.ts +2 -0
- package/dist/__tests__/discovery-scheduler.test.d.ts.map +1 -0
- package/dist/__tests__/discovery-scheduler.test.js +367 -0
- package/dist/__tests__/discovery-scheduler.test.js.map +1 -0
- package/dist/__tests__/env-forward-e2e.test.d.ts +2 -0
- package/dist/__tests__/env-forward-e2e.test.d.ts.map +1 -0
- package/dist/__tests__/env-forward-e2e.test.js +57 -0
- package/dist/__tests__/env-forward-e2e.test.js.map +1 -0
- package/dist/__tests__/gh-pr-creator.test.d.ts +2 -0
- package/dist/__tests__/gh-pr-creator.test.d.ts.map +1 -0
- package/dist/__tests__/gh-pr-creator.test.js +107 -0
- package/dist/__tests__/gh-pr-creator.test.js.map +1 -0
- package/dist/__tests__/git-worktree-provider.test.d.ts +2 -0
- package/dist/__tests__/git-worktree-provider.test.d.ts.map +1 -0
- package/dist/__tests__/git-worktree-provider.test.js +98 -0
- package/dist/__tests__/git-worktree-provider.test.js.map +1 -0
- package/dist/__tests__/gitignore-check.test.d.ts +2 -0
- package/dist/__tests__/gitignore-check.test.d.ts.map +1 -0
- package/dist/__tests__/gitignore-check.test.js +39 -0
- package/dist/__tests__/gitignore-check.test.js.map +1 -0
- package/dist/__tests__/idea-research-source.test.d.ts +2 -0
- package/dist/__tests__/idea-research-source.test.d.ts.map +1 -0
- package/dist/__tests__/idea-research-source.test.js +425 -0
- package/dist/__tests__/idea-research-source.test.js.map +1 -0
- package/dist/__tests__/idea-todo-source.test.d.ts +2 -0
- package/dist/__tests__/idea-todo-source.test.d.ts.map +1 -0
- package/dist/__tests__/idea-todo-source.test.js +258 -0
- package/dist/__tests__/idea-todo-source.test.js.map +1 -0
- package/dist/__tests__/introspection-dedupe.test.d.ts +2 -0
- package/dist/__tests__/introspection-dedupe.test.d.ts.map +1 -0
- package/dist/__tests__/introspection-dedupe.test.js +484 -0
- package/dist/__tests__/introspection-dedupe.test.js.map +1 -0
- package/dist/__tests__/introspection-source.test.d.ts +2 -0
- package/dist/__tests__/introspection-source.test.d.ts.map +1 -0
- package/dist/__tests__/introspection-source.test.js +1051 -0
- package/dist/__tests__/introspection-source.test.js.map +1 -0
- package/dist/__tests__/migration-roles.test.js +1 -22
- package/dist/__tests__/migration-roles.test.js.map +1 -1
- package/dist/__tests__/reconcile-researching.test.d.ts +2 -0
- package/dist/__tests__/reconcile-researching.test.d.ts.map +1 -0
- package/dist/__tests__/reconcile-researching.test.js +224 -0
- package/dist/__tests__/reconcile-researching.test.js.map +1 -0
- package/dist/__tests__/role-loader-preamble-all.test.js +3 -1
- package/dist/__tests__/role-loader-preamble-all.test.js.map +1 -1
- package/dist/__tests__/role-loader.test.js +95 -0
- package/dist/__tests__/role-loader.test.js.map +1 -1
- package/dist/__tests__/role-prompt-no-legacy-protocol.test.js +3 -1
- package/dist/__tests__/role-prompt-no-legacy-protocol.test.js.map +1 -1
- package/dist/__tests__/secret-scrub.test.d.ts +2 -0
- package/dist/__tests__/secret-scrub.test.d.ts.map +1 -0
- package/dist/__tests__/secret-scrub.test.js +55 -0
- package/dist/__tests__/secret-scrub.test.js.map +1 -0
- package/dist/__tests__/shipment-actions.test.d.ts +2 -0
- package/dist/__tests__/shipment-actions.test.d.ts.map +1 -0
- package/dist/__tests__/shipment-actions.test.js +378 -0
- package/dist/__tests__/shipment-actions.test.js.map +1 -0
- package/dist/__tests__/shipment-persistence.test.d.ts +2 -0
- package/dist/__tests__/shipment-persistence.test.d.ts.map +1 -0
- package/dist/__tests__/shipment-persistence.test.js +120 -0
- package/dist/__tests__/shipment-persistence.test.js.map +1 -0
- package/dist/__tests__/shipment-pipeline.test.d.ts +2 -0
- package/dist/__tests__/shipment-pipeline.test.d.ts.map +1 -0
- package/dist/__tests__/shipment-pipeline.test.js +392 -0
- package/dist/__tests__/shipment-pipeline.test.js.map +1 -0
- package/dist/__tests__/shipment-report.test.d.ts +2 -0
- package/dist/__tests__/shipment-report.test.d.ts.map +1 -0
- package/dist/__tests__/shipment-report.test.js +78 -0
- package/dist/__tests__/shipment-report.test.js.map +1 -0
- package/dist/__tests__/shipment-stdin-integration.test.d.ts +2 -0
- package/dist/__tests__/shipment-stdin-integration.test.d.ts.map +1 -0
- package/dist/__tests__/shipment-stdin-integration.test.js +49 -0
- package/dist/__tests__/shipment-stdin-integration.test.js.map +1 -0
- package/dist/__tests__/shipment-type-parity.test.d.ts +2 -0
- package/dist/__tests__/shipment-type-parity.test.d.ts.map +1 -0
- package/dist/__tests__/shipment-type-parity.test.js +10 -0
- package/dist/__tests__/shipment-type-parity.test.js.map +1 -0
- package/dist/__tests__/snapshot-copy-provider.test.d.ts +2 -0
- package/dist/__tests__/snapshot-copy-provider.test.d.ts.map +1 -0
- package/dist/__tests__/snapshot-copy-provider.test.js +88 -0
- package/dist/__tests__/snapshot-copy-provider.test.js.map +1 -0
- package/dist/__tests__/swarm-coordinator-backend.test.js +153 -0
- package/dist/__tests__/swarm-coordinator-backend.test.js.map +1 -1
- package/dist/__tests__/swarm-coordinator-complete-intercept.test.d.ts +2 -0
- package/dist/__tests__/swarm-coordinator-complete-intercept.test.d.ts.map +1 -0
- package/dist/__tests__/swarm-coordinator-complete-intercept.test.js +111 -0
- package/dist/__tests__/swarm-coordinator-complete-intercept.test.js.map +1 -0
- package/dist/__tests__/task-store-source.test.d.ts +2 -0
- package/dist/__tests__/task-store-source.test.d.ts.map +1 -0
- package/dist/__tests__/task-store-source.test.js +56 -0
- package/dist/__tests__/task-store-source.test.js.map +1 -0
- package/dist/__tests__/transport-detect.test.d.ts +2 -0
- package/dist/__tests__/transport-detect.test.d.ts.map +1 -0
- package/dist/__tests__/transport-detect.test.js +92 -0
- package/dist/__tests__/transport-detect.test.js.map +1 -0
- package/dist/__tests__/workcycle-runner-cascade.test.d.ts +2 -0
- package/dist/__tests__/workcycle-runner-cascade.test.d.ts.map +1 -0
- package/dist/__tests__/workcycle-runner-cascade.test.js +203 -0
- package/dist/__tests__/workcycle-runner-cascade.test.js.map +1 -0
- package/dist/__tests__/workcycle-runner.test.d.ts +2 -0
- package/dist/__tests__/workcycle-runner.test.d.ts.map +1 -0
- package/dist/__tests__/workcycle-runner.test.js +369 -0
- package/dist/__tests__/workcycle-runner.test.js.map +1 -0
- package/dist/__tests__/workspace-diff.test.d.ts +2 -0
- package/dist/__tests__/workspace-diff.test.d.ts.map +1 -0
- package/dist/__tests__/workspace-diff.test.js +62 -0
- package/dist/__tests__/workspace-diff.test.js.map +1 -0
- package/dist/__tests__/workspace-manager.test.d.ts +2 -0
- package/dist/__tests__/workspace-manager.test.d.ts.map +1 -0
- package/dist/__tests__/workspace-manager.test.js +120 -0
- package/dist/__tests__/workspace-manager.test.js.map +1 -0
- package/dist/__tests__/workspace-types.test.d.ts +2 -0
- package/dist/__tests__/workspace-types.test.d.ts.map +1 -0
- package/dist/__tests__/workspace-types.test.js +37 -0
- package/dist/__tests__/workspace-types.test.js.map +1 -0
- package/dist/__tests__/worktree-gc.test.d.ts +2 -0
- package/dist/__tests__/worktree-gc.test.d.ts.map +1 -0
- package/dist/__tests__/worktree-gc.test.js +183 -0
- package/dist/__tests__/worktree-gc.test.js.map +1 -0
- package/dist/always-on/activity-reader.d.ts +27 -0
- package/dist/always-on/activity-reader.d.ts.map +1 -0
- package/dist/always-on/activity-reader.js +95 -0
- package/dist/always-on/activity-reader.js.map +1 -0
- package/dist/always-on/always-on-manager.d.ts +170 -0
- package/dist/always-on/always-on-manager.d.ts.map +1 -0
- package/dist/always-on/always-on-manager.js +538 -0
- package/dist/always-on/always-on-manager.js.map +1 -0
- package/dist/always-on/config.d.ts +141 -0
- package/dist/always-on/config.d.ts.map +1 -0
- package/dist/always-on/config.js +324 -0
- package/dist/always-on/config.js.map +1 -0
- package/dist/always-on/discovery-scheduler.d.ts +60 -0
- package/dist/always-on/discovery-scheduler.d.ts.map +1 -0
- package/dist/always-on/discovery-scheduler.js +287 -0
- package/dist/always-on/discovery-scheduler.js.map +1 -0
- package/dist/always-on/ideas-client.d.ts +23 -0
- package/dist/always-on/ideas-client.d.ts.map +1 -0
- package/dist/always-on/ideas-client.js +13 -0
- package/dist/always-on/ideas-client.js.map +1 -0
- package/dist/always-on/reconcile-researching.d.ts +42 -0
- package/dist/always-on/reconcile-researching.d.ts.map +1 -0
- package/dist/always-on/reconcile-researching.js +133 -0
- package/dist/always-on/reconcile-researching.js.map +1 -0
- package/dist/always-on/task-sources/cascade-picker.d.ts +42 -0
- package/dist/always-on/task-sources/cascade-picker.d.ts.map +1 -0
- package/dist/always-on/task-sources/cascade-picker.js +65 -0
- package/dist/always-on/task-sources/cascade-picker.js.map +1 -0
- package/dist/always-on/task-sources/idea-dedupe.d.ts +62 -0
- package/dist/always-on/task-sources/idea-dedupe.d.ts.map +1 -0
- package/dist/always-on/task-sources/idea-dedupe.js +130 -0
- package/dist/always-on/task-sources/idea-dedupe.js.map +1 -0
- package/dist/always-on/task-sources/idea-research-source.d.ts +46 -0
- package/dist/always-on/task-sources/idea-research-source.d.ts.map +1 -0
- package/dist/always-on/task-sources/idea-research-source.js +308 -0
- package/dist/always-on/task-sources/idea-research-source.js.map +1 -0
- package/dist/always-on/task-sources/idea-sort.d.ts +3 -0
- package/dist/always-on/task-sources/idea-sort.d.ts.map +1 -0
- package/dist/always-on/task-sources/idea-sort.js +25 -0
- package/dist/always-on/task-sources/idea-sort.js.map +1 -0
- package/dist/always-on/task-sources/idea-todo-source.d.ts +48 -0
- package/dist/always-on/task-sources/idea-todo-source.d.ts.map +1 -0
- package/dist/always-on/task-sources/idea-todo-source.js +226 -0
- package/dist/always-on/task-sources/idea-todo-source.js.map +1 -0
- package/dist/always-on/task-sources/introspection-source.d.ts +101 -0
- package/dist/always-on/task-sources/introspection-source.d.ts.map +1 -0
- package/dist/always-on/task-sources/introspection-source.js +695 -0
- package/dist/always-on/task-sources/introspection-source.js.map +1 -0
- package/dist/always-on/task-sources/task-store-source.d.ts +15 -0
- package/dist/always-on/task-sources/task-store-source.d.ts.map +1 -0
- package/dist/always-on/task-sources/task-store-source.js +59 -0
- package/dist/always-on/task-sources/task-store-source.js.map +1 -0
- package/dist/always-on/task-sources/types.d.ts +108 -0
- package/dist/always-on/task-sources/types.d.ts.map +1 -0
- package/dist/always-on/task-sources/types.js +13 -0
- package/dist/always-on/task-sources/types.js.map +1 -0
- package/dist/always-on/types.d.ts +76 -0
- package/dist/always-on/types.d.ts.map +1 -0
- package/dist/always-on/types.js +17 -0
- package/dist/always-on/types.js.map +1 -0
- package/dist/always-on/workcycle-runner.d.ts +115 -0
- package/dist/always-on/workcycle-runner.d.ts.map +1 -0
- package/dist/always-on/workcycle-runner.js +285 -0
- package/dist/always-on/workcycle-runner.js.map +1 -0
- package/dist/always-on/worktree-gc.d.ts +41 -0
- package/dist/always-on/worktree-gc.d.ts.map +1 -0
- package/dist/always-on/worktree-gc.js +167 -0
- package/dist/always-on/worktree-gc.js.map +1 -0
- package/dist/index.d.ts +26 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +24 -1
- package/dist/index.js.map +1 -1
- package/dist/persistence.d.ts +37 -1
- package/dist/persistence.d.ts.map +1 -1
- package/dist/persistence.js +48 -0
- package/dist/persistence.js.map +1 -1
- package/dist/retrospective.d.ts.map +1 -1
- package/dist/retrospective.js +6 -0
- package/dist/retrospective.js.map +1 -1
- package/dist/roles/role-loader.d.ts +1 -1
- package/dist/roles/role-loader.d.ts.map +1 -1
- package/dist/roles/role-loader.js +18 -0
- package/dist/roles/role-loader.js.map +1 -1
- package/dist/roles/types.d.ts +12 -0
- package/dist/roles/types.d.ts.map +1 -1
- package/dist/shipment/gh-pr-creator.d.ts +28 -0
- package/dist/shipment/gh-pr-creator.d.ts.map +1 -0
- package/dist/shipment/gh-pr-creator.js +80 -0
- package/dist/shipment/gh-pr-creator.js.map +1 -0
- package/dist/shipment/report.d.ts +27 -0
- package/dist/shipment/report.d.ts.map +1 -0
- package/dist/shipment/report.js +41 -0
- package/dist/shipment/report.js.map +1 -0
- package/dist/shipment/secret-scrub.d.ts +12 -0
- package/dist/shipment/secret-scrub.d.ts.map +1 -0
- package/dist/shipment/secret-scrub.js +30 -0
- package/dist/shipment/secret-scrub.js.map +1 -0
- package/dist/shipment/shipment-actions.d.ts +85 -0
- package/dist/shipment/shipment-actions.d.ts.map +1 -0
- package/dist/shipment/shipment-actions.js +190 -0
- package/dist/shipment/shipment-actions.js.map +1 -0
- package/dist/shipment/shipment-pipeline.d.ts +48 -0
- package/dist/shipment/shipment-pipeline.d.ts.map +1 -0
- package/dist/shipment/shipment-pipeline.js +256 -0
- package/dist/shipment/shipment-pipeline.js.map +1 -0
- package/dist/shipment/transport-detect.d.ts +16 -0
- package/dist/shipment/transport-detect.d.ts.map +1 -0
- package/dist/shipment/transport-detect.js +54 -0
- package/dist/shipment/transport-detect.js.map +1 -0
- package/dist/shipment/workspace-diff.d.ts +39 -0
- package/dist/shipment/workspace-diff.d.ts.map +1 -0
- package/dist/shipment/workspace-diff.js +64 -0
- package/dist/shipment/workspace-diff.js.map +1 -0
- package/dist/swarm-coordinator.d.ts +20 -1
- package/dist/swarm-coordinator.d.ts.map +1 -1
- package/dist/swarm-coordinator.js +193 -10
- package/dist/swarm-coordinator.js.map +1 -1
- package/dist/types.d.ts +62 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/workspace/git-worktree-provider.d.ts +11 -0
- package/dist/workspace/git-worktree-provider.d.ts.map +1 -0
- package/dist/workspace/git-worktree-provider.js +123 -0
- package/dist/workspace/git-worktree-provider.js.map +1 -0
- package/dist/workspace/gitignore-check.d.ts +10 -0
- package/dist/workspace/gitignore-check.d.ts.map +1 -0
- package/dist/workspace/gitignore-check.js +25 -0
- package/dist/workspace/gitignore-check.js.map +1 -0
- package/dist/workspace/index.d.ts +5 -0
- package/dist/workspace/index.d.ts.map +1 -0
- package/dist/workspace/index.js +5 -0
- package/dist/workspace/index.js.map +1 -0
- package/dist/workspace/snapshot-copy-provider.d.ts +11 -0
- package/dist/workspace/snapshot-copy-provider.d.ts.map +1 -0
- package/dist/workspace/snapshot-copy-provider.js +66 -0
- package/dist/workspace/snapshot-copy-provider.js.map +1 -0
- package/dist/workspace/types.d.ts +36 -0
- package/dist/workspace/types.d.ts.map +1 -0
- package/dist/workspace/types.js +2 -0
- package/dist/workspace/types.js.map +1 -0
- package/dist/workspace/workspace-manager.d.ts +30 -0
- package/dist/workspace/workspace-manager.d.ts.map +1 -0
- package/dist/workspace/workspace-manager.js +104 -0
- package/dist/workspace/workspace-manager.js.map +1 -0
- package/package.json +4 -4
- package/roles/queen.md +1 -0
- package/templates/introspection.md +64 -0
- package/templates/research-only.md +58 -0
- package/roles/preset-analyst-simons.md +0 -39
- package/roles/preset-architect-knuth.md +0 -39
- package/roles/preset-designer-norman.md +0 -39
- package/roles/preset-designer.md +0 -39
- package/roles/preset-dev-carmack.md +0 -39
- package/roles/preset-dev-gosling.md +0 -39
- package/roles/preset-developer.md +0 -52
- package/roles/preset-manager-grove.md +0 -39
- package/roles/preset-manager-musk.md +0 -39
- package/roles/preset-pm.md +0 -78
- package/roles/preset-researcher-feynman.md +0 -39
- package/roles/preset-reviewer.md +0 -46
- package/roles/preset-strategist-buffett.md +0 -39
- package/roles/preset-strategist-munger.md +0 -39
- package/roles/preset-strategist-sunzi.md +0 -39
- package/roles/preset-tester-beck.md +0 -40
- package/roles/preset-tester.md +0 -47
- package/roles/preset-writer-orwell.md +0 -39
- package/roles/preset-writer.md +0 -39
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
export interface AlwaysOnTaskSourcesConfig {
|
|
2
|
+
/** L1 — TaskStore (sprint backlog). Default true. */
|
|
3
|
+
taskStore?: boolean;
|
|
4
|
+
/** L2a — Ideas with status=todo. Default true. */
|
|
5
|
+
ideaTodo?: boolean;
|
|
6
|
+
/** L2b — Ideas with status=idea (research cycle). Default true. */
|
|
7
|
+
ideaResearch?: boolean;
|
|
8
|
+
/** L3 — Queen self-introspection (opt-in). Default false. */
|
|
9
|
+
introspection?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export interface AlwaysOnConfig {
|
|
12
|
+
mode: "off" | "quiet" | "active" | "aggressive";
|
|
13
|
+
/** 1..20 cycles/day, integer. */
|
|
14
|
+
dailyBudget: number;
|
|
15
|
+
/**
|
|
16
|
+
* ISO timestamp; when set and in the future, the scheduler should treat
|
|
17
|
+
* every tick as gated regardless of mode. Cleared by setting back to
|
|
18
|
+
* undefined / null. M7.3 enforces via the manager's `pausedUntil` gate.
|
|
19
|
+
*/
|
|
20
|
+
pausedUntil?: string;
|
|
21
|
+
/**
|
|
22
|
+
* Template (a.k.a. team) name used when AlwaysOnManager spawns a synthetic
|
|
23
|
+
* cycle swarm. Forward-compatible: the UI doesn't expose this yet (lands
|
|
24
|
+
* later), so callers and the persisted config use the DEFAULT below when
|
|
25
|
+
* absent. Validated against an allowlist on read/write — bad values fall
|
|
26
|
+
* back to the default so an unknown template can never bring the scheduler
|
|
27
|
+
* down (C1 hotfix).
|
|
28
|
+
*/
|
|
29
|
+
templateName?: string;
|
|
30
|
+
/**
|
|
31
|
+
* M8.2 — per-source opt-in toggles. Omitted fields fall back to defaults
|
|
32
|
+
* (taskStore / ideaTodo / ideaResearch on; introspection off). Surfaced
|
|
33
|
+
* via JSON edit until M8.3 ships the UI toggles.
|
|
34
|
+
*/
|
|
35
|
+
taskSources?: AlwaysOnTaskSourcesConfig;
|
|
36
|
+
/**
|
|
37
|
+
* M8.2 — cooldown (in hours) between consecutive introspection cycles.
|
|
38
|
+
* Independent of dailyBudget. Default 24. Validated to a sane range on
|
|
39
|
+
* load/save; out-of-range values fall back to the default.
|
|
40
|
+
*/
|
|
41
|
+
introspectionCooldownHours?: number;
|
|
42
|
+
/**
|
|
43
|
+
* M8.2 — runtime state: ISO timestamp of the most recent introspection
|
|
44
|
+
* cycle that fired. Persisted so cooldown gates survive a restart.
|
|
45
|
+
*/
|
|
46
|
+
lastIntrospectionAt?: string;
|
|
47
|
+
/**
|
|
48
|
+
* M8.2 — runtime state: when true, every idea produced by the previous
|
|
49
|
+
* introspection cycle ended up archived. IntrospectionSource self-skips
|
|
50
|
+
* the next cycle while this flag is set; clears as soon as one prior
|
|
51
|
+
* idea survives (status != archived) on the next pre-check.
|
|
52
|
+
*/
|
|
53
|
+
lastIntrospectionRejected?: boolean;
|
|
54
|
+
/**
|
|
55
|
+
* M8 hotfix I1/I2 — fire-and-forget breadcrumb: the swarmId of an
|
|
56
|
+
* introspection cycle that was *spawned* on a prior tick but whose output
|
|
57
|
+
* has not yet been ingested. Set when IntrospectionSource queues the
|
|
58
|
+
* background swarm; cleared once the next pick observes the swarm has
|
|
59
|
+
* reached a terminal state and POSTs (or skips) the ideas. Persisted so
|
|
60
|
+
* an agent restart mid-cycle still picks up the in-flight result. Absent
|
|
61
|
+
* = no pending swarm to reconcile.
|
|
62
|
+
*/
|
|
63
|
+
pendingIntrospectionSwarmId?: string;
|
|
64
|
+
/**
|
|
65
|
+
* PR-B follow-up — workspace.cwd of the pending introspection swarm,
|
|
66
|
+
* captured at spawn time. After `swarm_complete` deletes the swarm from
|
|
67
|
+
* the coordinator registry, `swarmCoordinator.getSwarm()` returns
|
|
68
|
+
* undefined and the spawner can no longer resolve where the queen wrote
|
|
69
|
+
* her candidates. Persisting the cwd alongside the swarm id lets
|
|
70
|
+
* `processPendingSwarm` find the output file in the worktree even when
|
|
71
|
+
* the live workspace handle is gone. Cleared in lockstep with
|
|
72
|
+
* `pendingIntrospectionSwarmId`.
|
|
73
|
+
*/
|
|
74
|
+
pendingIntrospectionWorkspaceCwd?: string;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Runtime counters persisted alongside AlwaysOnConfig on disk so the daily
|
|
78
|
+
* budget survives an agent restart (M7.3). Kept structurally separate from
|
|
79
|
+
* AlwaysOnConfig so the wire-side `AlwaysOnConfig` in @mclawnet/shared can
|
|
80
|
+
* stay a clean user-facing surface — see always-on-parity.test.ts.
|
|
81
|
+
*/
|
|
82
|
+
export interface AlwaysOnRuntimeState {
|
|
83
|
+
/**
|
|
84
|
+
* Current day's fired count (mirrors DiscoveryScheduler.ticksToday). Persists
|
|
85
|
+
* across agent restart so a quick crash + relaunch doesn't reset the budget
|
|
86
|
+
* to 0 and double-spend the cap. Reset to 0 on load when ticksTodayDate is
|
|
87
|
+
* older than today.
|
|
88
|
+
*/
|
|
89
|
+
ticksToday?: number;
|
|
90
|
+
/** YYYY-MM-DD (local) the persisted `ticksToday` belongs to. */
|
|
91
|
+
ticksTodayDate?: string;
|
|
92
|
+
/** ISO timestamp of the most recent fired tick; absent when never. */
|
|
93
|
+
lastFireAt?: string;
|
|
94
|
+
}
|
|
95
|
+
export type AlwaysOnPersistedConfig = AlwaysOnConfig & AlwaysOnRuntimeState;
|
|
96
|
+
export declare const DEFAULT_ALWAYS_ON_CONFIG: AlwaysOnConfig;
|
|
97
|
+
/**
|
|
98
|
+
* M8.2 — default opt-in matrix. taskSources field omitted on disk falls back
|
|
99
|
+
* to this; UI/JSON edits override per-key (omitted keys still resolve to the
|
|
100
|
+
* default). Introspection stays off so the agent never wakes the user with
|
|
101
|
+
* auto-discovered ideas unless they've explicitly opted in.
|
|
102
|
+
*/
|
|
103
|
+
export declare const DEFAULT_ALWAYS_ON_TASK_SOURCES: Required<AlwaysOnTaskSourcesConfig>;
|
|
104
|
+
/** M8.2 — default cooldown between introspection cycles, in hours. */
|
|
105
|
+
export declare const DEFAULT_INTROSPECTION_COOLDOWN_HOURS = 24;
|
|
106
|
+
/**
|
|
107
|
+
* Template used when no override is persisted. "minimal" ships in
|
|
108
|
+
* `packages/@clawnet/swarm/templates/` and is the safest single-role default —
|
|
109
|
+
* picked over the legacy `"default"` literal which never had a backing file
|
|
110
|
+
* and crashed every always-on cycle pre-hotfix (C1).
|
|
111
|
+
*/
|
|
112
|
+
export declare const DEFAULT_ALWAYS_ON_TEMPLATE = "minimal";
|
|
113
|
+
/** Local YYYY-MM-DD (NOT UTC) so the daily-budget midnight matches user time. */
|
|
114
|
+
export declare function localYMD(d: Date): string;
|
|
115
|
+
/** Public so the agent boot scanner can distinguish "no config" from "corrupt config" (I4). */
|
|
116
|
+
export declare function alwaysOnConfigPath(workDir: string, home: string): string;
|
|
117
|
+
/**
|
|
118
|
+
* Merge a (possibly partial) taskSources object over the defaults, returning
|
|
119
|
+
* a fully-resolved record with every field present. The runtime always-on
|
|
120
|
+
* cascade reads this — undefined would force every caller to remember the
|
|
121
|
+
* defaults.
|
|
122
|
+
*/
|
|
123
|
+
export declare function resolveTaskSources(v: AlwaysOnTaskSourcesConfig | undefined): Required<AlwaysOnTaskSourcesConfig>;
|
|
124
|
+
export declare function loadAlwaysOnConfig(workDir: string, home: string): AlwaysOnPersistedConfig;
|
|
125
|
+
export declare function saveAlwaysOnConfig(workDir: string, home: string, config: AlwaysOnPersistedConfig): void;
|
|
126
|
+
/**
|
|
127
|
+
* Merge a partial config update over the persisted baseline. Used by the
|
|
128
|
+
* agent handler so the UI can PATCH only `{mode}` or `{pausedUntil}` without
|
|
129
|
+
* having to reconstruct dailyBudget client-side.
|
|
130
|
+
*
|
|
131
|
+
* `pausedUntil: null` (or empty string) clears the pause; omitting it leaves
|
|
132
|
+
* the existing value alone.
|
|
133
|
+
*/
|
|
134
|
+
export declare function mergeAlwaysOnConfig(current: AlwaysOnPersistedConfig, patch: Omit<Partial<AlwaysOnConfig>, "pausedUntil" | "lastIntrospectionAt" | "lastIntrospectionRejected" | "pendingIntrospectionSwarmId" | "pendingIntrospectionWorkspaceCwd"> & {
|
|
135
|
+
pausedUntil?: string | null;
|
|
136
|
+
lastIntrospectionAt?: string | null;
|
|
137
|
+
lastIntrospectionRejected?: boolean | null;
|
|
138
|
+
pendingIntrospectionSwarmId?: string | null;
|
|
139
|
+
pendingIntrospectionWorkspaceCwd?: string | null;
|
|
140
|
+
}): AlwaysOnPersistedConfig;
|
|
141
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/always-on/config.ts"],"names":[],"mappings":"AAcA,MAAM,WAAW,yBAAyB;IACxC,qDAAqD;IACrD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,kDAAkD;IAClD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,mEAAmE;IACnE,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,6DAA6D;IAC7D,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,YAAY,CAAC;IAChD,iCAAiC;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,WAAW,CAAC,EAAE,yBAAyB,CAAC;IACxC;;;;OAIG;IACH,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC;;;OAGG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B;;;;;OAKG;IACH,yBAAyB,CAAC,EAAE,OAAO,CAAC;IACpC;;;;;;;;OAQG;IACH,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC;;;;;;;;;OASG;IACH,gCAAgC,CAAC,EAAE,MAAM,CAAC;CAC3C;AAED;;;;;GAKG;AACH,MAAM,WAAW,oBAAoB;IACnC;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gEAAgE;IAChE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,sEAAsE;IACtE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,MAAM,uBAAuB,GAAG,cAAc,GAAG,oBAAoB,CAAC;AAE5E,eAAO,MAAM,wBAAwB,EAAE,cAGtC,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,8BAA8B,EAAE,QAAQ,CAAC,yBAAyB,CAK9E,CAAC;AAEF,sEAAsE;AACtE,eAAO,MAAM,oCAAoC,KAAK,CAAC;AAEvD;;;;;GAKG;AACH,eAAO,MAAM,0BAA0B,YAAY,CAAC;AAIpD,iFAAiF;AACjF,wBAAgB,QAAQ,CAAC,CAAC,EAAE,IAAI,GAAG,MAAM,CAKxC;AAMD,+FAA+F;AAC/F,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAExE;AA+BD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,CAAC,EAAE,yBAAyB,GAAG,SAAS,GACvC,QAAQ,CAAC,yBAAyB,CAAC,CAErC;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,uBAAuB,CAgEzF;AAED,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,uBAAuB,GAC9B,IAAI,CAqFN;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,uBAAuB,EAChC,KAAK,EAAE,IAAI,CACT,OAAO,CAAC,cAAc,CAAC,EACvB,aAAa,GAAG,qBAAqB,GAAG,2BAA2B,GAAG,6BAA6B,GAAG,kCAAkC,CACzI,GAAG;IACF,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,yBAAyB,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAC3C,2BAA2B,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5C,gCAAgC,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAClD,GACA,uBAAuB,CAkEzB"}
|
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
// Per-project always-on configuration persistence (M7.2).
|
|
2
|
+
//
|
|
3
|
+
// Stores the user's mode/dailyBudget/pause choice under
|
|
4
|
+
// `<projectRoot>/always-on.json` so M7.3's wired scheduler can rehydrate
|
|
5
|
+
// from disk after an agent restart.
|
|
6
|
+
//
|
|
7
|
+
// Deliberately small + dependency-free: just file I/O + validation.
|
|
8
|
+
// The runtime live state (ticksToday / recentTicks / nextTickAt) belongs
|
|
9
|
+
// to DiscoveryScheduler.snapshot() and is NOT persisted here.
|
|
10
|
+
import { existsSync, mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
|
|
11
|
+
import { dirname, join } from "node:path";
|
|
12
|
+
import { projectRoot as projRoot } from "@mclawnet/task";
|
|
13
|
+
export const DEFAULT_ALWAYS_ON_CONFIG = {
|
|
14
|
+
mode: "off",
|
|
15
|
+
dailyBudget: 3,
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* M8.2 — default opt-in matrix. taskSources field omitted on disk falls back
|
|
19
|
+
* to this; UI/JSON edits override per-key (omitted keys still resolve to the
|
|
20
|
+
* default). Introspection stays off so the agent never wakes the user with
|
|
21
|
+
* auto-discovered ideas unless they've explicitly opted in.
|
|
22
|
+
*/
|
|
23
|
+
export const DEFAULT_ALWAYS_ON_TASK_SOURCES = {
|
|
24
|
+
taskStore: true,
|
|
25
|
+
ideaTodo: true,
|
|
26
|
+
ideaResearch: true,
|
|
27
|
+
introspection: false,
|
|
28
|
+
};
|
|
29
|
+
/** M8.2 — default cooldown between introspection cycles, in hours. */
|
|
30
|
+
export const DEFAULT_INTROSPECTION_COOLDOWN_HOURS = 24;
|
|
31
|
+
/**
|
|
32
|
+
* Template used when no override is persisted. "minimal" ships in
|
|
33
|
+
* `packages/@clawnet/swarm/templates/` and is the safest single-role default —
|
|
34
|
+
* picked over the legacy `"default"` literal which never had a backing file
|
|
35
|
+
* and crashed every always-on cycle pre-hotfix (C1).
|
|
36
|
+
*/
|
|
37
|
+
export const DEFAULT_ALWAYS_ON_TEMPLATE = "minimal";
|
|
38
|
+
const CONFIG_FILENAME = "always-on.json";
|
|
39
|
+
/** Local YYYY-MM-DD (NOT UTC) so the daily-budget midnight matches user time. */
|
|
40
|
+
export function localYMD(d) {
|
|
41
|
+
const y = d.getFullYear();
|
|
42
|
+
const m = String(d.getMonth() + 1).padStart(2, "0");
|
|
43
|
+
const day = String(d.getDate()).padStart(2, "0");
|
|
44
|
+
return `${y}-${m}-${day}`;
|
|
45
|
+
}
|
|
46
|
+
function configPath(workDir, home) {
|
|
47
|
+
return join(projRoot(workDir, home), CONFIG_FILENAME);
|
|
48
|
+
}
|
|
49
|
+
/** Public so the agent boot scanner can distinguish "no config" from "corrupt config" (I4). */
|
|
50
|
+
export function alwaysOnConfigPath(workDir, home) {
|
|
51
|
+
return configPath(workDir, home);
|
|
52
|
+
}
|
|
53
|
+
function validMode(m) {
|
|
54
|
+
return m === "off" || m === "quiet" || m === "active" || m === "aggressive";
|
|
55
|
+
}
|
|
56
|
+
function validBudget(n) {
|
|
57
|
+
return typeof n === "number" && Number.isInteger(n) && n >= 1 && n <= 20;
|
|
58
|
+
}
|
|
59
|
+
function validCooldownHours(n) {
|
|
60
|
+
return typeof n === "number" && Number.isFinite(n) && n >= 0 && n <= 24 * 30;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Coerce an opaque value into a clean AlwaysOnTaskSourcesConfig. Unknown keys
|
|
64
|
+
* are dropped; non-boolean values are dropped (NOT coerced) so a typo doesn't
|
|
65
|
+
* silently flip a source on/off. Returns undefined when the input has no
|
|
66
|
+
* recognisable keys — caller stores nothing on disk in that case.
|
|
67
|
+
*/
|
|
68
|
+
function sanitiseTaskSources(v) {
|
|
69
|
+
if (!v || typeof v !== "object" || Array.isArray(v))
|
|
70
|
+
return undefined;
|
|
71
|
+
const src = v;
|
|
72
|
+
const out = {};
|
|
73
|
+
if (typeof src.taskStore === "boolean")
|
|
74
|
+
out.taskStore = src.taskStore;
|
|
75
|
+
if (typeof src.ideaTodo === "boolean")
|
|
76
|
+
out.ideaTodo = src.ideaTodo;
|
|
77
|
+
if (typeof src.ideaResearch === "boolean")
|
|
78
|
+
out.ideaResearch = src.ideaResearch;
|
|
79
|
+
if (typeof src.introspection === "boolean")
|
|
80
|
+
out.introspection = src.introspection;
|
|
81
|
+
return Object.keys(out).length === 0 ? undefined : out;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Merge a (possibly partial) taskSources object over the defaults, returning
|
|
85
|
+
* a fully-resolved record with every field present. The runtime always-on
|
|
86
|
+
* cascade reads this — undefined would force every caller to remember the
|
|
87
|
+
* defaults.
|
|
88
|
+
*/
|
|
89
|
+
export function resolveTaskSources(v) {
|
|
90
|
+
return { ...DEFAULT_ALWAYS_ON_TASK_SOURCES, ...(v ?? {}) };
|
|
91
|
+
}
|
|
92
|
+
export function loadAlwaysOnConfig(workDir, home) {
|
|
93
|
+
const path = configPath(workDir, home);
|
|
94
|
+
if (!existsSync(path))
|
|
95
|
+
return { ...DEFAULT_ALWAYS_ON_CONFIG };
|
|
96
|
+
try {
|
|
97
|
+
const data = JSON.parse(readFileSync(path, "utf-8"));
|
|
98
|
+
const cfg = {
|
|
99
|
+
mode: validMode(data.mode) ? data.mode : DEFAULT_ALWAYS_ON_CONFIG.mode,
|
|
100
|
+
dailyBudget: validBudget(data.dailyBudget)
|
|
101
|
+
? data.dailyBudget
|
|
102
|
+
: DEFAULT_ALWAYS_ON_CONFIG.dailyBudget,
|
|
103
|
+
...(typeof data.pausedUntil === "string" ? { pausedUntil: data.pausedUntil } : {}),
|
|
104
|
+
...(typeof data.templateName === "string" && data.templateName.length > 0
|
|
105
|
+
? { templateName: data.templateName }
|
|
106
|
+
: {}),
|
|
107
|
+
};
|
|
108
|
+
// M8.2 — task source toggles + introspection cooldown / runtime state.
|
|
109
|
+
const ts = sanitiseTaskSources(data.taskSources);
|
|
110
|
+
if (ts)
|
|
111
|
+
cfg.taskSources = ts;
|
|
112
|
+
if (validCooldownHours(data.introspectionCooldownHours)) {
|
|
113
|
+
cfg.introspectionCooldownHours = data.introspectionCooldownHours;
|
|
114
|
+
}
|
|
115
|
+
if (typeof data.lastIntrospectionAt === "string") {
|
|
116
|
+
cfg.lastIntrospectionAt = data.lastIntrospectionAt;
|
|
117
|
+
}
|
|
118
|
+
if (typeof data.lastIntrospectionRejected === "boolean") {
|
|
119
|
+
cfg.lastIntrospectionRejected = data.lastIntrospectionRejected;
|
|
120
|
+
}
|
|
121
|
+
if (typeof data.pendingIntrospectionSwarmId === "string" && data.pendingIntrospectionSwarmId.length > 0) {
|
|
122
|
+
cfg.pendingIntrospectionSwarmId = data.pendingIntrospectionSwarmId;
|
|
123
|
+
}
|
|
124
|
+
if (typeof data.pendingIntrospectionWorkspaceCwd === "string" && data.pendingIntrospectionWorkspaceCwd.length > 0) {
|
|
125
|
+
cfg.pendingIntrospectionWorkspaceCwd = data.pendingIntrospectionWorkspaceCwd;
|
|
126
|
+
}
|
|
127
|
+
// M7.3 runtime counters — best-effort restoration; bad shape drops silently.
|
|
128
|
+
if (typeof data.ticksToday === "number" &&
|
|
129
|
+
Number.isInteger(data.ticksToday) &&
|
|
130
|
+
data.ticksToday >= 0) {
|
|
131
|
+
cfg.ticksToday = data.ticksToday;
|
|
132
|
+
}
|
|
133
|
+
if (typeof data.ticksTodayDate === "string" &&
|
|
134
|
+
/^\d{4}-\d{2}-\d{2}$/.test(data.ticksTodayDate)) {
|
|
135
|
+
cfg.ticksTodayDate = data.ticksTodayDate;
|
|
136
|
+
}
|
|
137
|
+
if (typeof data.lastFireAt === "string") {
|
|
138
|
+
cfg.lastFireAt = data.lastFireAt;
|
|
139
|
+
}
|
|
140
|
+
return cfg;
|
|
141
|
+
}
|
|
142
|
+
catch (err) {
|
|
143
|
+
// Corrupt JSON / unreadable file → fall back to defaults so the user
|
|
144
|
+
// can still toggle the UI; their bad file gets replaced on next save.
|
|
145
|
+
// Hotfix I4: surface the failure so an unrecoverable file doesn't silently
|
|
146
|
+
// disable always-on across an agent restart.
|
|
147
|
+
// eslint-disable-next-line no-console
|
|
148
|
+
console.warn(`[always-on] config corrupt at ${path}; falling back to defaults: ${err instanceof Error ? err.message : String(err)}`);
|
|
149
|
+
return { ...DEFAULT_ALWAYS_ON_CONFIG };
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
export function saveAlwaysOnConfig(workDir, home, config) {
|
|
153
|
+
const path = configPath(workDir, home);
|
|
154
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
155
|
+
// Validate before writing; bad values get coerced to defaults rather than
|
|
156
|
+
// silently persisted.
|
|
157
|
+
const safe = {
|
|
158
|
+
mode: validMode(config.mode) ? config.mode : DEFAULT_ALWAYS_ON_CONFIG.mode,
|
|
159
|
+
dailyBudget: validBudget(config.dailyBudget)
|
|
160
|
+
? config.dailyBudget
|
|
161
|
+
: DEFAULT_ALWAYS_ON_CONFIG.dailyBudget,
|
|
162
|
+
...(typeof config.pausedUntil === "string"
|
|
163
|
+
? { pausedUntil: config.pausedUntil }
|
|
164
|
+
: {}),
|
|
165
|
+
...(typeof config.templateName === "string" && config.templateName.length > 0
|
|
166
|
+
? { templateName: config.templateName }
|
|
167
|
+
: {}),
|
|
168
|
+
...(typeof config.ticksToday === "number" &&
|
|
169
|
+
Number.isInteger(config.ticksToday) &&
|
|
170
|
+
config.ticksToday >= 0
|
|
171
|
+
? { ticksToday: config.ticksToday }
|
|
172
|
+
: {}),
|
|
173
|
+
...(typeof config.ticksTodayDate === "string" &&
|
|
174
|
+
/^\d{4}-\d{2}-\d{2}$/.test(config.ticksTodayDate)
|
|
175
|
+
? { ticksTodayDate: config.ticksTodayDate }
|
|
176
|
+
: {}),
|
|
177
|
+
...(typeof config.lastFireAt === "string" ? { lastFireAt: config.lastFireAt } : {}),
|
|
178
|
+
};
|
|
179
|
+
// M8.2 — round-trip task sources + introspection state. Sanitise on the
|
|
180
|
+
// way out too so a hand-edited config that smuggled a non-boolean doesn't
|
|
181
|
+
// get re-persisted.
|
|
182
|
+
const ts = sanitiseTaskSources(config.taskSources);
|
|
183
|
+
if (ts)
|
|
184
|
+
safe.taskSources = ts;
|
|
185
|
+
if (validCooldownHours(config.introspectionCooldownHours)) {
|
|
186
|
+
safe.introspectionCooldownHours = config.introspectionCooldownHours;
|
|
187
|
+
}
|
|
188
|
+
if (typeof config.lastIntrospectionAt === "string") {
|
|
189
|
+
safe.lastIntrospectionAt = config.lastIntrospectionAt;
|
|
190
|
+
}
|
|
191
|
+
if (typeof config.lastIntrospectionRejected === "boolean") {
|
|
192
|
+
safe.lastIntrospectionRejected = config.lastIntrospectionRejected;
|
|
193
|
+
}
|
|
194
|
+
if (typeof config.pendingIntrospectionSwarmId === "string" && config.pendingIntrospectionSwarmId.length > 0) {
|
|
195
|
+
safe.pendingIntrospectionSwarmId = config.pendingIntrospectionSwarmId;
|
|
196
|
+
}
|
|
197
|
+
if (typeof config.pendingIntrospectionWorkspaceCwd === "string" && config.pendingIntrospectionWorkspaceCwd.length > 0) {
|
|
198
|
+
safe.pendingIntrospectionWorkspaceCwd = config.pendingIntrospectionWorkspaceCwd;
|
|
199
|
+
}
|
|
200
|
+
// R3 I-F: atomic write. `writeFileSync` is `open(O_TRUNC) + write` — a
|
|
201
|
+
// concurrent reader (per-pick filter reads always-on.json on every tick)
|
|
202
|
+
// landing in the truncate-then-write window sees an empty/truncated file
|
|
203
|
+
// and loadAlwaysOnConfig silently falls back to DEFAULT_ALWAYS_ON_CONFIG,
|
|
204
|
+
// temporarily forcing mode=off + budget=3 + introspection=off until the
|
|
205
|
+
// write completes. Worse: a crash in the window loses ticksToday +
|
|
206
|
+
// pendingIntrospectionSwarmId. Fix: write to <path>.tmp then rename —
|
|
207
|
+
// atomic on POSIX. Mirrors the .1 backup rename used by always-on.log
|
|
208
|
+
// rotation. On stringify failure we clean up the .tmp so a partial file
|
|
209
|
+
// doesn't accumulate.
|
|
210
|
+
const tmpPath = `${path}.tmp`;
|
|
211
|
+
let serialised;
|
|
212
|
+
try {
|
|
213
|
+
serialised = JSON.stringify(safe, null, 2);
|
|
214
|
+
}
|
|
215
|
+
catch (err) {
|
|
216
|
+
// Defensive: shouldn't happen for our flat config shape, but a circular
|
|
217
|
+
// ref or BigInt would throw. Surface it so callers see the failure.
|
|
218
|
+
try {
|
|
219
|
+
unlinkSync(tmpPath);
|
|
220
|
+
}
|
|
221
|
+
catch {
|
|
222
|
+
/* nothing to clean if it doesn't exist */
|
|
223
|
+
}
|
|
224
|
+
throw err;
|
|
225
|
+
}
|
|
226
|
+
try {
|
|
227
|
+
writeFileSync(tmpPath, serialised, "utf-8");
|
|
228
|
+
renameSync(tmpPath, path);
|
|
229
|
+
}
|
|
230
|
+
catch (err) {
|
|
231
|
+
// Best-effort .tmp cleanup so a failed write doesn't leave behind a
|
|
232
|
+
// half-written sidecar. Swallow the cleanup error (the original error
|
|
233
|
+
// is what callers care about).
|
|
234
|
+
try {
|
|
235
|
+
unlinkSync(tmpPath);
|
|
236
|
+
}
|
|
237
|
+
catch {
|
|
238
|
+
/* may not exist if writeFileSync failed before open */
|
|
239
|
+
}
|
|
240
|
+
throw err;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Merge a partial config update over the persisted baseline. Used by the
|
|
245
|
+
* agent handler so the UI can PATCH only `{mode}` or `{pausedUntil}` without
|
|
246
|
+
* having to reconstruct dailyBudget client-side.
|
|
247
|
+
*
|
|
248
|
+
* `pausedUntil: null` (or empty string) clears the pause; omitting it leaves
|
|
249
|
+
* the existing value alone.
|
|
250
|
+
*/
|
|
251
|
+
export function mergeAlwaysOnConfig(current, patch) {
|
|
252
|
+
const next = { ...current };
|
|
253
|
+
if (patch.mode !== undefined && validMode(patch.mode))
|
|
254
|
+
next.mode = patch.mode;
|
|
255
|
+
if (patch.dailyBudget !== undefined && validBudget(patch.dailyBudget)) {
|
|
256
|
+
next.dailyBudget = patch.dailyBudget;
|
|
257
|
+
}
|
|
258
|
+
if (patch.templateName !== undefined) {
|
|
259
|
+
if (typeof patch.templateName === "string" && patch.templateName.length > 0) {
|
|
260
|
+
next.templateName = patch.templateName;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
if ("pausedUntil" in patch) {
|
|
264
|
+
const v = patch.pausedUntil;
|
|
265
|
+
if (v === null || v === "" || v === undefined) {
|
|
266
|
+
delete next.pausedUntil;
|
|
267
|
+
}
|
|
268
|
+
else if (typeof v === "string") {
|
|
269
|
+
next.pausedUntil = v;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
// M8.2 — taskSources: shallow merge over the existing record (not the
|
|
273
|
+
// defaults) so a patch with only { introspection: true } leaves the other
|
|
274
|
+
// toggles at whatever the user last set.
|
|
275
|
+
if (patch.taskSources !== undefined) {
|
|
276
|
+
const sanitised = sanitiseTaskSources(patch.taskSources);
|
|
277
|
+
if (sanitised) {
|
|
278
|
+
next.taskSources = { ...(next.taskSources ?? {}), ...sanitised };
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
if (patch.introspectionCooldownHours !== undefined) {
|
|
282
|
+
if (validCooldownHours(patch.introspectionCooldownHours)) {
|
|
283
|
+
next.introspectionCooldownHours = patch.introspectionCooldownHours;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
if ("lastIntrospectionAt" in patch) {
|
|
287
|
+
const v = patch.lastIntrospectionAt;
|
|
288
|
+
if (v === null || v === "") {
|
|
289
|
+
delete next.lastIntrospectionAt;
|
|
290
|
+
}
|
|
291
|
+
else if (typeof v === "string") {
|
|
292
|
+
next.lastIntrospectionAt = v;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
if ("lastIntrospectionRejected" in patch) {
|
|
296
|
+
const v = patch.lastIntrospectionRejected;
|
|
297
|
+
if (v === null) {
|
|
298
|
+
delete next.lastIntrospectionRejected;
|
|
299
|
+
}
|
|
300
|
+
else if (typeof v === "boolean") {
|
|
301
|
+
next.lastIntrospectionRejected = v;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
if ("pendingIntrospectionSwarmId" in patch) {
|
|
305
|
+
const v = patch.pendingIntrospectionSwarmId;
|
|
306
|
+
if (v === null || v === "") {
|
|
307
|
+
delete next.pendingIntrospectionSwarmId;
|
|
308
|
+
}
|
|
309
|
+
else if (typeof v === "string") {
|
|
310
|
+
next.pendingIntrospectionSwarmId = v;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
if ("pendingIntrospectionWorkspaceCwd" in patch) {
|
|
314
|
+
const v = patch.pendingIntrospectionWorkspaceCwd;
|
|
315
|
+
if (v === null || v === "") {
|
|
316
|
+
delete next.pendingIntrospectionWorkspaceCwd;
|
|
317
|
+
}
|
|
318
|
+
else if (typeof v === "string") {
|
|
319
|
+
next.pendingIntrospectionWorkspaceCwd = v;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
return next;
|
|
323
|
+
}
|
|
324
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/always-on/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { AlwaysOnMode, DiscoverySchedulerOptions, DiscoverySchedulerSnapshot, TickRecord } from "./types.js";
|
|
2
|
+
export declare class DiscoveryScheduler {
|
|
3
|
+
private mode;
|
|
4
|
+
private tickIntervalOverride;
|
|
5
|
+
private dailyBudget;
|
|
6
|
+
private userGates;
|
|
7
|
+
private onFire;
|
|
8
|
+
private onTick;
|
|
9
|
+
private now;
|
|
10
|
+
private timer;
|
|
11
|
+
private running;
|
|
12
|
+
private halted;
|
|
13
|
+
private inFlight;
|
|
14
|
+
private ticksToday;
|
|
15
|
+
private lastFireAt;
|
|
16
|
+
private recentTicks;
|
|
17
|
+
private nextTickAt;
|
|
18
|
+
constructor(opts: DiscoverySchedulerOptions);
|
|
19
|
+
/** Start the tick loop. No-op when mode === "off" or scheduler is halted. */
|
|
20
|
+
start(): void;
|
|
21
|
+
/** Stop the tick loop. Idempotent. */
|
|
22
|
+
stop(): void;
|
|
23
|
+
/**
|
|
24
|
+
* Manually trigger a tick. Bypasses the interval but still runs gates and
|
|
25
|
+
* still respects the in-flight guard: concurrent tickNow() calls reject the
|
|
26
|
+
* second caller with an Error so callers see deterministic semantics rather
|
|
27
|
+
* than silent overlap. Use `await` to serialise explicitly.
|
|
28
|
+
*/
|
|
29
|
+
tickNow(): Promise<TickRecord>;
|
|
30
|
+
/** Change mode at runtime. Cancels current timer and reschedules. */
|
|
31
|
+
setMode(mode: AlwaysOnMode): void;
|
|
32
|
+
/**
|
|
33
|
+
* Change daily budget at runtime (M7.3). `null` removes the cap entirely.
|
|
34
|
+
* Does not retro-affect counters; if the new budget is lower than
|
|
35
|
+
* `ticksToday`, the next gate evaluation will simply skip.
|
|
36
|
+
*/
|
|
37
|
+
setDailyBudget(budget: number | null): void;
|
|
38
|
+
/**
|
|
39
|
+
* Restore counters from persisted state (M7.3 AlwaysOnManager). Must be
|
|
40
|
+
* called BEFORE start() — restoring into a running scheduler is undefined
|
|
41
|
+
* behaviour. `lastFireAt` may be null when no prior fire exists.
|
|
42
|
+
*/
|
|
43
|
+
restoreState(state: {
|
|
44
|
+
ticksToday: number;
|
|
45
|
+
lastFireAt: Date | null;
|
|
46
|
+
}): void;
|
|
47
|
+
snapshot(): DiscoverySchedulerSnapshot;
|
|
48
|
+
private currentInterval;
|
|
49
|
+
/**
|
|
50
|
+
* Arm the next-tick timer. No-op when not running, halted, or mode=off.
|
|
51
|
+
* Always clears any existing timer first — both setMode() and a manual
|
|
52
|
+
* tickNow() can race with the previously armed interval.
|
|
53
|
+
*/
|
|
54
|
+
private schedule;
|
|
55
|
+
private runTick;
|
|
56
|
+
/** Built-ins (in order) then user gates. */
|
|
57
|
+
private buildGateChain;
|
|
58
|
+
private pushRecent;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=discovery-scheduler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discovery-scheduler.d.ts","sourceRoot":"","sources":["../../src/always-on/discovery-scheduler.ts"],"names":[],"mappings":"AAWA,OAAO,EACL,YAAY,EAGZ,yBAAyB,EACzB,0BAA0B,EAK1B,UAAU,EACX,MAAM,YAAY,CAAC;AAIpB,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,IAAI,CAAe;IAC3B,OAAO,CAAC,oBAAoB,CAAqB;IACjD,OAAO,CAAC,WAAW,CAAgB;IACnC,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,MAAM,CAAoD;IAClE,OAAO,CAAC,MAAM,CAA6C;IAC3D,OAAO,CAAC,GAAG,CAAa;IAExB,OAAO,CAAC,KAAK,CAA8C;IAC3D,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,QAAQ,CAAS;IAEzB,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,UAAU,CAAqB;IACvC,OAAO,CAAC,WAAW,CAAoB;IACvC,OAAO,CAAC,UAAU,CAAqB;gBAE3B,IAAI,EAAE,yBAAyB;IAU3C,6EAA6E;IAC7E,KAAK,IAAI,IAAI;IAUb,sCAAsC;IACtC,IAAI,IAAI,IAAI;IASZ;;;;;OAKG;IACG,OAAO,IAAI,OAAO,CAAC,UAAU,CAAC;IAOpC,qEAAqE;IACrE,OAAO,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI;IASjC;;;;OAIG;IACH,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAI3C;;;;OAIG;IACH,YAAY,CAAC,KAAK,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,IAAI,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI;IAW1E,QAAQ,IAAI,0BAA0B;IAYtC,OAAO,CAAC,eAAe;IAMvB;;;;OAIG;IACH,OAAO,CAAC,QAAQ;YAoCF,OAAO;IA8FrB,4CAA4C;IAC5C,OAAO,CAAC,cAAc;IAyBtB,OAAO,CAAC,UAAU;CAMnB"}
|