@kynetic-ai/spec 0.10.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 +150 -10
- package/dist/agent-runtime/dispatch.d.ts.map +1 -1
- package/dist/agent-runtime/dispatch.js +1248 -244
- 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 +172 -60
- 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/meta.d.ts.map +1 -1
- package/dist/cli/commands/meta.js +10 -1
- package/dist/cli/commands/meta.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 +107 -23
- package/dist/daemon/routes/aggregation.ts +184 -0
- package/dist/daemon/routes/inbox.ts +5 -0
- package/dist/daemon/routes/items.ts +167 -0
- package/dist/daemon/routes/meta.ts +141 -1
- package/dist/daemon/routes/plans.ts +147 -0
- 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 +581 -0
- package/dist/daemon/routes/tasks.ts +257 -2
- package/dist/daemon/routes/triage.ts +40 -1
- package/dist/daemon/routes/validation.ts +1 -1
- package/dist/daemon/server.ts +165 -50
- 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/alignment.d.ts.map +1 -1
- package/dist/parser/alignment.js +4 -2
- package/dist/parser/alignment.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 +663 -116
- package/dist/schema/meta.d.ts.map +1 -1
- package/dist/schema/meta.js +28 -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 +115 -71
- package/dist/sessions/store.d.ts.map +1 -1
- package/dist/sessions/store.js +357 -182
- 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/B25nWFyA.js +5 -0
- package/dist/web-ui/_app/immutable/chunks/B2bcA_Q_.js +1 -0
- 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/B8tYZKAE.js +1 -0
- package/dist/web-ui/_app/immutable/chunks/BFGAyJjD.js +1 -0
- package/dist/web-ui/_app/immutable/chunks/BG0850zf.js +1 -0
- package/dist/web-ui/_app/immutable/chunks/BG8eSzAd.js +1 -0
- 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/{D1ArdqNb.js → Bp5pFYXL.js} +1 -1
- package/dist/web-ui/_app/immutable/chunks/BsJFsuAT.js +1 -0
- 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/C0w6WDm5.js +1 -0
- 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/CWUQwB9H.js +1 -0
- 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/CaAJD3dl.js +1 -0
- package/dist/web-ui/_app/immutable/chunks/{i-XnOIX0.js → ChB5iyEL.js} +1 -1
- package/dist/web-ui/_app/immutable/chunks/ChQD-6N8.js +1 -0
- package/dist/web-ui/_app/immutable/chunks/{BCkp8Hs8.js → CqbsoCwA.js} +1 -1
- package/dist/web-ui/_app/immutable/chunks/DCeJW50p.js +1 -0
- package/dist/web-ui/_app/immutable/chunks/DJtZNgcs.js +1 -0
- 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/DW_subyT.js +2 -0
- 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/Dg_zDpDS.js +1 -0
- 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/DqT6OH_u.js +2 -0
- 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/HNjs76Zz.js +1 -0
- package/dist/web-ui/_app/immutable/chunks/HVMjDi4_.js +1 -0
- package/dist/web-ui/_app/immutable/chunks/P0A_fJvS.js +1 -0
- 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/Xvwhx_F1.js +1 -0
- package/dist/web-ui/_app/immutable/chunks/Yyz1XMQA.js +1 -0
- package/dist/web-ui/_app/immutable/chunks/dh5HeqUr.js +1 -0
- package/dist/web-ui/_app/immutable/chunks/fZMteyca.js +62 -0
- package/dist/web-ui/_app/immutable/chunks/{D28BF5MJ.js → gPrj-hqC.js} +1 -1
- package/dist/web-ui/_app/immutable/chunks/htcWMiYN.js +1 -0
- package/dist/web-ui/_app/immutable/chunks/oTsvd9y4.js +1 -0
- 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/y4GeEH6k.js +1 -0
- 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 -11
- package/package.json +14 -7
- 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.BxCxvrZR.css +0 -1
- package/dist/web-ui/_app/immutable/chunks/B-CZR0q8.js +0 -1
- package/dist/web-ui/_app/immutable/chunks/B1IR5Su5.js +0 -1
- package/dist/web-ui/_app/immutable/chunks/B_Cvvtc4.js +0 -1
- package/dist/web-ui/_app/immutable/chunks/BtFaGGII.js +0 -1
- package/dist/web-ui/_app/immutable/chunks/Bu8JVsCH.js +0 -1
- package/dist/web-ui/_app/immutable/chunks/C87u-CNA.js +0 -1
- package/dist/web-ui/_app/immutable/chunks/CrFkBTYp.js +0 -1
- package/dist/web-ui/_app/immutable/chunks/D6RtLpzL.js +0 -1
- package/dist/web-ui/_app/immutable/chunks/D7FHSgx2.js +0 -1
- package/dist/web-ui/_app/immutable/chunks/DBXrsxZQ.js +0 -2
- package/dist/web-ui/_app/immutable/chunks/Da_hHMuA.js +0 -1
- package/dist/web-ui/_app/immutable/chunks/Do6LchSF.js +0 -1
- package/dist/web-ui/_app/immutable/chunks/DoNPtcAw.js +0 -1
- package/dist/web-ui/_app/immutable/chunks/DtUbXRZz.js +0 -1
- package/dist/web-ui/_app/immutable/chunks/DyFPRlLl.js +0 -1
- package/dist/web-ui/_app/immutable/chunks/DzAP8lRM.js +0 -1
- package/dist/web-ui/_app/immutable/chunks/DzVXElzN.js +0 -2
- package/dist/web-ui/_app/immutable/chunks/aoPBFken.js +0 -1
- package/dist/web-ui/_app/immutable/chunks/laxtrUO3.js +0 -1
- package/dist/web-ui/_app/immutable/chunks/q1nIWgqB.js +0 -1
- package/dist/web-ui/_app/immutable/chunks/sTLbk5Nm.js +0 -1
- package/dist/web-ui/_app/immutable/chunks/vwKgQu5P.js +0 -5
- package/dist/web-ui/_app/immutable/entry/app.BCwMcqnT.js +0 -2
- package/dist/web-ui/_app/immutable/entry/start.wKCQH-tt.js +0 -1
- package/dist/web-ui/_app/immutable/nodes/0.CjGVMG74.js +0 -1
- package/dist/web-ui/_app/immutable/nodes/1.B6_AIPan.js +0 -1
- package/dist/web-ui/_app/immutable/nodes/2.q4oCS7Ws.js +0 -1
- package/dist/web-ui/_app/immutable/nodes/3.rTKZf9o2.js +0 -1
- package/dist/web-ui/_app/immutable/nodes/4.DVIDRu1d.js +0 -1
- package/dist/web-ui/_app/immutable/nodes/5.8PtPXIOd.js +0 -1
- package/dist/web-ui/_app/immutable/nodes/6.ZZrTemy_.js +0 -1
- package/dist/web-ui/_app/immutable/nodes/7.IP-gxCxi.js +0 -1
|
@@ -19,12 +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';
|
|
28
|
+
import { getCompletedSessionCountsByAgent } from '../../sessions/store.js';
|
|
27
29
|
import type { PubSubManager } from '../websocket/pubsub.js';
|
|
30
|
+
import type { SessionEventData } from '@kynetic-ai/shared';
|
|
28
31
|
|
|
29
32
|
const VALID_TASK_STATUSES = new Set<string>([
|
|
30
33
|
"pending", "in_progress", "pending_review", "needs_work", "blocked", "completed", "cancelled",
|
|
@@ -43,31 +46,33 @@ export interface AgentDispatchRouteOptions {
|
|
|
43
46
|
* Create a new dispatch engine with optional WebSocket broadcast wiring.
|
|
44
47
|
* AC: @daemon-agent-dispatch ac-3, ac-4
|
|
45
48
|
*/
|
|
46
|
-
function createEngine(
|
|
49
|
+
function createEngine(
|
|
50
|
+
projectDir: string,
|
|
51
|
+
cwd?: string,
|
|
52
|
+
pubsub?: PubSubManager,
|
|
53
|
+
): DispatchEngine {
|
|
47
54
|
return new DispatchEngine({
|
|
48
55
|
projectDir,
|
|
56
|
+
cwd,
|
|
49
57
|
kspecCliPath: DEFAULT_KSPEC_CLI_PATH,
|
|
50
58
|
onInvocationEvent: pubsub
|
|
51
59
|
? (event: InvocationEvent) => {
|
|
60
|
+
// AC: @ui-api-aggregation ac-4 - Include task_title for display
|
|
52
61
|
pubsub.broadcast('agents', 'agent_invocation', {
|
|
53
62
|
session_id: event.session_id,
|
|
54
63
|
agent_id: event.agent_id,
|
|
55
64
|
task_id: event.task_id ?? null,
|
|
65
|
+
task_title: event.task_title ?? null,
|
|
56
66
|
status: event.status,
|
|
57
67
|
timestamp: event.timestamp,
|
|
58
68
|
}, projectDir);
|
|
59
69
|
}
|
|
60
70
|
: undefined,
|
|
71
|
+
// AC: @session-event-broadcast ac-replaces-text-chunks
|
|
61
72
|
// AC: @cli-agent-commands ac-13, @daemon-agent-dispatch ac-8
|
|
62
|
-
|
|
63
|
-
? (
|
|
64
|
-
pubsub.broadcast('agents',
|
|
65
|
-
session_id: sessionId,
|
|
66
|
-
agent_id: agentId,
|
|
67
|
-
task_id: taskId,
|
|
68
|
-
text,
|
|
69
|
-
timestamp: Date.now(),
|
|
70
|
-
}, projectDir);
|
|
73
|
+
onSessionEvent: pubsub
|
|
74
|
+
? (event: SessionEventData) => {
|
|
75
|
+
pubsub.broadcast('agents', event.type, event, projectDir);
|
|
71
76
|
}
|
|
72
77
|
: undefined,
|
|
73
78
|
});
|
|
@@ -116,6 +121,28 @@ function processStateChangeEvent(
|
|
|
116
121
|
return { accepted: true };
|
|
117
122
|
}
|
|
118
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
|
+
|
|
119
146
|
export function createAgentDispatchRoutes(options: AgentDispatchRouteOptions = {}) {
|
|
120
147
|
const { pubsub } = options;
|
|
121
148
|
|
|
@@ -133,16 +160,34 @@ export function createAgentDispatchRoutes(options: AgentDispatchRouteOptions = {
|
|
|
133
160
|
}, { body: stateChangeBodySchema })
|
|
134
161
|
|
|
135
162
|
// AC: @daemon-agent-dispatch ac-6 - Unified dispatch start/stop via action field
|
|
136
|
-
.post('/dispatch', async ({ body, projectContext }) => {
|
|
163
|
+
.post('/dispatch', async ({ body, projectContext, request, set }) => {
|
|
137
164
|
const projectDir = projectContext.path;
|
|
138
165
|
|
|
139
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
|
+
|
|
140
178
|
let engine = engines.get(projectDir);
|
|
141
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
|
+
}
|
|
142
187
|
return { dispatch_enabled: true, reason: 'Already running' };
|
|
143
188
|
}
|
|
144
189
|
|
|
145
|
-
engine = createEngine(projectDir, pubsub);
|
|
190
|
+
engine = createEngine(projectDir, requestedCwd, pubsub);
|
|
146
191
|
engines.set(projectDir, engine);
|
|
147
192
|
await engine.start();
|
|
148
193
|
|
|
@@ -165,16 +210,34 @@ export function createAgentDispatchRoutes(options: AgentDispatchRouteOptions = {
|
|
|
165
210
|
})
|
|
166
211
|
|
|
167
212
|
// Start dispatch engine (legacy route)
|
|
168
|
-
.post('/dispatch/start', async ({ projectContext }) => {
|
|
213
|
+
.post('/dispatch/start', async ({ projectContext, request, set }) => {
|
|
169
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
|
+
}
|
|
170
225
|
|
|
171
226
|
let engine = engines.get(projectDir);
|
|
172
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
|
+
}
|
|
173
236
|
return { started: false, reason: 'Already running', status: engine.getStatus() };
|
|
174
237
|
}
|
|
175
238
|
|
|
176
239
|
// AC: @agent-dispatch-engine ac-10 - pass kspecCliPath so task notes work from daemon-started engine
|
|
177
|
-
engine = createEngine(projectDir, pubsub);
|
|
240
|
+
engine = createEngine(projectDir, requestedCwd, pubsub);
|
|
178
241
|
engines.set(projectDir, engine);
|
|
179
242
|
|
|
180
243
|
await engine.start();
|
|
@@ -214,18 +277,29 @@ export function createAgentDispatchRoutes(options: AgentDispatchRouteOptions = {
|
|
|
214
277
|
})
|
|
215
278
|
|
|
216
279
|
// AC: @daemon-agent-dispatch ac-5 - Public status endpoint
|
|
280
|
+
// AC: @ui-api-ref-resolution ac-1 - Include task_title for active invocations
|
|
217
281
|
.get('/status', async ({ projectContext }) => {
|
|
218
282
|
const projectDir = projectContext.path;
|
|
219
283
|
const engineStatus = engines.get(projectDir)?.getStatus();
|
|
220
284
|
|
|
221
|
-
let agentDefinitions: Array<{ id: string; name: string; adapter: string }> = [];
|
|
285
|
+
let agentDefinitions: Array<{ id: string; name: string; adapter: string; completed_sessions: number }> = [];
|
|
286
|
+
let completedCounts: Record<string, number> = {};
|
|
287
|
+
let refIndex: ReferenceIndex | null = null;
|
|
222
288
|
try {
|
|
223
289
|
const ctx = await initContext(projectDir);
|
|
224
|
-
const meta = await
|
|
290
|
+
const [meta, counts, tasks, items] = await Promise.all([
|
|
291
|
+
loadMetaContext(ctx),
|
|
292
|
+
getCompletedSessionCountsByAgent(ctx.specDir),
|
|
293
|
+
loadAllTasks(ctx),
|
|
294
|
+
loadAllItems(ctx),
|
|
295
|
+
]);
|
|
296
|
+
completedCounts = counts;
|
|
297
|
+
refIndex = new ReferenceIndex(tasks, items);
|
|
225
298
|
agentDefinitions = meta.agents.map((a) => ({
|
|
226
299
|
id: a.id,
|
|
227
300
|
name: a.name,
|
|
228
301
|
adapter: a.adapter ?? 'claude-agent-acp',
|
|
302
|
+
completed_sessions: completedCounts[a.id] ?? 0,
|
|
229
303
|
}));
|
|
230
304
|
} catch {
|
|
231
305
|
// Agent definitions unavailable — return empty array
|
|
@@ -233,12 +307,22 @@ export function createAgentDispatchRoutes(options: AgentDispatchRouteOptions = {
|
|
|
233
307
|
|
|
234
308
|
return {
|
|
235
309
|
dispatch_enabled: engineStatus?.running ?? false,
|
|
236
|
-
active_invocations: engineStatus?.invocations?.map((inv) =>
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
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
|
+
}) ?? [],
|
|
242
326
|
queue_depth: engineStatus?.queuedInvocations ?? 0,
|
|
243
327
|
agent_definitions: agentDefinitions,
|
|
244
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
|
|
@@ -18,12 +18,17 @@ import {
|
|
|
18
18
|
initContext,
|
|
19
19
|
loadAllItems,
|
|
20
20
|
loadAllTasks,
|
|
21
|
+
loadPlans,
|
|
22
|
+
findItemByRef,
|
|
23
|
+
findTaskByRef,
|
|
21
24
|
ReferenceIndex,
|
|
22
25
|
AlignmentIndex,
|
|
23
26
|
getCachedTestCoverage,
|
|
24
27
|
computeACCoverage,
|
|
25
28
|
type LoadedSpecItem,
|
|
29
|
+
type LoadedTask,
|
|
26
30
|
} from '../../parser/index.js';
|
|
31
|
+
import { getRelatedSessionsForItem } from './session-related.js';
|
|
27
32
|
|
|
28
33
|
interface ItemsRouteOptions {}
|
|
29
34
|
|
|
@@ -88,6 +93,49 @@ function computeParentMap(items: LoadedSpecItem[]): Map<string, string | undefin
|
|
|
88
93
|
return parentMap;
|
|
89
94
|
}
|
|
90
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
|
+
|
|
91
139
|
export function createItemsRoutes(options: ItemsRouteOptions = {}) {
|
|
92
140
|
// No closure-scoped kspecDir needed - comes from middleware
|
|
93
141
|
|
|
@@ -144,6 +192,26 @@ export function createItemsRoutes(options: ItemsRouteOptions = {}) {
|
|
|
144
192
|
);
|
|
145
193
|
}
|
|
146
194
|
|
|
195
|
+
// Plan filter — show only specs derived from a given plan
|
|
196
|
+
if (query.plan) {
|
|
197
|
+
const plans = await loadPlans(ctx);
|
|
198
|
+
const plan = plans.find(
|
|
199
|
+
(p) => p._ulid === query.plan || p.slugs.includes(query.plan!)
|
|
200
|
+
);
|
|
201
|
+
if (plan) {
|
|
202
|
+
const derivedRefs = new Set(
|
|
203
|
+
plan.derived_specs.map((r) => (r.startsWith('@') ? r.slice(1) : r))
|
|
204
|
+
);
|
|
205
|
+
filtered = filtered.filter(
|
|
206
|
+
(item) =>
|
|
207
|
+
derivedRefs.has(item._ulid) ||
|
|
208
|
+
item.slugs.some((s) => derivedRefs.has(s))
|
|
209
|
+
);
|
|
210
|
+
} else {
|
|
211
|
+
filtered = [];
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
147
215
|
// Pagination
|
|
148
216
|
const total = filtered.length;
|
|
149
217
|
const offset = Number(query.offset) || 0;
|
|
@@ -178,12 +246,80 @@ export function createItemsRoutes(options: ItemsRouteOptions = {}) {
|
|
|
178
246
|
maturity: t.Optional(t.Union([t.String(), t.Array(t.String())])),
|
|
179
247
|
implementation: t.Optional(t.Union([t.String(), t.Array(t.String())])),
|
|
180
248
|
tag: t.Optional(t.Union([t.String(), t.Array(t.String())])),
|
|
249
|
+
plan: t.Optional(t.String()),
|
|
181
250
|
limit: t.Optional(t.String()),
|
|
182
251
|
offset: t.Optional(t.String()),
|
|
183
252
|
}),
|
|
184
253
|
}
|
|
185
254
|
)
|
|
186
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
|
+
|
|
187
323
|
// AC: @api-contract ac-10 - Get single item by ref
|
|
188
324
|
.get(
|
|
189
325
|
'/:ref',
|
|
@@ -318,5 +454,36 @@ export function createItemsRoutes(options: ItemsRouteOptions = {}) {
|
|
|
318
454
|
ref: t.String(),
|
|
319
455
|
}),
|
|
320
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
|
+
}
|
|
321
488
|
);
|
|
322
489
|
}
|