@specforge/canary-cli 0.1.17 → 0.2.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.
Files changed (35) hide show
  1. package/dist/cli/commands/debug/register.js +1 -1
  2. package/dist/cli/commands/debug/register.js.map +1 -1
  3. package/dist/cli/commands/debug/types.d.ts.map +1 -1
  4. package/dist/cli/commands/debug/types.js +4 -2
  5. package/dist/cli/commands/debug/types.js.map +1 -1
  6. package/dist/cli/templates/agents/content/core/sfag-spec-creator.d.ts.map +1 -1
  7. package/dist/cli/templates/agents/content/core/sfag-spec-creator.js +40 -35
  8. package/dist/cli/templates/agents/content/core/sfag-spec-creator.js.map +1 -1
  9. package/dist/cli/templates/content/sf-commit.d.ts +1 -1
  10. package/dist/cli/templates/content/sf-commit.d.ts.map +1 -1
  11. package/dist/cli/templates/content/sf-commit.js +2 -2
  12. package/dist/cli/templates/content/sf-commit.js.map +1 -1
  13. package/dist/lib/workflow-definitions.js +2 -2
  14. package/dist/lib/workflow-definitions.js.map +1 -1
  15. package/dist/tools/index.d.ts.map +1 -1
  16. package/dist/tools/index.js +69 -36
  17. package/dist/tools/index.js.map +1 -1
  18. package/node_modules/@specforge/session-types/dist/runtime/lifecycle-contract.d.ts +5 -1
  19. package/node_modules/@specforge/session-types/dist/runtime/lifecycle-contract.d.ts.map +1 -1
  20. package/node_modules/@specforge/session-types/dist/runtime/planning-operations.d.ts +2 -2
  21. package/node_modules/@specforge/session-types/dist/runtime/planning-operations.d.ts.map +1 -1
  22. package/node_modules/@specforge/session-types/dist/runtime/planning-operations.js +18 -1
  23. package/node_modules/@specforge/session-types/dist/runtime/planning-operations.js.map +1 -1
  24. package/node_modules/@specforge/session-types/dist/runtime/planning-session-action.d.ts +3 -3
  25. package/node_modules/@specforge/session-types/dist/runtime/planning-session-action.d.ts.map +1 -1
  26. package/node_modules/@specforge/session-types/dist/runtime/planning-session-action.js +6 -1
  27. package/node_modules/@specforge/session-types/dist/runtime/planning-session-action.js.map +1 -1
  28. package/node_modules/@specforge/session-types/dist/runtime/planning-session-aggregate.d.ts +10 -0
  29. package/node_modules/@specforge/session-types/dist/runtime/planning-session-aggregate.d.ts.map +1 -1
  30. package/node_modules/@specforge/session-types/dist/runtime/planning-session-aggregate.js +8 -0
  31. package/node_modules/@specforge/session-types/dist/runtime/planning-session-aggregate.js.map +1 -1
  32. package/node_modules/@specforge/session-types/package.json +1 -1
  33. package/package.json +5 -5
  34. package/src/cli/templates/agents/content/core/sfag-spec-creator.ts +40 -35
  35. package/src/cli/templates/content/sf-commit.ts +2 -2
@@ -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",
@@ -638,7 +671,7 @@ Format options:
638
671
  },
639
672
  {
640
673
  name: "start_work_session",
641
- description: "Start working on a ticket. Returns full ticket details (description, implementation steps, AC, technicalDetails, codeReferences, typeReferences, tags, notes, complexity, priority) alongside checklistState and workSessionId. No need to call get_ticket separately. Returns error with statusReason if ticket is pending.",
674
+ description: "Start working on a ticket. Returns full ticket details (description, implementation steps, AC, technicalDetails, codeReferences, typeReferences, tags, notes, complexity, priority) alongside checklistState and workSessionId. No need to call the `get` tool (type:'ticket') separately. Returns error with statusReason if ticket is pending.",
642
675
  inputSchema: {
643
676
  type: "object",
644
677
  properties: {
@@ -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)
@@ -1050,7 +1083,7 @@ Set getTicket: true to fetch full ticket details in the response \u2014 useful f
1050
1083
  },
1051
1084
  {
1052
1085
  name: "reopen_specification",
1053
- description: 'Reopen a specification in "ready" status, regressing to "planning". After reopening, call start_planning_session to begin a new planning session.',
1086
+ description: 'Reopen a specification in "ready" status, regressing to "planning". Use when action_planning_session reports the spec is no longer in planning. After reopening, call start_planning_session to begin a new planning session.',
1054
1087
  inputSchema: {
1055
1088
  type: "object",
1056
1089
  properties: {