@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
|
@@ -4,14 +4,20 @@
|
|
|
4
4
|
* REST endpoints for meta operations:
|
|
5
5
|
* - GET /api/meta/session - get session context
|
|
6
6
|
* - GET /api/meta/agents - list agents
|
|
7
|
+
* - PATCH /api/meta/agents/:id - update agent definition
|
|
7
8
|
* - GET /api/meta/workflows - list workflows
|
|
8
9
|
* - GET /api/meta/observations - list observations with filter
|
|
10
|
+
* - GET /api/meta/config - project config from manifest + kspec.config.yaml
|
|
11
|
+
* - GET /api/meta/shadow - shadow branch status
|
|
12
|
+
* - GET /api/meta/conventions - convention definitions
|
|
9
13
|
*
|
|
10
14
|
* AC Coverage:
|
|
11
15
|
* - ac-15: GET /api/meta/session returns session context
|
|
12
16
|
* - ac-16: GET /api/meta/agents returns all agents
|
|
13
17
|
* - ac-17: GET /api/meta/workflows returns all workflows
|
|
14
18
|
* - ac-18: GET /api/meta/observations with filter
|
|
19
|
+
* - @ui-agent-dispatch ac-4: PATCH /api/meta/agents/:id updates agent definition
|
|
20
|
+
* - @ui-settings-view ac-1: GET /api/meta/config, /shadow, /conventions
|
|
15
21
|
*/
|
|
16
22
|
|
|
17
23
|
import { Elysia, t } from 'elysia';
|
|
@@ -19,7 +25,11 @@ import {
|
|
|
19
25
|
initContext,
|
|
20
26
|
loadMetaContext,
|
|
21
27
|
loadSessionContext,
|
|
28
|
+
saveMetaItem,
|
|
22
29
|
} from '../../parser/index.js';
|
|
30
|
+
import { commitIfShadow, getShadowStatus, hasRemoteTracking } from '../../parser/shadow.js';
|
|
31
|
+
import type { Agent } from '../../schema/meta.js';
|
|
32
|
+
import { AgentDispatchEventSchema } from '../../schema/meta.js';
|
|
23
33
|
|
|
24
34
|
interface MetaRouteOptions {}
|
|
25
35
|
|
|
@@ -57,6 +67,73 @@ export function createMetaRoutes(options: MetaRouteOptions = {}) {
|
|
|
57
67
|
};
|
|
58
68
|
})
|
|
59
69
|
|
|
70
|
+
// AC: @ui-agent-dispatch ac-4 - Update agent definition
|
|
71
|
+
// Body schema mirrors editable fields from AgentSchema (src/schema/meta.ts).
|
|
72
|
+
// Dispatch event enum values derived from AgentDispatchEventSchema.
|
|
73
|
+
.patch(
|
|
74
|
+
'/agents/:id',
|
|
75
|
+
async ({ params, body, projectContext }) => {
|
|
76
|
+
const ctx = await initContext(projectContext.path);
|
|
77
|
+
const meta = await loadMetaContext(ctx);
|
|
78
|
+
|
|
79
|
+
// Find the agent by id
|
|
80
|
+
const agent = meta.agents.find((a) => a.id === params.id);
|
|
81
|
+
if (!agent) {
|
|
82
|
+
throw new Error(`Agent not found: ${params.id}`);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Apply partial updates from body — result satisfies Agent type from schema
|
|
86
|
+
const updated: Agent = { ...agent, ...body };
|
|
87
|
+
|
|
88
|
+
await saveMetaItem(ctx, updated, 'agent');
|
|
89
|
+
await commitIfShadow(ctx.shadow, `meta: update agent ${params.id}`);
|
|
90
|
+
|
|
91
|
+
return updated;
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
params: t.Object({
|
|
95
|
+
id: t.String(),
|
|
96
|
+
}),
|
|
97
|
+
// Editable fields from AgentSchema — dispatch.on enum derived from AgentDispatchEventSchema
|
|
98
|
+
body: t.Object({
|
|
99
|
+
name: t.Optional(t.String()),
|
|
100
|
+
description: t.Optional(t.String()),
|
|
101
|
+
adapter: t.Optional(t.String()),
|
|
102
|
+
dispatch: t.Optional(
|
|
103
|
+
t.Array(
|
|
104
|
+
t.Object({
|
|
105
|
+
on: t.Union(AgentDispatchEventSchema.options.map((v) => t.Literal(v))),
|
|
106
|
+
filter: t.Optional(
|
|
107
|
+
t.Object({
|
|
108
|
+
automation: t.Optional(t.Union([t.Literal('eligible'), t.Literal('ineligible')])),
|
|
109
|
+
tags: t.Optional(t.Array(t.String())),
|
|
110
|
+
priority: t.Optional(t.Number()),
|
|
111
|
+
})
|
|
112
|
+
),
|
|
113
|
+
})
|
|
114
|
+
)
|
|
115
|
+
),
|
|
116
|
+
capabilities: t.Optional(t.Array(t.String())),
|
|
117
|
+
tools: t.Optional(t.Array(t.String())),
|
|
118
|
+
skills: t.Optional(t.Array(t.String())),
|
|
119
|
+
budget: t.Optional(
|
|
120
|
+
t.Object({
|
|
121
|
+
max_tasks: t.Optional(t.Number()),
|
|
122
|
+
max_retries: t.Optional(t.Number()),
|
|
123
|
+
timeout_minutes: t.Optional(t.Number()),
|
|
124
|
+
})
|
|
125
|
+
),
|
|
126
|
+
concurrency: t.Optional(
|
|
127
|
+
t.Object({
|
|
128
|
+
max_concurrent: t.Optional(t.Number()),
|
|
129
|
+
})
|
|
130
|
+
),
|
|
131
|
+
auto_approve: t.Optional(t.Boolean()),
|
|
132
|
+
prompt_template: t.Optional(t.String()),
|
|
133
|
+
}),
|
|
134
|
+
}
|
|
135
|
+
)
|
|
136
|
+
|
|
60
137
|
// AC: @api-contract ac-17 - List workflows
|
|
61
138
|
.get('/workflows', async ({ projectContext }) => {
|
|
62
139
|
// AC: @multi-directory-daemon ac-1, ac-24 - Use project context from middleware
|
|
@@ -114,5 +191,68 @@ export function createMetaRoutes(options: MetaRouteOptions = {}) {
|
|
|
114
191
|
type: t.Optional(t.Union([t.String(), t.Array(t.String())])),
|
|
115
192
|
}),
|
|
116
193
|
}
|
|
117
|
-
)
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
// AC: @ui-settings-view ac-1 - Project config from manifest
|
|
197
|
+
.get('/config', async ({ projectContext }) => {
|
|
198
|
+
const ctx = await initContext(projectContext.path);
|
|
199
|
+
const manifest = ctx.manifest;
|
|
200
|
+
const config = ctx.config;
|
|
201
|
+
|
|
202
|
+
return {
|
|
203
|
+
project: manifest?.project ?? null,
|
|
204
|
+
spec_version: manifest?.kynetic ?? null,
|
|
205
|
+
root_dir: ctx.projectRoot,
|
|
206
|
+
remote_tracking: config.shadow.remote
|
|
207
|
+
? { value: config.shadow.remote.value, type: config.shadow.remote.type }
|
|
208
|
+
: null,
|
|
209
|
+
daemon: {
|
|
210
|
+
port: config.daemon.port,
|
|
211
|
+
host: config.daemon.host,
|
|
212
|
+
auto_start: config.daemon.auto_start,
|
|
213
|
+
},
|
|
214
|
+
};
|
|
215
|
+
})
|
|
216
|
+
|
|
217
|
+
// AC: @ui-settings-view ac-1 - Shadow branch status
|
|
218
|
+
.get('/shadow', async ({ projectContext }) => {
|
|
219
|
+
const ctx = await initContext(projectContext.path);
|
|
220
|
+
|
|
221
|
+
if (!ctx.shadow) {
|
|
222
|
+
return {
|
|
223
|
+
enabled: false,
|
|
224
|
+
branch_name: null,
|
|
225
|
+
worktree_dir: null,
|
|
226
|
+
healthy: false,
|
|
227
|
+
remote_tracking: false,
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const status = await getShadowStatus(ctx.rootDir, {
|
|
232
|
+
branchName: ctx.shadow.branchName,
|
|
233
|
+
directory: ctx.config.shadow.directory,
|
|
234
|
+
});
|
|
235
|
+
const hasRemote = await hasRemoteTracking(ctx.shadow.worktreeDir, {
|
|
236
|
+
branchName: ctx.shadow.branchName,
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
return {
|
|
240
|
+
enabled: ctx.shadow.enabled,
|
|
241
|
+
branch_name: ctx.shadow.branchName,
|
|
242
|
+
worktree_dir: ctx.shadow.worktreeDir,
|
|
243
|
+
healthy: status.healthy,
|
|
244
|
+
remote_tracking: hasRemote,
|
|
245
|
+
};
|
|
246
|
+
})
|
|
247
|
+
|
|
248
|
+
// AC: @ui-settings-view ac-1 - Convention definitions
|
|
249
|
+
.get('/conventions', async ({ projectContext }) => {
|
|
250
|
+
const ctx = await initContext(projectContext.path);
|
|
251
|
+
const meta = await loadMetaContext(ctx);
|
|
252
|
+
|
|
253
|
+
return {
|
|
254
|
+
items: meta.conventions,
|
|
255
|
+
total: meta.conventions.length,
|
|
256
|
+
};
|
|
257
|
+
});
|
|
118
258
|
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plans API Routes
|
|
3
|
+
*
|
|
4
|
+
* REST endpoints for plan operations:
|
|
5
|
+
* - GET /api/plans - list plans with status filter and task progress
|
|
6
|
+
* - GET /api/plans/:ref - get single plan with content
|
|
7
|
+
*
|
|
8
|
+
* AC Coverage:
|
|
9
|
+
* - @ui-plans-view ac-1: Plan list with title, status, dates, linked counts, progress
|
|
10
|
+
* - @ui-plans-view ac-2: Plan detail with content for expand/detail view
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { Elysia, t } from 'elysia';
|
|
14
|
+
import {
|
|
15
|
+
initContext,
|
|
16
|
+
loadPlans,
|
|
17
|
+
loadAllTasks,
|
|
18
|
+
findPlanByRef,
|
|
19
|
+
type LoadedPlan,
|
|
20
|
+
} from '../../parser/index.js';
|
|
21
|
+
import type { PlanSummary, PlanDetail } from '@kynetic-ai/shared';
|
|
22
|
+
|
|
23
|
+
interface PlansRouteOptions {}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Build a task status lookup map from loaded tasks.
|
|
27
|
+
*/
|
|
28
|
+
function buildTaskStatusMap(tasks: Array<{ _ulid: string; slugs: string[]; status: string }>) {
|
|
29
|
+
const tasksByRef = new Map<string, { status: string }>();
|
|
30
|
+
for (const task of tasks) {
|
|
31
|
+
tasksByRef.set(task._ulid, { status: task.status });
|
|
32
|
+
for (const slug of task.slugs) {
|
|
33
|
+
tasksByRef.set(slug, { status: task.status });
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return tasksByRef;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Compute task progress for a plan's derived tasks.
|
|
41
|
+
*/
|
|
42
|
+
function computeTaskProgress(
|
|
43
|
+
derivedTasks: string[],
|
|
44
|
+
tasksByRef: Map<string, { status: string }>
|
|
45
|
+
) {
|
|
46
|
+
const progress = { total: 0, completed: 0, in_progress: 0, pending: 0, blocked: 0 };
|
|
47
|
+
for (const ref of derivedTasks) {
|
|
48
|
+
const cleanRef = ref.startsWith('@') ? ref.slice(1) : ref;
|
|
49
|
+
const task = tasksByRef.get(cleanRef);
|
|
50
|
+
if (task) {
|
|
51
|
+
progress.total++;
|
|
52
|
+
if (task.status === 'completed') progress.completed++;
|
|
53
|
+
else if (task.status === 'in_progress' || task.status === 'pending_review' || task.status === 'needs_work') progress.in_progress++;
|
|
54
|
+
else if (task.status === 'blocked') progress.blocked++;
|
|
55
|
+
else progress.pending++;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return progress;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Map a loaded plan to a PlanSummary.
|
|
63
|
+
*/
|
|
64
|
+
function toPlanSummary(
|
|
65
|
+
plan: LoadedPlan,
|
|
66
|
+
tasksByRef: Map<string, { status: string }>
|
|
67
|
+
): PlanSummary {
|
|
68
|
+
return {
|
|
69
|
+
_ulid: plan._ulid,
|
|
70
|
+
slugs: plan.slugs,
|
|
71
|
+
title: plan.title,
|
|
72
|
+
status: plan.status,
|
|
73
|
+
created_at: plan.created_at,
|
|
74
|
+
approved_at: plan.approved_at ?? undefined,
|
|
75
|
+
completed_at: plan.completed_at ?? undefined,
|
|
76
|
+
derived_specs: plan.derived_specs,
|
|
77
|
+
derived_tasks: plan.derived_tasks,
|
|
78
|
+
spec_count: plan.derived_specs.length,
|
|
79
|
+
task_count: plan.derived_tasks.length,
|
|
80
|
+
task_progress: computeTaskProgress(plan.derived_tasks, tasksByRef),
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export function createPlansRoutes(options: PlansRouteOptions = {}) {
|
|
85
|
+
return new Elysia({ prefix: '/api/plans' })
|
|
86
|
+
// AC: @ui-plans-view ac-1 - List plans with progress
|
|
87
|
+
.get(
|
|
88
|
+
'/',
|
|
89
|
+
async ({ query, projectContext }) => {
|
|
90
|
+
const ctx = await initContext(projectContext.path);
|
|
91
|
+
const plans = await loadPlans(ctx);
|
|
92
|
+
const tasks = await loadAllTasks(ctx);
|
|
93
|
+
const tasksByRef = buildTaskStatusMap(tasks);
|
|
94
|
+
|
|
95
|
+
// Apply status filter
|
|
96
|
+
let filtered: LoadedPlan[] = plans;
|
|
97
|
+
if (query.status) {
|
|
98
|
+
const statusFilters = Array.isArray(query.status) ? query.status : [query.status];
|
|
99
|
+
filtered = filtered.filter((plan) => statusFilters.includes(plan.status));
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Sort by created_at descending (newest first)
|
|
103
|
+
const sorted = [...filtered].sort(
|
|
104
|
+
(a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime()
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
// AC: @ui-plans-view ac-1 - Compute progress for each plan
|
|
108
|
+
const items: PlanSummary[] = sorted.map((plan) => toPlanSummary(plan, tasksByRef));
|
|
109
|
+
|
|
110
|
+
return {
|
|
111
|
+
items,
|
|
112
|
+
total: items.length,
|
|
113
|
+
};
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
query: t.Object({
|
|
117
|
+
status: t.Optional(t.Union([t.String(), t.Array(t.String())])),
|
|
118
|
+
}),
|
|
119
|
+
}
|
|
120
|
+
)
|
|
121
|
+
// AC: @ui-plans-view ac-2 - Get single plan with content (lazy-loaded by UI on expand)
|
|
122
|
+
.get(
|
|
123
|
+
'/:ref',
|
|
124
|
+
async ({ params, error: errorResponse, projectContext }) => {
|
|
125
|
+
const ctx = await initContext(projectContext.path);
|
|
126
|
+
const plan = await findPlanByRef(ctx, params.ref);
|
|
127
|
+
|
|
128
|
+
if (!plan) {
|
|
129
|
+
return errorResponse(404, {
|
|
130
|
+
error: 'not_found',
|
|
131
|
+
message: `Plan reference "${params.ref}" not found`,
|
|
132
|
+
suggestion: 'Use kspec plan list to find valid plan references',
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const tasks = await loadAllTasks(ctx);
|
|
137
|
+
const tasksByRef = buildTaskStatusMap(tasks);
|
|
138
|
+
|
|
139
|
+
const detail: PlanDetail = {
|
|
140
|
+
...toPlanSummary(plan, tasksByRef),
|
|
141
|
+
content: plan.content,
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
return detail;
|
|
145
|
+
}
|
|
146
|
+
);
|
|
147
|
+
}
|
|
@@ -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, {
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reference Resolution Utilities
|
|
3
|
+
*
|
|
4
|
+
* Server-side resolution of @references to display-ready metadata.
|
|
5
|
+
* Used by API routes to include resolved titles alongside raw refs.
|
|
6
|
+
*
|
|
7
|
+
* AC: @ui-api-ref-resolution ac-1, ac-2, ac-3
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { ReferenceIndex } from '../../parser/index.js';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Resolved metadata for a single-valued reference.
|
|
14
|
+
* AC: @ui-api-ref-resolution ac-1
|
|
15
|
+
*/
|
|
16
|
+
export interface ResolvedRef {
|
|
17
|
+
ref: string;
|
|
18
|
+
title: string | null;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Resolved metadata for an array reference entry with status.
|
|
23
|
+
* AC: @ui-api-ref-resolution ac-2
|
|
24
|
+
*/
|
|
25
|
+
export interface ResolvedRefEntry {
|
|
26
|
+
ref: string;
|
|
27
|
+
title: string | null;
|
|
28
|
+
status: string | null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Lightweight index entry for the ref index endpoint.
|
|
33
|
+
* AC: @ui-api-ref-resolution ac-4, ac-5
|
|
34
|
+
*/
|
|
35
|
+
export interface RefIndexEntry {
|
|
36
|
+
title: string;
|
|
37
|
+
type: string;
|
|
38
|
+
status?: string;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Resolve a single-valued reference to its title.
|
|
43
|
+
* Returns null title if the ref cannot be resolved (ac-3).
|
|
44
|
+
*
|
|
45
|
+
* AC: @ui-api-ref-resolution ac-1, ac-3
|
|
46
|
+
*/
|
|
47
|
+
export function resolveRefTitle(
|
|
48
|
+
index: ReferenceIndex,
|
|
49
|
+
ref: string | undefined | null,
|
|
50
|
+
): string | null {
|
|
51
|
+
if (!ref) return null;
|
|
52
|
+
const result = index.resolve(ref);
|
|
53
|
+
if (!result.ok) return null;
|
|
54
|
+
const item = result.item as { title?: string };
|
|
55
|
+
return item.title ?? null;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Resolve an array of references to entries with title and status.
|
|
60
|
+
* Invalid/deleted refs get null title but preserve the raw ref (ac-3).
|
|
61
|
+
*
|
|
62
|
+
* AC: @ui-api-ref-resolution ac-2, ac-3
|
|
63
|
+
*/
|
|
64
|
+
export function resolveRefEntries(
|
|
65
|
+
index: ReferenceIndex,
|
|
66
|
+
refs: string[] | undefined | null,
|
|
67
|
+
): ResolvedRefEntry[] {
|
|
68
|
+
if (!refs || refs.length === 0) return [];
|
|
69
|
+
return refs.map((ref) => {
|
|
70
|
+
const result = index.resolve(ref);
|
|
71
|
+
if (!result.ok) {
|
|
72
|
+
return { ref, title: null, status: null };
|
|
73
|
+
}
|
|
74
|
+
const item = result.item as { title?: string; status?: string };
|
|
75
|
+
return {
|
|
76
|
+
ref,
|
|
77
|
+
title: item.title ?? null,
|
|
78
|
+
status: item.status ?? null,
|
|
79
|
+
};
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Build a lightweight ref index map for the index endpoint.
|
|
85
|
+
* Includes both ULID and slug keys for each entity.
|
|
86
|
+
*
|
|
87
|
+
* AC: @ui-api-ref-resolution ac-4, ac-5
|
|
88
|
+
*/
|
|
89
|
+
export function buildRefIndex(
|
|
90
|
+
index: ReferenceIndex,
|
|
91
|
+
): Record<string, RefIndexEntry> {
|
|
92
|
+
const result: Record<string, RefIndexEntry> = {};
|
|
93
|
+
|
|
94
|
+
for (const ulid of index.getAllUlids()) {
|
|
95
|
+
const item = index.getByUlid(ulid);
|
|
96
|
+
if (!item) continue;
|
|
97
|
+
|
|
98
|
+
const typed = item as { title?: string; type?: string; status?: string; slugs?: string[] };
|
|
99
|
+
if (!typed.title) continue;
|
|
100
|
+
|
|
101
|
+
const entry: RefIndexEntry = {
|
|
102
|
+
title: typed.title,
|
|
103
|
+
type: typed.type ?? 'unknown',
|
|
104
|
+
...(typed.status ? { status: typed.status } : {}),
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
// Index by ULID
|
|
108
|
+
result[ulid] = entry;
|
|
109
|
+
|
|
110
|
+
// Index by slugs
|
|
111
|
+
if (typed.slugs) {
|
|
112
|
+
for (const slug of typed.slugs) {
|
|
113
|
+
result[slug] = entry;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return result;
|
|
119
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ref Index API Route
|
|
3
|
+
*
|
|
4
|
+
* Lightweight endpoint for resolving arbitrary refs to display metadata.
|
|
5
|
+
* Returns a map of all resolvable refs (tasks, items, traits) with
|
|
6
|
+
* title, type, and status. Both ULID and slug keys are included.
|
|
7
|
+
*
|
|
8
|
+
* AC Coverage:
|
|
9
|
+
* - @ui-api-ref-resolution ac-4: Returns map of all resolvable refs with display metadata
|
|
10
|
+
* - @ui-api-ref-resolution ac-5: Payload is significantly smaller than full entity lists
|
|
11
|
+
* - @trait-api-endpoint ac-1: Returns 2xx with JSON body
|
|
12
|
+
* - @trait-api-endpoint ac-6: Includes X-Request-Id header (via middleware)
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { Elysia } from 'elysia';
|
|
16
|
+
import {
|
|
17
|
+
initContext,
|
|
18
|
+
loadAllTasks,
|
|
19
|
+
loadAllItems,
|
|
20
|
+
loadPlans,
|
|
21
|
+
ReferenceIndex,
|
|
22
|
+
} from '../../parser/index.js';
|
|
23
|
+
import { buildRefIndex } from './ref-resolution.js';
|
|
24
|
+
|
|
25
|
+
export function createRefsRoutes() {
|
|
26
|
+
return new Elysia({ prefix: '/api/refs' })
|
|
27
|
+
|
|
28
|
+
// AC: @ui-api-ref-resolution ac-4, ac-5 - Lightweight ref index endpoint
|
|
29
|
+
// AC: @trait-api-endpoint ac-1 - Returns 2xx with JSON body
|
|
30
|
+
.get('/', async ({ projectContext }) => {
|
|
31
|
+
const ctx = await initContext(projectContext.path);
|
|
32
|
+
const [tasks, items, plans] = await Promise.all([
|
|
33
|
+
loadAllTasks(ctx),
|
|
34
|
+
loadAllItems(ctx),
|
|
35
|
+
loadPlans(ctx),
|
|
36
|
+
]);
|
|
37
|
+
const index = new ReferenceIndex(tasks, items, [], plans);
|
|
38
|
+
const refs = buildRefIndex(index);
|
|
39
|
+
|
|
40
|
+
return { refs };
|
|
41
|
+
});
|
|
42
|
+
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AlignmentIndex,
|
|
3
|
+
ReferenceIndex,
|
|
4
|
+
type LoadedSpecItem,
|
|
5
|
+
type LoadedTask,
|
|
6
|
+
} from '../../parser/index.js';
|
|
7
|
+
import { getSessionCache } from '../../sessions/cache.js';
|
|
8
|
+
import type { SessionLogSummary } from '../../sessions/store.js';
|
|
9
|
+
|
|
10
|
+
interface RelatedSessionsNotFound {
|
|
11
|
+
error: 'not_found';
|
|
12
|
+
message: string;
|
|
13
|
+
suggestion: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function sortSessions(sessions: SessionLogSummary[]): SessionLogSummary[] {
|
|
17
|
+
return [...sessions].sort(
|
|
18
|
+
(a, b) => new Date(b.started_at).getTime() - new Date(a.started_at).getTime()
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function buildTaskRefSet(task: Pick<LoadedTask, '_ulid' | 'slugs'>): Set<string> {
|
|
23
|
+
const refs = new Set<string>([task._ulid, `@${task._ulid}`]);
|
|
24
|
+
for (const slug of task.slugs) {
|
|
25
|
+
refs.add(slug);
|
|
26
|
+
refs.add(`@${slug}`);
|
|
27
|
+
}
|
|
28
|
+
return refs;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function filterSessionsByTaskRefs(
|
|
32
|
+
sessions: SessionLogSummary[],
|
|
33
|
+
taskRefs: Set<string>
|
|
34
|
+
): SessionLogSummary[] {
|
|
35
|
+
return sessions.filter((session) => {
|
|
36
|
+
if (!session.task_id) return false;
|
|
37
|
+
const taskId = session.task_id.startsWith('@')
|
|
38
|
+
? session.task_id.slice(1)
|
|
39
|
+
: session.task_id;
|
|
40
|
+
return taskRefs.has(taskId) || taskRefs.has(session.task_id);
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export async function getRelatedSessionsForTask(params: {
|
|
45
|
+
items: LoadedSpecItem[];
|
|
46
|
+
tasks: LoadedTask[];
|
|
47
|
+
taskRef: string;
|
|
48
|
+
sessionsDir: string;
|
|
49
|
+
}): Promise<
|
|
50
|
+
| { sessions: SessionLogSummary[]; task: LoadedTask }
|
|
51
|
+
| { error: RelatedSessionsNotFound }
|
|
52
|
+
> {
|
|
53
|
+
const { items, tasks, taskRef, sessionsDir } = params;
|
|
54
|
+
const refIndex = new ReferenceIndex(tasks, items);
|
|
55
|
+
const resolved = refIndex.resolve(taskRef);
|
|
56
|
+
|
|
57
|
+
if (!resolved.ok) {
|
|
58
|
+
return {
|
|
59
|
+
error: {
|
|
60
|
+
error: 'not_found',
|
|
61
|
+
message: `Task reference "${taskRef}" not found`,
|
|
62
|
+
suggestion: 'Use GET /api/tasks or kspec task list to find valid task references',
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const task = tasks.find((candidate) => candidate._ulid === resolved.ulid);
|
|
68
|
+
if (!task) {
|
|
69
|
+
return {
|
|
70
|
+
error: {
|
|
71
|
+
error: 'not_found',
|
|
72
|
+
message: `Reference "${taskRef}" is not a task`,
|
|
73
|
+
suggestion: 'This reference might point to a spec item instead',
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const sessionCache = getSessionCache(sessionsDir);
|
|
79
|
+
const sessions = await sessionCache.getAll(sessionsDir);
|
|
80
|
+
const filtered = filterSessionsByTaskRefs(sessions, buildTaskRefSet(task));
|
|
81
|
+
|
|
82
|
+
return {
|
|
83
|
+
task,
|
|
84
|
+
sessions: sortSessions(filtered),
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export async function getRelatedSessionsForItem(params: {
|
|
89
|
+
itemRef: string;
|
|
90
|
+
items: LoadedSpecItem[];
|
|
91
|
+
tasks: LoadedTask[];
|
|
92
|
+
sessionsDir: string;
|
|
93
|
+
}): Promise<
|
|
94
|
+
| { item: LoadedSpecItem; sessions: SessionLogSummary[] }
|
|
95
|
+
| { error: RelatedSessionsNotFound }
|
|
96
|
+
> {
|
|
97
|
+
const { itemRef, items, tasks, sessionsDir } = params;
|
|
98
|
+
const refIndex = new ReferenceIndex(tasks, items);
|
|
99
|
+
const alignmentIndex = new AlignmentIndex(tasks, items);
|
|
100
|
+
alignmentIndex.buildLinks(refIndex);
|
|
101
|
+
|
|
102
|
+
const resolved = refIndex.resolve(itemRef);
|
|
103
|
+
if (!resolved.ok) {
|
|
104
|
+
return {
|
|
105
|
+
error: {
|
|
106
|
+
error: 'not_found',
|
|
107
|
+
message: `Item reference "${itemRef}" not found`,
|
|
108
|
+
suggestion: 'Use GET /api/items or kspec item list to find valid item references',
|
|
109
|
+
},
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const item = items.find((candidate) => candidate._ulid === resolved.ulid);
|
|
114
|
+
if (!item) {
|
|
115
|
+
return {
|
|
116
|
+
error: {
|
|
117
|
+
error: 'not_found',
|
|
118
|
+
message: `Reference "${itemRef}" is not a spec item`,
|
|
119
|
+
suggestion: 'This reference might point to a task instead',
|
|
120
|
+
},
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const linkedTasks = alignmentIndex.getTasksForSpec(resolved.ulid);
|
|
125
|
+
const taskRefs = new Set<string>();
|
|
126
|
+
for (const task of linkedTasks) {
|
|
127
|
+
for (const ref of buildTaskRefSet(task)) {
|
|
128
|
+
taskRefs.add(ref);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const sessionCache = getSessionCache(sessionsDir);
|
|
133
|
+
const sessions = await sessionCache.getAll(sessionsDir);
|
|
134
|
+
const filtered = filterSessionsByTaskRefs(sessions, taskRefs);
|
|
135
|
+
|
|
136
|
+
return {
|
|
137
|
+
item,
|
|
138
|
+
sessions: sortSessions(filtered),
|
|
139
|
+
};
|
|
140
|
+
}
|