@specforge/canary-cli 0.1.18 → 0.2.1

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.
Files changed (38) hide show
  1. package/dist/cli/commands/debug/types.d.ts.map +1 -1
  2. package/dist/cli/commands/debug/types.js +4 -1
  3. package/dist/cli/commands/debug/types.js.map +1 -1
  4. package/dist/cli/templates/agents/content/core/sfag-spec-creator.d.ts.map +1 -1
  5. package/dist/cli/templates/agents/content/core/sfag-spec-creator.js +40 -35
  6. package/dist/cli/templates/agents/content/core/sfag-spec-creator.js.map +1 -1
  7. package/dist/lib/workflow-definitions.js +1 -1
  8. package/dist/lib/workflow-definitions.js.map +1 -1
  9. package/dist/tools/index.d.ts.map +1 -1
  10. package/dist/tools/index.js +67 -153
  11. package/dist/tools/index.js.map +1 -1
  12. package/node_modules/@specforge/session-types/dist/runtime/lifecycle-contract.d.ts +5 -1
  13. package/node_modules/@specforge/session-types/dist/runtime/lifecycle-contract.d.ts.map +1 -1
  14. package/node_modules/@specforge/session-types/dist/runtime/planning-operations.d.ts +2 -2
  15. package/node_modules/@specforge/session-types/dist/runtime/planning-operations.d.ts.map +1 -1
  16. package/node_modules/@specforge/session-types/dist/runtime/planning-operations.js +18 -1
  17. package/node_modules/@specforge/session-types/dist/runtime/planning-operations.js.map +1 -1
  18. package/node_modules/@specforge/session-types/dist/runtime/planning-session-action.d.ts +3 -3
  19. package/node_modules/@specforge/session-types/dist/runtime/planning-session-action.d.ts.map +1 -1
  20. package/node_modules/@specforge/session-types/dist/runtime/planning-session-action.js +6 -1
  21. package/node_modules/@specforge/session-types/dist/runtime/planning-session-action.js.map +1 -1
  22. package/node_modules/@specforge/session-types/dist/runtime/planning-session-aggregate.d.ts +10 -0
  23. package/node_modules/@specforge/session-types/dist/runtime/planning-session-aggregate.d.ts.map +1 -1
  24. package/node_modules/@specforge/session-types/dist/runtime/planning-session-aggregate.js +8 -0
  25. package/node_modules/@specforge/session-types/dist/runtime/planning-session-aggregate.js.map +1 -1
  26. package/node_modules/@specforge/session-types/dist/schema/work-session-test-result.d.ts.map +1 -1
  27. package/node_modules/@specforge/session-types/dist/schema/work-session-test-result.js +11 -0
  28. package/node_modules/@specforge/session-types/dist/schema/work-session-test-result.js.map +1 -1
  29. package/node_modules/@specforge/session-types/dist/schema/work-session.d.ts +11 -0
  30. package/node_modules/@specforge/session-types/dist/schema/work-session.d.ts.map +1 -1
  31. package/node_modules/@specforge/session-types/dist/schema/work-session.js +9 -0
  32. package/node_modules/@specforge/session-types/dist/schema/work-session.js.map +1 -1
  33. package/node_modules/@specforge/session-types/dist/stores/work-session-store.d.ts +9 -0
  34. package/node_modules/@specforge/session-types/dist/stores/work-session-store.d.ts.map +1 -1
  35. package/node_modules/@specforge/session-types/package.json +1 -1
  36. package/node_modules/@specforge/types/dist/mcp/tools/action-work-session.d.ts +1 -1
  37. package/package.json +4 -4
  38. package/src/cli/templates/agents/content/core/sfag-spec-creator.ts +40 -35
@@ -281,7 +281,7 @@ Format options:
281
281
  },
