@kynetic-ai/spec 0.1.2 → 0.3.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 +250 -17
- package/dist/acp/client.d.ts +18 -4
- package/dist/acp/client.d.ts.map +1 -1
- package/dist/acp/client.js +44 -26
- package/dist/acp/client.js.map +1 -1
- package/dist/acp/framing.d.ts +2 -2
- package/dist/acp/framing.d.ts.map +1 -1
- package/dist/acp/framing.js +37 -29
- package/dist/acp/framing.js.map +1 -1
- package/dist/acp/index.d.ts +6 -7
- package/dist/acp/index.d.ts.map +1 -1
- package/dist/acp/index.js +3 -3
- package/dist/acp/index.js.map +1 -1
- package/dist/acp/types.d.ts +5 -5
- package/dist/acp/types.d.ts.map +1 -1
- package/dist/acp/types.js +18 -18
- package/dist/acp/types.js.map +1 -1
- package/dist/agents/adapters.d.ts.map +1 -1
- package/dist/agents/adapters.js +24 -13
- package/dist/agents/adapters.js.map +1 -1
- package/dist/agents/index.d.ts +2 -2
- package/dist/agents/index.js +2 -2
- package/dist/agents/spawner.d.ts +4 -4
- package/dist/agents/spawner.d.ts.map +1 -1
- package/dist/agents/spawner.js +6 -6
- package/dist/agents/spawner.js.map +1 -1
- package/dist/cli/batch-context.d.ts +43 -0
- package/dist/cli/batch-context.d.ts.map +1 -0
- package/dist/cli/batch-context.js +93 -0
- package/dist/cli/batch-context.js.map +1 -0
- package/dist/cli/batch-exec.d.ts +116 -0
- package/dist/cli/batch-exec.d.ts.map +1 -0
- package/dist/cli/batch-exec.js +694 -0
- package/dist/cli/batch-exec.js.map +1 -0
- package/dist/cli/batch.d.ts +4 -2
- package/dist/cli/batch.d.ts.map +1 -1
- package/dist/cli/batch.js +15 -14
- package/dist/cli/batch.js.map +1 -1
- package/dist/cli/command-annotations.d.ts +23 -0
- package/dist/cli/command-annotations.d.ts.map +1 -0
- package/dist/cli/command-annotations.js +27 -0
- package/dist/cli/command-annotations.js.map +1 -0
- package/dist/cli/commands/agents.d.ts +46 -0
- package/dist/cli/commands/agents.d.ts.map +1 -0
- package/dist/cli/commands/agents.js +377 -0
- package/dist/cli/commands/agents.js.map +1 -0
- package/dist/cli/commands/batch.d.ts +20 -0
- package/dist/cli/commands/batch.d.ts.map +1 -0
- package/dist/cli/commands/batch.js +214 -0
- package/dist/cli/commands/batch.js.map +1 -0
- package/dist/cli/commands/clone-for-testing.d.ts +1 -1
- package/dist/cli/commands/clone-for-testing.d.ts.map +1 -1
- package/dist/cli/commands/clone-for-testing.js +37 -47
- package/dist/cli/commands/clone-for-testing.js.map +1 -1
- package/dist/cli/commands/derive.d.ts +1 -1
- package/dist/cli/commands/derive.d.ts.map +1 -1
- package/dist/cli/commands/derive.js +140 -88
- package/dist/cli/commands/derive.js.map +1 -1
- package/dist/cli/commands/doctor.d.ts +11 -0
- package/dist/cli/commands/doctor.d.ts.map +1 -0
- package/dist/cli/commands/doctor.js +152 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/export.d.ts +12 -0
- package/dist/cli/commands/export.d.ts.map +1 -0
- package/dist/cli/commands/export.js +134 -0
- package/dist/cli/commands/export.js.map +1 -0
- package/dist/cli/commands/help.d.ts +1 -1
- package/dist/cli/commands/help.d.ts.map +1 -1
- package/dist/cli/commands/help.js +163 -37
- package/dist/cli/commands/help.js.map +1 -1
- package/dist/cli/commands/inbox.d.ts +1 -1
- package/dist/cli/commands/inbox.d.ts.map +1 -1
- package/dist/cli/commands/inbox.js +178 -56
- package/dist/cli/commands/inbox.js.map +1 -1
- package/dist/cli/commands/index.d.ts +31 -19
- package/dist/cli/commands/index.d.ts.map +1 -1
- package/dist/cli/commands/index.js +31 -19
- package/dist/cli/commands/index.js.map +1 -1
- package/dist/cli/commands/init.d.ts +5 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +108 -57
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/item.d.ts +1 -1
- package/dist/cli/commands/item.d.ts.map +1 -1
- package/dist/cli/commands/item.js +557 -274
- package/dist/cli/commands/item.js.map +1 -1
- package/dist/cli/commands/link.d.ts +1 -1
- package/dist/cli/commands/link.d.ts.map +1 -1
- package/dist/cli/commands/link.js +55 -46
- package/dist/cli/commands/link.js.map +1 -1
- package/dist/cli/commands/log.d.ts +1 -1
- package/dist/cli/commands/log.d.ts.map +1 -1
- package/dist/cli/commands/log.js +57 -51
- package/dist/cli/commands/log.js.map +1 -1
- package/dist/cli/commands/merge-driver.d.ts +19 -0
- package/dist/cli/commands/merge-driver.d.ts.map +1 -0
- package/dist/cli/commands/merge-driver.js +398 -0
- package/dist/cli/commands/merge-driver.js.map +1 -0
- package/dist/cli/commands/meta.d.ts +1 -1
- package/dist/cli/commands/meta.d.ts.map +1 -1
- package/dist/cli/commands/meta.js +533 -399
- package/dist/cli/commands/meta.js.map +1 -1
- package/dist/cli/commands/module.d.ts +1 -1
- package/dist/cli/commands/module.d.ts.map +1 -1
- package/dist/cli/commands/module.js +30 -25
- package/dist/cli/commands/module.js.map +1 -1
- package/dist/cli/commands/plan-import.d.ts +11 -0
- package/dist/cli/commands/plan-import.d.ts.map +1 -0
- package/dist/cli/commands/plan-import.js +516 -0
- package/dist/cli/commands/plan-import.js.map +1 -0
- package/dist/cli/commands/plan.d.ts +10 -0
- package/dist/cli/commands/plan.d.ts.map +1 -0
- package/dist/cli/commands/plan.js +421 -0
- package/dist/cli/commands/plan.js.map +1 -0
- package/dist/cli/commands/ralph.d.ts +1 -1
- package/dist/cli/commands/ralph.d.ts.map +1 -1
- package/dist/cli/commands/ralph.js +1097 -169
- package/dist/cli/commands/ralph.js.map +1 -1
- package/dist/cli/commands/refs.d.ts +13 -0
- package/dist/cli/commands/refs.d.ts.map +1 -0
- package/dist/cli/commands/refs.js +283 -0
- package/dist/cli/commands/refs.js.map +1 -0
- package/dist/cli/commands/search.d.ts +1 -1
- package/dist/cli/commands/search.d.ts.map +1 -1
- package/dist/cli/commands/search.js +199 -37
- package/dist/cli/commands/search.js.map +1 -1
- package/dist/cli/commands/serve.d.ts +10 -0
- package/dist/cli/commands/serve.d.ts.map +1 -0
- package/dist/cli/commands/serve.js +491 -0
- package/dist/cli/commands/serve.js.map +1 -0
- package/dist/cli/commands/session.d.ts +25 -6
- package/dist/cli/commands/session.d.ts.map +1 -1
- package/dist/cli/commands/session.js +811 -127
- package/dist/cli/commands/session.js.map +1 -1
- package/dist/cli/commands/setup-seeding.d.ts +81 -0
- package/dist/cli/commands/setup-seeding.d.ts.map +1 -0
- package/dist/cli/commands/setup-seeding.js +292 -0
- package/dist/cli/commands/setup-seeding.js.map +1 -0
- package/dist/cli/commands/setup.d.ts +77 -3
- package/dist/cli/commands/setup.d.ts.map +1 -1
- package/dist/cli/commands/setup.js +1233 -274
- package/dist/cli/commands/setup.js.map +1 -1
- package/dist/cli/commands/shadow.d.ts +1 -1
- package/dist/cli/commands/shadow.d.ts.map +1 -1
- package/dist/cli/commands/shadow.js +70 -50
- package/dist/cli/commands/shadow.js.map +1 -1
- package/dist/cli/commands/skill-crud.d.ts +58 -0
- package/dist/cli/commands/skill-crud.d.ts.map +1 -0
- package/dist/cli/commands/skill-crud.js +753 -0
- package/dist/cli/commands/skill-crud.js.map +1 -0
- package/dist/cli/commands/skill-diff.d.ts +27 -0
- package/dist/cli/commands/skill-diff.d.ts.map +1 -0
- package/dist/cli/commands/skill-diff.js +840 -0
- package/dist/cli/commands/skill-diff.js.map +1 -0
- package/dist/cli/commands/skill-install.d.ts +53 -0
- package/dist/cli/commands/skill-install.d.ts.map +1 -0
- package/dist/cli/commands/skill-install.js +452 -0
- package/dist/cli/commands/skill-install.js.map +1 -0
- package/dist/cli/commands/skill.d.ts +20 -0
- package/dist/cli/commands/skill.d.ts.map +1 -0
- package/dist/cli/commands/skill.js +36 -0
- package/dist/cli/commands/skill.js.map +1 -0
- package/dist/cli/commands/task.d.ts +1 -1
- package/dist/cli/commands/task.d.ts.map +1 -1
- package/dist/cli/commands/task.js +569 -346
- package/dist/cli/commands/task.js.map +1 -1
- package/dist/cli/commands/tasks.d.ts +26 -1
- package/dist/cli/commands/tasks.d.ts.map +1 -1
- package/dist/cli/commands/tasks.js +227 -122
- package/dist/cli/commands/tasks.js.map +1 -1
- package/dist/cli/commands/trait.d.ts +1 -1
- package/dist/cli/commands/trait.d.ts.map +1 -1
- package/dist/cli/commands/trait.js +166 -101
- package/dist/cli/commands/trait.js.map +1 -1
- package/dist/cli/commands/triage.d.ts +7 -0
- package/dist/cli/commands/triage.d.ts.map +1 -0
- package/dist/cli/commands/triage.js +569 -0
- package/dist/cli/commands/triage.js.map +1 -0
- package/dist/cli/commands/util.d.ts +7 -0
- package/dist/cli/commands/util.d.ts.map +1 -0
- package/dist/cli/commands/util.js +30 -0
- package/dist/cli/commands/util.js.map +1 -0
- package/dist/cli/commands/validate.d.ts +1 -1
- package/dist/cli/commands/validate.d.ts.map +1 -1
- package/dist/cli/commands/validate.js +264 -83
- package/dist/cli/commands/validate.js.map +1 -1
- package/dist/cli/commands/workflow.d.ts +16 -0
- package/dist/cli/commands/workflow.d.ts.map +1 -0
- package/dist/cli/commands/workflow.js +851 -0
- package/dist/cli/commands/workflow.js.map +1 -0
- package/dist/cli/exit-codes.d.ts +7 -0
- package/dist/cli/exit-codes.d.ts.map +1 -1
- package/dist/cli/exit-codes.js +26 -18
- package/dist/cli/exit-codes.js.map +1 -1
- package/dist/cli/help/content.d.ts.map +1 -1
- package/dist/cli/help/content.js +86 -71
- package/dist/cli/help/content.js.map +1 -1
- package/dist/cli/index.d.ts +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +131 -19
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/introspection.d.ts +6 -2
- package/dist/cli/introspection.d.ts.map +1 -1
- package/dist/cli/introspection.js +11 -8
- package/dist/cli/introspection.js.map +1 -1
- package/dist/cli/output.d.ts +64 -4
- package/dist/cli/output.d.ts.map +1 -1
- package/dist/cli/output.js +235 -85
- package/dist/cli/output.js.map +1 -1
- package/dist/cli/parse-utils.d.ts +21 -0
- package/dist/cli/parse-utils.d.ts.map +1 -0
- package/dist/cli/parse-utils.js +32 -0
- package/dist/cli/parse-utils.js.map +1 -0
- package/dist/cli/pid-utils.d.ts +72 -0
- package/dist/cli/pid-utils.d.ts.map +1 -0
- package/dist/cli/pid-utils.js +174 -0
- package/dist/cli/pid-utils.js.map +1 -0
- package/dist/cli/suggest.d.ts.map +1 -1
- package/dist/cli/suggest.js +1 -2
- package/dist/cli/suggest.js.map +1 -1
- package/dist/cli/validators.d.ts +43 -0
- package/dist/cli/validators.d.ts.map +1 -0
- package/dist/cli/validators.js +84 -0
- package/dist/cli/validators.js.map +1 -0
- package/dist/daemon/index.ts +52 -0
- package/dist/daemon/middleware/project-context.ts +126 -0
- package/dist/daemon/pid.ts +179 -0
- package/dist/daemon/project-context.ts +343 -0
- package/dist/daemon/routes/inbox.ts +164 -0
- package/dist/daemon/routes/items.ts +322 -0
- package/dist/daemon/routes/meta.ts +118 -0
- package/dist/daemon/routes/projects.ts +162 -0
- package/dist/daemon/routes/tasks.ts +327 -0
- package/dist/daemon/routes/triage.ts +468 -0
- package/dist/daemon/routes/validation.ts +248 -0
- package/dist/daemon/server.ts +408 -0
- package/dist/daemon/watcher.ts +195 -0
- package/dist/daemon/websocket/handler.ts +138 -0
- package/dist/daemon/websocket/heartbeat.ts +71 -0
- package/dist/daemon/websocket/pubsub.ts +125 -0
- package/dist/daemon/websocket/types.ts +66 -0
- package/dist/export/html.d.ts +19 -0
- package/dist/export/html.d.ts.map +1 -0
- package/dist/export/html.js +239 -0
- package/dist/export/html.js.map +1 -0
- package/dist/export/index.d.ts +10 -0
- package/dist/export/index.d.ts.map +1 -0
- package/dist/export/index.js +10 -0
- package/dist/export/index.js.map +1 -0
- package/dist/export/json.d.ts +24 -0
- package/dist/export/json.d.ts.map +1 -0
- package/dist/export/json.js +198 -0
- package/dist/export/json.js.map +1 -0
- package/dist/export/triage.d.ts +51 -0
- package/dist/export/triage.d.ts.map +1 -0
- package/dist/export/triage.js +83 -0
- package/dist/export/triage.js.map +1 -0
- package/dist/export/types.d.ts +122 -0
- package/dist/export/types.d.ts.map +1 -0
- package/dist/export/types.js +9 -0
- package/dist/export/types.js.map +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/lib/claude-plugin-registry.d.ts +66 -0
- package/dist/lib/claude-plugin-registry.d.ts.map +1 -0
- package/dist/lib/claude-plugin-registry.js +318 -0
- package/dist/lib/claude-plugin-registry.js.map +1 -0
- package/dist/merge/arrays.d.ts +87 -0
- package/dist/merge/arrays.d.ts.map +1 -0
- package/dist/merge/arrays.js +164 -0
- package/dist/merge/arrays.js.map +1 -0
- package/dist/merge/file-type.d.ts +32 -0
- package/dist/merge/file-type.d.ts.map +1 -0
- package/dist/merge/file-type.js +70 -0
- package/dist/merge/file-type.js.map +1 -0
- package/dist/merge/index.d.ts +14 -0
- package/dist/merge/index.d.ts.map +1 -0
- package/dist/merge/index.js +11 -0
- package/dist/merge/index.js.map +1 -0
- package/dist/merge/objects.d.ts +46 -0
- package/dist/merge/objects.d.ts.map +1 -0
- package/dist/merge/objects.js +193 -0
- package/dist/merge/objects.js.map +1 -0
- package/dist/merge/parse.d.ts +23 -0
- package/dist/merge/parse.d.ts.map +1 -0
- package/dist/merge/parse.js +78 -0
- package/dist/merge/parse.js.map +1 -0
- package/dist/merge/resolve.d.ts +66 -0
- package/dist/merge/resolve.d.ts.map +1 -0
- package/dist/merge/resolve.js +189 -0
- package/dist/merge/resolve.js.map +1 -0
- package/dist/merge/types.d.ts +82 -0
- package/dist/merge/types.d.ts.map +1 -0
- package/dist/merge/types.js +8 -0
- package/dist/merge/types.js.map +1 -0
- package/dist/parser/agent-data-sections.d.ts +53 -0
- package/dist/parser/agent-data-sections.d.ts.map +1 -0
- package/dist/parser/agent-data-sections.js +118 -0
- package/dist/parser/agent-data-sections.js.map +1 -0
- package/dist/parser/alignment.d.ts +4 -4
- package/dist/parser/alignment.d.ts.map +1 -1
- package/dist/parser/alignment.js +27 -22
- package/dist/parser/alignment.js.map +1 -1
- package/dist/parser/assess.d.ts +5 -5
- package/dist/parser/assess.d.ts.map +1 -1
- package/dist/parser/assess.js +36 -32
- package/dist/parser/assess.js.map +1 -1
- package/dist/parser/config.d.ts +351 -0
- package/dist/parser/config.d.ts.map +1 -0
- package/dist/parser/config.js +326 -0
- package/dist/parser/config.js.map +1 -0
- package/dist/parser/convention-validation.d.ts +1 -1
- package/dist/parser/convention-validation.d.ts.map +1 -1
- package/dist/parser/convention-validation.js +21 -16
- package/dist/parser/convention-validation.js.map +1 -1
- package/dist/parser/coverage-cache.d.ts +49 -0
- package/dist/parser/coverage-cache.d.ts.map +1 -0
- package/dist/parser/coverage-cache.js +123 -0
- package/dist/parser/coverage-cache.js.map +1 -0
- package/dist/parser/daemon-status.d.ts +37 -0
- package/dist/parser/daemon-status.d.ts.map +1 -0
- package/dist/parser/daemon-status.js +67 -0
- package/dist/parser/daemon-status.js.map +1 -0
- package/dist/parser/doctor.d.ts +107 -0
- package/dist/parser/doctor.d.ts.map +1 -0
- package/dist/parser/doctor.js +366 -0
- package/dist/parser/doctor.js.map +1 -0
- package/dist/parser/fix.d.ts +1 -1
- package/dist/parser/fix.d.ts.map +1 -1
- package/dist/parser/fix.js +31 -27
- package/dist/parser/fix.js.map +1 -1
- package/dist/parser/index.d.ts +16 -11
- package/dist/parser/index.d.ts.map +1 -1
- package/dist/parser/index.js +16 -11
- package/dist/parser/index.js.map +1 -1
- package/dist/parser/items.d.ts +8 -2
- package/dist/parser/items.d.ts.map +1 -1
- package/dist/parser/items.js +71 -35
- package/dist/parser/items.js.map +1 -1
- package/dist/parser/meta.d.ts +167 -9
- package/dist/parser/meta.d.ts.map +1 -1
- package/dist/parser/meta.js +379 -46
- package/dist/parser/meta.js.map +1 -1
- package/dist/parser/plan-document.d.ts +189 -0
- package/dist/parser/plan-document.d.ts.map +1 -0
- package/dist/parser/plan-document.js +340 -0
- package/dist/parser/plan-document.js.map +1 -0
- package/dist/parser/plans.d.ts +59 -0
- package/dist/parser/plans.d.ts.map +1 -0
- package/dist/parser/plans.js +239 -0
- package/dist/parser/plans.js.map +1 -0
- package/dist/parser/refs.d.ts +22 -9
- package/dist/parser/refs.d.ts.map +1 -1
- package/dist/parser/refs.js +102 -50
- package/dist/parser/refs.js.map +1 -1
- package/dist/parser/setup-status.d.ts +71 -0
- package/dist/parser/setup-status.d.ts.map +1 -0
- package/dist/parser/setup-status.js +269 -0
- package/dist/parser/setup-status.js.map +1 -0
- package/dist/parser/shadow.d.ts +150 -19
- package/dist/parser/shadow.d.ts.map +1 -1
- package/dist/parser/shadow.js +548 -187
- package/dist/parser/shadow.js.map +1 -1
- package/dist/parser/skill-render.d.ts +317 -0
- package/dist/parser/skill-render.d.ts.map +1 -0
- package/dist/parser/skill-render.js +943 -0
- package/dist/parser/skill-render.js.map +1 -0
- package/dist/parser/traits.d.ts +3 -3
- package/dist/parser/traits.d.ts.map +1 -1
- package/dist/parser/traits.js +2 -2
- package/dist/parser/traits.js.map +1 -1
- package/dist/parser/validate-skills.d.ts +32 -0
- package/dist/parser/validate-skills.d.ts.map +1 -0
- package/dist/parser/validate-skills.js +202 -0
- package/dist/parser/validate-skills.js.map +1 -0
- package/dist/parser/validate.d.ts +45 -3
- package/dist/parser/validate.d.ts.map +1 -1
- package/dist/parser/validate.js +622 -105
- package/dist/parser/validate.js.map +1 -1
- package/dist/parser/yaml.d.ts +83 -19
- package/dist/parser/yaml.d.ts.map +1 -1
- package/dist/parser/yaml.js +478 -173
- package/dist/parser/yaml.js.map +1 -1
- package/dist/ralph/cli-renderer.d.ts +8 -1
- package/dist/ralph/cli-renderer.d.ts.map +1 -1
- package/dist/ralph/cli-renderer.js +105 -34
- package/dist/ralph/cli-renderer.js.map +1 -1
- package/dist/ralph/events.d.ts +10 -10
- package/dist/ralph/events.d.ts.map +1 -1
- package/dist/ralph/events.js +277 -98
- package/dist/ralph/events.js.map +1 -1
- package/dist/ralph/index.d.ts +5 -2
- package/dist/ralph/index.d.ts.map +1 -1
- package/dist/ralph/index.js +9 -3
- package/dist/ralph/index.js.map +1 -1
- package/dist/ralph/loop-errors.d.ts +83 -0
- package/dist/ralph/loop-errors.d.ts.map +1 -0
- package/dist/ralph/loop-errors.js +150 -0
- package/dist/ralph/loop-errors.js.map +1 -0
- package/dist/ralph/subagent.d.ts +83 -0
- package/dist/ralph/subagent.d.ts.map +1 -0
- package/dist/ralph/subagent.js +174 -0
- package/dist/ralph/subagent.js.map +1 -0
- package/dist/ralph/wrap-up.d.ts +125 -0
- package/dist/ralph/wrap-up.d.ts.map +1 -0
- package/dist/ralph/wrap-up.js +270 -0
- package/dist/ralph/wrap-up.js.map +1 -0
- package/dist/schema/batch.d.ts +95 -0
- package/dist/schema/batch.d.ts.map +1 -0
- package/dist/schema/batch.js +24 -0
- package/dist/schema/batch.js.map +1 -0
- package/dist/schema/common.d.ts +2 -2
- package/dist/schema/common.d.ts.map +1 -1
- package/dist/schema/common.js +34 -31
- package/dist/schema/common.js.map +1 -1
- package/dist/schema/inbox.d.ts +12 -12
- package/dist/schema/inbox.js +4 -4
- package/dist/schema/inbox.js.map +1 -1
- package/dist/schema/index.d.ts +8 -5
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/index.js +8 -5
- package/dist/schema/index.js.map +1 -1
- package/dist/schema/meta.d.ts +1454 -27
- package/dist/schema/meta.d.ts.map +1 -1
- package/dist/schema/meta.js +198 -21
- package/dist/schema/meta.js.map +1 -1
- package/dist/schema/plan.d.ts +285 -0
- package/dist/schema/plan.d.ts.map +1 -0
- package/dist/schema/plan.js +81 -0
- package/dist/schema/plan.js.map +1 -0
- package/dist/schema/spec.d.ts +72 -33
- package/dist/schema/spec.d.ts.map +1 -1
- package/dist/schema/spec.js +22 -9
- package/dist/schema/spec.js.map +1 -1
- package/dist/schema/task.d.ts +172 -161
- package/dist/schema/task.d.ts.map +1 -1
- package/dist/schema/task.js +21 -12
- package/dist/schema/task.js.map +1 -1
- package/dist/schema/triage.d.ts +266 -0
- package/dist/schema/triage.d.ts.map +1 -0
- package/dist/schema/triage.js +134 -0
- package/dist/schema/triage.js.map +1 -0
- package/dist/sessions/index.d.ts +2 -2
- package/dist/sessions/index.d.ts.map +1 -1
- package/dist/sessions/index.js +3 -3
- package/dist/sessions/index.js.map +1 -1
- package/dist/sessions/store.d.ts +233 -1
- package/dist/sessions/store.d.ts.map +1 -1
- package/dist/sessions/store.js +628 -31
- package/dist/sessions/store.js.map +1 -1
- package/dist/sessions/types.d.ts +10 -10
- package/dist/sessions/types.d.ts.map +1 -1
- package/dist/sessions/types.js +10 -9
- package/dist/sessions/types.js.map +1 -1
- package/dist/strings/errors.d.ts +51 -0
- package/dist/strings/errors.d.ts.map +1 -1
- package/dist/strings/errors.js +136 -106
- package/dist/strings/errors.js.map +1 -1
- package/dist/strings/guidance.d.ts.map +1 -1
- package/dist/strings/guidance.js +16 -16
- package/dist/strings/guidance.js.map +1 -1
- package/dist/strings/index.d.ts +4 -4
- package/dist/strings/index.d.ts.map +1 -1
- package/dist/strings/index.js +4 -4
- package/dist/strings/index.js.map +1 -1
- package/dist/strings/labels.d.ts +4 -0
- package/dist/strings/labels.d.ts.map +1 -1
- package/dist/strings/labels.js +45 -41
- package/dist/strings/labels.js.map +1 -1
- package/dist/strings/validation.d.ts.map +1 -1
- package/dist/strings/validation.js +71 -71
- package/dist/strings/validation.js.map +1 -1
- package/dist/utils/commit.d.ts +1 -1
- package/dist/utils/commit.d.ts.map +1 -1
- package/dist/utils/commit.js +28 -26
- package/dist/utils/commit.js.map +1 -1
- package/dist/utils/git.d.ts +1 -1
- package/dist/utils/git.d.ts.map +1 -1
- package/dist/utils/git.js +40 -38
- package/dist/utils/git.js.map +1 -1
- package/dist/utils/grep.js +11 -11
- package/dist/utils/grep.js.map +1 -1
- package/dist/utils/index.d.ts +7 -7
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +4 -4
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/time.d.ts.map +1 -1
- package/dist/utils/time.js +10 -10
- package/dist/utils/time.js.map +1 -1
- package/package.json +28 -5
- package/plugin/.claude-plugin/marketplace.json +17 -0
- package/plugin/.claude-plugin/plugin.json +5 -0
- package/plugin/plugins/kspec/skills/help/SKILL.md +42 -0
- package/plugin/plugins/kspec/skills/triage/SKILL.md +206 -0
- package/plugin/plugins/kspec/skills/triage/docs/automation.md +120 -0
- package/plugin/plugins/kspec/skills/triage/docs/inbox.md +144 -0
- package/plugin/plugins/kspec/skills/triage/docs/observations.md +85 -0
- package/templates/agents-sections/01-quick-start.md +22 -0
- package/templates/agents-sections/02-shadow-branch.md +34 -0
- package/templates/agents-sections/03-task-lifecycle.md +48 -0
- package/templates/agents-sections/04-pr-workflow.md +17 -0
- package/templates/agents-sections/05-commit-convention.md +27 -0
- package/templates/agents-sections/06-ralph-loop.md +45 -0
- package/templates/hooks/pre-commit +34 -0
- package/templates/skills/help/SKILL.md +37 -0
- package/templates/skills/manifest.yaml +15 -0
- package/templates/skills/triage/SKILL.md +199 -0
- package/templates/skills/triage/docs/automation.md +120 -0
- package/templates/skills/triage/docs/inbox.md +144 -0
- package/templates/skills/triage/docs/observations.md +85 -0
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inbox API Routes
|
|
3
|
+
*
|
|
4
|
+
* REST endpoints for inbox item operations:
|
|
5
|
+
* - GET /api/inbox - list all items
|
|
6
|
+
* - POST /api/inbox - create item
|
|
7
|
+
* - DELETE /api/inbox/:ref - delete item
|
|
8
|
+
*
|
|
9
|
+
* AC Coverage:
|
|
10
|
+
* - ac-12: GET /api/inbox returns items ordered by created_at desc
|
|
11
|
+
* - ac-13: POST /api/inbox creates item with generated ULID
|
|
12
|
+
* - ac-14: DELETE /api/inbox/:ref removes item
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { Elysia, t } from 'elysia';
|
|
16
|
+
import {
|
|
17
|
+
initContext,
|
|
18
|
+
loadInboxItems,
|
|
19
|
+
createInboxItem,
|
|
20
|
+
saveInboxItem,
|
|
21
|
+
deleteInboxItem,
|
|
22
|
+
findInboxItemByRef,
|
|
23
|
+
ReferenceIndex,
|
|
24
|
+
loadAllTasks,
|
|
25
|
+
loadAllItems,
|
|
26
|
+
type InboxItemInput,
|
|
27
|
+
} from '../../parser/index.js';
|
|
28
|
+
import { commitIfShadow } from '../../parser/shadow.js';
|
|
29
|
+
import type { PubSubManager } from '../websocket/pubsub';
|
|
30
|
+
|
|
31
|
+
interface InboxRouteOptions {
|
|
32
|
+
pubsub: PubSubManager;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function createInboxRoutes(options: InboxRouteOptions) {
|
|
36
|
+
const { pubsub } = options;
|
|
37
|
+
|
|
38
|
+
return new Elysia({ prefix: '/api/inbox' })
|
|
39
|
+
// AC: @api-contract ac-12 - List inbox items ordered by created_at desc
|
|
40
|
+
.get('/', async ({ projectContext }) => {
|
|
41
|
+
// AC: @multi-directory-daemon ac-1, ac-24 - Use project context from middleware
|
|
42
|
+
const ctx = await initContext(projectContext.path);
|
|
43
|
+
const items = await loadInboxItems(ctx);
|
|
44
|
+
|
|
45
|
+
// AC: @api-contract ac-12 - Sort by created_at descending (newest first)
|
|
46
|
+
const sorted = [...items].sort(
|
|
47
|
+
(a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime()
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
return {
|
|
51
|
+
items: sorted,
|
|
52
|
+
total: sorted.length,
|
|
53
|
+
};
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
// AC: @api-contract ac-13 - Create inbox item
|
|
57
|
+
.post(
|
|
58
|
+
'/',
|
|
59
|
+
async ({ body, error: errorResponse, projectContext }) => {
|
|
60
|
+
// AC: @multi-directory-daemon ac-1, ac-24 - Use project context from middleware
|
|
61
|
+
const ctx = await initContext(projectContext.path);
|
|
62
|
+
|
|
63
|
+
// AC: @trait-api-endpoint ac-3 - Validate body
|
|
64
|
+
if (!body.text || typeof body.text !== 'string' || body.text.trim().length === 0) {
|
|
65
|
+
return errorResponse(400, {
|
|
66
|
+
error: 'validation_error',
|
|
67
|
+
details: [
|
|
68
|
+
{
|
|
69
|
+
field: 'text',
|
|
70
|
+
message: 'Text is required and must be a non-empty string',
|
|
71
|
+
},
|
|
72
|
+
],
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Create inbox item input
|
|
77
|
+
const input: InboxItemInput = {
|
|
78
|
+
text: body.text,
|
|
79
|
+
tags: body.tags,
|
|
80
|
+
added_by: body.added_by,
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
// AC: @api-contract ac-13 - Generate ULID and create item
|
|
84
|
+
const item = createInboxItem(input, ctx.config?.identity?.author);
|
|
85
|
+
|
|
86
|
+
// Save and commit
|
|
87
|
+
await saveInboxItem(ctx, item);
|
|
88
|
+
await commitIfShadow(ctx.shadow, `inbox: add item ${item._ulid}`);
|
|
89
|
+
|
|
90
|
+
// Broadcast update
|
|
91
|
+
// AC: @multi-directory-daemon ac-18 - Broadcast scoped to request project
|
|
92
|
+
pubsub.broadcast('inbox:updates', 'inbox_item_created', {
|
|
93
|
+
ulid: item._ulid,
|
|
94
|
+
}, projectContext.path);
|
|
95
|
+
|
|
96
|
+
// AC: @api-contract ac-13 - Return item with generated ULID
|
|
97
|
+
return {
|
|
98
|
+
success: true,
|
|
99
|
+
item,
|
|
100
|
+
};
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
body: t.Object({
|
|
104
|
+
text: t.String(),
|
|
105
|
+
tags: t.Optional(t.Array(t.String())),
|
|
106
|
+
added_by: t.Optional(t.String()),
|
|
107
|
+
}),
|
|
108
|
+
}
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
// AC: @api-contract ac-14 - Delete inbox item
|
|
112
|
+
.delete(
|
|
113
|
+
'/:ref',
|
|
114
|
+
async ({ params, error: errorResponse, projectContext }) => {
|
|
115
|
+
// AC: @multi-directory-daemon ac-1, ac-24 - Use project context from middleware
|
|
116
|
+
const ctx = await initContext(projectContext.path);
|
|
117
|
+
const inboxItems = await loadInboxItems(ctx);
|
|
118
|
+
const tasks = await loadAllTasks(ctx);
|
|
119
|
+
const specItems = await loadAllItems(ctx);
|
|
120
|
+
const index = new ReferenceIndex(tasks, specItems);
|
|
121
|
+
|
|
122
|
+
// Resolve ref
|
|
123
|
+
const result = index.resolve(params.ref);
|
|
124
|
+
if (!result.ok) {
|
|
125
|
+
return errorResponse(404, {
|
|
126
|
+
error: 'not_found',
|
|
127
|
+
message: `Inbox item reference "${params.ref}" not found`,
|
|
128
|
+
suggestion: 'Use kspec inbox list to find valid inbox item references',
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Verify it's an inbox item
|
|
133
|
+
const item = findInboxItemByRef(inboxItems, result.ulid);
|
|
134
|
+
if (!item) {
|
|
135
|
+
return errorResponse(404, {
|
|
136
|
+
error: 'not_found',
|
|
137
|
+
message: `Reference "${params.ref}" is not an inbox item`,
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// AC: @api-contract ac-14 - Delete item
|
|
142
|
+
await deleteInboxItem(ctx, result.ulid);
|
|
143
|
+
await commitIfShadow(ctx.shadow, `inbox: delete ${params.ref}`);
|
|
144
|
+
|
|
145
|
+
// Broadcast update
|
|
146
|
+
// AC: @multi-directory-daemon ac-18 - Broadcast scoped to request project
|
|
147
|
+
pubsub.broadcast('inbox:updates', 'inbox_item_deleted', {
|
|
148
|
+
ref: params.ref,
|
|
149
|
+
ulid: result.ulid,
|
|
150
|
+
}, projectContext.path);
|
|
151
|
+
|
|
152
|
+
// AC: @api-contract ac-14 - Return success confirmation
|
|
153
|
+
return {
|
|
154
|
+
success: true,
|
|
155
|
+
deleted: result.ulid,
|
|
156
|
+
};
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
params: t.Object({
|
|
160
|
+
ref: t.String(),
|
|
161
|
+
}),
|
|
162
|
+
}
|
|
163
|
+
);
|
|
164
|
+
}
|
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spec Item API Routes
|
|
3
|
+
*
|
|
4
|
+
* REST endpoints for spec item operations:
|
|
5
|
+
* - GET /api/items - list with filters and pagination
|
|
6
|
+
* - GET /api/items/:ref - get single item
|
|
7
|
+
* - GET /api/items/:ref/tasks - get linked tasks
|
|
8
|
+
*
|
|
9
|
+
* AC Coverage:
|
|
10
|
+
* - ac-8: GET /api/items returns array of spec items
|
|
11
|
+
* - ac-9: Type filter with multi-value support
|
|
12
|
+
* - ac-10: GET /api/items/:ref with full details
|
|
13
|
+
* - ac-11: GET /api/items/:ref/tasks via AlignmentIndex
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { Elysia, t } from 'elysia';
|
|
17
|
+
import {
|
|
18
|
+
initContext,
|
|
19
|
+
loadAllItems,
|
|
20
|
+
loadAllTasks,
|
|
21
|
+
ReferenceIndex,
|
|
22
|
+
AlignmentIndex,
|
|
23
|
+
getCachedTestCoverage,
|
|
24
|
+
computeACCoverage,
|
|
25
|
+
type LoadedSpecItem,
|
|
26
|
+
} from '../../parser/index.js';
|
|
27
|
+
|
|
28
|
+
interface ItemsRouteOptions {}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Compute parent ULIDs for items based on _path and _sourceFile.
|
|
32
|
+
* Items are nested when they share the same source file and
|
|
33
|
+
* one item's path is a prefix of another's path.
|
|
34
|
+
*/
|
|
35
|
+
function computeParentMap(items: LoadedSpecItem[]): Map<string, string | undefined> {
|
|
36
|
+
const parentMap = new Map<string, string | undefined>();
|
|
37
|
+
|
|
38
|
+
// Group items by source file
|
|
39
|
+
const byFile = new Map<string, LoadedSpecItem[]>();
|
|
40
|
+
for (const item of items) {
|
|
41
|
+
const file = item._sourceFile || '';
|
|
42
|
+
if (!byFile.has(file)) {
|
|
43
|
+
byFile.set(file, []);
|
|
44
|
+
}
|
|
45
|
+
byFile.get(file)!.push(item);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// For each file, determine parent relationships based on path
|
|
49
|
+
for (const [, fileItems] of byFile) {
|
|
50
|
+
// Sort by path length (shorter paths are potential parents)
|
|
51
|
+
const sorted = [...fileItems].sort((a, b) => {
|
|
52
|
+
const aLen = a._path?.length || 0;
|
|
53
|
+
const bLen = b._path?.length || 0;
|
|
54
|
+
return aLen - bLen;
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
for (const item of sorted) {
|
|
58
|
+
const itemPath = item._path;
|
|
59
|
+
|
|
60
|
+
if (!itemPath) {
|
|
61
|
+
// Root item in file - no parent
|
|
62
|
+
parentMap.set(item._ulid, undefined);
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Find the closest parent by matching path prefix
|
|
67
|
+
// Path format: "features[0].requirements[0]"
|
|
68
|
+
// Parent path: "features[0]" or undefined (root item)
|
|
69
|
+
const lastDot = itemPath.lastIndexOf('.');
|
|
70
|
+
const parentPath = lastDot > -1 ? itemPath.substring(0, lastDot) : undefined;
|
|
71
|
+
|
|
72
|
+
// Find parent item
|
|
73
|
+
let parentUlid: string | undefined;
|
|
74
|
+
if (parentPath === undefined) {
|
|
75
|
+
// Direct child of the root item (the item with no path)
|
|
76
|
+
const rootItem = fileItems.find(i => !i._path);
|
|
77
|
+
parentUlid = rootItem?._ulid;
|
|
78
|
+
} else {
|
|
79
|
+
// Find item with matching parent path
|
|
80
|
+
const parentItem = fileItems.find(i => i._path === parentPath);
|
|
81
|
+
parentUlid = parentItem?._ulid;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
parentMap.set(item._ulid, parentUlid);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return parentMap;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export function createItemsRoutes(options: ItemsRouteOptions = {}) {
|
|
92
|
+
// No closure-scoped kspecDir needed - comes from middleware
|
|
93
|
+
|
|
94
|
+
return new Elysia({ prefix: '/api/items' })
|
|
95
|
+
// AC: @api-contract ac-8, ac-9 - List items with type filter
|
|
96
|
+
.get(
|
|
97
|
+
'/',
|
|
98
|
+
async ({ query, projectContext }) => {
|
|
99
|
+
// AC: @multi-directory-daemon ac-1, ac-24 - Use project context from middleware
|
|
100
|
+
const ctx = await initContext(projectContext.path);
|
|
101
|
+
const items = await loadAllItems(ctx);
|
|
102
|
+
|
|
103
|
+
// Compute parent relationships from path structure
|
|
104
|
+
const parentMap = computeParentMap(items);
|
|
105
|
+
|
|
106
|
+
// Apply filters
|
|
107
|
+
let filtered = items;
|
|
108
|
+
|
|
109
|
+
// AC: @api-contract ac-9 - Multi-value type filter
|
|
110
|
+
if (query.type) {
|
|
111
|
+
const typeFilters = Array.isArray(query.type) ? query.type : [query.type];
|
|
112
|
+
filtered = filtered.filter((item) => typeFilters.includes(item.type));
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Optional maturity filter (not in ACs but useful)
|
|
116
|
+
if (query.maturity) {
|
|
117
|
+
const maturityFilters = Array.isArray(query.maturity) ? query.maturity : [query.maturity];
|
|
118
|
+
filtered = filtered.filter((item) => {
|
|
119
|
+
if (typeof item.status === 'object' && item.status?.maturity) {
|
|
120
|
+
return maturityFilters.includes(item.status.maturity);
|
|
121
|
+
}
|
|
122
|
+
return false;
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Optional implementation filter (not in ACs but useful)
|
|
127
|
+
if (query.implementation) {
|
|
128
|
+
const implFilters = Array.isArray(query.implementation)
|
|
129
|
+
? query.implementation
|
|
130
|
+
: [query.implementation];
|
|
131
|
+
filtered = filtered.filter((item) => {
|
|
132
|
+
if (typeof item.status === 'object' && item.status?.implementation) {
|
|
133
|
+
return implFilters.includes(item.status.implementation);
|
|
134
|
+
}
|
|
135
|
+
return false;
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Tag filter (not in ACs but useful)
|
|
140
|
+
if (query.tag) {
|
|
141
|
+
const tagFilters = Array.isArray(query.tag) ? query.tag : [query.tag];
|
|
142
|
+
filtered = filtered.filter((item) =>
|
|
143
|
+
item.tags?.some((t) => tagFilters.includes(t))
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Pagination
|
|
148
|
+
const total = filtered.length;
|
|
149
|
+
const offset = Number(query.offset) || 0;
|
|
150
|
+
const limit = Number(query.limit) || total;
|
|
151
|
+
|
|
152
|
+
const paginated = filtered.slice(offset, offset + limit);
|
|
153
|
+
|
|
154
|
+
// AC: @api-contract ac-8 - Return spec items (modules, features, requirements)
|
|
155
|
+
const result = paginated.map((item) => ({
|
|
156
|
+
_ulid: item._ulid,
|
|
157
|
+
slugs: item.slugs,
|
|
158
|
+
title: item.title,
|
|
159
|
+
type: item.type,
|
|
160
|
+
status: item.status,
|
|
161
|
+
tags: item.tags,
|
|
162
|
+
parent: parentMap.get(item._ulid),
|
|
163
|
+
created_at: item.created_at,
|
|
164
|
+
acceptance_criteria_count: item.acceptance_criteria?.length || 0,
|
|
165
|
+
}));
|
|
166
|
+
|
|
167
|
+
// AC: @trait-api-endpoint ac-4 - Return pagination wrapper
|
|
168
|
+
return {
|
|
169
|
+
items: result,
|
|
170
|
+
total,
|
|
171
|
+
offset,
|
|
172
|
+
limit,
|
|
173
|
+
};
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
query: t.Object({
|
|
177
|
+
type: t.Optional(t.Union([t.String(), t.Array(t.String())])),
|
|
178
|
+
maturity: t.Optional(t.Union([t.String(), t.Array(t.String())])),
|
|
179
|
+
implementation: t.Optional(t.Union([t.String(), t.Array(t.String())])),
|
|
180
|
+
tag: t.Optional(t.Union([t.String(), t.Array(t.String())])),
|
|
181
|
+
limit: t.Optional(t.String()),
|
|
182
|
+
offset: t.Optional(t.String()),
|
|
183
|
+
}),
|
|
184
|
+
}
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
// AC: @api-contract ac-10 - Get single item by ref
|
|
188
|
+
.get(
|
|
189
|
+
'/:ref',
|
|
190
|
+
async ({ params, error: errorResponse, projectContext }) => {
|
|
191
|
+
// AC: @multi-directory-daemon ac-1, ac-24 - Use project context from middleware
|
|
192
|
+
const ctx = await initContext(projectContext.path);
|
|
193
|
+
const items = await loadAllItems(ctx);
|
|
194
|
+
const tasks = await loadAllTasks(ctx);
|
|
195
|
+
const index = new ReferenceIndex(tasks, items);
|
|
196
|
+
|
|
197
|
+
// Compute parent relationships from path structure
|
|
198
|
+
const parentMap = computeParentMap(items);
|
|
199
|
+
|
|
200
|
+
// AC: @api-contract ac-10, @trait-api-endpoint ac-2 - Resolve ref via ReferenceIndex
|
|
201
|
+
const result = index.resolve(params.ref);
|
|
202
|
+
|
|
203
|
+
if (!result.ok) {
|
|
204
|
+
// AC: @trait-api-endpoint ac-2 - Return 404 with error details
|
|
205
|
+
return errorResponse(404, {
|
|
206
|
+
error: 'not_found',
|
|
207
|
+
message: `Item reference "${params.ref}" not found`,
|
|
208
|
+
suggestion: 'Use kspec item list or kspec search to find valid item references',
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// Find the item
|
|
213
|
+
const item = items.find((i) => i._ulid === result.ulid);
|
|
214
|
+
if (!item) {
|
|
215
|
+
return errorResponse(404, {
|
|
216
|
+
error: 'not_found',
|
|
217
|
+
message: `Reference "${params.ref}" is not a spec item`,
|
|
218
|
+
suggestion: 'This reference might point to a task instead',
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// AC: @web-dashboard ac-15 - Compute test coverage for acceptance criteria
|
|
223
|
+
// Uses cached coverage scan for performance (avoids re-scanning on every request)
|
|
224
|
+
let acceptanceCriteriaWithCoverage = item.acceptance_criteria;
|
|
225
|
+
if (item.acceptance_criteria && item.acceptance_criteria.length > 0) {
|
|
226
|
+
try {
|
|
227
|
+
const coveredACs = await getCachedTestCoverage(projectContext.path);
|
|
228
|
+
acceptanceCriteriaWithCoverage = computeACCoverage(item, coveredACs);
|
|
229
|
+
} catch (err) {
|
|
230
|
+
// Coverage scan failed - leave as undefined
|
|
231
|
+
console.warn('AC coverage scan failed:', err);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// AC: @api-contract ac-10 - Return full item with acceptance_criteria, traits, relationships
|
|
236
|
+
return {
|
|
237
|
+
_ulid: item._ulid,
|
|
238
|
+
slugs: item.slugs,
|
|
239
|
+
title: item.title,
|
|
240
|
+
type: item.type,
|
|
241
|
+
status: item.status,
|
|
242
|
+
tags: item.tags,
|
|
243
|
+
parent: parentMap.get(item._ulid),
|
|
244
|
+
description: item.description,
|
|
245
|
+
acceptance_criteria: acceptanceCriteriaWithCoverage,
|
|
246
|
+
traits: item.traits,
|
|
247
|
+
relationships: item.relationships,
|
|
248
|
+
created_at: item.created_at,
|
|
249
|
+
_sourceFile: item._sourceFile,
|
|
250
|
+
};
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
params: t.Object({
|
|
254
|
+
ref: t.String(),
|
|
255
|
+
}),
|
|
256
|
+
}
|
|
257
|
+
)
|
|
258
|
+
|
|
259
|
+
// AC: @api-contract ac-11 - Get tasks linked to spec item
|
|
260
|
+
.get(
|
|
261
|
+
'/:ref/tasks',
|
|
262
|
+
async ({ params, error: errorResponse, projectContext }) => {
|
|
263
|
+
// AC: @multi-directory-daemon ac-1, ac-24 - Use project context from middleware
|
|
264
|
+
const ctx = await initContext(projectContext.path);
|
|
265
|
+
const items = await loadAllItems(ctx);
|
|
266
|
+
const tasks = await loadAllTasks(ctx);
|
|
267
|
+
const refIndex = new ReferenceIndex(tasks, items);
|
|
268
|
+
const alignIndex = new AlignmentIndex(tasks, items);
|
|
269
|
+
alignIndex.buildLinks(refIndex);
|
|
270
|
+
|
|
271
|
+
// Resolve ref
|
|
272
|
+
const result = refIndex.resolve(params.ref);
|
|
273
|
+
|
|
274
|
+
if (!result.ok) {
|
|
275
|
+
return errorResponse(404, {
|
|
276
|
+
error: 'not_found',
|
|
277
|
+
message: `Item reference "${params.ref}" not found`,
|
|
278
|
+
suggestion: 'Use kspec item list to find valid item references',
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
const item = items.find((i) => i._ulid === result.ulid);
|
|
283
|
+
if (!item) {
|
|
284
|
+
return errorResponse(404, {
|
|
285
|
+
error: 'not_found',
|
|
286
|
+
message: `Reference "${params.ref}" is not a spec item`,
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// AC: @api-contract ac-11 - Get tasks via AlignmentIndex
|
|
291
|
+
const linkedTasks = alignIndex.getTasksForSpec(result.ulid);
|
|
292
|
+
|
|
293
|
+
// Return tasks with summary info
|
|
294
|
+
const result_items = linkedTasks.map((task) => ({
|
|
295
|
+
_ulid: task._ulid,
|
|
296
|
+
slugs: task.slugs,
|
|
297
|
+
title: task.title,
|
|
298
|
+
type: task.type || 'task',
|
|
299
|
+
status: task.status,
|
|
300
|
+
priority: task.priority,
|
|
301
|
+
spec_ref: task.spec_ref,
|
|
302
|
+
tags: task.tags || [],
|
|
303
|
+
depends_on: task.depends_on || [],
|
|
304
|
+
started_at: task.started_at,
|
|
305
|
+
completed_at: task.completed_at,
|
|
306
|
+
created_at: task.created_at,
|
|
307
|
+
notes_count: task.notes?.length || 0,
|
|
308
|
+
todos_count: task.todos?.length || 0,
|
|
309
|
+
}));
|
|
310
|
+
|
|
311
|
+
return {
|
|
312
|
+
items: result_items,
|
|
313
|
+
total: result_items.length,
|
|
314
|
+
};
|
|
315
|
+
},
|
|
316
|
+
{
|
|
317
|
+
params: t.Object({
|
|
318
|
+
ref: t.String(),
|
|
319
|
+
}),
|
|
320
|
+
}
|
|
321
|
+
);
|
|
322
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Meta API Routes
|
|
3
|
+
*
|
|
4
|
+
* REST endpoints for meta operations:
|
|
5
|
+
* - GET /api/meta/session - get session context
|
|
6
|
+
* - GET /api/meta/agents - list agents
|
|
7
|
+
* - GET /api/meta/workflows - list workflows
|
|
8
|
+
* - GET /api/meta/observations - list observations with filter
|
|
9
|
+
*
|
|
10
|
+
* AC Coverage:
|
|
11
|
+
* - ac-15: GET /api/meta/session returns session context
|
|
12
|
+
* - ac-16: GET /api/meta/agents returns all agents
|
|
13
|
+
* - ac-17: GET /api/meta/workflows returns all workflows
|
|
14
|
+
* - ac-18: GET /api/meta/observations with filter
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { Elysia, t } from 'elysia';
|
|
18
|
+
import {
|
|
19
|
+
initContext,
|
|
20
|
+
loadMetaContext,
|
|
21
|
+
loadSessionContext,
|
|
22
|
+
} from '../../parser/index.js';
|
|
23
|
+
|
|
24
|
+
interface MetaRouteOptions {}
|
|
25
|
+
|
|
26
|
+
export function createMetaRoutes(options: MetaRouteOptions = {}) {
|
|
27
|
+
// No closure-scoped kspecDir needed - comes from middleware
|
|
28
|
+
|
|
29
|
+
return new Elysia({ prefix: '/api/meta' })
|
|
30
|
+
// AC: @api-contract ac-15 - Get session context
|
|
31
|
+
.get('/session', async ({ projectContext }) => {
|
|
32
|
+
// AC: @multi-directory-daemon ac-1, ac-24 - Use project context from middleware
|
|
33
|
+
const ctx = await initContext(projectContext.path);
|
|
34
|
+
const session = await loadSessionContext(ctx);
|
|
35
|
+
|
|
36
|
+
// AC: @api-contract ac-15 - Return session context (focus, threads, questions)
|
|
37
|
+
return {
|
|
38
|
+
focus: session.focus,
|
|
39
|
+
threads: session.threads || [],
|
|
40
|
+
questions: session.questions || [],
|
|
41
|
+
updated_at: session.updated_at,
|
|
42
|
+
};
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
// AC: @api-contract ac-16 - List agents
|
|
46
|
+
.get('/agents', async ({ projectContext }) => {
|
|
47
|
+
// AC: @multi-directory-daemon ac-1, ac-24 - Use project context from middleware
|
|
48
|
+
const ctx = await initContext(projectContext.path);
|
|
49
|
+
const meta = await loadMetaContext(ctx);
|
|
50
|
+
|
|
51
|
+
// AC: @api-contract ac-16 - Return all defined agents
|
|
52
|
+
const agents = meta.agents;
|
|
53
|
+
|
|
54
|
+
return {
|
|
55
|
+
items: agents,
|
|
56
|
+
total: agents.length,
|
|
57
|
+
};
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
// AC: @api-contract ac-17 - List workflows
|
|
61
|
+
.get('/workflows', async ({ projectContext }) => {
|
|
62
|
+
// AC: @multi-directory-daemon ac-1, ac-24 - Use project context from middleware
|
|
63
|
+
const ctx = await initContext(projectContext.path);
|
|
64
|
+
const meta = await loadMetaContext(ctx);
|
|
65
|
+
|
|
66
|
+
// AC: @api-contract ac-17 - Return all defined workflows
|
|
67
|
+
const workflows = meta.workflows;
|
|
68
|
+
|
|
69
|
+
return {
|
|
70
|
+
items: workflows,
|
|
71
|
+
total: workflows.length,
|
|
72
|
+
};
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
// AC: @api-contract ac-18 - List observations with filter
|
|
76
|
+
.get(
|
|
77
|
+
'/observations',
|
|
78
|
+
async ({ query, projectContext }) => {
|
|
79
|
+
// AC: @multi-directory-daemon ac-1, ac-24 - Use project context from middleware
|
|
80
|
+
const ctx = await initContext(projectContext.path);
|
|
81
|
+
const meta = await loadMetaContext(ctx);
|
|
82
|
+
|
|
83
|
+
// Start with all observations
|
|
84
|
+
let filtered = meta.observations || [];
|
|
85
|
+
|
|
86
|
+
// AC: @api-contract ac-18 - Filter by resolved status
|
|
87
|
+
if (query.resolved !== undefined) {
|
|
88
|
+
const resolvedFilter = query.resolved === 'true';
|
|
89
|
+
filtered = filtered.filter((obs) => {
|
|
90
|
+
const isResolved = !!obs.resolved_at;
|
|
91
|
+
return isResolved === resolvedFilter;
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Optional type filter (not in ACs but useful)
|
|
96
|
+
if (query.type) {
|
|
97
|
+
const typeFilters = Array.isArray(query.type) ? query.type : [query.type];
|
|
98
|
+
filtered = filtered.filter((obs) => typeFilters.includes(obs.type));
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Sort by created_at descending (newest first)
|
|
102
|
+
const sorted = [...filtered].sort(
|
|
103
|
+
(a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime()
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
return {
|
|
107
|
+
items: sorted,
|
|
108
|
+
total: sorted.length,
|
|
109
|
+
};
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
query: t.Object({
|
|
113
|
+
resolved: t.Optional(t.String()),
|
|
114
|
+
type: t.Optional(t.Union([t.String(), t.Array(t.String())])),
|
|
115
|
+
}),
|
|
116
|
+
}
|
|
117
|
+
);
|
|
118
|
+
}
|