@pennyfarthing/core 7.4.1 → 7.6.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 (127) hide show
  1. package/package.json +1 -1
  2. package/packages/core/dist/cli/commands/doctor-legacy.test.d.ts +13 -0
  3. package/packages/core/dist/cli/commands/doctor-legacy.test.d.ts.map +1 -0
  4. package/packages/core/dist/cli/commands/doctor-legacy.test.js +207 -0
  5. package/packages/core/dist/cli/commands/doctor-legacy.test.js.map +1 -0
  6. package/packages/core/dist/cli/commands/doctor.d.ts +16 -0
  7. package/packages/core/dist/cli/commands/doctor.d.ts.map +1 -1
  8. package/packages/core/dist/cli/commands/doctor.js +130 -2
  9. package/packages/core/dist/cli/commands/doctor.js.map +1 -1
  10. package/packages/core/dist/cli/commands/init.d.ts.map +1 -1
  11. package/packages/core/dist/cli/commands/init.js +17 -27
  12. package/packages/core/dist/cli/commands/init.js.map +1 -1
  13. package/packages/core/dist/cli/commands/update.d.ts.map +1 -1
  14. package/packages/core/dist/cli/commands/update.js +21 -52
  15. package/packages/core/dist/cli/commands/update.js.map +1 -1
  16. package/packages/core/dist/cli/utils/symlinks.d.ts +15 -0
  17. package/packages/core/dist/cli/utils/symlinks.d.ts.map +1 -1
  18. package/packages/core/dist/cli/utils/symlinks.js +148 -2
  19. package/packages/core/dist/cli/utils/symlinks.js.map +1 -1
  20. package/packages/core/dist/cli/utils/themes.d.ts.map +1 -1
  21. package/packages/core/dist/cli/utils/themes.js +9 -0
  22. package/packages/core/dist/cli/utils/themes.js.map +1 -1
  23. package/pennyfarthing-dist/agents/dev.md +29 -24
  24. package/pennyfarthing-dist/agents/handoff.md +42 -119
  25. package/pennyfarthing-dist/agents/reviewer.md +32 -37
  26. package/pennyfarthing-dist/agents/sm-handoff.md +43 -66
  27. package/pennyfarthing-dist/agents/sm.md +52 -35
  28. package/pennyfarthing-dist/agents/tea.md +25 -8
  29. package/pennyfarthing-dist/agents/testing-runner.md +4 -4
  30. package/pennyfarthing-dist/commands/architect.md +0 -55
  31. package/pennyfarthing-dist/commands/dev.md +1 -54
  32. package/pennyfarthing-dist/commands/devops.md +0 -52
  33. package/pennyfarthing-dist/commands/health-check.md +33 -0
  34. package/pennyfarthing-dist/commands/orchestrator.md +0 -49
  35. package/pennyfarthing-dist/commands/pm.md +0 -53
  36. package/pennyfarthing-dist/commands/reviewer.md +1 -58
  37. package/pennyfarthing-dist/commands/sm.md +1 -64
  38. package/pennyfarthing-dist/commands/sprint.md +133 -0
  39. package/pennyfarthing-dist/commands/standalone.md +194 -0
  40. package/pennyfarthing-dist/commands/tea.md +1 -57
  41. package/pennyfarthing-dist/commands/tech-writer.md +0 -46
  42. package/pennyfarthing-dist/commands/theme-maker.md +10 -5
  43. package/pennyfarthing-dist/commands/ux-designer.md +0 -55
  44. package/pennyfarthing-dist/guides/XML-TAGS.md +156 -0
  45. package/pennyfarthing-dist/guides/agent-behavior.md +64 -38
  46. package/pennyfarthing-dist/guides/measurement-framework.md +210 -0
  47. package/pennyfarthing-dist/personas/themes/a-team.yaml +130 -0
  48. package/pennyfarthing-dist/personas/themes/alice-in-wonderland.yaml +1 -1
  49. package/pennyfarthing-dist/personas/themes/ancient-strategists.yaml +1 -1
  50. package/pennyfarthing-dist/personas/themes/arcane.yaml +1 -1
  51. package/pennyfarthing-dist/personas/themes/better-call-saul.yaml +1 -1
  52. package/pennyfarthing-dist/personas/themes/big-lebowski.yaml +1 -1
  53. package/pennyfarthing-dist/personas/themes/black-sails.yaml +1 -1
  54. package/pennyfarthing-dist/personas/themes/blade-runner.yaml +1 -1
  55. package/pennyfarthing-dist/personas/themes/bobiverse.yaml +1 -1
  56. package/pennyfarthing-dist/personas/themes/breaking-bad.yaml +1 -1
  57. package/pennyfarthing-dist/personas/themes/count-of-monte-cristo.yaml +1 -1
  58. package/pennyfarthing-dist/personas/themes/cowboy-bebop.yaml +1 -1
  59. package/pennyfarthing-dist/personas/themes/deadwood.yaml +1 -1
  60. package/pennyfarthing-dist/personas/themes/dickens.yaml +1 -1
  61. package/pennyfarthing-dist/personas/themes/discworld.yaml +1 -1
  62. package/pennyfarthing-dist/personas/themes/doctor-who.yaml +1 -1
  63. package/pennyfarthing-dist/personas/themes/don-quixote.yaml +1 -1
  64. package/pennyfarthing-dist/personas/themes/dune.yaml +1 -1
  65. package/pennyfarthing-dist/personas/themes/enlightenment-thinkers.yaml +1 -1
  66. package/pennyfarthing-dist/personas/themes/expeditionary-force.yaml +1 -1
  67. package/pennyfarthing-dist/personas/themes/futurama.yaml +1 -1
  68. package/pennyfarthing-dist/personas/themes/game-of-thrones.yaml +1 -1
  69. package/pennyfarthing-dist/personas/themes/gilligans-island.yaml +131 -1
  70. package/pennyfarthing-dist/personas/themes/gothic-literature.yaml +1 -1
  71. package/pennyfarthing-dist/personas/themes/great-gatsby.yaml +1 -1
  72. package/pennyfarthing-dist/personas/themes/hannibal.yaml +1 -1
  73. package/pennyfarthing-dist/personas/themes/harry-potter.yaml +1 -1
  74. package/pennyfarthing-dist/personas/themes/his-dark-materials.yaml +1 -1
  75. package/pennyfarthing-dist/personas/themes/inspector-morse.yaml +1 -1
  76. package/pennyfarthing-dist/personas/themes/jane-austen.yaml +1 -1
  77. package/pennyfarthing-dist/personas/themes/legion-of-doom.yaml +130 -0
  78. package/pennyfarthing-dist/personas/themes/mad-max.yaml +1 -1
  79. package/pennyfarthing-dist/personas/themes/moby-dick.yaml +1 -1
  80. package/pennyfarthing-dist/personas/themes/neuromancer.yaml +1 -1
  81. package/pennyfarthing-dist/personas/themes/parks-and-rec.yaml +130 -0
  82. package/pennyfarthing-dist/personas/themes/princess-bride.yaml +130 -0
  83. package/pennyfarthing-dist/personas/themes/renaissance-masters.yaml +1 -1
  84. package/pennyfarthing-dist/personas/themes/russian-masters.yaml +1 -1
  85. package/pennyfarthing-dist/personas/themes/sandman.yaml +1 -1
  86. package/pennyfarthing-dist/personas/themes/scientific-revolutionaries.yaml +1 -1
  87. package/pennyfarthing-dist/personas/themes/shakespeare.yaml +1 -1
  88. package/pennyfarthing-dist/personas/themes/star-trek-tng.yaml +139 -3
  89. package/pennyfarthing-dist/personas/themes/star-trek-tos.yaml +124 -0
  90. package/pennyfarthing-dist/personas/themes/star-wars.yaml +1 -1
  91. package/pennyfarthing-dist/personas/themes/succession.yaml +1 -1
  92. package/pennyfarthing-dist/personas/themes/superfriends.yaml +131 -1
  93. package/pennyfarthing-dist/personas/themes/ted-lasso.yaml +131 -1
  94. package/pennyfarthing-dist/personas/themes/the-americans.yaml +1 -1
  95. package/pennyfarthing-dist/personas/themes/the-expanse.yaml +131 -1
  96. package/pennyfarthing-dist/personas/themes/the-good-place.yaml +1 -1
  97. package/pennyfarthing-dist/personas/themes/the-matrix.yaml +1 -1
  98. package/pennyfarthing-dist/personas/themes/the-sopranos.yaml +1 -1
  99. package/pennyfarthing-dist/personas/themes/west-wing.yaml +6 -6
  100. package/pennyfarthing-dist/personas/themes/world-explorers.yaml +1 -1
  101. package/pennyfarthing-dist/personas/themes/wwii-leaders.yaml +1 -1
  102. package/pennyfarthing-dist/scripts/core/check-context.sh +23 -6
  103. package/pennyfarthing-dist/scripts/core/phase-check-start.sh +95 -0
  104. package/pennyfarthing-dist/scripts/git/release.sh +3 -2
  105. package/pennyfarthing-dist/scripts/health/drift-detection.sh +162 -0
  106. package/pennyfarthing-dist/scripts/hooks/bell-mode-hook.sh +87 -0
  107. package/pennyfarthing-dist/scripts/jira/create-jira-epic.sh +1 -1
  108. package/pennyfarthing-dist/scripts/misc/deploy.sh +1 -1
  109. package/pennyfarthing-dist/scripts/misc/statusline.sh +25 -32
  110. package/pennyfarthing-dist/scripts/sprint/import-epic-to-future.mjs +377 -0
  111. package/pennyfarthing-dist/scripts/sprint/import-epic-to-future.sh +9 -0
  112. package/pennyfarthing-dist/scripts/theme/compute-theme-tiers.js +492 -0
  113. package/pennyfarthing-dist/scripts/theme/compute-theme-tiers.sh +8 -200
  114. package/pennyfarthing-dist/scripts/workflow/list-workflows.sh +38 -5
  115. package/pennyfarthing-dist/scripts/workflow/phase-owner.sh +40 -0
  116. package/pennyfarthing-dist/skills/theme-creation/SKILL.md +12 -7
  117. package/pennyfarthing-dist/workflows/epics-and-stories/steps/step-04-final-validation.md +11 -3
  118. package/pennyfarthing-dist/workflows/epics-and-stories/steps/step-05-import-to-future.md +122 -0
  119. package/pennyfarthing-dist/workflows/epics-and-stories/workflow.yaml +3 -2
  120. package/packages/core/dist/workflow/generic-handoff.d.ts +0 -281
  121. package/packages/core/dist/workflow/generic-handoff.d.ts.map +0 -1
  122. package/packages/core/dist/workflow/generic-handoff.js +0 -411
  123. package/packages/core/dist/workflow/generic-handoff.js.map +0 -1
  124. package/packages/core/dist/workflow/generic-handoff.test.d.ts +0 -21
  125. package/packages/core/dist/workflow/generic-handoff.test.d.ts.map +0 -1
  126. package/packages/core/dist/workflow/generic-handoff.test.js +0 -499
  127. package/packages/core/dist/workflow/generic-handoff.test.js.map +0 -1