282
282
  {
283
283
  name: "action_planning_session",
284
- description: "Execute a planning action within an active session. Wraps all planning operations (create/update/delete epics, tickets, dependencies, blueprints) plus get_planning_status (readiness X-ray, worst-first) with automatic status tracking. The operation.type IS the backend PlanningOperationName. The spec status advances or regresses automatically based on the action type and gate checks. Returns updated progress, blockers, and next suggested actions after every call. To read a single ticket, use the `get` tool (type:'ticket').",
284
+ description: "Execute a planning action within an active session. Wraps the planning write operations (create/update/delete for epics, tickets and blueprints; plus the dependency, blueprint-link, step-link, justify and creator-election operations) and the read operation get_planning_status. The operation.type IS the backend PlanningOperationName; the remaining fields are the operation payload. To read a single ticket, use the `get` tool (type:'ticket').",
285
285
  inputSchema: {
286
286
  type: "object",
287
287
  properties: {
@@ -297,7 +297,10 @@ Format options:
297
297
  "update_epic",
298
298
  "delete_epic",
299
299
  "create_ticket",
300
- "update_ticket",
300
+ "ticket_general_actions",
301
+ "ticket_step_actions",
302
+ "ticket_criteria_actions",
303
+ "ticket_test_actions",
301
304
  "delete_ticket",
302
305
  "create_blueprint",
303
306
  "update_blueprint",
@@ -367,48 +370,78 @@ Format options:
367
370
  required: ["type", "id", "fields"]
368
371
  },
369
372
  // create_ticket — SHELL (ticket_decomposition): epicId/title/description
370
- // + ticketType (the impl/verification decision, set HERE and immutable via
371
- // update_ticket). The remaining body fields are authored by update_ticket in
372
- // ticket_expansion; dependencies via create_dependencies in cross_validation.
373
+ // + ticketType (the impl/verification decision, set HERE). The remaining body
374
+ // fields are authored by the ticket node verbs in ticket_expansion;
375
+ // dependencies via create_dependencies in cross_validation.
373
376
  {
374
377
  properties: {
375
378
  type: { const: "create_ticket" },
376
379
  epicId: { type: "string", description: "Parent epic id" },
377
380
  title: { type: "string", minLength: 1, description: "Ticket title (non-empty)" },
378
381
  description: { type: "string" },
379
- ticketType: { type: "string", enum: ["implementation", "verification"], description: "Ticket type \u2014 set here (decomposition); defaults to implementation. Not changeable via update_ticket." }
382
+ ticketType: { type: "string", enum: ["implementation", "verification"], description: "Ticket type \u2014 set here (decomposition); defaults to implementation. Editing it later via ticket_general_actions rolls the session back to ticket_decomposition." }
380
383
  },
381
384
  required: ["type", "epicId", "title"]
382
385
  },
386
+ // ME.19.1 (D8/D20) — the four ticket NODE VERBS replace the retired free-form
387
+ // `update_ticket`. Each targets ONE scope with a TYPED payload (no `fields`
388
+ // bag); complexity/planningType/ticketType are enums, so an out-of-enum value
389
+ // is denied at the schema gate before persistence. `status` is NOT settable
390
+ // (system/event-driven). Blueprint links are NOT settable here — use
391
+ // link_blueprint_to_tickets.
392
+ // ticket_general_actions — shell/general fields (partial edit).
383
393
  {
394
+ description: "Edit a ticket's shell/general fields. Only the keys you send are changed. Fields that do not apply are declared with the `justify` op (undo with `unjustify`), never by writing values here.",
384
395
  properties: {
385
- type: { const: "update_ticket" },
386
- id: { type: "string", description: "Ticket id (use list_tickets / lookup_ticket to find)." },
387
- fields: {
388
- type: "object",
389
- description: "Partial ticket update \u2014 only the keys you send are changed. Child-backed arrays (acceptanceCriteria, implementationSteps, filesToBe*, testSpecification.testTypes, codeSnippets, typeSnippets) replace the whole set. Blueprint links are NOT settable here \u2014 use link_blueprint_to_tickets (from ticket_decomposition onward), the sole writer of the blueprint\u2194ticket relation. Fields that do not apply are declared with the `justify` op (undo with `unjustify`), never by writing values here.",
390
- properties: {
391
- title: { type: "string" },
392
- description: { type: "string" },
393
- complexity: { type: "string", enum: ["small", "medium", "large", "xlarge"] },
394
- estimatedMinutes: { type: "integer", minimum: 0 },
395
- acceptanceCriteria: { type: "array", items: { type: "object", properties: { given: { type: "string" }, when: { type: "string" }, then: { type: "string" } }, required: ["given", "when", "then"] } },
396
- implementationSteps: { type: "array", description: "Ordered build steps. Declare the file(s) each step produces INLINE via `producesFiles: [path]` (each path must also appear in filesToBeCreated/filesToBeModified) \u2014 links the step\u2194file in the SAME call so the ticket_expansion gate passes without a second pass. Every step MUST link \u22651 file and every produced file MUST be linked by \u22651 step (hard gates). `link_step_file` remains for post-hoc edits.", items: { type: "object", properties: { text: { type: "string" }, producesFiles: { type: "array", items: { type: "string" }, description: "Paths this step produces \u2014 each must match an entry in filesToBeCreated/filesToBeModified; links the step\u2194file inline (path-based)." } }, required: ["text"] } },
397
- filesToBeCreated: { type: "array", items: { type: "string" } },
398
- filesToBeModified: { type: "array", items: { type: "string" } },
399
- filesToBeDeleted: { type: "array", items: { type: "string" } },
400
- filesToBeReferenced: { type: "array", items: { type: "string" } },
401
- guardrails: { type: "array", items: { type: "string" } },
402
- testSpecification: { type: "object", properties: { testTypes: { type: "array", items: { type: "string", enum: ["unit", "integration", "e2e", "typecheck", "lint", "build", "contract", "structural", "layout", "a11y", "performance"] } }, qualityGates: { type: "array", items: { type: "string" } }, testCommands: { type: "array", items: { type: "string" } }, coverageTarget: { type: "integer", minimum: 0, maximum: 100 } } },
403
- codeReferences: { type: "array", description: "Existing code to reuse/anchor on.", items: { type: "object", properties: { filePath: { type: "string" }, symbol: { type: "string" }, description: { type: "string" } }, required: ["filePath"] } },
404
- typeReferences: { type: "array", description: "Existing types to use.", items: { type: "object", properties: { filePath: { type: "string" }, typeName: { type: "string" }, description: { type: "string" } }, required: ["filePath", "typeName"] } },
405
- codeSnippets: { type: "array", description: "Concrete code to write. Attach a snippet to its step INLINE via `stepId` (create-and-link); a snippet linking NO step is dangling and blocks the ticket.", items: { type: "object", properties: { language: { type: "string" }, content: { type: "string" }, description: { type: "string" }, stepId: { type: "string", description: "Implementation step id this snippet follows \u2014 links the snippet\u2194step inline." } }, required: ["language", "content"] } },
406
- typeSnippets: { type: "array", description: "Type/interface definitions to write. Attach to a step INLINE via `stepId` (create-and-link); a snippet linking NO step is dangling and blocks the ticket.", items: { type: "object", properties: { language: { type: "string" }, content: { type: "string" }, description: { type: "string" }, stepId: { type: "string", description: "Implementation step id this snippet follows \u2014 links the snippet\u2194step inline." } }, required: ["language", "content"] } },
407
- tags: { type: "array", items: { type: "string" } }
408
- }
409
- }
396
+ type: { const: "ticket_general_actions" },
397
+ ticketId: { type: "string", description: "Ticket id (use list_tickets / lookup_ticket to find)." },
398
+ title: { type: "string", description: "Concise imperative title." },
399
+ description: { type: "string", description: "What this ticket delivers and why." },
400
+ complexity: { type: "string", enum: ["small", "medium", "large", "xlarge"] },
401
+ planningType: { type: "string", enum: ["planning", "on_flight", "review"], description: "Changing this rolls the session back to ticket_decomposition to re-score." },
402
+ ticketType: { type: "string", enum: ["implementation", "verification"], description: "Changing this rolls the session back to ticket_decomposition to re-score." },
403
+ epicId: { type: "string", description: "Re-parent the ticket to another epic." },
404
+ order: { type: "integer", description: "Rank hint within the epic." },
405
+ guardrails: { type: "array", items: { type: "string" }, description: "Per-ticket guardrail ids or descriptions." },
406
+ estimatedMinutes: { type: "integer", minimum: 0 }
410
407
  },
411
- required: ["type", "id", "fields"]
408
+ required: ["type", "ticketId"]
409
+ },
410
+ // ticket_step_actions — batch add/edit/remove/reorder of implementation steps.
411
+ {
412
+ description: "Batch-edit a ticket's implementation steps (add/edit/remove/reorder in one call). A step is a unit of FUNCTIONAL WORK \u2014 describe the functions/components/adjustments it makes AND what each does, never a bare filename. Declare the file(s) each step touches INLINE via `files: [{path, role}]`, role one of creates|modifies|deletes|imports|reads (imports couples to a build/run dependency; reads is a context-only glance). Fields that do not apply are declared with the `justify` op, never by writing empty values here.",
413
+ properties: {
414
+ type: { const: "ticket_step_actions" },
415
+ ticketId: { type: "string", description: "Ticket id (use list_tickets / lookup_ticket to find)." },
416
+ add: { type: "array", description: "New steps to append.", items: { type: "object", properties: { text: { type: "string" }, files: { type: "array", description: "Files this step touches, by role \u2014 derives the step\u2194file link + the TicketFileChange row.", items: { type: "object", properties: { path: { type: "string" }, role: { type: "string", enum: ["creates", "modifies", "deletes", "imports", "reads"] }, symbol: { type: "string" }, why: { type: "string" } }, required: ["path", "role"] } } }, required: ["text"] } },
417
+ edit: { type: "array", description: "Existing steps to edit (by stepId).", items: { type: "object", properties: { stepId: { type: "string" }, text: { type: "string" }, files: { type: "array", items: { type: "object", properties: { path: { type: "string" }, role: { type: "string", enum: ["creates", "modifies", "deletes", "imports", "reads"] }, symbol: { type: "string" }, why: { type: "string" } }, required: ["path", "role"] } } }, required: ["stepId"] } },
418
+ remove: { type: "array", items: { type: "string" }, description: "Step ids to remove." },
419
+ reorder: { type: "array", items: { type: "string" }, description: "Step ids in the desired order." }
420
+ },
421
+ required: ["type", "ticketId"]
422
+ },
423
+ // ticket_criteria_actions — batch add/edit/remove/reorder of acceptance criteria.
424
+ {
425
+ description: "Batch-edit a ticket's acceptance criteria (given/when/then; add/edit/remove/reorder in one call). Fields that do not apply are declared with the `justify` op, never by writing empty values here.",
426
+ properties: {
427
+ type: { const: "ticket_criteria_actions" },
428
+ ticketId: { type: "string", description: "Ticket id (use list_tickets / lookup_ticket to find)." },
429
+ add: { type: "array", description: "New acceptance criteria to append.", items: { type: "object", properties: { given: { type: "string" }, when: { type: "string" }, then: { type: "string" } }, required: ["given", "when", "then"] } },
430
+ edit: { type: "array", description: "Existing criteria to edit (by criterionId).", items: { type: "object", properties: { criterionId: { type: "string" }, given: { type: "string" }, when: { type: "string" }, then: { type: "string" } }, required: ["criterionId"] } },
431
+ remove: { type: "array", items: { type: "string" }, description: "Criterion ids to remove." },
432
+ reorder: { type: "array", items: { type: "string" }, description: "Criterion ids in the desired order." }
433
+ },
434
+ required: ["type", "ticketId"]
435
+ },
436
+ // ticket_test_actions — author the existing single-object testSpecification.
437
+ {
438
+ description: "Author a ticket's testSpecification (testTypes, qualityGates, testCommands, coverageTarget). Fields that do not apply are declared with the `justify` op, never by writing empty values here.",
439
+ properties: {
440
+ type: { const: "ticket_test_actions" },
441
+ ticketId: { type: "string", description: "Ticket id (use list_tickets / lookup_ticket to find)." },
442
+ testSpecification: { type: "object", properties: { testTypes: { type: "array", items: { type: "string", enum: ["unit", "integration", "e2e", "typecheck", "lint", "build", "contract", "structural", "layout", "a11y", "performance"] } }, qualityGates: { type: "array", items: { type: "string" } }, testCommands: { type: "array", items: { type: "string" } }, coverageTarget: { type: "integer", minimum: 0, maximum: 100 } } }
443
+ },
444
+ required: ["type", "ticketId", "testSpecification"]
412
445
  },
413
446
  {
414
447
  properties: {
@@ -469,7 +502,7 @@ Format options:
469
502
  type: "object",
470
503
  properties: {
471
504
  path: { type: "string", description: "The orphan shared file path to resolve." },
472
- kind: { type: "string", enum: ["toBeCreated", "toBeModified", "toBeDeleted", "toBeReferenced"], description: "The target file-change kind on the elected ticket (normally toBeCreated)." },
505
+ kind: { type: "string", enum: ["creates", "modifies", "deletes", "imports", "reads"], description: "The step-file role the elected ticket takes for this path (normally creates)." },
473
506
  creatorTicketId: { type: "string", description: "The elected creator ticket (topologically-earliest toucher)." },
474
507
  producingStep: {
475
508
  type: "object",
@@ -654,7 +687,7 @@ Format options:
654
687
  name: "action_work_session",
655
688
  description: `Update checklist state during an active WorkSession. Combines step completion, AC validation, test result reporting, file tracking, reference review confirmation, and discovery reporting into a single atomic operation. All state changes are recorded on the WorkSession and its related validation/completion records.
656
689
 
657
- Use this instead of calling update_ticket for checklist changes. Provides:
690
+ Use this instead of reopening the planning session for checklist changes. Provides:
658
691
  - Step completion (individual or bulk via WorkSessionImplStepCompletion)
659
692
  - Acceptance criteria validation (individual or bulk via WorkSessionAcceptanceCheck)
660
693
  - Test result reporting (merged by test type via WorkSessionTestResult)
@@ -704,125 +737,6 @@ Set getTicket: true to fetch full ticket details in the response \u2014 useful f
704
737
  },
705
738
  required: ["action"]
706
739
  },
707
- steps: {
708
- type: "array",
709
- description: "Individual step completion updates",
710
- items: {
711
- type: "object",
712
- properties: {
713
- index: {
714
- type: "number",
715
- description: "Zero-based index of the step among the ticket's implementation steps (TicketImplementationStep rows, ordered by `order`)"
716
- },
717
- completed: {
718
- type: "boolean",
719
- description: "Whether the step is completed"
720
- },
721
- notes: {
722
- type: "string",
723
- description: "Optional note about this step"
724
- }
725
- },
726
- required: ["index", "completed"]
727
- }
728
- },
729
- allStepsDone: {
730
- type: "boolean",
731
- description: "Shortcut: mark all steps as completed"
732
- },
733
- acceptanceCriteria: {
734
- type: "array",
735
- description: "Individual AC validation updates",
736
- items: {
737
- type: "object",
738
- properties: {
739
- index: {
740
- type: "number",
741
- description: "Zero-based index of the AC in the acceptanceCriteria array"
742
- },
743
- validated: {
744
- type: "boolean",
745
- description: "Whether the AC is validated"
746
- },
747
- notes: {
748
- type: "string",
749
- description: "Optional note about this AC"
750
- }
751
- },
752
- required: ["index", "validated"]
753
- }
754
- },
755
- allACValidated: {
756
- type: "boolean",
757
- description: "Shortcut: mark all acceptance criteria as validated"
758
- },
759
- testResults: {
760
- type: "array",
761
- description: "Test result reports to append (merged by testType)",
762
- items: {
763
- type: "object",
764
- properties: {
765
- testType: {
766
- type: "string",
767
- description: 'Type of test (e.g., "unit", "integration", "e2e", "lint", "typeCheck")'
768
- },
769
- passed: {
770
- type: "number",
771
- description: "Number of tests that passed"
772
- },
773
- failed: {
774
- type: "number",
775
- description: "Number of tests that failed"
776
- },
777
- skipped: {
778
- type: "number",
779
- description: "Number of tests skipped"
780
- },
781
- command: {
782
- type: "string",
783
- description: "Command used to run the tests"
784
- },
785
- output: {
786
- type: "string",
787
- description: "Test output (truncated if needed)"
788
- },
789
- duration: {
790
- type: "number",
791
- description: "Duration in milliseconds"
792
- },
793
- suites: {
794
- type: "array",
795
- description: "Optional suite-level breakdown",
796
- items: {
797
- type: "object",
798
- properties: {
799
- name: { type: "string", description: "Suite name" },
800
- passed: { type: "number", description: "Passed tests in suite" },
801
- failed: { type: "number", description: "Failed tests in suite" },
802
- skipped: { type: "number", description: "Skipped tests in suite" },
803
- duration: { type: "number", description: "Suite duration in ms" }
804
- },
805
- required: ["name", "passed", "failed"]
806
- }
807
- },
808
- tests: {
809
- type: "array",
810
- description: "Optional individual test breakdown",
811
- items: {
812
- type: "object",
813
- properties: {
814
- name: { type: "string", description: "Test name" },
815
- suite: { type: "string", description: "Parent suite name" },
816
- status: { type: "string", enum: ["passed", "failed", "skipped"], description: "Test result" },
817
- duration: { type: "number", description: "Test duration in ms" }
818
- },
819
- required: ["name", "status"]
820
- }
821
- }
822
- },
823
- required: ["testType", "passed", "failed"]
824
- }
825
- },
826
740
  notes: {
827
741
  type: "string",
828
742
  description: "Additional notes to append to the ticket"