@kynetic-ai/spec 0.11.0 → 0.12.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 +55 -455
- package/dist/agent-runtime/bootstrap.d.ts +31 -0
- package/dist/agent-runtime/bootstrap.d.ts.map +1 -0
- package/dist/agent-runtime/bootstrap.js +302 -0
- package/dist/agent-runtime/bootstrap.js.map +1 -0
- package/dist/agent-runtime/dispatch.d.ts +119 -10
- package/dist/agent-runtime/dispatch.d.ts.map +1 -1
- package/dist/agent-runtime/dispatch.js +1154 -219
- package/dist/agent-runtime/dispatch.js.map +1 -1
- package/dist/agent-runtime/invocation.d.ts +28 -1
- package/dist/agent-runtime/invocation.d.ts.map +1 -1
- package/dist/agent-runtime/invocation.js +171 -59
- package/dist/agent-runtime/invocation.js.map +1 -1
- package/dist/agent-runtime/prompts.d.ts +9 -0
- package/dist/agent-runtime/prompts.d.ts.map +1 -1
- package/dist/agent-runtime/prompts.js +42 -7
- package/dist/agent-runtime/prompts.js.map +1 -1
- package/dist/agent-runtime/session-event-accumulator.d.ts +83 -0
- package/dist/agent-runtime/session-event-accumulator.d.ts.map +1 -0
- package/dist/agent-runtime/session-event-accumulator.js +203 -0
- package/dist/agent-runtime/session-event-accumulator.js.map +1 -0
- package/dist/agent-runtime/session-event-types.d.ts +67 -0
- package/dist/agent-runtime/session-event-types.d.ts.map +1 -0
- package/dist/agent-runtime/session-event-types.js +13 -0
- package/dist/agent-runtime/session-event-types.js.map +1 -0
- package/dist/agent-runtime/workspace.d.ts +244 -0
- package/dist/agent-runtime/workspace.d.ts.map +1 -0
- package/dist/agent-runtime/workspace.js +2025 -0
- package/dist/agent-runtime/workspace.js.map +1 -0
- package/dist/agents/adapters.d.ts.map +1 -1
- package/dist/agents/adapters.js +58 -13
- package/dist/agents/adapters.js.map +1 -1
- package/dist/agents/spawner.d.ts +8 -0
- package/dist/agents/spawner.d.ts.map +1 -1
- package/dist/agents/spawner.js +25 -3
- package/dist/agents/spawner.js.map +1 -1
- package/dist/cli/batch-exec.js +1 -1
- package/dist/cli/batch-exec.js.map +1 -1
- package/dist/cli/command-annotations.d.ts +15 -3
- package/dist/cli/command-annotations.d.ts.map +1 -1
- package/dist/cli/command-annotations.js +23 -3
- package/dist/cli/command-annotations.js.map +1 -1
- package/dist/cli/commands/agent.d.ts +2 -0
- package/dist/cli/commands/agent.d.ts.map +1 -1
- package/dist/cli/commands/agent.js +144 -27
- package/dist/cli/commands/agent.js.map +1 -1
- package/dist/cli/commands/agents.d.ts.map +1 -1
- package/dist/cli/commands/agents.js +5 -5
- package/dist/cli/commands/agents.js.map +1 -1
- package/dist/cli/commands/derive.d.ts.map +1 -1
- package/dist/cli/commands/derive.js +118 -3
- package/dist/cli/commands/derive.js.map +1 -1
- package/dist/cli/commands/guard.d.ts.map +1 -1
- package/dist/cli/commands/guard.js +8 -6
- package/dist/cli/commands/guard.js.map +1 -1
- package/dist/cli/commands/index.d.ts +1 -0
- package/dist/cli/commands/index.d.ts.map +1 -1
- package/dist/cli/commands/index.js +1 -0
- package/dist/cli/commands/index.js.map +1 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +20 -0
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/item.d.ts.map +1 -1
- package/dist/cli/commands/item.js +205 -47
- package/dist/cli/commands/item.js.map +1 -1
- package/dist/cli/commands/log.d.ts.map +1 -1
- package/dist/cli/commands/log.js +24 -10
- package/dist/cli/commands/log.js.map +1 -1
- package/dist/cli/commands/plan-import.d.ts +3 -3
- package/dist/cli/commands/plan-import.d.ts.map +1 -1
- package/dist/cli/commands/plan-import.js +213 -528
- package/dist/cli/commands/plan-import.js.map +1 -1
- package/dist/cli/commands/plan.d.ts.map +1 -1
- package/dist/cli/commands/plan.js +533 -83
- package/dist/cli/commands/plan.js.map +1 -1
- package/dist/cli/commands/review.d.ts +14 -0
- package/dist/cli/commands/review.d.ts.map +1 -0
- package/dist/cli/commands/review.js +1142 -0
- package/dist/cli/commands/review.js.map +1 -0
- package/dist/cli/commands/serve.d.ts +1 -0
- package/dist/cli/commands/serve.d.ts.map +1 -1
- package/dist/cli/commands/serve.js +33 -10
- package/dist/cli/commands/serve.js.map +1 -1
- package/dist/cli/commands/session/checkpoint.d.ts +2 -4
- package/dist/cli/commands/session/checkpoint.d.ts.map +1 -1
- package/dist/cli/commands/session/checkpoint.js +6 -107
- package/dist/cli/commands/session/checkpoint.js.map +1 -1
- package/dist/cli/commands/session/commands.d.ts.map +1 -1
- package/dist/cli/commands/session/commands.js +33 -23
- package/dist/cli/commands/session/commands.js.map +1 -1
- package/dist/cli/commands/session/compact.js +4 -4
- package/dist/cli/commands/session/compact.js.map +1 -1
- package/dist/cli/commands/session/create.js +2 -2
- package/dist/cli/commands/session/create.js.map +1 -1
- package/dist/cli/commands/session/format.d.ts.map +1 -1
- package/dist/cli/commands/session/format.js +1 -6
- package/dist/cli/commands/session/format.js.map +1 -1
- package/dist/cli/commands/session/log.d.ts +32 -7
- package/dist/cli/commands/session/log.d.ts.map +1 -1
- package/dist/cli/commands/session/log.js +166 -60
- package/dist/cli/commands/session/log.js.map +1 -1
- package/dist/cli/commands/session/migrate.d.ts +9 -0
- package/dist/cli/commands/session/migrate.d.ts.map +1 -0
- package/dist/cli/commands/session/migrate.js +46 -0
- package/dist/cli/commands/session/migrate.js.map +1 -0
- package/dist/cli/commands/session/stale-close.d.ts.map +1 -1
- package/dist/cli/commands/session/stale-close.js +5 -8
- package/dist/cli/commands/session/stale-close.js.map +1 -1
- package/dist/cli/commands/session/types.d.ts +1 -1
- package/dist/cli/commands/session/types.d.ts.map +1 -1
- package/dist/cli/commands/setup.d.ts +2 -2
- package/dist/cli/commands/setup.d.ts.map +1 -1
- package/dist/cli/commands/setup.js +287 -257
- package/dist/cli/commands/setup.js.map +1 -1
- package/dist/cli/commands/shadow.d.ts.map +1 -1
- package/dist/cli/commands/shadow.js +147 -31
- package/dist/cli/commands/shadow.js.map +1 -1
- package/dist/cli/commands/skill-crud.d.ts +7 -0
- package/dist/cli/commands/skill-crud.d.ts.map +1 -1
- package/dist/cli/commands/skill-crud.js +41 -18
- package/dist/cli/commands/skill-crud.js.map +1 -1
- package/dist/cli/commands/skill-diff.d.ts.map +1 -1
- package/dist/cli/commands/skill-diff.js +29 -3
- package/dist/cli/commands/skill-diff.js.map +1 -1
- package/dist/cli/commands/skill-install.d.ts.map +1 -1
- package/dist/cli/commands/skill-install.js +5 -4
- package/dist/cli/commands/skill-install.js.map +1 -1
- package/dist/cli/commands/task.d.ts.map +1 -1
- package/dist/cli/commands/task.js +359 -49
- package/dist/cli/commands/task.js.map +1 -1
- package/dist/cli/commands/trait.d.ts.map +1 -1
- package/dist/cli/commands/trait.js +5 -27
- package/dist/cli/commands/trait.js.map +1 -1
- package/dist/cli/commands/validate.d.ts.map +1 -1
- package/dist/cli/commands/validate.js +113 -52
- package/dist/cli/commands/validate.js.map +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +69 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/output.d.ts +26 -0
- package/dist/cli/output.d.ts.map +1 -1
- package/dist/cli/output.js +108 -1
- package/dist/cli/output.js.map +1 -1
- package/dist/cli/sync-mode.d.ts +44 -0
- package/dist/cli/sync-mode.d.ts.map +1 -0
- package/dist/cli/sync-mode.js +64 -0
- package/dist/cli/sync-mode.js.map +1 -0
- package/dist/daemon/middleware/project-context.ts +25 -7
- package/dist/daemon/project-context.ts +18 -0
- package/dist/daemon/routes/agent-dispatch.ts +99 -22
- package/dist/daemon/routes/aggregation.ts +184 -0
- package/dist/daemon/routes/inbox.ts +5 -0
- package/dist/daemon/routes/items.ts +145 -0
- package/dist/daemon/routes/meta.ts +1 -1
- package/dist/daemon/routes/projects.ts +28 -6
- package/dist/daemon/routes/ref-resolution.ts +119 -0
- package/dist/daemon/routes/refs.ts +42 -0
- package/dist/daemon/routes/session-related.ts +140 -0
- package/dist/daemon/routes/sessions.ts +420 -19
- package/dist/daemon/routes/tasks.ts +62 -5
- package/dist/daemon/routes/triage.ts +40 -1
- package/dist/daemon/server.ts +143 -49
- package/dist/daemon/session-sync.ts +11 -0
- package/dist/daemon/shadow-sync.ts +11 -0
- package/dist/daemon/watcher.ts +56 -5
- package/dist/daemon/websocket/project-resolution.ts +77 -0
- package/dist/export/json.d.ts.map +1 -1
- package/dist/export/json.js +104 -1
- package/dist/export/json.js.map +1 -1
- package/dist/export/types.d.ts +52 -1
- package/dist/export/types.d.ts.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/parser/agent-detection.d.ts +1 -1
- package/dist/parser/agent-detection.d.ts.map +1 -1
- package/dist/parser/agent-detection.js +10 -0
- package/dist/parser/agent-detection.js.map +1 -1
- package/dist/parser/config.d.ts +397 -2
- package/dist/parser/config.d.ts.map +1 -1
- package/dist/parser/config.js +125 -3
- package/dist/parser/config.js.map +1 -1
- package/dist/parser/dispatch-workspaces.d.ts +18 -0
- package/dist/parser/dispatch-workspaces.d.ts.map +1 -0
- package/dist/parser/dispatch-workspaces.js +209 -0
- package/dist/parser/dispatch-workspaces.js.map +1 -0
- package/dist/parser/doctor.d.ts.map +1 -1
- package/dist/parser/doctor.js +27 -8
- package/dist/parser/doctor.js.map +1 -1
- package/dist/parser/file-lock.d.ts.map +1 -1
- package/dist/parser/file-lock.js +9 -2
- package/dist/parser/file-lock.js.map +1 -1
- package/dist/parser/index.d.ts +6 -0
- package/dist/parser/index.d.ts.map +1 -1
- package/dist/parser/index.js +6 -0
- package/dist/parser/index.js.map +1 -1
- package/dist/parser/plans.d.ts.map +1 -1
- package/dist/parser/plans.js +1 -0
- package/dist/parser/plans.js.map +1 -1
- package/dist/parser/refs.d.ts +8 -1
- package/dist/parser/refs.d.ts.map +1 -1
- package/dist/parser/refs.js +27 -1
- package/dist/parser/refs.js.map +1 -1
- package/dist/parser/review-operations.d.ts +72 -0
- package/dist/parser/review-operations.d.ts.map +1 -0
- package/dist/parser/review-operations.js +185 -0
- package/dist/parser/review-operations.js.map +1 -0
- package/dist/parser/review-task-integration.d.ts +78 -0
- package/dist/parser/review-task-integration.d.ts.map +1 -0
- package/dist/parser/review-task-integration.js +173 -0
- package/dist/parser/review-task-integration.js.map +1 -0
- package/dist/parser/review-threads.d.ts +101 -0
- package/dist/parser/review-threads.d.ts.map +1 -0
- package/dist/parser/review-threads.js +222 -0
- package/dist/parser/review-threads.js.map +1 -0
- package/dist/parser/review-validation.d.ts +69 -0
- package/dist/parser/review-validation.d.ts.map +1 -0
- package/dist/parser/review-validation.js +207 -0
- package/dist/parser/review-validation.js.map +1 -0
- package/dist/parser/reviews.d.ts +58 -0
- package/dist/parser/reviews.d.ts.map +1 -0
- package/dist/parser/reviews.js +230 -0
- package/dist/parser/reviews.js.map +1 -0
- package/dist/parser/session-branch.d.ts +91 -0
- package/dist/parser/session-branch.d.ts.map +1 -0
- package/dist/parser/session-branch.js +565 -0
- package/dist/parser/session-branch.js.map +1 -0
- package/dist/parser/session-sync-scheduler.d.ts +53 -0
- package/dist/parser/session-sync-scheduler.d.ts.map +1 -0
- package/dist/parser/session-sync-scheduler.js +100 -0
- package/dist/parser/session-sync-scheduler.js.map +1 -0
- package/dist/parser/setup-status.d.ts +7 -1
- package/dist/parser/setup-status.d.ts.map +1 -1
- package/dist/parser/setup-status.js +104 -39
- package/dist/parser/setup-status.js.map +1 -1
- package/dist/parser/shadow-sync-scheduler.d.ts +71 -0
- package/dist/parser/shadow-sync-scheduler.d.ts.map +1 -0
- package/dist/parser/shadow-sync-scheduler.js +139 -0
- package/dist/parser/shadow-sync-scheduler.js.map +1 -0
- package/dist/parser/shadow.d.ts +121 -14
- package/dist/parser/shadow.d.ts.map +1 -1
- package/dist/parser/shadow.js +752 -27
- package/dist/parser/shadow.js.map +1 -1
- package/dist/parser/skill-render.d.ts +24 -0
- package/dist/parser/skill-render.d.ts.map +1 -1
- package/dist/parser/skill-render.js +98 -26
- package/dist/parser/skill-render.js.map +1 -1
- package/dist/parser/validate.d.ts +43 -3
- package/dist/parser/validate.d.ts.map +1 -1
- package/dist/parser/validate.js +204 -30
- package/dist/parser/validate.js.map +1 -1
- package/dist/parser/yaml.d.ts +47 -11
- package/dist/parser/yaml.d.ts.map +1 -1
- package/dist/parser/yaml.js +329 -149
- package/dist/parser/yaml.js.map +1 -1
- package/dist/review/checks.d.ts +97 -0
- package/dist/review/checks.d.ts.map +1 -0
- package/dist/review/checks.js +175 -0
- package/dist/review/checks.js.map +1 -0
- package/dist/review/index.d.ts +3 -0
- package/dist/review/index.d.ts.map +1 -0
- package/dist/review/index.js +3 -0
- package/dist/review/index.js.map +1 -0
- package/dist/review/subject-bindings.d.ts +83 -0
- package/dist/review/subject-bindings.d.ts.map +1 -0
- package/dist/review/subject-bindings.js +175 -0
- package/dist/review/subject-bindings.js.map +1 -0
- package/dist/schema/common.d.ts +26 -0
- package/dist/schema/common.d.ts.map +1 -1
- package/dist/schema/common.js +13 -0
- package/dist/schema/common.js.map +1 -1
- package/dist/schema/dispatch-workspace.d.ts +2643 -0
- package/dist/schema/dispatch-workspace.d.ts.map +1 -0
- package/dist/schema/dispatch-workspace.js +187 -0
- package/dist/schema/dispatch-workspace.js.map +1 -0
- package/dist/schema/inbox.d.ts +8 -8
- package/dist/schema/index.d.ts +2 -0
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/index.js +2 -0
- package/dist/schema/index.js.map +1 -1
- package/dist/schema/meta.d.ts +648 -116
- package/dist/schema/meta.d.ts.map +1 -1
- package/dist/schema/meta.js +27 -0
- package/dist/schema/meta.js.map +1 -1
- package/dist/schema/plan.d.ts +30 -19
- package/dist/schema/plan.d.ts.map +1 -1
- package/dist/schema/plan.js +3 -1
- package/dist/schema/plan.js.map +1 -1
- package/dist/schema/review-records.d.ts +2676 -0
- package/dist/schema/review-records.d.ts.map +1 -0
- package/dist/schema/review-records.js +232 -0
- package/dist/schema/review-records.js.map +1 -0
- package/dist/schema/spec.d.ts +32 -14
- package/dist/schema/spec.d.ts.map +1 -1
- package/dist/schema/spec.js +5 -0
- package/dist/schema/spec.js.map +1 -1
- package/dist/schema/task.d.ts +187 -29
- package/dist/schema/task.d.ts.map +1 -1
- package/dist/schema/task.js +12 -2
- package/dist/schema/task.js.map +1 -1
- package/dist/schema/triage.d.ts +22 -22
- package/dist/sessions/cache.d.ts +119 -0
- package/dist/sessions/cache.d.ts.map +1 -0
- package/dist/sessions/cache.js +284 -0
- package/dist/sessions/cache.js.map +1 -0
- package/dist/sessions/index.d.ts +1 -0
- package/dist/sessions/index.d.ts.map +1 -1
- package/dist/sessions/index.js +2 -0
- package/dist/sessions/index.js.map +1 -1
- package/dist/sessions/legacy.d.ts +77 -0
- package/dist/sessions/legacy.d.ts.map +1 -0
- package/dist/sessions/legacy.js +146 -0
- package/dist/sessions/legacy.js.map +1 -0
- package/dist/sessions/store.d.ts +103 -73
- package/dist/sessions/store.d.ts.map +1 -1
- package/dist/sessions/store.js +335 -186
- package/dist/sessions/store.js.map +1 -1
- package/dist/sessions/types.d.ts +44 -16
- package/dist/sessions/types.d.ts.map +1 -1
- package/dist/sessions/types.js +11 -2
- package/dist/sessions/types.js.map +1 -1
- package/dist/strings/errors.d.ts +32 -0
- package/dist/strings/errors.d.ts.map +1 -1
- package/dist/strings/errors.js +17 -0
- package/dist/strings/errors.js.map +1 -1
- package/dist/strings/labels.d.ts +1 -0
- package/dist/strings/labels.d.ts.map +1 -1
- package/dist/strings/labels.js +1 -0
- package/dist/strings/labels.js.map +1 -1
- package/dist/utils/activity.d.ts +101 -0
- package/dist/utils/activity.d.ts.map +1 -0
- package/dist/utils/activity.js +408 -0
- package/dist/utils/activity.js.map +1 -0
- package/dist/utils/git.d.ts +31 -0
- package/dist/utils/git.d.ts.map +1 -1
- package/dist/utils/git.js +87 -0
- package/dist/utils/git.js.map +1 -1
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +1 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/web-ui/_app/immutable/assets/0.tmlwn-Ih.css +1 -0
- package/dist/web-ui/_app/immutable/assets/9.BwwJybWx.css +1 -0
- package/dist/web-ui/_app/immutable/chunks/2KqE8gtn.js +1 -0
- package/dist/web-ui/_app/immutable/chunks/70-t_QvE.js +1 -0
- package/dist/web-ui/_app/immutable/chunks/AiWQj974.js +1 -0
- package/dist/web-ui/_app/immutable/chunks/{CPPfDSei.js → B25nWFyA.js} +4 -4
- package/dist/web-ui/_app/immutable/chunks/{DBYE9jOd.js → B2bcA_Q_.js} +1 -1
- package/dist/web-ui/_app/immutable/chunks/B5e5HYyB.js +1 -0
- package/dist/web-ui/_app/immutable/chunks/B7-5z6eA.js +1 -0
- package/dist/web-ui/_app/immutable/chunks/B7bGmhK0.js +1 -0
- package/dist/web-ui/_app/immutable/chunks/{DzO4hlg9.js → B8tYZKAE.js} +1 -1
- package/dist/web-ui/_app/immutable/chunks/{B5LJFxqa.js → BFGAyJjD.js} +1 -1
- package/dist/web-ui/_app/immutable/chunks/BG0850zf.js +1 -0
- package/dist/web-ui/_app/immutable/chunks/{DAMmvwn4.js → BG8eSzAd.js} +1 -1
- package/dist/web-ui/_app/immutable/chunks/BIMxXS8I.js +1 -0
- package/dist/web-ui/_app/immutable/chunks/BSzL1fpU.js +1 -0
- package/dist/web-ui/_app/immutable/chunks/BYtjHfeq.js +1 -0
- package/dist/web-ui/_app/immutable/chunks/{DxCk-KHc.js → Bp5pFYXL.js} +1 -1
- package/dist/web-ui/_app/immutable/chunks/{B8a0xDxR.js → BsJFsuAT.js} +1 -1
- package/dist/web-ui/_app/immutable/chunks/BvpNHcD6.js +1 -0
- package/dist/web-ui/_app/immutable/chunks/BypqA25-.js +1 -0
- package/dist/web-ui/_app/immutable/chunks/{BVA9Exy-.js → C0w6WDm5.js} +1 -1
- package/dist/web-ui/_app/immutable/chunks/C5_PAZ0y.js +1 -0
- package/dist/web-ui/_app/immutable/chunks/CDRO15Iv.js +1 -0
- package/dist/web-ui/_app/immutable/chunks/CF1CoqD5.js +1 -0
- package/dist/web-ui/_app/immutable/chunks/CS2sa4_m.js +1 -0
- package/dist/web-ui/_app/immutable/chunks/{BJ0JX3ea.js → CWUQwB9H.js} +1 -1
- package/dist/web-ui/_app/immutable/chunks/CY5FDdSU.js +1 -0
- package/dist/web-ui/_app/immutable/chunks/C_7MTDoj.js +1 -0
- package/dist/web-ui/_app/immutable/chunks/{D3vxvonu.js → CaAJD3dl.js} +1 -1
- package/dist/web-ui/_app/immutable/chunks/{BP352uRn.js → ChB5iyEL.js} +1 -1
- package/dist/web-ui/_app/immutable/chunks/{pE6cYWlS.js → ChQD-6N8.js} +1 -1
- package/dist/web-ui/_app/immutable/chunks/{Eo4gF7ih.js → CqbsoCwA.js} +1 -1
- package/dist/web-ui/_app/immutable/chunks/DCeJW50p.js +1 -0
- package/dist/web-ui/_app/immutable/chunks/{Cncwi6fQ.js → DJtZNgcs.js} +1 -1
- package/dist/web-ui/_app/immutable/chunks/DKIeaprD.js +1 -0
- package/dist/web-ui/_app/immutable/chunks/DLd2uVIA.js +1 -0
- package/dist/web-ui/_app/immutable/chunks/{DjcCz-PU.js → DW_subyT.js} +2 -2
- package/dist/web-ui/_app/immutable/chunks/DbU6lVn0.js +1 -0
- package/dist/web-ui/_app/immutable/chunks/Dc7ZCC5m.js +1 -0
- package/dist/web-ui/_app/immutable/chunks/Dd5umPsk.js +2 -0
- package/dist/web-ui/_app/immutable/chunks/{BysXJlZb.js → Dg_zDpDS.js} +1 -1
- package/dist/web-ui/_app/immutable/chunks/Dgqu8Yuc.js +1 -0
- package/dist/web-ui/_app/immutable/chunks/DmxsPZTB.js +1 -0
- package/dist/web-ui/_app/immutable/chunks/DphTaFUB.js +1 -0
- package/dist/web-ui/_app/immutable/chunks/DqK4iHp0.js +1 -0
- package/dist/web-ui/_app/immutable/chunks/{D9QNBZM2.js → DqT6OH_u.js} +2 -2
- package/dist/web-ui/_app/immutable/chunks/Ds9I9wQb.js +1 -0
- package/dist/web-ui/_app/immutable/chunks/Du5ng3u4.js +1 -0
- package/dist/web-ui/_app/immutable/chunks/DxJw79Wi.js +1 -0
- package/dist/web-ui/_app/immutable/chunks/GFTX8GgV.js +1 -0
- package/dist/web-ui/_app/immutable/chunks/{C076q4JN.js → HNjs76Zz.js} +1 -1
- package/dist/web-ui/_app/immutable/chunks/HVMjDi4_.js +1 -0
- package/dist/web-ui/_app/immutable/chunks/{BkOJ8DkV.js → P0A_fJvS.js} +1 -1
- package/dist/web-ui/_app/immutable/chunks/T3vGWjIL.js +1 -0
- package/dist/web-ui/_app/immutable/chunks/VTmrX9Qu.js +1 -0
- package/dist/web-ui/_app/immutable/chunks/{k_Qegko0.js → Xvwhx_F1.js} +1 -1
- package/dist/web-ui/_app/immutable/chunks/Yyz1XMQA.js +1 -0
- package/dist/web-ui/_app/immutable/chunks/{62JVKtnb.js → dh5HeqUr.js} +1 -1
- package/dist/web-ui/_app/immutable/chunks/fZMteyca.js +62 -0
- package/dist/web-ui/_app/immutable/chunks/{D82RulSH.js → gPrj-hqC.js} +1 -1
- package/dist/web-ui/_app/immutable/chunks/htcWMiYN.js +1 -0
- package/dist/web-ui/_app/immutable/chunks/{CwELQvbx.js → oTsvd9y4.js} +1 -1
- package/dist/web-ui/_app/immutable/chunks/qJfLUwU4.js +1 -0
- package/dist/web-ui/_app/immutable/chunks/xCtiO_JE.js +1 -0
- package/dist/web-ui/_app/immutable/chunks/{DvA-KON-.js → y4GeEH6k.js} +1 -1
- package/dist/web-ui/_app/immutable/entry/app.C4h_eOn6.js +2 -0
- package/dist/web-ui/_app/immutable/entry/start.CQFTf9ep.js +1 -0
- package/dist/web-ui/_app/immutable/nodes/0.Dh1xO970.js +1 -0
- package/dist/web-ui/_app/immutable/nodes/1.l75D3Opx.js +1 -0
- package/dist/web-ui/_app/immutable/nodes/10.DBidBPc-.js +1 -0
- package/dist/web-ui/_app/immutable/nodes/11.Ab0gUKWe.js +1 -0
- package/dist/web-ui/_app/immutable/nodes/12.CMsnoxfs.js +1 -0
- package/dist/web-ui/_app/immutable/nodes/13.D8YKuknB.js +1 -0
- package/dist/web-ui/_app/immutable/nodes/14.DZ0aan7y.js +1 -0
- package/dist/web-ui/_app/immutable/nodes/15.CUIKreDL.js +2 -0
- package/dist/web-ui/_app/immutable/nodes/16.BWc8--BO.js +1 -0
- package/dist/web-ui/_app/immutable/nodes/2.CDUonbuh.js +1 -0
- package/dist/web-ui/_app/immutable/nodes/3.Ctg3M00i.js +1 -0
- package/dist/web-ui/_app/immutable/nodes/4.Ci-JDwbA.js +2 -0
- package/dist/web-ui/_app/immutable/nodes/5.CTyEDAq0.js +1 -0
- package/dist/web-ui/_app/immutable/nodes/6.BTZZqsAb.js +1 -0
- package/dist/web-ui/_app/immutable/nodes/7.BI52g_Jo.js +137 -0
- package/dist/web-ui/_app/immutable/nodes/8.3hZPaB9x.js +1 -0
- package/dist/web-ui/_app/immutable/nodes/9.DS49kvwl.js +29 -0
- package/dist/web-ui/_app/version.json +1 -1
- package/dist/web-ui/favicon-192.png +0 -0
- package/dist/web-ui/favicon-32.png +0 -0
- package/dist/web-ui/favicon.ico +0 -0
- package/dist/web-ui/index.html +14 -14
- package/package.json +12 -6
- package/plugin/.claude-plugin/marketplace.json +1 -1
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/plugins/kspec/skills/merge/SKILL.md +127 -0
- package/plugin/plugins/kspec/skills/plan/SKILL.md +55 -26
- package/plugin/plugins/kspec/skills/review/SKILL.md +350 -133
- package/plugin/plugins/kspec/skills/task-work/SKILL.md +96 -106
- package/templates/agents-sections/04-pr-workflow.md +15 -12
- package/templates/agents-sections/06-ralph-loop.md +15 -10
- package/templates/skills/manifest.yaml +25 -7
- package/templates/skills/merge/SKILL.md +120 -0
- package/templates/skills/plan/SKILL.md +55 -26
- package/templates/skills/review/SKILL.md +346 -130
- package/templates/skills/task-work/SKILL.md +93 -103
- package/dist/web-ui/_app/immutable/assets/0.BJaYkGW2.css +0 -1
- package/dist/web-ui/_app/immutable/assets/9.SzGLxi4x.css +0 -1
- package/dist/web-ui/_app/immutable/chunks/-lc0BifF.js +0 -1
- package/dist/web-ui/_app/immutable/chunks/8RBjHMN1.js +0 -1
- package/dist/web-ui/_app/immutable/chunks/B5wTVqxm.js +0 -1
- package/dist/web-ui/_app/immutable/chunks/B6VSmczZ.js +0 -1
- package/dist/web-ui/_app/immutable/chunks/BEOQc37C.js +0 -1
- package/dist/web-ui/_app/immutable/chunks/BHtYorjv.js +0 -1
- package/dist/web-ui/_app/immutable/chunks/BMuCqDX8.js +0 -1
- package/dist/web-ui/_app/immutable/chunks/BUZujXJ2.js +0 -1
- package/dist/web-ui/_app/immutable/chunks/BWET-efb.js +0 -1
- package/dist/web-ui/_app/immutable/chunks/BXkNecpt.js +0 -1
- package/dist/web-ui/_app/immutable/chunks/BYzrIfX8.js +0 -1
- package/dist/web-ui/_app/immutable/chunks/BpuwufMc.js +0 -1
- package/dist/web-ui/_app/immutable/chunks/BwMO4RrG.js +0 -1
- package/dist/web-ui/_app/immutable/chunks/C33JaVbg.js +0 -1
- package/dist/web-ui/_app/immutable/chunks/CGtqifKp.js +0 -1
- package/dist/web-ui/_app/immutable/chunks/CHDZZ7OG.js +0 -1
- package/dist/web-ui/_app/immutable/chunks/CUir3f4J.js +0 -60
- package/dist/web-ui/_app/immutable/chunks/CrCIbn0C.js +0 -1
- package/dist/web-ui/_app/immutable/chunks/D6TVmR9T.js +0 -1
- package/dist/web-ui/_app/immutable/chunks/D7LTux4W.js +0 -1
- package/dist/web-ui/_app/immutable/chunks/DAh4Wfku.js +0 -1
- package/dist/web-ui/_app/immutable/chunks/DAx07bEQ.js +0 -1
- package/dist/web-ui/_app/immutable/chunks/DOno4cA2.js +0 -1
- package/dist/web-ui/_app/immutable/chunks/DQA8NZIH.js +0 -2
- package/dist/web-ui/_app/immutable/chunks/DRfPm2bo.js +0 -1
- package/dist/web-ui/_app/immutable/chunks/DhQhksaB.js +0 -1
- package/dist/web-ui/_app/immutable/chunks/DjG7s6hm.js +0 -1
- package/dist/web-ui/_app/immutable/chunks/DkltRNvh.js +0 -1
- package/dist/web-ui/_app/immutable/chunks/DlaTnPKL.js +0 -1
- package/dist/web-ui/_app/immutable/chunks/ExCq5swK.js +0 -1
- package/dist/web-ui/_app/immutable/chunks/T3zZGv51.js +0 -1
- package/dist/web-ui/_app/immutable/chunks/XZumBYeP.js +0 -1
- package/dist/web-ui/_app/immutable/chunks/_ySfNjkF.js +0 -1
- package/dist/web-ui/_app/immutable/chunks/iEtR5cV6.js +0 -1
- package/dist/web-ui/_app/immutable/entry/app.Cgu6uKeS.js +0 -2
- package/dist/web-ui/_app/immutable/entry/start.9XifnLoB.js +0 -1
- package/dist/web-ui/_app/immutable/nodes/0.DISwcKSK.js +0 -1
- package/dist/web-ui/_app/immutable/nodes/1.Cx2Ufqp1.js +0 -1
- package/dist/web-ui/_app/immutable/nodes/10.C3z8ijXL.js +0 -1
- package/dist/web-ui/_app/immutable/nodes/11.DZdIjZmM.js +0 -1
- package/dist/web-ui/_app/immutable/nodes/12.FsIGfAOa.js +0 -1
- package/dist/web-ui/_app/immutable/nodes/13.DZoFwagf.js +0 -1
- package/dist/web-ui/_app/immutable/nodes/14.DaIzDKbQ.js +0 -1
- package/dist/web-ui/_app/immutable/nodes/15.BYyt4XWF.js +0 -2
- package/dist/web-ui/_app/immutable/nodes/16.CQkSqpOe.js +0 -1
- package/dist/web-ui/_app/immutable/nodes/2.Bkf_j2UJ.js +0 -1
- package/dist/web-ui/_app/immutable/nodes/3.kaMCurJG.js +0 -1
- package/dist/web-ui/_app/immutable/nodes/4.BSsFPTHG.js +0 -2
- package/dist/web-ui/_app/immutable/nodes/5.CpPlcCEZ.js +0 -1
- package/dist/web-ui/_app/immutable/nodes/6.BN4FqQmY.js +0 -1
- package/dist/web-ui/_app/immutable/nodes/7.9kBYIZik.js +0 -1
- package/dist/web-ui/_app/immutable/nodes/8.BuijtZ6B.js +0 -1
- package/dist/web-ui/_app/immutable/nodes/9.C-Weba8R.js +0 -1
|
@@ -19,13 +19,15 @@
|
|
|
19
19
|
* - @agent-dispatch-engine ac-4: CLI posts state change event to daemon
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
|
+
import path from 'node:path';
|
|
22
23
|
import { Elysia, t } from 'elysia';
|
|
23
24
|
import { DispatchEngine } from '../../agent-runtime/dispatch.js';
|
|
24
25
|
import type { TaskStateChange, TaskStatus, InvocationEvent } from '../../agent-runtime/dispatch.js';
|
|
25
26
|
import { DEFAULT_KSPEC_CLI_PATH } from '../../agent-runtime/invocation.js';
|
|
26
|
-
import { initContext, loadMetaContext } from '../../parser/index.js';
|
|
27
|
+
import { initContext, loadMetaContext, loadAllTasks, loadAllItems, ReferenceIndex, resolveProjectRoots } from '../../parser/index.js';
|
|
27
28
|
import { getCompletedSessionCountsByAgent } from '../../sessions/store.js';
|
|
28
29
|
import type { PubSubManager } from '../websocket/pubsub.js';
|
|
30
|
+
import type { SessionEventData } from '@kynetic-ai/shared';
|
|
29
31
|
|
|
30
32
|
const VALID_TASK_STATUSES = new Set<string>([
|
|
31
33
|
"pending", "in_progress", "pending_review", "needs_work", "blocked", "completed", "cancelled",
|
|
@@ -44,31 +46,33 @@ export interface AgentDispatchRouteOptions {
|
|
|
44
46
|
* Create a new dispatch engine with optional WebSocket broadcast wiring.
|
|
45
47
|
* AC: @daemon-agent-dispatch ac-3, ac-4
|
|
46
48
|
*/
|
|
47
|
-
function createEngine(
|
|
49
|
+
function createEngine(
|
|
50
|
+
projectDir: string,
|
|
51
|
+
cwd?: string,
|
|
52
|
+
pubsub?: PubSubManager,
|
|
53
|
+
): DispatchEngine {
|
|
48
54
|
return new DispatchEngine({
|
|
49
55
|
projectDir,
|
|
56
|
+
cwd,
|
|
50
57
|
kspecCliPath: DEFAULT_KSPEC_CLI_PATH,
|
|
51
58
|
onInvocationEvent: pubsub
|
|
52
59
|
? (event: InvocationEvent) => {
|
|
60
|
+
// AC: @ui-api-aggregation ac-4 - Include task_title for display
|
|
53
61
|
pubsub.broadcast('agents', 'agent_invocation', {
|
|
54
62
|
session_id: event.session_id,
|
|
55
63
|
agent_id: event.agent_id,
|
|
56
64
|
task_id: event.task_id ?? null,
|
|
65
|
+
task_title: event.task_title ?? null,
|
|
57
66
|
status: event.status,
|
|
58
67
|
timestamp: event.timestamp,
|
|
59
68
|
}, projectDir);
|
|
60
69
|
}
|
|
61
70
|
: undefined,
|
|
71
|
+
// AC: @session-event-broadcast ac-replaces-text-chunks
|
|
62
72
|
// AC: @cli-agent-commands ac-13, @daemon-agent-dispatch ac-8
|
|
63
|
-
|
|
64
|
-
? (
|
|
65
|
-
pubsub.broadcast('agents',
|
|
66
|
-
session_id: sessionId,
|
|
67
|
-
agent_id: agentId,
|
|
68
|
-
task_id: taskId,
|
|
69
|
-
text,
|
|
70
|
-
timestamp: Date.now(),
|
|
71
|
-
}, projectDir);
|
|
73
|
+
onSessionEvent: pubsub
|
|
74
|
+
? (event: SessionEventData) => {
|
|
75
|
+
pubsub.broadcast('agents', event.type, event, projectDir);
|
|
72
76
|
}
|
|
73
77
|
: undefined,
|
|
74
78
|
});
|
|
@@ -117,6 +121,28 @@ function processStateChangeEvent(
|
|
|
117
121
|
return { accepted: true };
|
|
118
122
|
}
|
|
119
123
|
|
|
124
|
+
export function resolveDispatchCwd(
|
|
125
|
+
projectDir: string,
|
|
126
|
+
requestedCwd: string | null,
|
|
127
|
+
): string {
|
|
128
|
+
if (requestedCwd && !path.isAbsolute(requestedCwd)) {
|
|
129
|
+
throw new Error('Dispatch cwd must be an absolute path');
|
|
130
|
+
}
|
|
131
|
+
const cwd = requestedCwd ? path.resolve(requestedCwd) : projectDir;
|
|
132
|
+
|
|
133
|
+
if (cwd === projectDir) {
|
|
134
|
+
return cwd;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const projectRoots = resolveProjectRoots(projectDir);
|
|
138
|
+
const cwdRoots = resolveProjectRoots(cwd);
|
|
139
|
+
if (!projectRoots || !cwdRoots || projectRoots.mainRoot !== cwdRoots.mainRoot) {
|
|
140
|
+
throw new Error('Dispatch cwd must belong to the same git project');
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return cwd;
|
|
144
|
+
}
|
|
145
|
+
|
|
120
146
|
export function createAgentDispatchRoutes(options: AgentDispatchRouteOptions = {}) {
|
|
121
147
|
const { pubsub } = options;
|
|
122
148
|
|
|
@@ -134,16 +160,34 @@ export function createAgentDispatchRoutes(options: AgentDispatchRouteOptions = {
|
|
|
134
160
|
}, { body: stateChangeBodySchema })
|
|
135
161
|
|
|
136
162
|
// AC: @daemon-agent-dispatch ac-6 - Unified dispatch start/stop via action field
|
|
137
|
-
.post('/dispatch', async ({ body, projectContext }) => {
|
|
163
|
+
.post('/dispatch', async ({ body, projectContext, request, set }) => {
|
|
138
164
|
const projectDir = projectContext.path;
|
|
139
165
|
|
|
140
166
|
if (body.action === 'start') {
|
|
167
|
+
let requestedCwd: string;
|
|
168
|
+
try {
|
|
169
|
+
requestedCwd = resolveDispatchCwd(projectDir, request.headers.get('X-Kspec-Cwd'));
|
|
170
|
+
} catch (err) {
|
|
171
|
+
set.status = 400;
|
|
172
|
+
return {
|
|
173
|
+
dispatch_enabled: false,
|
|
174
|
+
error: err instanceof Error ? err.message : String(err),
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
|
|
141
178
|
let engine = engines.get(projectDir);
|
|
142
179
|
if (engine?.getStatus().running) {
|
|
180
|
+
if (engine.getCwd() !== requestedCwd) {
|
|
181
|
+
set.status = 409;
|
|
182
|
+
return {
|
|
183
|
+
dispatch_enabled: true,
|
|
184
|
+
error: `Dispatch engine already running for ${projectDir} with cwd ${engine.getCwd()}`,
|
|
185
|
+
};
|
|
186
|
+
}
|
|
143
187
|
return { dispatch_enabled: true, reason: 'Already running' };
|
|
144
188
|
}
|
|
145
189
|
|
|
146
|
-
engine = createEngine(projectDir, pubsub);
|
|
190
|
+
engine = createEngine(projectDir, requestedCwd, pubsub);
|
|
147
191
|
engines.set(projectDir, engine);
|
|
148
192
|
await engine.start();
|
|
149
193
|
|
|
@@ -166,16 +210,34 @@ export function createAgentDispatchRoutes(options: AgentDispatchRouteOptions = {
|
|
|
166
210
|
})
|
|
167
211
|
|
|
168
212
|
// Start dispatch engine (legacy route)
|
|
169
|
-
.post('/dispatch/start', async ({ projectContext }) => {
|
|
213
|
+
.post('/dispatch/start', async ({ projectContext, request, set }) => {
|
|
170
214
|
const projectDir = projectContext.path;
|
|
215
|
+
let requestedCwd: string;
|
|
216
|
+
try {
|
|
217
|
+
requestedCwd = resolveDispatchCwd(projectDir, request.headers.get('X-Kspec-Cwd'));
|
|
218
|
+
} catch (err) {
|
|
219
|
+
set.status = 400;
|
|
220
|
+
return {
|
|
221
|
+
started: false,
|
|
222
|
+
error: err instanceof Error ? err.message : String(err),
|
|
223
|
+
};
|
|
224
|
+
}
|
|
171
225
|
|
|
172
226
|
let engine = engines.get(projectDir);
|
|
173
227
|
if (engine?.getStatus().running) {
|
|
228
|
+
if (engine.getCwd() !== requestedCwd) {
|
|
229
|
+
set.status = 409;
|
|
230
|
+
return {
|
|
231
|
+
started: false,
|
|
232
|
+
error: `Dispatch engine already running for ${projectDir} with cwd ${engine.getCwd()}`,
|
|
233
|
+
status: engine.getStatus(),
|
|
234
|
+
};
|
|
235
|
+
}
|
|
174
236
|
return { started: false, reason: 'Already running', status: engine.getStatus() };
|
|
175
237
|
}
|
|
176
238
|
|
|
177
239
|
// AC: @agent-dispatch-engine ac-10 - pass kspecCliPath so task notes work from daemon-started engine
|
|
178
|
-
engine = createEngine(projectDir, pubsub);
|
|
240
|
+
engine = createEngine(projectDir, requestedCwd, pubsub);
|
|
179
241
|
engines.set(projectDir, engine);
|
|
180
242
|
|
|
181
243
|
await engine.start();
|
|
@@ -215,19 +277,24 @@ export function createAgentDispatchRoutes(options: AgentDispatchRouteOptions = {
|
|
|
215
277
|
})
|
|
216
278
|
|
|
217
279
|
// AC: @daemon-agent-dispatch ac-5 - Public status endpoint
|
|
280
|
+
// AC: @ui-api-ref-resolution ac-1 - Include task_title for active invocations
|
|
218
281
|
.get('/status', async ({ projectContext }) => {
|
|
219
282
|
const projectDir = projectContext.path;
|
|
220
283
|
const engineStatus = engines.get(projectDir)?.getStatus();
|
|
221
284
|
|
|
222
285
|
let agentDefinitions: Array<{ id: string; name: string; adapter: string; completed_sessions: number }> = [];
|
|
223
286
|
let completedCounts: Record<string, number> = {};
|
|
287
|
+
let refIndex: ReferenceIndex | null = null;
|
|
224
288
|
try {
|
|
225
289
|
const ctx = await initContext(projectDir);
|
|
226
|
-
const [meta, counts] = await Promise.all([
|
|
290
|
+
const [meta, counts, tasks, items] = await Promise.all([
|
|
227
291
|
loadMetaContext(ctx),
|
|
228
292
|
getCompletedSessionCountsByAgent(ctx.specDir),
|
|
293
|
+
loadAllTasks(ctx),
|
|
294
|
+
loadAllItems(ctx),
|
|
229
295
|
]);
|
|
230
296
|
completedCounts = counts;
|
|
297
|
+
refIndex = new ReferenceIndex(tasks, items);
|
|
231
298
|
agentDefinitions = meta.agents.map((a) => ({
|
|
232
299
|
id: a.id,
|
|
233
300
|
name: a.name,
|
|
@@ -240,12 +307,22 @@ export function createAgentDispatchRoutes(options: AgentDispatchRouteOptions = {
|
|
|
240
307
|
|
|
241
308
|
return {
|
|
242
309
|
dispatch_enabled: engineStatus?.running ?? false,
|
|
243
|
-
active_invocations: engineStatus?.invocations?.map((inv) =>
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
310
|
+
active_invocations: engineStatus?.invocations?.map((inv) => {
|
|
311
|
+
let task_title: string | null = null;
|
|
312
|
+
if (inv.taskRef && refIndex) {
|
|
313
|
+
const result = refIndex.resolve(inv.taskRef);
|
|
314
|
+
if (result.ok) {
|
|
315
|
+
task_title = (result.item as { title?: string }).title ?? null;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
return {
|
|
319
|
+
session_id: inv.sessionId,
|
|
320
|
+
agent_id: inv.agentId,
|
|
321
|
+
task_ref: inv.taskRef ?? null,
|
|
322
|
+
task_title,
|
|
323
|
+
elapsed_ms: inv.elapsedMs,
|
|
324
|
+
};
|
|
325
|
+
}) ?? [],
|
|
249
326
|
queue_depth: engineStatus?.queuedInvocations ?? 0,
|
|
250
327
|
agent_definitions: agentDefinitions,
|
|
251
328
|
};
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Aggregation API Routes
|
|
3
|
+
*
|
|
4
|
+
* Pre-computed server-side aggregation endpoints:
|
|
5
|
+
* - GET /api/aggregation/tasks/summary - Task status counts with dependency-aware distinctions
|
|
6
|
+
* - GET /api/aggregation/validation - Extended validation/alignment stats with entity and AC counts
|
|
7
|
+
* - GET /api/aggregation/inbox - Inbox items with inline triage status
|
|
8
|
+
*
|
|
9
|
+
* AC Coverage:
|
|
10
|
+
* - @ui-api-aggregation ac-1: Task status summary with ready vs blocked distinctions
|
|
11
|
+
* - @ui-api-aggregation ac-2: Validation/alignment stats with entity counts, AC counts, orphan counts
|
|
12
|
+
* - @ui-api-aggregation ac-3: Inbox items with inline triage status
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { Elysia } from 'elysia';
|
|
16
|
+
import {
|
|
17
|
+
initContext,
|
|
18
|
+
loadAllTasks,
|
|
19
|
+
loadInboxItems,
|
|
20
|
+
loadTriageRecords,
|
|
21
|
+
findTriageRecordByInboxRef,
|
|
22
|
+
buildIndexes,
|
|
23
|
+
validate,
|
|
24
|
+
AlignmentIndex,
|
|
25
|
+
areDependenciesMet,
|
|
26
|
+
} from '../../parser/index.js';
|
|
27
|
+
import type {
|
|
28
|
+
TaskStatusSummary,
|
|
29
|
+
ValidationAggregation,
|
|
30
|
+
InboxItemWithTriage,
|
|
31
|
+
} from '@kynetic-ai/shared';
|
|
32
|
+
|
|
33
|
+
interface AggregationRouteOptions {}
|
|
34
|
+
|
|
35
|
+
export function createAggregationRoutes(options: AggregationRouteOptions = {}) {
|
|
36
|
+
return new Elysia({ prefix: '/api/aggregation' })
|
|
37
|
+
// AC: @ui-api-aggregation ac-1 - Task status summary with dependency-aware distinctions
|
|
38
|
+
.get('/tasks/summary', async ({ projectContext }) => {
|
|
39
|
+
const ctx = await initContext(projectContext.path);
|
|
40
|
+
const tasks = await loadAllTasks(ctx);
|
|
41
|
+
|
|
42
|
+
// Count tasks by status
|
|
43
|
+
const counts: Record<string, number> = {};
|
|
44
|
+
for (const task of tasks) {
|
|
45
|
+
counts[task.status] = (counts[task.status] || 0) + 1;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Dependency-aware distinctions: ready vs blocked by incomplete dependencies
|
|
49
|
+
let ready = 0;
|
|
50
|
+
let blockedByDependencies = 0;
|
|
51
|
+
for (const task of tasks) {
|
|
52
|
+
if (task.status !== 'pending' && task.status !== 'needs_work') continue;
|
|
53
|
+
if (task.blocked_by.length > 0) {
|
|
54
|
+
blockedByDependencies++;
|
|
55
|
+
} else if (!areDependenciesMet(task, tasks)) {
|
|
56
|
+
blockedByDependencies++;
|
|
57
|
+
} else {
|
|
58
|
+
ready++;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const result: TaskStatusSummary = {
|
|
63
|
+
counts,
|
|
64
|
+
ready,
|
|
65
|
+
blocked_by_dependencies: blockedByDependencies,
|
|
66
|
+
total: tasks.length,
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
return result;
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
// AC: @ui-api-aggregation ac-2 - Extended validation/alignment stats
|
|
73
|
+
.get('/validation', async ({ projectContext }) => {
|
|
74
|
+
const ctx = await initContext(projectContext.path);
|
|
75
|
+
const { tasks, items, refIndex } = await buildIndexes(ctx);
|
|
76
|
+
|
|
77
|
+
// Run validation for error/warning counts and completeness data
|
|
78
|
+
const validationResult = await validate(ctx);
|
|
79
|
+
|
|
80
|
+
// Build alignment index
|
|
81
|
+
const alignIndex = new AlignmentIndex(tasks, items);
|
|
82
|
+
alignIndex.buildLinks(refIndex);
|
|
83
|
+
const alignStats = alignIndex.getStats();
|
|
84
|
+
const alignWarnings = alignIndex.findAlignmentWarnings();
|
|
85
|
+
|
|
86
|
+
// Entity counts
|
|
87
|
+
const traitCount = items.filter((item) => item.type === 'trait').length;
|
|
88
|
+
|
|
89
|
+
// AC counts from completeness warnings
|
|
90
|
+
// Count total ACs across all non-trait items
|
|
91
|
+
let totalACs = 0;
|
|
92
|
+
for (const item of items) {
|
|
93
|
+
if (item.type !== 'trait') {
|
|
94
|
+
totalACs += item.acceptance_criteria?.length || 0;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Count uncovered ACs from completeness warnings
|
|
99
|
+
// Each warning represents one item with N uncovered ACs listed in details
|
|
100
|
+
// Details format: "Uncovered: ac-1, ac-2, ac-3"
|
|
101
|
+
const uncoveredWarnings = validationResult.completenessWarnings.filter(
|
|
102
|
+
(w) => w.type === 'missing_test_coverage' && w.subtype === 'own_ac'
|
|
103
|
+
);
|
|
104
|
+
let uncoveredCount = 0;
|
|
105
|
+
for (const warning of uncoveredWarnings) {
|
|
106
|
+
if (warning.details) {
|
|
107
|
+
// Parse "Uncovered: ac-1, ac-2, ac-3" to count individual ACs
|
|
108
|
+
const acList = warning.details.replace(/^Uncovered:\s*/, '');
|
|
109
|
+
uncoveredCount += acList.split(',').filter((s) => s.trim().length > 0).length;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
const coveredCount = Math.max(0, totalACs - uncoveredCount);
|
|
113
|
+
|
|
114
|
+
const result: ValidationAggregation = {
|
|
115
|
+
stats: {
|
|
116
|
+
totalSpecs: alignStats.totalSpecs,
|
|
117
|
+
specsWithTasks: alignStats.specsWithTasks,
|
|
118
|
+
alignedSpecs: alignStats.alignedSpecs,
|
|
119
|
+
orphanedSpecs: alignStats.orphanedSpecs,
|
|
120
|
+
},
|
|
121
|
+
warnings: alignWarnings,
|
|
122
|
+
entity_counts: {
|
|
123
|
+
items: validationResult.stats.itemsChecked,
|
|
124
|
+
tasks: validationResult.stats.tasksChecked,
|
|
125
|
+
traits: traitCount,
|
|
126
|
+
},
|
|
127
|
+
ac_counts: {
|
|
128
|
+
total: totalACs,
|
|
129
|
+
covered: coveredCount,
|
|
130
|
+
uncovered: uncoveredCount,
|
|
131
|
+
},
|
|
132
|
+
orphan_count: validationResult.orphans.length,
|
|
133
|
+
valid: validationResult.valid,
|
|
134
|
+
error_count: validationResult.schemaErrors.length + validationResult.refErrors.length,
|
|
135
|
+
warning_count: validationResult.refWarnings.length + validationResult.completenessWarnings.length,
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
return result;
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
// AC: @ui-api-aggregation ac-3 - Inbox items with inline triage status
|
|
142
|
+
.get('/inbox', async ({ projectContext }) => {
|
|
143
|
+
const ctx = await initContext(projectContext.path);
|
|
144
|
+
const inboxItems = await loadInboxItems(ctx);
|
|
145
|
+
const triageRecords = await loadTriageRecords(ctx);
|
|
146
|
+
|
|
147
|
+
// Sort by created_at descending (newest first)
|
|
148
|
+
const sorted = [...inboxItems].sort(
|
|
149
|
+
(a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime()
|
|
150
|
+
);
|
|
151
|
+
|
|
152
|
+
// Merge triage status inline
|
|
153
|
+
const items: InboxItemWithTriage[] = sorted.map((item) => {
|
|
154
|
+
const triageRecord = findTriageRecordByInboxRef(triageRecords, item._ulid);
|
|
155
|
+
|
|
156
|
+
const result: InboxItemWithTriage = {
|
|
157
|
+
_ulid: item._ulid,
|
|
158
|
+
text: item.text,
|
|
159
|
+
tags: item.tags,
|
|
160
|
+
added_by: item.added_by,
|
|
161
|
+
created_at: item.created_at,
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
if (triageRecord) {
|
|
165
|
+
result.triage = {
|
|
166
|
+
_ulid: triageRecord._ulid,
|
|
167
|
+
status: triageRecord.status as 'pending' | 'triaged' | 'acted_on',
|
|
168
|
+
action: triageRecord.action as 'promote' | 'delete' | 'defer' | 'spec-gap' | 'duplicate' | undefined,
|
|
169
|
+
reasoning: triageRecord.reasoning,
|
|
170
|
+
decided_by: triageRecord.decided_by,
|
|
171
|
+
acted_at: triageRecord.acted_at,
|
|
172
|
+
result_ref: triageRecord.result_ref,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
return result;
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
return {
|
|
180
|
+
items,
|
|
181
|
+
total: items.length,
|
|
182
|
+
};
|
|
183
|
+
});
|
|
184
|
+
}
|
|
@@ -88,9 +88,14 @@ export function createInboxRoutes(options: InboxRouteOptions) {
|
|
|
88
88
|
await commitIfShadow(ctx.shadow, `inbox: add item ${item._ulid}`);
|
|
89
89
|
|
|
90
90
|
// Broadcast update
|
|
91
|
+
// AC: @ui-api-aggregation ac-4 - Include full item data for in-place UI updates
|
|
91
92
|
// AC: @multi-directory-daemon ac-18 - Broadcast scoped to request project
|
|
92
93
|
pubsub.broadcast('inbox:updates', 'inbox_item_created', {
|
|
93
94
|
ulid: item._ulid,
|
|
95
|
+
text: item.text,
|
|
96
|
+
tags: item.tags,
|
|
97
|
+
added_by: item.added_by,
|
|
98
|
+
created_at: item.created_at,
|
|
94
99
|
}, projectContext.path);
|
|
95
100
|
|
|
96
101
|
// AC: @api-contract ac-13 - Return item with generated ULID
|
|
@@ -19,12 +19,16 @@ import {
|
|
|
19
19
|
loadAllItems,
|
|
20
20
|
loadAllTasks,
|
|
21
21
|
loadPlans,
|
|
22
|
+
findItemByRef,
|
|
23
|
+
findTaskByRef,
|
|
22
24
|
ReferenceIndex,
|
|
23
25
|
AlignmentIndex,
|
|
24
26
|
getCachedTestCoverage,
|
|
25
27
|
computeACCoverage,
|
|
26
28
|
type LoadedSpecItem,
|
|
29
|
+
type LoadedTask,
|
|
27
30
|
} from '../../parser/index.js';
|
|
31
|
+
import { getRelatedSessionsForItem } from './session-related.js';
|
|
28
32
|
|
|
29
33
|
interface ItemsRouteOptions {}
|
|
30
34
|
|
|
@@ -89,6 +93,49 @@ function computeParentMap(items: LoadedSpecItem[]): Map<string, string | undefin
|
|
|
89
93
|
return parentMap;
|
|
90
94
|
}
|
|
91
95
|
|
|
96
|
+
function getItemImplementationStatus(item: LoadedSpecItem): string | undefined {
|
|
97
|
+
if (typeof item.status === 'string') {
|
|
98
|
+
return item.status;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return item.status?.implementation;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function getItemMaturity(item: LoadedSpecItem): string | undefined {
|
|
105
|
+
if (typeof item.status === 'object') {
|
|
106
|
+
return item.status?.maturity;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return undefined;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function toBatchSpecItemSummary(item: LoadedSpecItem) {
|
|
113
|
+
return {
|
|
114
|
+
kind: 'item',
|
|
115
|
+
ulid: item._ulid,
|
|
116
|
+
slugs: item.slugs,
|
|
117
|
+
title: item.title,
|
|
118
|
+
type: item.type,
|
|
119
|
+
status: getItemImplementationStatus(item),
|
|
120
|
+
maturity: getItemMaturity(item),
|
|
121
|
+
traits: item.traits ?? [],
|
|
122
|
+
ac_count: item.acceptance_criteria?.length ?? 0,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function toBatchTaskSummary(task: LoadedTask) {
|
|
127
|
+
return {
|
|
128
|
+
kind: 'task',
|
|
129
|
+
ulid: task._ulid,
|
|
130
|
+
slugs: task.slugs,
|
|
131
|
+
title: task.title,
|
|
132
|
+
status: task.status,
|
|
133
|
+
priority: task.priority,
|
|
134
|
+
spec_ref: task.spec_ref,
|
|
135
|
+
assignee: task.assignee,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
|
|
92
139
|
export function createItemsRoutes(options: ItemsRouteOptions = {}) {
|
|
93
140
|
// No closure-scoped kspecDir needed - comes from middleware
|
|
94
141
|
|
|
@@ -206,6 +253,73 @@ export function createItemsRoutes(options: ItemsRouteOptions = {}) {
|
|
|
206
253
|
}
|
|
207
254
|
)
|
|
208
255
|
|
|
256
|
+
.post(
|
|
257
|
+
'/batch',
|
|
258
|
+
async ({ body, error: errorResponse, projectContext }) => {
|
|
259
|
+
const refs = body.refs;
|
|
260
|
+
|
|
261
|
+
// AC: @trait-api-endpoint ac-3 - Validate body
|
|
262
|
+
if (!Array.isArray(refs)) {
|
|
263
|
+
return errorResponse(400, {
|
|
264
|
+
error: 'validation_error',
|
|
265
|
+
details: [
|
|
266
|
+
{
|
|
267
|
+
field: 'refs',
|
|
268
|
+
message: 'Refs is required and must be an array of item references',
|
|
269
|
+
},
|
|
270
|
+
],
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// AC: @batch-item-fetch-api ac-5 - Enforce max batch size
|
|
275
|
+
if (refs.length > 100) {
|
|
276
|
+
return errorResponse(400, {
|
|
277
|
+
error: 'validation_error',
|
|
278
|
+
details: [
|
|
279
|
+
{
|
|
280
|
+
field: 'refs',
|
|
281
|
+
message: 'Maximum batch size is 100 refs',
|
|
282
|
+
},
|
|
283
|
+
],
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// AC: @multi-directory-daemon ac-1, ac-24 - Use project context from middleware
|
|
288
|
+
const ctx = await initContext(projectContext.path);
|
|
289
|
+
const items = await loadAllItems(ctx);
|
|
290
|
+
const tasks = await loadAllTasks(ctx);
|
|
291
|
+
|
|
292
|
+
const resolvedItems = [];
|
|
293
|
+
const unresolved: string[] = [];
|
|
294
|
+
|
|
295
|
+
for (const ref of refs) {
|
|
296
|
+
const task = findTaskByRef(tasks, ref);
|
|
297
|
+
if (task) {
|
|
298
|
+
resolvedItems.push(toBatchTaskSummary(task));
|
|
299
|
+
continue;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
const item = findItemByRef(items, ref);
|
|
303
|
+
if (item) {
|
|
304
|
+
resolvedItems.push(toBatchSpecItemSummary(item));
|
|
305
|
+
continue;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
unresolved.push(ref);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
return {
|
|
312
|
+
items: resolvedItems,
|
|
313
|
+
unresolved,
|
|
314
|
+
};
|
|
315
|
+
},
|
|
316
|
+
{
|
|
317
|
+
body: t.Object({
|
|
318
|
+
refs: t.Optional(t.Array(t.String())),
|
|
319
|
+
}),
|
|
320
|
+
}
|
|
321
|
+
)
|
|
322
|
+
|
|
209
323
|
// AC: @api-contract ac-10 - Get single item by ref
|
|
210
324
|
.get(
|
|
211
325
|
'/:ref',
|
|
@@ -340,5 +454,36 @@ export function createItemsRoutes(options: ItemsRouteOptions = {}) {
|
|
|
340
454
|
ref: t.String(),
|
|
341
455
|
}),
|
|
342
456
|
}
|
|
457
|
+
)
|
|
458
|
+
|
|
459
|
+
.get(
|
|
460
|
+
'/:ref/sessions',
|
|
461
|
+
async ({ params, error: errorResponse, projectContext }) => {
|
|
462
|
+
const ctx = await initContext(projectContext.path);
|
|
463
|
+
const items = await loadAllItems(ctx);
|
|
464
|
+
const tasks = await loadAllTasks(ctx);
|
|
465
|
+
const result = await getRelatedSessionsForItem({
|
|
466
|
+
itemRef: params.ref,
|
|
467
|
+
items,
|
|
468
|
+
tasks,
|
|
469
|
+
sessionsDir: ctx.sessionsDir,
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
if ('error' in result) {
|
|
473
|
+
return errorResponse(404, result.error);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
return {
|
|
477
|
+
items: result.sessions,
|
|
478
|
+
total: result.sessions.length,
|
|
479
|
+
offset: 0,
|
|
480
|
+
limit: result.sessions.length,
|
|
481
|
+
};
|
|
482
|
+
},
|
|
483
|
+
{
|
|
484
|
+
params: t.Object({
|
|
485
|
+
ref: t.String(),
|
|
486
|
+
}),
|
|
487
|
+
}
|
|
343
488
|
);
|
|
344
489
|
}
|
|
@@ -202,7 +202,7 @@ export function createMetaRoutes(options: MetaRouteOptions = {}) {
|
|
|
202
202
|
return {
|
|
203
203
|
project: manifest?.project ?? null,
|
|
204
204
|
spec_version: manifest?.kynetic ?? null,
|
|
205
|
-
root_dir: ctx.
|
|
205
|
+
root_dir: ctx.projectRoot,
|
|
206
206
|
remote_tracking: config.shadow.remote
|
|
207
207
|
? { value: config.shadow.remote.value, type: config.shadow.remote.type }
|
|
208
208
|
: null,
|
|
@@ -20,10 +20,14 @@ import type { ProjectContextManager } from '../project-context';
|
|
|
20
20
|
|
|
21
21
|
interface ProjectsRouteOptions {
|
|
22
22
|
projectManager: ProjectContextManager;
|
|
23
|
+
/** Called after a project is registered (e.g., to start session sync). */
|
|
24
|
+
onProjectRegistered?: (projectPath: string) => Promise<void>;
|
|
25
|
+
/** Called before a project is unregistered (e.g., to stop session sync). */
|
|
26
|
+
onProjectUnregistered?: (projectPath: string) => void;
|
|
23
27
|
}
|
|
24
28
|
|
|
25
29
|
export function createProjectsRoutes(options: ProjectsRouteOptions) {
|
|
26
|
-
const { projectManager } = options;
|
|
30
|
+
const { projectManager, onProjectRegistered, onProjectUnregistered } = options;
|
|
27
31
|
|
|
28
32
|
return new Elysia({ prefix: '/api/projects' })
|
|
29
33
|
// AC: @multi-directory-daemon ac-28 - List registered projects
|
|
@@ -91,6 +95,16 @@ export function createProjectsRoutes(options: ProjectsRouteOptions) {
|
|
|
91
95
|
throw error;
|
|
92
96
|
}
|
|
93
97
|
|
|
98
|
+
// Start session sync for the newly registered project
|
|
99
|
+
if (onProjectRegistered) {
|
|
100
|
+
try {
|
|
101
|
+
await onProjectRegistered(context.path);
|
|
102
|
+
} catch (error) {
|
|
103
|
+
// Session sync init failure does not block project registration
|
|
104
|
+
console.error(`[daemon] Failed to start session sync for ${context.path}:`, error);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
94
108
|
return {
|
|
95
109
|
success: true,
|
|
96
110
|
project: {
|
|
@@ -135,23 +149,31 @@ export function createProjectsRoutes(options: ProjectsRouteOptions) {
|
|
|
135
149
|
// AC: @multi-directory-daemon ac-30 - Decode path from URL parameter
|
|
136
150
|
const projectPath = decodeURIComponent(params.encodedPath);
|
|
137
151
|
|
|
138
|
-
// Validate project exists
|
|
139
|
-
|
|
152
|
+
// Validate project exists and get normalized context
|
|
153
|
+
let context;
|
|
154
|
+
try {
|
|
155
|
+
context = projectManager.getProject(projectPath);
|
|
156
|
+
} catch {
|
|
140
157
|
return errorResponse(404, {
|
|
141
158
|
error: `Project not registered: ${projectPath}`,
|
|
142
159
|
});
|
|
143
160
|
}
|
|
144
161
|
|
|
145
162
|
try {
|
|
163
|
+
// Stop session sync before unregistering (use normalized path)
|
|
164
|
+
if (onProjectUnregistered) {
|
|
165
|
+
onProjectUnregistered(context.path);
|
|
166
|
+
}
|
|
167
|
+
|
|
146
168
|
// AC: @multi-directory-daemon ac-30 - Stop file watcher
|
|
147
|
-
await projectManager.stopWatcher(
|
|
169
|
+
await projectManager.stopWatcher(context.path);
|
|
148
170
|
|
|
149
171
|
// AC: @multi-directory-daemon ac-30 - Unregister project
|
|
150
|
-
projectManager.unregisterProject(
|
|
172
|
+
projectManager.unregisterProject(context.path);
|
|
151
173
|
|
|
152
174
|
return {
|
|
153
175
|
success: true,
|
|
154
|
-
message: `Project unregistered: ${
|
|
176
|
+
message: `Project unregistered: ${context.path}`,
|
|
155
177
|
};
|
|
156
178
|
} catch (error: unknown) {
|
|
157
179
|
return errorResponse(500, {
|