@edspencer/paddock 0.0.1 → 0.56.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.
- package/README.md +69 -0
- package/install-notice.mjs +29 -0
- package/package.json +58 -5
- package/packages/server/dist/adoptable.d.ts +127 -0
- package/packages/server/dist/adoptable.js +315 -0
- package/packages/server/dist/app.d.ts +67 -0
- package/packages/server/dist/app.js +325 -0
- package/packages/server/dist/archive.d.ts +42 -0
- package/packages/server/dist/archive.js +125 -0
- package/packages/server/dist/attachments-config.d.ts +114 -0
- package/packages/server/dist/attachments-config.js +165 -0
- package/packages/server/dist/attachments-hint.d.ts +53 -0
- package/packages/server/dist/attachments-hint.js +140 -0
- package/packages/server/dist/attachments.d.ts +33 -0
- package/packages/server/dist/attachments.js +117 -0
- package/packages/server/dist/auth.d.ts +84 -0
- package/packages/server/dist/auth.js +247 -0
- package/packages/server/dist/background.d.ts +36 -0
- package/packages/server/dist/background.js +137 -0
- package/packages/server/dist/bind-safety.d.ts +56 -0
- package/packages/server/dist/bind-safety.js +51 -0
- package/packages/server/dist/brand.d.ts +44 -0
- package/packages/server/dist/brand.js +88 -0
- package/packages/server/dist/chat-dto.d.ts +210 -0
- package/packages/server/dist/chat-dto.js +308 -0
- package/packages/server/dist/cli/import-chats.d.ts +21 -0
- package/packages/server/dist/cli/import-chats.js +197 -0
- package/packages/server/dist/cli/paddock.d.ts +2 -0
- package/packages/server/dist/cli/paddock.js +247 -0
- package/packages/server/dist/concurrency.d.ts +57 -0
- package/packages/server/dist/concurrency.js +71 -0
- package/packages/server/dist/config.d.ts +512 -0
- package/packages/server/dist/config.js +593 -0
- package/packages/server/dist/curation-config.d.ts +55 -0
- package/packages/server/dist/curation-config.js +64 -0
- package/packages/server/dist/event-bus.d.ts +87 -0
- package/packages/server/dist/event-bus.js +48 -0
- package/packages/server/dist/git.d.ts +128 -0
- package/packages/server/dist/git.js +446 -0
- package/packages/server/dist/github-auth.d.ts +44 -0
- package/packages/server/dist/github-auth.js +169 -0
- package/packages/server/dist/herdctl-agent-config.d.ts +98 -0
- package/packages/server/dist/herdctl-agent-config.js +331 -0
- package/packages/server/dist/herdctl-agent-names.d.ts +172 -0
- package/packages/server/dist/herdctl-agent-names.js +228 -0
- package/packages/server/dist/herdctl-jobs-index.d.ts +65 -0
- package/packages/server/dist/herdctl-jobs-index.js +225 -0
- package/packages/server/dist/herdctl-jobs.d.ts +98 -0
- package/packages/server/dist/herdctl-jobs.js +225 -0
- package/packages/server/dist/herdctl.d.ts +572 -0
- package/packages/server/dist/herdctl.js +1218 -0
- package/packages/server/dist/hook-config.d.ts +217 -0
- package/packages/server/dist/hook-config.js +224 -0
- package/packages/server/dist/http-bytes.d.ts +24 -0
- package/packages/server/dist/http-bytes.js +52 -0
- package/packages/server/dist/index.d.ts +1 -0
- package/packages/server/dist/index.js +14 -0
- package/packages/server/dist/instance-config.d.ts +135 -0
- package/packages/server/dist/instance-config.js +345 -0
- package/packages/server/dist/localcommand.d.ts +23 -0
- package/packages/server/dist/localcommand.js +140 -0
- package/packages/server/dist/management-auth.d.ts +99 -0
- package/packages/server/dist/management-auth.js +165 -0
- package/packages/server/dist/management-config.d.ts +164 -0
- package/packages/server/dist/management-config.js +286 -0
- package/packages/server/dist/management-mcp-server.d.ts +20 -0
- package/packages/server/dist/management-mcp-server.js +95 -0
- package/packages/server/dist/management-metadata.d.ts +67 -0
- package/packages/server/dist/management-metadata.js +56 -0
- package/packages/server/dist/management-ops.d.ts +110 -0
- package/packages/server/dist/management-ops.js +449 -0
- package/packages/server/dist/management-policy.d.ts +172 -0
- package/packages/server/dist/management-policy.js +259 -0
- package/packages/server/dist/message-provenance.d.ts +112 -0
- package/packages/server/dist/message-provenance.js +260 -0
- package/packages/server/dist/models.d.ts +164 -0
- package/packages/server/dist/models.js +208 -0
- package/packages/server/dist/openapi.d.ts +66 -0
- package/packages/server/dist/openapi.js +183 -0
- package/packages/server/dist/parent-detach.d.ts +30 -0
- package/packages/server/dist/parent-detach.js +109 -0
- package/packages/server/dist/preload.d.ts +43 -0
- package/packages/server/dist/preload.js +55 -0
- package/packages/server/dist/project-files.d.ts +76 -0
- package/packages/server/dist/project-files.js +191 -0
- package/packages/server/dist/project-mime.d.ts +35 -0
- package/packages/server/dist/project-mime.js +55 -0
- package/packages/server/dist/project-paths.d.ts +88 -0
- package/packages/server/dist/project-paths.js +126 -0
- package/packages/server/dist/project-types.d.ts +316 -0
- package/packages/server/dist/project-types.js +48 -0
- package/packages/server/dist/projects.d.ts +202 -0
- package/packages/server/dist/projects.js +894 -0
- package/packages/server/dist/queued-message.d.ts +35 -0
- package/packages/server/dist/queued-message.js +116 -0
- package/packages/server/dist/read-state.d.ts +46 -0
- package/packages/server/dist/read-state.js +139 -0
- package/packages/server/dist/recovery-config.d.ts +111 -0
- package/packages/server/dist/recovery-config.js +105 -0
- package/packages/server/dist/recovery.d.ts +262 -0
- package/packages/server/dist/recovery.js +490 -0
- package/packages/server/dist/resume-drain.d.ts +122 -0
- package/packages/server/dist/resume-drain.js +158 -0
- package/packages/server/dist/route-context.d.ts +168 -0
- package/packages/server/dist/route-context.js +39 -0
- package/packages/server/dist/route-errors.d.ts +8 -0
- package/packages/server/dist/route-errors.js +13 -0
- package/packages/server/dist/routes/chats.d.ts +12 -0
- package/packages/server/dist/routes/chats.js +1406 -0
- package/packages/server/dist/routes/git.d.ts +13 -0
- package/packages/server/dist/routes/git.js +236 -0
- package/packages/server/dist/routes/mcp.d.ts +83 -0
- package/packages/server/dist/routes/mcp.js +250 -0
- package/packages/server/dist/routes/meta.d.ts +15 -0
- package/packages/server/dist/routes/meta.js +447 -0
- package/packages/server/dist/routes/projects.d.ts +25 -0
- package/packages/server/dist/routes/projects.js +736 -0
- package/packages/server/dist/routes/triggers.d.ts +21 -0
- package/packages/server/dist/routes/triggers.js +324 -0
- package/packages/server/dist/routes/workspace-mount.d.ts +48 -0
- package/packages/server/dist/routes/workspace-mount.js +32 -0
- package/packages/server/dist/routes.d.ts +26 -0
- package/packages/server/dist/routes.js +29 -0
- package/packages/server/dist/run-provenance.d.ts +109 -0
- package/packages/server/dist/run-provenance.js +206 -0
- package/packages/server/dist/runs.d.ts +92 -0
- package/packages/server/dist/runs.js +72 -0
- package/packages/server/dist/schedule-config.d.ts +68 -0
- package/packages/server/dist/schedule-config.js +75 -0
- package/packages/server/dist/schedule-session.d.ts +34 -0
- package/packages/server/dist/schedule-session.js +120 -0
- package/packages/server/dist/self-mcp-descriptions.d.ts +20 -0
- package/packages/server/dist/self-mcp-descriptions.js +145 -0
- package/packages/server/dist/self-mcp-read.d.ts +15 -0
- package/packages/server/dist/self-mcp-read.js +97 -0
- package/packages/server/dist/self-mcp-triggers.d.ts +30 -0
- package/packages/server/dist/self-mcp-triggers.js +144 -0
- package/packages/server/dist/self-mcp-types.d.ts +248 -0
- package/packages/server/dist/self-mcp-types.js +10 -0
- package/packages/server/dist/self-mcp-util.d.ts +73 -0
- package/packages/server/dist/self-mcp-util.js +157 -0
- package/packages/server/dist/self-mcp-write.d.ts +35 -0
- package/packages/server/dist/self-mcp-write.js +215 -0
- package/packages/server/dist/self-mcp.d.ts +95 -0
- package/packages/server/dist/self-mcp.js +448 -0
- package/packages/server/dist/send-file-mcp.d.ts +46 -0
- package/packages/server/dist/send-file-mcp.js +281 -0
- package/packages/server/dist/session-hub.d.ts +186 -0
- package/packages/server/dist/session-hub.js +291 -0
- package/packages/server/dist/spawn-capability.d.ts +99 -0
- package/packages/server/dist/spawn-capability.js +106 -0
- package/packages/server/dist/star.d.ts +26 -0
- package/packages/server/dist/star.js +94 -0
- package/packages/server/dist/start.d.ts +1 -0
- package/packages/server/dist/start.js +21 -0
- package/packages/server/dist/subagents.d.ts +337 -0
- package/packages/server/dist/subagents.js +626 -0
- package/packages/server/dist/sweep.d.ts +122 -0
- package/packages/server/dist/sweep.js +696 -0
- package/packages/server/dist/tooldetails.d.ts +33 -0
- package/packages/server/dist/tooldetails.js +466 -0
- package/packages/server/dist/transcribe.d.ts +69 -0
- package/packages/server/dist/transcribe.js +119 -0
- package/packages/server/dist/transcripts.d.ts +42 -0
- package/packages/server/dist/transcripts.js +164 -0
- package/packages/server/dist/trigger-config.d.ts +278 -0
- package/packages/server/dist/trigger-config.js +417 -0
- package/packages/server/dist/trigger-runtime.d.ts +94 -0
- package/packages/server/dist/trigger-runtime.js +82 -0
- package/packages/server/dist/trigger-session.d.ts +34 -0
- package/packages/server/dist/trigger-session.js +122 -0
- package/packages/server/dist/triggers.d.ts +83 -0
- package/packages/server/dist/triggers.js +124 -0
- package/packages/server/dist/trusted-proxy.d.ts +57 -0
- package/packages/server/dist/trusted-proxy.js +157 -0
- package/packages/server/dist/turn-notice.d.ts +154 -0
- package/packages/server/dist/turn-notice.js +271 -0
- package/packages/server/dist/unread.d.ts +36 -0
- package/packages/server/dist/unread.js +123 -0
- package/packages/server/dist/usage.d.ts +66 -0
- package/packages/server/dist/usage.js +243 -0
- package/packages/server/dist/wake-injection.d.ts +156 -0
- package/packages/server/dist/wake-injection.js +136 -0
- package/packages/server/dist/whisper-local.d.ts +9 -0
- package/packages/server/dist/whisper-local.js +122 -0
- package/packages/server/dist/ws-context.d.ts +158 -0
- package/packages/server/dist/ws-context.js +1 -0
- package/packages/server/dist/ws-protocol.d.ts +423 -0
- package/packages/server/dist/ws-protocol.js +251 -0
- package/packages/server/dist/ws-self-mcp.d.ts +52 -0
- package/packages/server/dist/ws-self-mcp.js +28 -0
- package/packages/server/dist/ws-triggers.d.ts +29 -0
- package/packages/server/dist/ws-triggers.js +261 -0
- package/packages/server/dist/ws-turn.d.ts +86 -0
- package/packages/server/dist/ws-turn.js +751 -0
- package/packages/server/dist/ws.d.ts +62 -0
- package/packages/server/dist/ws.js +1024 -0
- package/packages/server/package.json +6 -0
- package/packages/web/dist/assets/InstanceConfigPage-4cQGTj9Y.js +2 -0
- package/packages/web/dist/assets/MarkdownRenderer-CJZFLj_8.js +30 -0
- package/packages/web/dist/assets/ProjectRedirect-BHwVbbqB.js +2 -0
- package/packages/web/dist/assets/ProjectView-BOvuAITg.js +13 -0
- package/packages/web/dist/assets/ProjectsGrid-BCojZOGY.js +2 -0
- package/packages/web/dist/assets/arc-BVyxvnkl.js +2 -0
- package/packages/web/dist/assets/architectureDiagram-3BPJPVTR-Cd9Puqg1.js +37 -0
- package/packages/web/dist/assets/bash-I8pq0VWm.js +2 -0
- package/packages/web/dist/assets/blockDiagram-GPEHLZMM-B_AQt_Rx.js +133 -0
- package/packages/web/dist/assets/c-D2F1sQUL.js +2 -0
- package/packages/web/dist/assets/c4Diagram-AAUBKEIU-7e0TQtXB.js +11 -0
- package/packages/web/dist/assets/channel-C_1aISNn.js +2 -0
- package/packages/web/dist/assets/chunk-2J33WTMH-Dz4WZmUZ.js +2 -0
- package/packages/web/dist/assets/chunk-4BX2VUAB-DVWYldo6.js +2 -0
- package/packages/web/dist/assets/chunk-55IACEB6-BIMrizQd.js +2 -0
- package/packages/web/dist/assets/chunk-727SXJPM-CL2q9fF1.js +207 -0
- package/packages/web/dist/assets/chunk-AQP2D5EJ-BSq3HlQ9.js +232 -0
- package/packages/web/dist/assets/chunk-FMBD7UC4-Bgt64pLE.js +16 -0
- package/packages/web/dist/assets/chunk-ND2GUHAM-C8Pr2A38.js +2 -0
- package/packages/web/dist/assets/chunk-QZHKN3VN-BAOqh-MN.js +2 -0
- package/packages/web/dist/assets/classDiagram-4FO5ZUOK-B8JE7cHJ.js +2 -0
- package/packages/web/dist/assets/classDiagram-v2-Q7XG4LA2-B8JE7cHJ.js +2 -0
- package/packages/web/dist/assets/core-lJeGACQg.js +4 -0
- package/packages/web/dist/assets/cose-bilkent-S5V4N54A-BF4tameA.js +2 -0
- package/packages/web/dist/assets/cpp-Bm3ii6kY.js +2 -0
- package/packages/web/dist/assets/csharp-BNpuYZMG.js +2 -0
- package/packages/web/dist/assets/css-DazXZka4.js +2 -0
- package/packages/web/dist/assets/cytoscape.esm-CUqq0XTU.js +332 -0
- package/packages/web/dist/assets/dagre-BM42HDAG-DdsLM6ql.js +5 -0
- package/packages/web/dist/assets/defaultLocale-DX6XiGOO.js +2 -0
- package/packages/web/dist/assets/diagram-2AECGRRQ-BQ78S_RM.js +44 -0
- package/packages/web/dist/assets/diagram-5GNKFQAL-CAKE6nHE.js +11 -0
- package/packages/web/dist/assets/diagram-KO2AKTUF-fEvHRXgr.js +4 -0
- package/packages/web/dist/assets/diagram-LMA3HP47-CtWsgeSm.js +25 -0
- package/packages/web/dist/assets/diagram-OG6HWLK6-Buog8k7_.js +25 -0
- package/packages/web/dist/assets/erDiagram-TEJ5UH35-CWvVVPZS.js +86 -0
- package/packages/web/dist/assets/flowDiagram-I6XJVG4X-DsCGXtp4.js +163 -0
- package/packages/web/dist/assets/format-DamJQ9LO.js +2 -0
- package/packages/web/dist/assets/ganttDiagram-6RSMTGT7-CsdwIvvC.js +293 -0
- package/packages/web/dist/assets/gitGraphDiagram-PVQCEYII-hZvrX1sD.js +107 -0
- package/packages/web/dist/assets/go-BPx_y7j8.js +2 -0
- package/packages/web/dist/assets/graph-BlwPajkw.js +2 -0
- package/packages/web/dist/assets/index-CGbZdrm8.js +71 -0
- package/packages/web/dist/assets/index-DJDQ210-.css +1 -0
- package/packages/web/dist/assets/infoDiagram-5YYISTIA-nE_Vtz_l.js +3 -0
- package/packages/web/dist/assets/ini-B3BVgEsG.js +2 -0
- package/packages/web/dist/assets/init-Gi6I4Gst.js +2 -0
- package/packages/web/dist/assets/ishikawaDiagram-YF4QCWOH-2Nlqs0oH.js +71 -0
- package/packages/web/dist/assets/java-B5VKqtH2.js +2 -0
- package/packages/web/dist/assets/javascript-BKRaQes9.js +2 -0
- package/packages/web/dist/assets/journeyDiagram-JHISSGLW-mjU1fMc4.js +140 -0
- package/packages/web/dist/assets/json-DIYVocXf.js +2 -0
- package/packages/web/dist/assets/kanban-definition-UN3LZRKU-C_9xNaa3.js +90 -0
- package/packages/web/dist/assets/katex-C5jXJg4s.js +258 -0
- package/packages/web/dist/assets/kotlin-Cw-eF_bm.js +3 -0
- package/packages/web/dist/assets/lastTab-CU1zsF0j.js +2 -0
- package/packages/web/dist/assets/layout-Boy8vhSP.js +2 -0
- package/packages/web/dist/assets/linear-BxKd91ho.js +2 -0
- package/packages/web/dist/assets/mermaid.core-C-CuhD8I.js +310 -0
- package/packages/web/dist/assets/mindmap-definition-RKZ34NQL-Bs6yfcZv.js +97 -0
- package/packages/web/dist/assets/ordinal-Cboi1Yqb.js +2 -0
- package/packages/web/dist/assets/php-CRdd4dfS.js +3 -0
- package/packages/web/dist/assets/pieDiagram-4H26LBE5-DNdqX7O5.js +31 -0
- package/packages/web/dist/assets/python-kSlZHhJb.js +2 -0
- package/packages/web/dist/assets/quadrantDiagram-W4KKPZXB-ZMJl9OdZ.js +8 -0
- package/packages/web/dist/assets/queued-LamEU0GH.js +2 -0
- package/packages/web/dist/assets/requirementDiagram-4Y6WPE33-RmxMdm2q.js +85 -0
- package/packages/web/dist/assets/ruby-7T4ktxyv.js +2 -0
- package/packages/web/dist/assets/rust-HC3MBUhY.js +2 -0
- package/packages/web/dist/assets/sankeyDiagram-5OEKKPKP-OAAhWcfK.js +41 -0
- package/packages/web/dist/assets/scss-DZLA7YXz.js +2 -0
- package/packages/web/dist/assets/sequenceDiagram-3UESZ5HK-BWF7rCyN.js +163 -0
- package/packages/web/dist/assets/sql-BC88IN-V.js +2 -0
- package/packages/web/dist/assets/stateDiagram-AJRCARHV-M3b_zqqo.js +2 -0
- package/packages/web/dist/assets/stateDiagram-v2-BHNVJYJU-CI7saFDa.js +2 -0
- package/packages/web/dist/assets/swift-Dn8kKO_1.js +2 -0
- package/packages/web/dist/assets/timeline-definition-PNZ67QCA-BpOCh63N.js +121 -0
- package/packages/web/dist/assets/typescript-C2FFdlUC.js +2 -0
- package/packages/web/dist/assets/vennDiagram-CIIHVFJN-D_iPH45Q.js +35 -0
- package/packages/web/dist/assets/wardley-L42UT6IY-DVD9I2Om.js +174 -0
- package/packages/web/dist/assets/wardleyDiagram-YWT4CUSO-Bn1IKwjn.js +79 -0
- package/packages/web/dist/assets/xml-BXBhIUeX.js +2 -0
- package/packages/web/dist/assets/xychartDiagram-2RQKCTM6-DwtI0bkR.js +8 -0
- package/packages/web/dist/assets/yaml-drsDnIKT.js +2 -0
- package/packages/web/dist/favicon.ico +0 -0
- package/packages/web/dist/fonts/inter-latin.woff2 +0 -0
- package/packages/web/dist/fonts/jetbrains-mono-latin.woff2 +0 -0
- package/packages/web/dist/icons/apple-touch-icon.png +0 -0
- package/packages/web/dist/icons/favicon-16.png +0 -0
- package/packages/web/dist/icons/favicon-32.png +0 -0
- package/packages/web/dist/icons/icon-192.png +0 -0
- package/packages/web/dist/icons/icon-512.png +0 -0
- package/packages/web/dist/icons/maskable-512.png +0 -0
- package/packages/web/dist/index.html +56 -0
- package/packages/web/dist/manifest.webmanifest +32 -0
- package/packages/web/dist/sw.js +139 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sweeper curation budgets — the per-file token limits the post-turn curator
|
|
3
|
+
* keeps OVERVIEW.md / CHANGELOG.md / CLAUDE.md under (issue #379), with a
|
|
4
|
+
* per-project override layer (issue #384).
|
|
5
|
+
*
|
|
6
|
+
* ── Config discipline (the `recovery`/`driveMode` pattern) ────────────────────
|
|
7
|
+
* Every budget is an instance default (`PADDOCK_CURATION_*` env, YAML instance
|
|
8
|
+
* file beneath it — resolved in config.ts's `loadCurationConfig`) with an
|
|
9
|
+
* optional PER-PROJECT override (`project.yaml` →
|
|
10
|
+
* {@link import("./projects.js").ProjectYaml.curation}). An absent/invalid
|
|
11
|
+
* override inherits the instance default, resolved at sweep time by
|
|
12
|
+
* {@link resolveCurationConfig} — never baked into the DTO (mirrors how
|
|
13
|
+
* `recovery` resolves via `resolveRecoveryConfig`). A malformed override is
|
|
14
|
+
* ignored rather than fatal so a hand-edited `project.yaml` can't wedge a sweep.
|
|
15
|
+
*
|
|
16
|
+
* #379 shipped these instance-only; #384 adds the override so a docs-heavy
|
|
17
|
+
* project can raise its CHANGELOG budget (or a lean project tighten it) without
|
|
18
|
+
* changing the fleet-wide default.
|
|
19
|
+
*/
|
|
20
|
+
/** Built-in defaults when neither env nor YAML nor a project override sets a budget. */
|
|
21
|
+
export const DEFAULT_CURATION = Object.freeze({
|
|
22
|
+
overviewMaxTokens: 2000,
|
|
23
|
+
changelogMaxTokens: 8000,
|
|
24
|
+
claudeMaxTokens: 6000,
|
|
25
|
+
});
|
|
26
|
+
/** True when `n` is a usable budget: a positive, finite integer. */
|
|
27
|
+
function isPositiveInt(n) {
|
|
28
|
+
return typeof n === "number" && Number.isInteger(n) && n > 0 && Number.isFinite(n);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Validate + normalise an untrusted value (from `project.yaml` or a PATCH body)
|
|
32
|
+
* into a {@link CurationOverride}, dropping any field that is missing or invalid,
|
|
33
|
+
* and returning `undefined` when nothing valid remains (so an empty override is
|
|
34
|
+
* never persisted). Each budget must be a positive integer. Defensive by design —
|
|
35
|
+
* a malformed hand-edit degrades to "inherit the instance default", never a
|
|
36
|
+
* sweep crash.
|
|
37
|
+
*/
|
|
38
|
+
export function sanitizeCurationOverride(value) {
|
|
39
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
40
|
+
return undefined;
|
|
41
|
+
const o = value;
|
|
42
|
+
const out = {};
|
|
43
|
+
if (isPositiveInt(o.overviewMaxTokens))
|
|
44
|
+
out.overviewMaxTokens = o.overviewMaxTokens;
|
|
45
|
+
if (isPositiveInt(o.changelogMaxTokens))
|
|
46
|
+
out.changelogMaxTokens = o.changelogMaxTokens;
|
|
47
|
+
if (isPositiveInt(o.claudeMaxTokens))
|
|
48
|
+
out.claudeMaxTokens = o.claudeMaxTokens;
|
|
49
|
+
return Object.keys(out).length > 0 ? out : undefined;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Resolve the effective curation budgets for a sweep: a valid per-project
|
|
53
|
+
* override wins field-by-field; every absent field inherits the instance default
|
|
54
|
+
* (which is itself `env > paddock.config.yaml > built-in default`). The override
|
|
55
|
+
* is re-sanitised so a corrupt on-disk value can't leak through.
|
|
56
|
+
*/
|
|
57
|
+
export function resolveCurationConfig(override, instanceDefault) {
|
|
58
|
+
const clean = sanitizeCurationOverride(override) ?? {};
|
|
59
|
+
return {
|
|
60
|
+
overviewMaxTokens: clean.overviewMaxTokens ?? instanceDefault.overviewMaxTokens,
|
|
61
|
+
changelogMaxTokens: clean.changelogMaxTokens ?? instanceDefault.changelogMaxTokens,
|
|
62
|
+
claudeMaxTokens: clean.claudeMaxTokens ?? instanceDefault.claudeMaxTokens,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-process lifecycle event bus (Epic G, ticket G1 — hook foundation).
|
|
3
|
+
*
|
|
4
|
+
* Paddock lifecycle events (a chat archived, later: created/forked/unarchived) fire
|
|
5
|
+
* INSIDE Paddock's own server — unlike schedules (Epic D), there is no herdctl seam
|
|
6
|
+
* to add. This tiny typed emitter is that seam: the place that COMMITS a lifecycle
|
|
7
|
+
* action ({@link ArchiveEvent}, from the archive route / the self-MCP archive tool)
|
|
8
|
+
* `emit`s the event AFTER it commits, and the hook dispatcher (wired in `ws.ts`)
|
|
9
|
+
* `on`s it to fire each of the project's enabled hooks via `startAgentTurn`.
|
|
10
|
+
*
|
|
11
|
+
* Two invariants make this safe as a foundation (GG-2, non-blocking after-commit):
|
|
12
|
+
*
|
|
13
|
+
* 1. **`emit` never throws into its caller and never blocks it.** Listeners run
|
|
14
|
+
* fire-and-forget; a listener that throws (sync or async) is swallowed so the
|
|
15
|
+
* triggering action (the archive) can NEVER fail or hang because of a hook. This
|
|
16
|
+
* is the whole point — a buggy hook must not break the thing that triggered it.
|
|
17
|
+
* 2. **The bus event name IS a hook/trigger `event` value.** So a dispatcher is a
|
|
18
|
+
* trivial `bus.on("onArchive", …)` that matches hooks/triggers with that `event`.
|
|
19
|
+
* v1 wired `onArchive` (hooks + event triggers); T5 adds `afterTurn`, which drives
|
|
20
|
+
* the folded-in sweeper (the default post-turn curator trigger).
|
|
21
|
+
*
|
|
22
|
+
* Kept deliberately minimal (no Node `EventEmitter`: its `error`-event footgun and
|
|
23
|
+
* default max-listener warnings are noise here) and dependency-free, matching the
|
|
24
|
+
* hand-rolled sidecar style of the rest of the server.
|
|
25
|
+
*/
|
|
26
|
+
/**
|
|
27
|
+
* Payload for the `onArchive` event: which chat, in which project, was archived.
|
|
28
|
+
* The dispatcher passes `slug` to resolve the project's hooks and `sessionId` into
|
|
29
|
+
* the fired hook's prompt so the hook knows WHAT was archived (e.g. which pm server
|
|
30
|
+
* / clone to tear down).
|
|
31
|
+
*/
|
|
32
|
+
export interface ArchiveEvent {
|
|
33
|
+
/** The project slug whose chat was archived. */
|
|
34
|
+
slug: string;
|
|
35
|
+
/** The archived chat's session id. */
|
|
36
|
+
sessionId: string;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Payload for the `afterTurn` event (Epic T / T5): a turn just completed in `slug`.
|
|
40
|
+
* Emitted at every post-turn commit site (a human chat turn, a session-mode wake, and
|
|
41
|
+
* every server-initiated `startAgentTurn`) so the folded-in sweeper — the default
|
|
42
|
+
* `curate-overview` `event`/`afterTurn` trigger — dispatches EXACTLY ONCE per turn.
|
|
43
|
+
* `sessionId` is the chat whose turn completed (`null` when none was resolved), carried
|
|
44
|
+
* for parity with `onArchive`; the curator only needs the `slug` to sweep.
|
|
45
|
+
*/
|
|
46
|
+
export interface AfterTurnEvent {
|
|
47
|
+
/** The project slug whose chat turn just completed. */
|
|
48
|
+
slug: string;
|
|
49
|
+
/** The completed turn's session id, or `null` if none was resolved. */
|
|
50
|
+
sessionId: string | null;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* The typed event map. The bus event name IS a trigger/hook `event` value, so
|
|
54
|
+
* `on`/`emit` line up with the dispatchers. `onArchive` fires the enabled onArchive
|
|
55
|
+
* hooks + event triggers (Epic G/T); `afterTurn` (T5) drives the post-turn curator
|
|
56
|
+
* (the sweeper). Adding a sibling event is: a new value here + its payload + an `emit`
|
|
57
|
+
* at the commit site.
|
|
58
|
+
*/
|
|
59
|
+
export interface PaddockEventMap {
|
|
60
|
+
onArchive: ArchiveEvent;
|
|
61
|
+
afterTurn: AfterTurnEvent;
|
|
62
|
+
}
|
|
63
|
+
/** A lifecycle event name — a key of {@link PaddockEventMap}, matching a trigger/hook event. */
|
|
64
|
+
export type PaddockEventName = keyof PaddockEventMap;
|
|
65
|
+
/** A listener for event `E`; may be async — its result is awaited-and-swallowed. */
|
|
66
|
+
export type EventListener<E extends PaddockEventName> = (payload: PaddockEventMap[E]) => void | Promise<void>;
|
|
67
|
+
/**
|
|
68
|
+
* A minimal typed publish/subscribe hub. One instance is constructed in `app.ts` and
|
|
69
|
+
* shared by the commit sites (archive route / self-MCP archive tool → `emit`) and the
|
|
70
|
+
* hook dispatcher in `ws.ts` (→ `on`).
|
|
71
|
+
*/
|
|
72
|
+
export declare class PaddockEventBus {
|
|
73
|
+
private readonly listeners;
|
|
74
|
+
/**
|
|
75
|
+
* Subscribe `listener` to `event`. Returns an unsubscribe function. Multiple
|
|
76
|
+
* listeners per event are supported (v1 registers one — the hook dispatcher).
|
|
77
|
+
*/
|
|
78
|
+
on<E extends PaddockEventName>(event: E, listener: EventListener<E>): () => void;
|
|
79
|
+
/**
|
|
80
|
+
* Fire `event` to every subscribed listener, FIRE-AND-FORGET. Returns immediately
|
|
81
|
+
* (never awaits a listener) and never throws into the caller — a listener that
|
|
82
|
+
* throws synchronously or rejects asynchronously is swallowed. So the action that
|
|
83
|
+
* emitted the event (an archive commit) is fully decoupled from hook execution: it
|
|
84
|
+
* neither waits on hooks nor fails because of them (GG-2).
|
|
85
|
+
*/
|
|
86
|
+
emit<E extends PaddockEventName>(event: E, payload: PaddockEventMap[E]): void;
|
|
87
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A minimal typed publish/subscribe hub. One instance is constructed in `app.ts` and
|
|
3
|
+
* shared by the commit sites (archive route / self-MCP archive tool → `emit`) and the
|
|
4
|
+
* hook dispatcher in `ws.ts` (→ `on`).
|
|
5
|
+
*/
|
|
6
|
+
export class PaddockEventBus {
|
|
7
|
+
listeners = new Map();
|
|
8
|
+
/**
|
|
9
|
+
* Subscribe `listener` to `event`. Returns an unsubscribe function. Multiple
|
|
10
|
+
* listeners per event are supported (v1 registers one — the hook dispatcher).
|
|
11
|
+
*/
|
|
12
|
+
on(event, listener) {
|
|
13
|
+
let set = this.listeners.get(event);
|
|
14
|
+
if (!set) {
|
|
15
|
+
set = new Set();
|
|
16
|
+
this.listeners.set(event, set);
|
|
17
|
+
}
|
|
18
|
+
set.add(listener);
|
|
19
|
+
return () => {
|
|
20
|
+
this.listeners.get(event)?.delete(listener);
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Fire `event` to every subscribed listener, FIRE-AND-FORGET. Returns immediately
|
|
25
|
+
* (never awaits a listener) and never throws into the caller — a listener that
|
|
26
|
+
* throws synchronously or rejects asynchronously is swallowed. So the action that
|
|
27
|
+
* emitted the event (an archive commit) is fully decoupled from hook execution: it
|
|
28
|
+
* neither waits on hooks nor fails because of them (GG-2).
|
|
29
|
+
*/
|
|
30
|
+
emit(event, payload) {
|
|
31
|
+
const set = this.listeners.get(event);
|
|
32
|
+
if (!set || set.size === 0)
|
|
33
|
+
return;
|
|
34
|
+
for (const listener of set) {
|
|
35
|
+
try {
|
|
36
|
+
// A listener may be sync or async. Wrap in Promise.resolve so a synchronous
|
|
37
|
+
// throw and an async rejection are both funneled into the same swallow — the
|
|
38
|
+
// emitter's caller is never affected either way.
|
|
39
|
+
void Promise.resolve()
|
|
40
|
+
.then(() => listener(payload))
|
|
41
|
+
.catch(() => undefined);
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
/* a synchronous throw before the microtask — swallow too */
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Clone an external git repo into `dest` — the checkout that becomes a
|
|
3
|
+
* repo-backed project's working directory (issue #187). Shells out to the `git`
|
|
4
|
+
* binary via execFile (arg array, no shell → no injection surface), the same
|
|
5
|
+
* discipline as {@link GitService}.
|
|
6
|
+
*
|
|
7
|
+
* A FULL clone (not `--depth 1`): a repo-backed project is where you *do
|
|
8
|
+
* engineering*, so the keeper wants real history — `git log`, blame, bisect, and
|
|
9
|
+
* a non-shallow base for branches/PRs — from the start. Credentials are the
|
|
10
|
+
* ambient git environment's job (a public URL needs none; a private repo needs a
|
|
11
|
+
* box-level credential helper / token — per-project scoped credentials are a
|
|
12
|
+
* documented #187 follow-up). Throws with git's stderr on failure so the caller
|
|
13
|
+
* can surface a clean error and roll back the half-created project.
|
|
14
|
+
*/
|
|
15
|
+
export declare function cloneRepo(url: string, dest: string): Promise<void>;
|
|
16
|
+
/** A single changed path within a project (porcelain v1 semantics). */
|
|
17
|
+
export interface GitFileChange {
|
|
18
|
+
/** Path relative to the project directory. */
|
|
19
|
+
path: string;
|
|
20
|
+
/** Two-letter porcelain code, trimmed (e.g. "M", "??", "A", "RM"). */
|
|
21
|
+
status: string;
|
|
22
|
+
/** Whether the change is staged (index differs from HEAD). */
|
|
23
|
+
staged: boolean;
|
|
24
|
+
/** True for an untracked ("??") path. */
|
|
25
|
+
untracked: boolean;
|
|
26
|
+
/** Lines added (undefined for a binary change). Untracked text files count as all-added. */
|
|
27
|
+
added?: number;
|
|
28
|
+
/** Lines removed (undefined for a binary change / an untracked file). */
|
|
29
|
+
removed?: number;
|
|
30
|
+
/** True when the change is binary (no line-level stat). */
|
|
31
|
+
binary?: boolean;
|
|
32
|
+
}
|
|
33
|
+
/** A project's git status (or `repo: false` when the store isn't a repo). */
|
|
34
|
+
export interface GitProjectStatus {
|
|
35
|
+
/** Whether `projectsRoot` is a git working tree at all. */
|
|
36
|
+
repo: boolean;
|
|
37
|
+
/** Current branch (omitted when not a repo / detached). */
|
|
38
|
+
branch?: string;
|
|
39
|
+
/** Changes confined to this project's subtree. */
|
|
40
|
+
files: GitFileChange[];
|
|
41
|
+
/** True when the project subtree has no pending changes. */
|
|
42
|
+
clean: boolean;
|
|
43
|
+
}
|
|
44
|
+
export declare class GitService {
|
|
45
|
+
private readonly projectsRoot;
|
|
46
|
+
private readonly author;
|
|
47
|
+
/** Cached repo-detection result for `projectsRoot` (null = not yet checked). */
|
|
48
|
+
private repoFlag;
|
|
49
|
+
/**
|
|
50
|
+
* @param projectsRoot Absolute path to the projects root the service operates on.
|
|
51
|
+
* @param author Commit identity used when Paddock commits on a project's behalf.
|
|
52
|
+
* Folded into PaddockConfig from `PADDOCK_GIT_AUTHOR_*` (issue #269); defaults
|
|
53
|
+
* preserve the pre-fold values so a bare `new GitService(root)` is unchanged.
|
|
54
|
+
*/
|
|
55
|
+
constructor(projectsRoot: string, author?: {
|
|
56
|
+
name: string;
|
|
57
|
+
email: string;
|
|
58
|
+
});
|
|
59
|
+
/** Run git in a directory, returning stdout. Throws on non-zero exit. */
|
|
60
|
+
private git;
|
|
61
|
+
/**
|
|
62
|
+
* Whether the backing store is a git working tree. Cached after the first
|
|
63
|
+
* successful check (repo-ness doesn't change under a running server); a thrown
|
|
64
|
+
* git / missing-binary error resolves to `false`.
|
|
65
|
+
*/
|
|
66
|
+
isRepo(): Promise<boolean>;
|
|
67
|
+
/** Force the next `isRepo()` to re-check (e.g. after `git init` at runtime). */
|
|
68
|
+
resetRepoCache(): void;
|
|
69
|
+
/**
|
|
70
|
+
* Status for one project's subtree. Returns `{ repo: false }` when the store
|
|
71
|
+
* isn't a repo (the UI then hides the git affordance). Paths are relative to
|
|
72
|
+
* `projectDir`.
|
|
73
|
+
*/
|
|
74
|
+
projectStatus(projectDir: string): Promise<GitProjectStatus>;
|
|
75
|
+
/**
|
|
76
|
+
* `git diff --numstat` for a project's tracked working-tree changes, keyed by
|
|
77
|
+
* PROJECT-relative path (`--relative` makes git emit paths relative to the
|
|
78
|
+
* project dir, matching the porcelain paths). Binary changes report `-\t-` and
|
|
79
|
+
* are flagged `binary`. Returns an empty map on any failure.
|
|
80
|
+
*/
|
|
81
|
+
private trackedNumstat;
|
|
82
|
+
/**
|
|
83
|
+
* Unified diff for a project's tracked changes (working tree vs HEAD), or for
|
|
84
|
+
* a single file when `file` is given. Untracked files don't appear in a diff
|
|
85
|
+
* (they're listed by `projectStatus`). Returns "" when not a repo / no diff.
|
|
86
|
+
*/
|
|
87
|
+
projectDiff(projectDir: string, file?: string): Promise<string>;
|
|
88
|
+
/** Commit identity (from config, no global git config needed). */
|
|
89
|
+
private identity;
|
|
90
|
+
/** Origin remote info + ahead/behind vs upstream (best-effort). */
|
|
91
|
+
remote(): Promise<{
|
|
92
|
+
repo: boolean;
|
|
93
|
+
configured: boolean;
|
|
94
|
+
url?: string;
|
|
95
|
+
branch?: string;
|
|
96
|
+
ahead?: number;
|
|
97
|
+
behind?: number;
|
|
98
|
+
}>;
|
|
99
|
+
/**
|
|
100
|
+
* Stage + commit a single project's changes (tracked mods, deletions, and
|
|
101
|
+
* untracked files within its subtree). `committed: false` when nothing was
|
|
102
|
+
* pending. Explicit identity so the LXC needs no global git config.
|
|
103
|
+
*
|
|
104
|
+
* When `paths` (project-relative) is given, commit ONLY those files — the
|
|
105
|
+
* pathspec scopes both the staging and the commit, so unselected changes stay
|
|
106
|
+
* uncommitted (issue #258). Paths are validated to stay inside the subtree; an
|
|
107
|
+
* all-invalid selection is an error rather than a silent commit-everything.
|
|
108
|
+
* Omitting `paths` keeps the legacy commit-the-whole-subtree behavior.
|
|
109
|
+
*/
|
|
110
|
+
commitProject(projectDir: string, message: string, paths?: string[]): Promise<{
|
|
111
|
+
committed: boolean;
|
|
112
|
+
hash?: string;
|
|
113
|
+
error?: string;
|
|
114
|
+
}>;
|
|
115
|
+
/**
|
|
116
|
+
* Uncommitted-file counts per top-level project subtree, in ONE `git status`
|
|
117
|
+
* over the whole store (cheap — no per-project fan-out) so the projects grid
|
|
118
|
+
* can flag "N uncommitted" without opening each project (issue #258). Keyed by
|
|
119
|
+
* the first path segment (= project slug); only dirty projects appear. `{}`
|
|
120
|
+
* when the store isn't a repo.
|
|
121
|
+
*/
|
|
122
|
+
dirtyCounts(): Promise<Record<string, number>>;
|
|
123
|
+
/** Push the current branch to origin (sets upstream on first push). */
|
|
124
|
+
push(): Promise<{
|
|
125
|
+
pushed: boolean;
|
|
126
|
+
error?: string;
|
|
127
|
+
}>;
|
|
128
|
+
}
|