@@ -1,411 +0,0 @@
1
- /**
2
- * Generic Workflow-Driven Handoff
3
- *
4
- * Replaces hardcoded handoff files with workflow-driven logic.
5
- * Reads phase requirements from workflow definitions.
6
- *
7
- * Provides functions to:
8
- * - Find current phase in a workflow
9
- * - Determine next phase (forward or rejection loop)
10
- * - Check gate conditions based on gate type
11
- * - Format session file updates for phase transitions
12
- */
13
- import { existsSync, readFileSync } from 'fs';
14
- /**
15
- * Find a phase by name in a workflow definition
16
- *
17
- * @param workflow - The workflow definition to search
18
- * @param phaseName - Name of the phase to find
19
- * @returns The phase definition or null if not found
20
- *
21
- * @example
22
- * ```typescript
23
- * const phase = findCurrentPhase(workflow, 'red');
24
- * if (phase) {
25
- * console.log(`Found phase: ${phase.name}, agent: ${phase.agent}`);
26
- * }
27
- * ```
28
- */
29
- export function findCurrentPhase(workflow, phaseName) {
30
- if (!workflow.phases) {
31
- return null;
32
- }
33
- return workflow.phases.find(phase => phase.name === phaseName) ?? null;
34
- }
35
- /**
36
- * Get the next phase in the workflow
37
- *
38
- * For normal progression, returns the next phase in sequence.
39
- * For rejection (verdict='rejected'), returns the phase to loop back to
40
- * (typically the most recent phase with a tests_pass gate).
41
- *
42
- * @param workflow - The workflow definition
43
- * @param currentPhaseName - Name of the current phase
44
- * @param options - Options for handling rejection loops
45
- * @returns The next phase or null if at end/not found
46
- *
47
- * @example
48
- * ```typescript
49
- * // Normal progression
50
- * const next = getNextPhase(workflow, 'red');
51
- *
52
- * // Rejection loop
53
- * const next = getNextPhase(workflow, 'review', { verdict: 'rejected' });
54
- * ```
55
- */
56
- export function getNextPhase(workflow, currentPhaseName, options) {
57
- if (!workflow.phases) {
58
- return null;
59
- }
60
- const currentIndex = workflow.phases.findIndex(phase => phase.name === currentPhaseName);
61
- if (currentIndex === -1) {
62
- return null;
63
- }
64
- // Handle rejection: loop back to previous phase with tests_pass gate
65
- if (options?.verdict === 'rejected') {
66
- // Search backwards for a phase with tests_pass gate
67
- for (let i = currentIndex - 1; i >= 0; i--) {
68
- const phase = workflow.phases[i];
69
- if (phase.gate?.type === 'tests_pass') {
70
- return phase;
71
- }
72
- }
73
- // Fallback: return the phase immediately before current
74
- if (currentIndex > 0) {
75
- return workflow.phases[currentIndex - 1];
76
- }
77
- return null;
78
- }
79
- // Forward progression: return next phase in sequence
80
- if (currentIndex < workflow.phases.length - 1) {
81
- return workflow.phases[currentIndex + 1];
82
- }
83
- // At final phase - no next
84
- return null;
85
- }
86
- /**
87
- * Check if a gate condition is satisfied
88
- *
89
- * Gate types:
90
- * - tests_fail: testsRed must be true
91
- * - tests_pass: testsGreen must be true
92
- * - approval: verdict must be provided (approved or rejected)
93
- * - manual: always passes
94
- * - (none): always passes
95
- *
96
- * @param workflow - The workflow definition
97
- * @param phaseName - Name of the phase to check
98
- * @param context - Gate check context with test results, verdicts, etc.
99
- * @returns Gate check result
100
- *
101
- * @example
102
- * ```typescript
103
- * const result = checkGate(workflow, 'red', { testsRed: true });
104
- * if (result.passed) {
105
- * // Proceed with handoff
106
- * }
107
- * ```
108
- */
109
- export function checkGate(workflow, phaseName, context) {
110
- const phase = findCurrentPhase(workflow, phaseName);
111
- if (!phase) {
112
- return {
113
- passed: false,
114
- message: `Phase "${phaseName}" not found in workflow`
115
- };
116
- }
117
- // No gate defined - always passes
118
- if (!phase.gate) {
119
- return { passed: true };
120
- }
121
- const gateType = phase.gate.type;
122
- switch (gateType) {
123
- case 'tests_fail':
124
- // RED phase: tests must be failing
125
- if (context.testsRed === true) {
126
- return { passed: true, gateType };
127
- }
128
- return {
129
- passed: false,
130
- gateType,
131
- message: 'Tests must be failing (RED) to proceed from this phase'
132
- };
133
- case 'tests_pass':
134
- // GREEN phase: tests must be passing
135
- if (context.testsGreen === true) {
136
- return { passed: true, gateType };
137
- }
138
- return {
139
- passed: false,
140
- gateType,
141
- message: `Tests must be passing (GREEN) to proceed. Currently ${context.testFailCount ?? 0} failing.`
142
- };
143
- case 'approval':
144
- // Review phase: verdict must be provided
145
- if (context.verdict === 'approved' || context.verdict === 'rejected') {
146
- return { passed: true, gateType };
147
- }
148
- return {
149
- passed: false,
150
- gateType,
151
- message: 'Verdict (approved or rejected) is required to proceed from this phase'
152
- };
153
- case 'manual':
154
- // Manual gate: always passes
155
- return { passed: true, gateType };
156
- default:
157
- // Unknown gate type - treat as manual (pass)
158
- return { passed: true, gateType };
159
- }
160
- }
161
- /**
162
- * Format the workflow tracking section for a session file update
163
- *
164
- * @param params - Phase transition parameters
165
- * @returns Markdown string for the workflow tracking section
166
- *
167
- * @example
168
- * ```typescript
169
- * const markdown = formatPhaseTransition({
170
- * workflowName: 'tdd',
171
- * fromPhase: 'red',
172
- * toPhase: 'green',
173
- * startedAt: '2026-01-13T14:00:00Z',
174
- * endedAt: '2026-01-13T14:30:00Z'
175
- * });
176
- * ```
177
- */
178
- export function formatPhaseTransition(params) {
179
- const { workflowName, fromPhase, toPhase, startedAt, endedAt } = params;
180
- const duration = calculateDuration(startedAt, endedAt);
181
- const now = new Date().toISOString();
182
- // Build markdown for the workflow tracking section
183
- const lines = [
184
- `**Workflow:** ${workflowName}`,
185
- `**Phase:** ${toPhase}`,
186
- `**Phase Started:** ${now}`,
187
- '',
188
- '### Phase History',
189
- '| Phase | Started | Ended | Duration |',
190
- '|-------|---------|-------|----------|',
191
- `| ${fromPhase} | ${startedAt} | ${endedAt} | ${duration} |`
192
- ];
193
- return lines.join('\n');
194
- }
195
- /**
196
- * Calculate duration between two ISO 8601 timestamps
197
- *
198
- * @param startedAt - Start timestamp
199
- * @param endedAt - End timestamp
200
- * @returns Formatted duration string (e.g., "30m", "2h 30m", "45s")
201
- */
202
- export function calculateDuration(startedAt, endedAt) {
203
- const start = new Date(startedAt);
204
- const end = new Date(endedAt);
205
- // Handle invalid timestamps
206
- if (isNaN(start.getTime()) || isNaN(end.getTime())) {
207
- return '0m';
208
- }
209
- const diffMs = Math.abs(end.getTime() - start.getTime());
210
- const diffSeconds = Math.floor(diffMs / 1000);
211
- const diffMinutes = Math.floor(diffSeconds / 60);
212
- const diffHours = Math.floor(diffMinutes / 60);
213
- // Format based on duration length
214
- if (diffSeconds < 60) {
215
- return `${diffSeconds}s`;
216
- }
217
- if (diffHours === 0) {
218
- return `${diffMinutes}m`;
219
- }
220
- const remainingMinutes = diffMinutes % 60;
221
- if (remainingMinutes === 0) {
222
- return `${diffHours}h`;
223
- }
224
- return `${diffHours}h ${remainingMinutes}m`;
225
- }
226
- /**
227
- * Read handoff mode from Cyclist settings file
228
- * Returns 'manual' as default if file doesn't exist or is invalid
229
- *
230
- * @param settingsPath - Path to the settings file (JSON or YAML)
231
- * @returns The handoff mode setting
232
- */
233
- export function readHandoffMode(settingsPath) {
234
- try {
235
- if (!existsSync(settingsPath)) {
236
- return 'manual';
237
- }
238
- const content = readFileSync(settingsPath, 'utf-8');
239
- // Try JSON first, then YAML
240
- if (settingsPath.endsWith('.json') || content.trim().startsWith('{')) {
241
- return parseHandoffModeFromJson(content);
242
- }
243
- else {
244
- return parseHandoffModeFromYaml(content);
245
- }
246
- }
247
- catch {
248
- return 'manual';
249
- }
250
- }
251
- /**
252
- * Parse handoff mode from JSON string
253
- * Handles both new format (handoff_mode) and legacy format (auto_handoff boolean)
254
- *
255
- * @param jsonContent - JSON string containing settings
256
- * @returns The handoff mode setting
257
- */
258
- export function parseHandoffModeFromJson(jsonContent) {
259
- try {
260
- const parsed = JSON.parse(jsonContent);
261
- const workflow = parsed?.workflow;
262
- if (!workflow) {
263
- return 'manual';
264
- }
265
- // New format: handoff_mode
266
- if (workflow.handoff_mode === 'auto' || workflow.handoff_mode === 'manual') {
267
- return workflow.handoff_mode;
268
- }
269
- // Legacy format: auto_handoff boolean
270
- if ('auto_handoff' in workflow) {
271
- return workflow.auto_handoff === true ? 'auto' : 'manual';
272
- }
273
- return 'manual';
274
- }
275
- catch {
276
- return 'manual';
277
- }
278
- }
279
- /**
280
- * Parse handoff mode from YAML string
281
- * Handles both new format (handoff_mode) and legacy format (auto_handoff boolean)
282
- *
283
- * @param yamlContent - YAML string containing settings
284
- * @returns The handoff mode setting
285
- */
286
- export function parseHandoffModeFromYaml(yamlContent) {
287
- try {
288
- // Simple YAML parsing for handoff_mode - look for the pattern
289
- // workflow:
290
- // handoff_mode: auto|manual
291
- const lines = yamlContent.split('\n');
292
- let inWorkflow = false;
293
- for (const line of lines) {
294
- const trimmed = line.trim();
295
- if (trimmed === 'workflow:') {
296
- inWorkflow = true;
297
- continue;
298
- }
299
- if (inWorkflow) {
300
- // Check for new format
301
- const modeMatch = trimmed.match(/^handoff_mode:\s*['"]?(auto|manual)['"]?$/);
302
- if (modeMatch) {
303
- return modeMatch[1];
304
- }
305
- // Check for legacy format
306
- const autoMatch = trimmed.match(/^auto_handoff:\s*(true|false)$/i);
307
- if (autoMatch) {
308
- return autoMatch[1].toLowerCase() === 'true' ? 'auto' : 'manual';
309
- }
310
- // Exit workflow section when we hit a non-indented line
311
- if (!line.startsWith(' ') && !line.startsWith('\t') && trimmed !== '') {
312
- inWorkflow = false;
313
- }
314
- }
315
- }
316
- return 'manual';
317
- }
318
- catch {
319
- return 'manual';
320
- }
321
- }
322
- /**
323
- * Get handoff behavior based on mode
324
- *
325
- * @param mode - The handoff mode setting
326
- * @returns Behavior configuration for the mode
327
- */
328
- export function getHandoffBehavior(mode) {
329
- if (mode === 'auto') {
330
- return {
331
- action: 'immediate',
332
- requiresConfirmation: false,
333
- };
334
- }
335
- return {
336
- action: 'prompt',
337
- requiresConfirmation: true,
338
- message: 'Ready for handoff. Confirm to proceed to next agent.',
339
- };
340
- }
341
- /**
342
- * Format handoff history entry for session file
343
- * Creates a markdown section with table row for the handoff
344
- *
345
- * @param entry - Handoff history entry to format
346
- * @returns Markdown string for the handoff history section
347
- */
348
- export function formatHandoffHistory(entry) {
349
- const lines = [
350
- '## Handoff History',
351
- '',
352
- '| Phase | Agent | Timestamp | Mode |',
353
- '|-------|-------|-----------|------|',
354
- `| ${entry.phase} | ${entry.agent} | ${entry.timestamp} | ${entry.handoffMode} |`,
355
- ];
356
- return lines.join('\n');
357
- }
358
- // =============================================================================
359
- // Context Clear Signal (Story MSSCI-11840)
360
- // =============================================================================
361
- /**
362
- * Threshold for context percentage to trigger context clear
363
- * When auto mode is enabled and context exceeds this threshold, emit CONTEXT_CLEAR
364
- */
365
- export const CONTEXT_CLEAR_THRESHOLD = 60;
366
- /**
367
- * Determine if CONTEXT_CLEAR marker should be emitted
368
- *
369
- * Returns true when:
370
- * - handoffMode is 'auto'
371
- * - contextPercent exceeds CONTEXT_CLEAR_THRESHOLD
372
- *
373
- * @param params - Context clear parameters
374
- * @returns true if CONTEXT_CLEAR should be emitted
375
- */
376
- export function shouldEmitContextClear(params) {
377
- return params.handoffMode === 'auto' && params.contextPercent > CONTEXT_CLEAR_THRESHOLD;
378
- }
379
- /**
380
- * Format the CYCLIST marker for context clear or regular handoff
381
- *
382
- * When auto mode and high context: returns CONTEXT_CLEAR marker
383
- * Otherwise: returns regular HANDOFF marker
384
- *
385
- * @param params - Context clear parameters including nextAgent
386
- * @returns Marker string (<!-- CYCLIST:CONTEXT_CLEAR:/agent --> or <!-- CYCLIST:HANDOFF:/agent -->)
387
- */
388
- export function formatContextClearMarker(params) {
389
- const { nextAgent = '/dev' } = params;
390
- if (shouldEmitContextClear(params)) {
391
- return `<!-- CYCLIST:CONTEXT_CLEAR:${nextAgent} -->`;
392
- }
393
- return `<!-- CYCLIST:HANDOFF:${nextAgent} -->`;
394
- }
395
- /**
396
- * Format a human-readable output message for context clear handoffs
397
- *
398
- * Includes context percentage and the marker for Cyclist to detect
399
- *
400
- * @param params - Context clear parameters
401
- * @returns Formatted output string for display
402
- */
403
- export function formatContextClearOutput(params) {
404
- const { contextPercent, nextAgent = '/dev' } = params;
405
- const marker = formatContextClearMarker(params);
406
- if (shouldEmitContextClear(params)) {
407
- return `Context at ${contextPercent}% - emitting CONTEXT_CLEAR for automatic session clear and reload.\n\n${marker}`;
408
- }
409
- return `Handoff to ${nextAgent}\n\n${marker}`;
410
- }
411
- //# sourceMappingURL=generic-handoff.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"generic-handoff.js","sourceRoot":"","sources":["../../src/workflow/generic-handoff.ts"],"names":[],"mappings":"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"}
@@ -1,21 +0,0 @@
1
- /**
2
- * Tests for Story 31-7: Generic Workflow-Driven Handoff Subagent
3
- *
4
- * These tests define the contract for the generic handoff module that
5
- * replaces 5 hardcoded handoff files (sm-handoff, tea-handoff, dev-handoff,
6
- * reviewer-handoff-approve, reviewer-handoff-reject).
7
- *
8
- * The generic handoff reads phase requirements from workflow definitions
9
- * and performs gate checks based on phase gate type.
10
- *
11
- * Test categories:
12
- * 1. findCurrentPhase() - Locate phase by name in workflow
13
- * 2. getNextPhase() - Determine next phase (forward or rejection loop)
14
- * 3. checkGate() - Run gate-specific checks
15
- * 4. formatPhaseTransition() - Format session file updates
16
- * 5. Integration - Full handoff scenarios with TDD/trivial workflows
17
- *
18
- * Run with: npm test
19
- */
20
- export {};
21
- //# sourceMappingURL=generic-handoff.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"generic-handoff.test.d.ts","sourceRoot":"","sources":["../../src/workflow/generic-handoff.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG"}