@pennyfarthing/core 11.2.2 → 11.3.2

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 (168) hide show
  1. package/README.md +3 -3
  2. package/package.json +1 -1
  3. package/packages/core/dist/cli/commands/doctor-legacy.test.js +2 -2
  4. package/packages/core/dist/cli/commands/doctor-legacy.test.js.map +1 -1
  5. package/packages/core/dist/cli/commands/doctor.d.ts +63 -0
  6. package/packages/core/dist/cli/commands/doctor.d.ts.map +1 -1
  7. package/packages/core/dist/cli/commands/doctor.js +280 -43
  8. package/packages/core/dist/cli/commands/doctor.js.map +1 -1
  9. package/packages/core/dist/cli/commands/init.d.ts +12 -0
  10. package/packages/core/dist/cli/commands/init.d.ts.map +1 -1
  11. package/packages/core/dist/cli/commands/init.js +45 -0
  12. package/packages/core/dist/cli/commands/init.js.map +1 -1
  13. package/packages/core/dist/cli/commands/pyproject-install.test.d.ts +19 -0
  14. package/packages/core/dist/cli/commands/pyproject-install.test.d.ts.map +1 -0
  15. package/packages/core/dist/cli/commands/pyproject-install.test.js +261 -0
  16. package/packages/core/dist/cli/commands/pyproject-install.test.js.map +1 -0
  17. package/packages/core/dist/cli/commands/update-consolidation.test.js +14 -6
  18. package/packages/core/dist/cli/commands/update-consolidation.test.js.map +1 -1
  19. package/packages/core/dist/cli/commands/update.d.ts.map +1 -1
  20. package/packages/core/dist/cli/commands/update.js +5 -1
  21. package/packages/core/dist/cli/commands/update.js.map +1 -1
  22. package/packages/core/dist/cli/index.js +2 -0
  23. package/packages/core/dist/cli/index.js.map +1 -1
  24. package/packages/core/dist/cli/utils/python.d.ts +1 -0
  25. package/packages/core/dist/cli/utils/python.d.ts.map +1 -1
  26. package/packages/core/dist/cli/utils/python.js +22 -1
  27. package/packages/core/dist/cli/utils/python.js.map +1 -1
  28. package/packages/core/dist/cli/utils/settings-hook-migration.test.d.ts +17 -0
  29. package/packages/core/dist/cli/utils/settings-hook-migration.test.d.ts.map +1 -0
  30. package/packages/core/dist/cli/utils/settings-hook-migration.test.js +382 -0
  31. package/packages/core/dist/cli/utils/settings-hook-migration.test.js.map +1 -0
  32. package/packages/core/dist/cli/utils/settings-pf-wrapper.test.d.ts +16 -0
  33. package/packages/core/dist/cli/utils/settings-pf-wrapper.test.d.ts.map +1 -0
  34. package/packages/core/dist/cli/utils/settings-pf-wrapper.test.js +377 -0
  35. package/packages/core/dist/cli/utils/settings-pf-wrapper.test.js.map +1 -0
  36. package/packages/core/dist/cli/utils/settings.d.ts.map +1 -1
  37. package/packages/core/dist/cli/utils/settings.js +15 -2
  38. package/packages/core/dist/cli/utils/settings.js.map +1 -1
  39. package/packages/core/dist/server/paths.d.ts.map +1 -1
  40. package/packages/core/dist/server/paths.js +6 -0
  41. package/packages/core/dist/server/paths.js.map +1 -1
  42. package/packages/core/dist/server/settings.d.ts.map +1 -1
  43. package/packages/core/dist/server/settings.js +5 -0
  44. package/packages/core/dist/server/settings.js.map +1 -1
  45. package/packages/core/dist/workflow/tandem-workflow-templates.test.js +7 -5
  46. package/packages/core/dist/workflow/tandem-workflow-templates.test.js.map +1 -1
  47. package/packages/core/dist/workflow/workflow-graph-validation.d.ts +65 -0
  48. package/packages/core/dist/workflow/workflow-graph-validation.d.ts.map +1 -0
  49. package/packages/core/dist/workflow/workflow-graph-validation.js +190 -0
  50. package/packages/core/dist/workflow/workflow-graph-validation.js.map +1 -0
  51. package/packages/core/dist/workflow/workflow-graph-validation.test.d.ts +18 -0
  52. package/packages/core/dist/workflow/workflow-graph-validation.test.d.ts.map +1 -0
  53. package/packages/core/dist/workflow/workflow-graph-validation.test.js +706 -0
  54. package/packages/core/dist/workflow/workflow-graph-validation.test.js.map +1 -0
  55. package/packages/core/dist/workflow/workflow-migration.test.js +6 -5
  56. package/packages/core/dist/workflow/workflow-migration.test.js.map +1 -1
  57. package/pennyfarthing-dist/agents/dev.md +4 -2
  58. package/pennyfarthing-dist/agents/devops.md +2 -10
  59. package/pennyfarthing-dist/agents/reviewer-preflight.md +4 -5
  60. package/pennyfarthing-dist/agents/sm.md +4 -17
  61. package/pennyfarthing-dist/commands/pf-health-check.md +30 -11
  62. package/pennyfarthing-dist/gates/{confidence-sm.md → confidence.md} +16 -17
  63. package/pennyfarthing-dist/gates/dev-exit.md +75 -0
  64. package/pennyfarthing-dist/gates/merge-ready.md +49 -0
  65. package/pennyfarthing-dist/gates/release-ready.md +95 -0
  66. package/pennyfarthing-dist/gates/reviewer-preflight-check.md +90 -0
  67. package/pennyfarthing-dist/gates/sm-setup-exit.md +82 -0
  68. package/pennyfarthing-dist/guides/agent-behavior.md +88 -30
  69. package/pennyfarthing-dist/guides/gates.md +7 -2
  70. package/pennyfarthing-dist/scripts/lib/find-root.sh +5 -0
  71. package/pennyfarthing-dist/scripts/lib/run-pf.sh +7 -0
  72. package/pennyfarthing-dist/skills/pf-settings/skill.md +42 -0
  73. package/pennyfarthing-dist/skills/skill-registry.yaml +15 -0
  74. package/pennyfarthing-dist/templates/pyproject.toml +27 -0
  75. package/pennyfarthing-dist/workflows/bdd-tandem.yaml +7 -3
  76. package/pennyfarthing-dist/workflows/bdd.yaml +7 -3
  77. package/pennyfarthing-dist/workflows/installation-check/steps/step-01-foundation.md +77 -0
  78. package/pennyfarthing-dist/workflows/installation-check/steps/step-02-commands.md +82 -0
  79. package/pennyfarthing-dist/workflows/installation-check/steps/step-03-hooks.md +121 -0
  80. package/pennyfarthing-dist/workflows/installation-check/steps/step-04-scripts.md +83 -0
  81. package/pennyfarthing-dist/workflows/installation-check/steps/step-05-layout.md +81 -0
  82. package/pennyfarthing-dist/workflows/installation-check/steps/step-06-legacy.md +94 -0
  83. package/pennyfarthing-dist/workflows/installation-check/steps/step-07-tools.md +80 -0
  84. package/pennyfarthing-dist/workflows/installation-check/steps/step-08-summary.md +99 -0
  85. package/pennyfarthing-dist/workflows/installation-check/workflow.yaml +47 -0
  86. package/pennyfarthing-dist/workflows/tdd-tandem.yaml +7 -3
  87. package/pennyfarthing-dist/workflows/tdd.yaml +7 -3
  88. package/pennyfarthing-dist/workflows/trivial.yaml +7 -3
  89. package/pennyfarthing_scripts/__pycache__/__init__.cpython-314.pyc +0 -0
  90. package/pennyfarthing_scripts/__pycache__/cli.cpython-314.pyc +0 -0
  91. package/pennyfarthing_scripts/__pycache__/context.cpython-314.pyc +0 -0
  92. package/pennyfarthing_scripts/bc/__pycache__/cli.cpython-314.pyc +0 -0
  93. package/pennyfarthing_scripts/bc/__pycache__/focus.cpython-314.pyc +0 -0
  94. package/pennyfarthing_scripts/bc/__pycache__/split.cpython-314.pyc +0 -0
  95. package/pennyfarthing_scripts/bc/cli.py +21 -0
  96. package/pennyfarthing_scripts/bc/focus.py +1 -0
  97. package/pennyfarthing_scripts/bc/split.py +52 -0
  98. package/pennyfarthing_scripts/bikerack/__pycache__/audit_log_panel.cpython-314.pyc +0 -0
  99. package/pennyfarthing_scripts/bikerack/__pycache__/base_panel.cpython-314.pyc +0 -0
  100. package/pennyfarthing_scripts/bikerack/__pycache__/changed_panel.cpython-314.pyc +0 -0
  101. package/pennyfarthing_scripts/bikerack/__pycache__/context_meter_footer.cpython-314.pyc +0 -0
  102. package/pennyfarthing_scripts/bikerack/__pycache__/debug_panel.cpython-314.pyc +0 -0
  103. package/pennyfarthing_scripts/bikerack/__pycache__/diffs_panel.cpython-314.pyc +0 -0
  104. package/pennyfarthing_scripts/bikerack/__pycache__/events.cpython-314.pyc +0 -0
  105. package/pennyfarthing_scripts/bikerack/__pycache__/launcher.cpython-314.pyc +0 -0
  106. package/pennyfarthing_scripts/bikerack/__pycache__/portrait_resolver.cpython-314.pyc +0 -0
  107. package/pennyfarthing_scripts/bikerack/__pycache__/progress_panel.cpython-314.pyc +0 -0
  108. package/pennyfarthing_scripts/bikerack/__pycache__/sprint_panel.cpython-314.pyc +0 -0
  109. package/pennyfarthing_scripts/bikerack/__pycache__/tui.cpython-314.pyc +0 -0
  110. package/pennyfarthing_scripts/bikerack/__pycache__/ws_client.cpython-314.pyc +0 -0
  111. package/pennyfarthing_scripts/bikerack/context_meter_footer.py +53 -3
  112. package/pennyfarthing_scripts/bikerack/tui.py +202 -8
  113. package/pennyfarthing_scripts/bmad/__init__.py +1 -0
  114. package/pennyfarthing_scripts/bmad/__pycache__/__init__.cpython-314.pyc +0 -0
  115. package/pennyfarthing_scripts/bmad/__pycache__/cli.cpython-314.pyc +0 -0
  116. package/pennyfarthing_scripts/bmad/__pycache__/parser.cpython-314.pyc +0 -0
  117. package/pennyfarthing_scripts/bmad/__pycache__/sync.cpython-314.pyc +0 -0
  118. package/pennyfarthing_scripts/bmad/__pycache__/test_parser.cpython-314-pytest-9.0.2.pyc +0 -0
  119. package/pennyfarthing_scripts/bmad/__pycache__/test_sync.cpython-314-pytest-9.0.2.pyc +0 -0
  120. package/pennyfarthing_scripts/bmad/cli.py +197 -0
  121. package/pennyfarthing_scripts/bmad/importer.py +200 -0
  122. package/pennyfarthing_scripts/bmad/parser.py +233 -0
  123. package/pennyfarthing_scripts/bmad/sync.py +464 -0
  124. package/pennyfarthing_scripts/bmad/test_parser.py +253 -0
  125. package/pennyfarthing_scripts/bmad/test_sync.py +223 -0
  126. package/pennyfarthing_scripts/cli.py +10 -0
  127. package/pennyfarthing_scripts/common/__pycache__/config.cpython-314.pyc +0 -0
  128. package/pennyfarthing_scripts/consultation/__pycache__/cli.cpython-314.pyc +0 -0
  129. package/pennyfarthing_scripts/handoff/__pycache__/cli.cpython-314.pyc +0 -0
  130. package/pennyfarthing_scripts/handoff/__pycache__/complete_phase.cpython-314.pyc +0 -0
  131. package/pennyfarthing_scripts/handoff/__pycache__/gate_file.cpython-314.pyc +0 -0
  132. package/pennyfarthing_scripts/handoff/__pycache__/gate_runner.cpython-314.pyc +0 -0
  133. package/pennyfarthing_scripts/handoff/__pycache__/marker.cpython-314.pyc +0 -0
  134. package/pennyfarthing_scripts/handoff/__pycache__/resolve_gate.cpython-314.pyc +0 -0
  135. package/pennyfarthing_scripts/hooks/__pycache__/__init__.cpython-314.pyc +0 -0
  136. package/pennyfarthing_scripts/hooks/__pycache__/bell_mode.cpython-314.pyc +0 -0
  137. package/pennyfarthing_scripts/hooks/__pycache__/cli.cpython-314.pyc +0 -0
  138. package/pennyfarthing_scripts/hooks/__pycache__/context_breaker.cpython-314.pyc +0 -0
  139. package/pennyfarthing_scripts/hooks/__pycache__/context_warning.cpython-314.pyc +0 -0
  140. package/pennyfarthing_scripts/hooks/__pycache__/cyclist_pretooluse.cpython-314.pyc +0 -0
  141. package/pennyfarthing_scripts/hooks/__pycache__/pre_edit_check.cpython-314.pyc +0 -0
  142. package/pennyfarthing_scripts/hooks/__pycache__/reflector_check.cpython-314.pyc +0 -0
  143. package/pennyfarthing_scripts/hooks/__pycache__/schema_validation.cpython-314.pyc +0 -0
  144. package/pennyfarthing_scripts/hooks/__pycache__/session_start.cpython-314.pyc +0 -0
  145. package/pennyfarthing_scripts/hooks/__pycache__/session_stop.cpython-314.pyc +0 -0
  146. package/pennyfarthing_scripts/hooks/__pycache__/sprint_yaml_validation.cpython-314.pyc +0 -0
  147. package/pennyfarthing_scripts/hooks/__pycache__/statusline.cpython-314.pyc +0 -0
  148. package/pennyfarthing_scripts/prime/__pycache__/workflow.cpython-314.pyc +0 -0
  149. package/pennyfarthing_scripts/settings/__init__.py +0 -0
  150. package/pennyfarthing_scripts/settings/__pycache__/__init__.cpython-314.pyc +0 -0
  151. package/pennyfarthing_scripts/settings/__pycache__/cli.cpython-314.pyc +0 -0
  152. package/pennyfarthing_scripts/settings/__pycache__/settings.cpython-314.pyc +0 -0
  153. package/pennyfarthing_scripts/settings/cli.py +55 -0
  154. package/pennyfarthing_scripts/settings/settings.py +98 -0
  155. package/pennyfarthing_scripts/sprint/__pycache__/cli.cpython-314.pyc +0 -0
  156. package/pennyfarthing_scripts/sprint/__pycache__/loader.cpython-314.pyc +0 -0
  157. package/pennyfarthing_scripts/sprint/__pycache__/story_update.cpython-314.pyc +0 -0
  158. package/pennyfarthing_scripts/tests/__pycache__/test_confidence_sm_evaluation.cpython-314-pytest-9.0.2.pyc +0 -0
  159. package/pennyfarthing_scripts/tests/__pycache__/test_confidence_sm_gate.cpython-314-pytest-9.0.2.pyc +0 -0
  160. package/pennyfarthing_scripts/tests/__pycache__/test_gate_file_resolution.cpython-314-pytest-9.0.2.pyc +0 -0
  161. package/pennyfarthing_scripts/tests/__pycache__/test_gate_runner.cpython-314-pytest-9.0.2.pyc +0 -0
  162. package/pennyfarthing_scripts/tests/__pycache__/test_resolve_gate_file_field.cpython-314-pytest-9.0.2.pyc +0 -0
  163. package/pennyfarthing_scripts/tests/__pycache__/test_workflow_list_team.cpython-314.pyc +0 -0
  164. package/pennyfarthing_scripts/tests/test_confidence_sm_gate.py +17 -16
  165. package/pennyfarthing_scripts/tests/test_resolve_gate_file_field.py +45 -47
  166. package/pennyfarthing_scripts/tests/test_workflow_list_team.py +0 -4
  167. package/pennyfarthing_scripts/workflow/__pycache__/cli.cpython-314.pyc +0 -0
  168. package/pennyfarthing_scripts/workflow/__pycache__/state.cpython-314.pyc +0 -0
@@ -0,0 +1,90 @@
1
+ <gate name="reviewer-preflight-check" model="haiku">
2
+
3
+ <purpose>
4
+ Composite gate for reviewer preflight. Extends tests-pass with code smell
5
+ detection and error boundary checks. The reviewer-preflight subagent runs
6
+ this gate before the Reviewer does critical analysis.
7
+ </purpose>
8
+
9
+ <ref gate="gates/tests-pass" />
10
+
11
+ <check name="no-debug-code">
12
+ No debug artifacts in changed files.
13
+ Search changed files (`git diff --name-only develop...HEAD`) for:
14
+ - `console.log` (not guarded by `process.env.NODE_ENV`)
15
+ - `dangerouslySetInnerHTML`
16
+ - `.skip(` (test skips)
17
+ - `TODO` / `FIXME`
18
+ Count by category. None found = pass.
19
+ </check>
20
+
21
+ <check name="error-boundaries">
22
+ UI components have error boundaries (UI repos only).
23
+ For React component files in diff, verify error boundary wrapping.
24
+ Skip for non-UI repos.
25
+ </check>
26
+
27
+ <pass>
28
+ Run all checks from `gates/tests-pass` (test-suite, working-tree, branch-status),
29
+ then run no-debug-code and error-boundaries.
30
+
31
+ If ALL pass, return:
32
+
33
+ ```yaml
34
+ GATE_RESULT:
35
+ status: pass
36
+ gate: reviewer-preflight-check
37
+ message: "Preflight clear: tests green, no smells, boundaries present"
38
+ checks:
39
+ - name: test-suite
40
+ status: pass
41
+ detail: "{passed}/{total} passing ({source: cached|fresh})"
42
+ - name: working-tree
43
+ status: pass
44
+ detail: "No uncommitted changes"
45
+ - name: branch-status
46
+ status: pass
47
+ detail: "On branch {branch}"
48
+ - name: no-debug-code
49
+ status: pass
50
+ detail: "No debug patterns in {N} changed files"
51
+ - name: error-boundaries
52
+ status: pass
53
+ detail: "Error boundaries present (or N/A for non-UI)"
54
+ ```
55
+ </pass>
56
+
57
+ <fail>
58
+ If ANY check fails, report all results. Note: code smells are advisory (YELLOW)
59
+ rather than blocking (RED) — the Reviewer makes the final call.
60
+
61
+ ```yaml
62
+ GATE_RESULT:
63
+ status: fail
64
+ gate: reviewer-preflight-check
65
+ message: "Preflight issues: {summary}"
66
+ checks:
67
+ - name: test-suite
68
+ status: pass | fail
69
+ detail: "{test results or failure list}"
70
+ - name: working-tree
71
+ status: pass | fail
72
+ detail: "{clean or list of uncommitted files}"
73
+ - name: branch-status
74
+ status: pass | fail
75
+ detail: "{branch info}"
76
+ - name: no-debug-code
77
+ status: pass | fail
78
+ detail: "{clean or smell counts by category}"
79
+ - name: error-boundaries
80
+ status: pass | fail
81
+ detail: "{present, missing list, or N/A}"
82
+ recovery:
83
+ - "Fix failing tests before review"
84
+ - "Commit or stash uncommitted changes"
85
+ - "Remove debug code: {locations}"
86
+ - "Add error boundaries to: {components}"
87
+ ```
88
+ </fail>
89
+
90
+ </gate>
@@ -0,0 +1,82 @@
1
+ <gate name="sm-setup-exit" model="haiku">
2
+
3
+ <purpose>
4
+ Verify SM has completed story setup before handing off to the next agent.
5
+ Without a properly configured session file, the next agent cannot function.
6
+ Extracts the inline pre-handoff checklist from sm.md.
7
+ </purpose>
8
+
9
+ <pass>
10
+ Run these checks in order:
11
+
12
+ 1. **session-exists:** Check `.session/{story-id}-session.md` exists.
13
+ ```bash
14
+ ls .session/{story-id}-session.md
15
+ ```
16
+
17
+ 2. **session-fields-set:** Read session file and verify:
18
+ - `**Workflow:**` field present and non-empty
19
+ - `**Phase:**` field present and set to `setup`
20
+
21
+ 3. **story-context-exists:** Verify:
22
+ - `sprint/context/context-epic-{N}.md` exists (extract epic number from story ID)
23
+ - Session file contains technical approach section
24
+ - Session file contains acceptance criteria
25
+
26
+ 4. **branch-created:** For each repo in session `**Repos:**`:
27
+ - Run `git branch --show-current`
28
+ - Confirm not on `main` or `develop`
29
+
30
+ If ALL pass, return:
31
+
32
+ ```yaml
33
+ GATE_RESULT:
34
+ status: pass
35
+ gate: sm-setup-exit
36
+ message: "Session {story-id} ready. Workflow: {workflow}, Branch: {branch}"
37
+ checks:
38
+ - name: session-exists
39
+ status: pass
40
+ detail: ".session/{story-id}-session.md exists"
41
+ - name: session-fields-set
42
+ status: pass
43
+ detail: "Workflow: {workflow}, Phase: setup"
44
+ - name: story-context-exists
45
+ status: pass
46
+ detail: "Epic context and story ACs present"
47
+ - name: branch-created
48
+ status: pass
49
+ detail: "Branch {branch} created in {repos}"
50
+ ```
51
+ </pass>
52
+
53
+ <fail>
54
+ If ANY check fails, report all results:
55
+
56
+ ```yaml
57
+ GATE_RESULT:
58
+ status: fail
59
+ gate: sm-setup-exit
60
+ message: "Setup incomplete: {summary}"
61
+ checks:
62
+ - name: session-exists
63
+ status: pass | fail
64
+ detail: "{exists or missing}"
65
+ - name: session-fields-set
66
+ status: pass | fail
67
+ detail: "{fields present or missing fields list}"
68
+ - name: story-context-exists
69
+ status: pass | fail
70
+ detail: "{context present or missing sections}"
71
+ - name: branch-created
72
+ status: pass | fail
73
+ detail: "{branch status per repo}"
74
+ recovery:
75
+ - "Run sm-setup to create session file"
76
+ - "Set Workflow and Phase fields in session"
77
+ - "Write story context with technical approach and ACs"
78
+ - "Create feature branch: git checkout -b feat/{story-slug}"
79
+ ```
80
+ </fail>
81
+
82
+ </gate>
@@ -101,46 +101,104 @@ See `.pennyfarthing/guides/tandem-protocol.md` for full protocol details.
101
101
  ---
102
102
 
103
103
  <team-mode>
104
- ## Team Mode Protocol
104
+ ## Team Mode — Phase-Scoped Native Teams
105
105
 
106
- When a workflow phase has a `team:` configuration block, the phase agent acts as
107
- **team lead** and spawns teammates for parallel collaboration within that phase.
106
+ Team mode enables parallel agent collaboration within a single workflow phase using Claude Code's native Agent Teams. The phase agent is always the **team lead**; spawned agents are **teammates**. Teams are created at phase start and destroyed before handoff.
108
107
 
109
- ### Team Creation
108
+ **Prerequisites:**
109
+ - Workflow phase has a `team:` block in its YAML definition
110
+ - `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS` env var is set
111
+ - Interactive session (not `-p` mode)
112
+ - Feature detection passes (`pf detect teams` or equivalent)
110
113
 
111
- On phase entry, detect the `team:` block in workflow YAML. Use `TeamCreate`
112
- to create a phase-scoped team named after the phase (e.g., `"green-phase"`).
114
+ **If prerequisites are not met:** Fall back to solo execution (optionally with tandem consultation). No error — team mode is always optional.
113
115
 
114
- ### Teammate Spawning
116
+ ### Detection
115
117
 
116
- Spawn teammates via the Task tool with `team_name` parameter. Each teammate
117
- runs `pf agent start {agent}` for full Prime activation. Keep spawn prompts
118
- under 500 tokens — teammates auto-load CLAUDE.md, MCP servers, and skills.
118
+ On activation, check the workflow YAML for a `team:` block on your phase:
119
119
 
120
- ### Communication
120
+ ```yaml
121
+ phases:
122
+ - name: green
123
+ agent: dev
124
+ team:
125
+ teammates:
126
+ - agent: architect
127
+ task: "Review implementation approach and patterns"
128
+ - agent: tea
129
+ task: "Verify tests stay green, flag regressions"
130
+ ```
131
+
132
+ If `team:` is present and prerequisites are met, you are the **team lead** for this phase.
133
+
134
+ ### Team Lead Responsibilities
135
+
136
+ **On phase entry:**
137
+
138
+ 1. **Create the team:**
139
+ ```
140
+ TeamCreate("phase-{PHASE}-{STORY_ID}")
141
+ ```
142
+
143
+ 2. **Spawn teammates** per workflow YAML config. Each teammate gets a spawn prompt:
144
+ ```
145
+ Task(team_name="phase-{PHASE}-{STORY_ID}", name="{agent}",
146
+ prompt="Run `pf agent start {agent}`. Story: {STORY_ID}.
147
+ {task assignment from YAML}")
148
+ ```
149
+ Teammates auto-load CLAUDE.md, MCP servers, and skills from the working directory. Spawn prompts only need the activation command and task assignment — keep under 500 tokens.
150
+
151
+ 3. **Coordinate via SendMessage.** Use `SendMessage` for all intra-phase communication with teammates:
152
+ - Assign work: `SendMessage(to="{teammate}", message="Implement the adapter pattern for...")`
153
+ - Check status: `SendMessage(to="{teammate}", message="Status on your review?")`
154
+ - Broadcast: `SendMessage(message="Shifting approach — using strategy pattern instead")`
155
+
156
+ 4. **Do your own work.** You are still the primary implementer. Teammates assist — they don't replace you.
157
+
158
+ **Before exit protocol:**
121
159
 
122
- - **Inter-phase handoff:** Use Reflector markers (`<!-- CYCLIST:HANDOFF -->`)
123
- for phase transitions — unchanged from sequential mode.
124
- - **Intra-phase collaboration:** Use `SendMessage` for real-time teammate
125
- communication. Never use markers for intra-phase messaging.
160
+ 5. **Shut down all teammates.** This is mandatory before starting the normal exit protocol:
161
+ ```
162
+ SendMessage(to="{teammate}", message="Phase complete. Shut down.")
163
+ ```
164
+ Wait for teammates to go idle, then:
165
+ ```
166
+ TeamDelete("phase-{PHASE}-{STORY_ID}")
167
+ ```
168
+
169
+ 6. **Proceed with normal exit protocol** (assessment → resolve-gate → complete-phase → marker).
170
+
171
+ ### Teammate Responsibilities
172
+
173
+ When spawned as a teammate (you receive a task via spawn prompt, not a phase handoff):
126
174
 
127
- ### Teammate Behavior
175
+ 1. **Recognize you are a teammate, not the lead.** You do not own the phase. You do not run the exit protocol. You do not emit handoff markers.
128
176
 
129
- Teammates know they are NOT the lead. They:
130
- - Communicate via SendMessage (DMs to lead or other teammates)
131
- - Go idle when their assigned task is complete
132
- - Respond to shutdown requests with shutdown_response
177
+ 2. **Activate normally** via `pf agent start {agent}`. Read the session file for story context.
133
178
 
134
- ### Cleanup Before Handoff
179
+ 3. **Communicate via SendMessage.** All collaboration with the lead and other teammates uses `SendMessage`:
180
+ - Report findings: `SendMessage(to="lead", message="Found coupling issue in...")`
181
+ - Ask questions: `SendMessage(to="lead", message="Should I use the existing adapter?")`
182
+ - Share status: `SendMessage(to="lead", message="Review complete. 2 issues found.")`
135
183
 
136
- Before starting the exit protocol, the lead MUST:
137
- 1. Send `shutdown_request` to all teammates via SendMessage
138
- 2. Wait for `shutdown_response` from each teammate
139
- 3. Run `TeamDelete` to clean up the team
140
- 4. Then proceed with normal handoff (resolve-gate → complete-phase → marker)
184
+ 4. **Go idle when your task is done.** Once your assigned task is complete, send a final status message and wait. Do not start new work unprompted.
141
185
 
142
- Teams are **phase-scoped** created at phase start, destroyed at phase end.
143
- Handoff between phases is unchanged.
186
+ 5. **Respond to shutdown requests.** When the lead sends a shutdown message, wrap up immediately. Save any observations to the session file or sidecar, then stop.
187
+
188
+ ### Communication Channels
189
+
190
+ | Channel | Scope | Used For |
191
+ |---------|-------|----------|
192
+ | `SendMessage` | Intra-phase (within team) | Lead ↔ teammate collaboration, status updates, task assignment |
193
+ | Reflector markers (`<!-- CYCLIST:... -->`) | Inter-phase (between phases) | Handoff from one phase agent to the next — **unchanged** |
194
+ | Session file | Cross-phase persistence | Story state, assessments, ACs — written by lead only in team mode |
195
+ | Sidecar files | Agent learning | Teammates may write to their own sidecar with file locking |
196
+
197
+ <critical>
198
+ **Never use SendMessage for inter-phase handoff.** Markers and `pf handoff` are the only way to transition between phases. SendMessage is for real-time collaboration within a phase.
199
+
200
+ **Never use markers for intra-phase communication.** Markers are routing signals for Cyclist UI and the handoff system. They have no meaning inside a team.
201
+ </critical>
144
202
  </team-mode>
145
203
 
146
204
  ---
@@ -167,8 +225,8 @@ Handoff between phases is unchanged.
167
225
  ## Exit Protocol
168
226
 
169
227
  1. Write assessment to session
170
- 2. Terminate tandem backseat (if active)
171
- 3. **If team is active:** Shut down all teammates → `TeamDelete` to clean up
228
+ 2. **If team mode active:** Shut down all teammates via `SendMessage`, then `TeamDelete`. Wait for cleanup before proceeding.
229
+ 3. Terminate tandem backseat (if active)
172
230
  4. `"$CLAUDE_PROJECT_DIR"/.pennyfarthing/scripts/core/pf.sh handoff resolve-gate {story-id} {workflow} {phase}` → RESOLVE_RESULT
173
231
  5. If blocked → report error, STOP
174
232
  6. If skip → jump to step 8
@@ -15,7 +15,12 @@ Gates live in `pennyfarthing-dist/gates/` and are referenced by workflow YAML fi
15
15
  | **tests-pass** | `gates/tests-pass.md` | Verify all tests pass, working tree clean, correct branch | Dev → Reviewer transitions |
16
16
  | **tests-fail** | `gates/tests-fail.md` | Verify tests are RED (failing) with AC coverage | TEA → Dev transitions |
17
17
  | **approval** | `gates/approval.md` | Verify reviewer has issued explicit APPROVED verdict | Reviewer → SM transitions |
18
- | **confidence-sm** | `gates/confidence-sm.md` | Check if user instruction to SM is ambiguous | SM entry gate |
18
+ | **confidence** | `gates/confidence.md` | Check if user instruction is ambiguous | Any agent entry gate |
19
+ | **dev-exit** | `gates/dev-exit.md` | Composite: tests-pass + no debug code | Dev → Reviewer transitions |
20
+ | **sm-setup-exit** | `gates/sm-setup-exit.md` | Session file, fields, context, branch created | SM → next agent transitions |
21
+ | **merge-ready** | `gates/merge-ready.md` | No open non-draft PRs | SM new work gate |
22
+ | **release-ready** | `gates/release-ready.md` | Composite: tests-pass + build, version, changelog | DevOps pre-deploy |
23
+ | **reviewer-preflight-check** | `gates/reviewer-preflight-check.md` | Composite: tests-pass + code smells, error boundaries | Reviewer preflight |
19
24
 
20
25
  ## Gate File Format
21
26
 
@@ -96,7 +101,7 @@ Extended evaluation criteria can live in `gates/evaluations/`:
96
101
 
97
102
  | File | Purpose |
98
103
  |------|---------|
99
- | `evaluations/confidence-sm.md` | Detailed rubric for SM confidence scoring |
104
+ | `evaluations/confidence-sm.md` | Historical evaluation of SM confidence gate (led to agent-agnostic `confidence` gate) |
100
105
 
101
106
  ## Creating Custom Gates
102
107
 
@@ -29,6 +29,11 @@ if [[ -n "$_caller_script" ]]; then
29
29
  _pkg="${_pkg%/.pennyfarthing}"
30
30
  if [[ "$_pkg" == */node_modules/* ]]; then
31
31
  PROJECT_ROOT="${_pkg%/node_modules/*}"
32
+ elif [[ -d "$_pkg/.pennyfarthing" ]]; then
33
+ PROJECT_ROOT="$_pkg"
34
+ elif [[ -d "$_pkg/../.pennyfarthing" ]]; then
35
+ # Dogfooding: pennyfarthing/ inlined inside orchestrator
36
+ PROJECT_ROOT="$(cd "$_pkg/.." && pwd -P)"
32
37
  else
33
38
  PROJECT_ROOT="$_pkg"
34
39
  fi
@@ -18,15 +18,22 @@ _pf_project=""
18
18
  if [[ -f "$PROJECT_ROOT/pennyfarthing/pyproject.toml" ]]; then
19
19
  # Dogfooding: inlined framework repo
20
20
  _pf_project="$PROJECT_ROOT/pennyfarthing"
21
+ elif [[ -f "$PROJECT_ROOT/node_modules/@pennyfarthing/core/pyproject.toml" ]]; then
22
+ # Symlink install: npm package has full Python source
23
+ _pf_project="$PROJECT_ROOT/node_modules/@pennyfarthing/core"
21
24
  elif [[ -f "$PROJECT_ROOT/pyproject.toml" ]]; then
22
25
  # Consumer: project-level pyproject.toml with pennyfarthing-scripts dep
23
26
  _pf_project="$PROJECT_ROOT"
27
+ elif [[ -f "$PROJECT_ROOT/.pennyfarthing/pyproject.toml" ]]; then
28
+ # Consumer: auto-generated by pennyfarthing init
29
+ _pf_project="$PROJECT_ROOT/.pennyfarthing"
24
30
  fi
25
31
 
26
32
  if [[ -z "$_pf_project" ]]; then
27
33
  echo "Error: No pyproject.toml found for pennyfarthing-scripts" >&2
28
34
  echo "Expected: $PROJECT_ROOT/pennyfarthing/pyproject.toml (dogfooding)" >&2
29
35
  echo " or: $PROJECT_ROOT/pyproject.toml (consumer)" >&2
36
+ echo " or: $PROJECT_ROOT/.pennyfarthing/pyproject.toml (auto-generated)" >&2
30
37
  exit 1
31
38
  fi
32
39
 
@@ -0,0 +1,42 @@
1
+ ---
2
+ name: pf-settings
3
+ description: |
4
+ View and manage .pennyfarthing/config.local.yaml settings.
5
+ Get, set, and show configuration values using dot-path notation.
6
+ args: "[show|get|set] [key] [value]"
7
+ ---
8
+
9
+ # /pf-settings - Configuration Settings
10
+
11
+ View and manage `.pennyfarthing/config.local.yaml` settings.
12
+
13
+ ## Quick Reference
14
+
15
+ | Command | CLI | Purpose |
16
+ |---------|-----|---------|
17
+ | `/pf-settings show` | `pf.sh settings show` | Pretty-print all settings |
18
+ | `/pf-settings get <key>` | `pf.sh settings get <key>` | Get value by dot-path |
19
+ | `/pf-settings set <key> <value>` | `pf.sh settings set <key> <value>` | Set value by dot-path |
20
+
21
+ ## Examples
22
+
23
+ ```bash
24
+ # Show all interesting settings (theme, workflow, display, split, last_panel)
25
+ pf.sh settings show
26
+
27
+ # Get a specific value
28
+ pf.sh settings get theme # → fifth-element
29
+ pf.sh settings get workflow.relay_mode # → True
30
+ pf.sh settings get display.colorPreset # → catppuccin
31
+
32
+ # Set a value (auto-coerces bool/int)
33
+ pf.sh settings set workflow.bell_mode false
34
+ pf.sh settings set workflow.relay_mode true
35
+ pf.sh settings set display.colorPreset monokai
36
+ ```
37
+
38
+ ## Notes
39
+
40
+ - Dot-path notation traverses nested keys: `workflow.relay_mode` → `workflow: { relay_mode: ... }`
41
+ - Value coercion: `true`/`false` → bool, numeric strings → int, else string
42
+ - `show` skips large blobs (layout, bikerack_layout, panels, theme_characters) for readability
@@ -216,6 +216,21 @@ skills:
216
216
  related_skills: []
217
217
  keywords: [grants, scopes, tools, runtime, security]
218
218
 
219
+ pf-settings:
220
+ name: pf-settings
221
+ description: View and manage .pennyfarthing/config.local.yaml settings
222
+ category: tools
223
+ tags: [configuration, settings, config]
224
+ version: "1.0.0"
225
+ command_group: settings
226
+ examples:
227
+ - context: View all settings
228
+ invocation: /pf-settings show
229
+ - context: Get a specific setting
230
+ invocation: /pf-settings get workflow.relay_mode
231
+ related_skills: [pf-theme, pf-bc]
232
+ keywords: [theme, relay, bell, permission, display, config]
233
+
219
234
  pf-persona-benchmark:
220
235
  name: pf-persona-benchmark
221
236
  description: Run benchmarks to compare persona effectiveness
@@ -0,0 +1,27 @@
1
+ # Auto-generated by pennyfarthing init — provides Python dependencies for hooks.
2
+ # This file enables `uv run --project` to resolve pennyfarthing_scripts.
3
+ # Safe to customize: init/update will not overwrite this file once created.
4
+
5
+ [project]
6
+ name = "pennyfarthing-scripts"
7
+ version = "0.0.0"
8
+ description = "Python utilities for Pennyfarthing agent orchestration"
9
+ requires-python = ">=3.11"
10
+
11
+ dependencies = [
12
+ "pyyaml>=6.0",
13
+ "ruamel.yaml>=0.18",
14
+ "httpx>=0.28",
15
+ "click>=8.0",
16
+ "pydriller>=2.6",
17
+ ]
18
+
19
+ [project.scripts]
20
+ pf = "pennyfarthing_scripts.cli:main"
21
+
22
+ [build-system]
23
+ requires = ["setuptools>=68.0"]
24
+ build-backend = "setuptools.build_meta"
25
+
26
+ [tool.setuptools.packages.find]
27
+ include = ["pennyfarthing_scripts*"]
@@ -24,6 +24,10 @@ workflow:
24
24
  - name: setup
25
25
  agent: sm
26
26
  output: [session_file, branches, story_context]
27
+ gate:
28
+ file: gates/sm-setup-exit
29
+ type: sm_setup_exit
30
+ condition: Session file created with workflow, phase, context, and branch
27
31
 
28
32
  - name: design
29
33
  agent: ux-designer
@@ -54,9 +58,9 @@ workflow:
54
58
  input: [failing_tests, design_spec, story_context]
55
59
  output: [implementation, passing_tests]
56
60
  gate:
57
- file: gates/tests-pass
58
- type: tests_pass
59
- condition: All tests passing, UX spec implemented
61
+ file: gates/dev-exit
62
+ type: dev_exit
63
+ condition: Tests green, tree clean, no debug code, correct branch
60
64
  tandem:
61
65
  partner: ux-designer
62
66
  scope: file-watch
@@ -13,6 +13,10 @@ workflow:
13
13
  - name: setup
14
14
  agent: sm
15
15
  output: [session_file, branches, story_context]
16
+ gate:
17
+ file: gates/sm-setup-exit
18
+ type: sm_setup_exit
19
+ condition: Session file created with workflow, phase, context, and branch
16
20
 
17
21
  - name: design
18
22
  agent: ux-designer
@@ -37,9 +41,9 @@ workflow:
37
41
  input: [failing_tests, design_spec, story_context]
38
42
  output: [implementation, passing_tests]
39
43
  gate:
40
- file: gates/tests-pass
41
- type: tests_pass
42
- condition: All tests passing, UX spec implemented
44
+ file: gates/dev-exit
45
+ type: dev_exit
46
+ condition: Tests green, tree clean, no debug code, correct branch
43
47
 
44
48
  - name: review
45
49
  agent: reviewer
@@ -0,0 +1,77 @@
1
+ # Step 1: Foundation Check
2
+
3
+ <step-meta>
4
+ step: 1
5
+ name: foundation
6
+ workflow: installation-check
7
+ agent: devops
8
+ gate: false
9
+ next: step-02-commands
10
+ </step-meta>
11
+
12
+ <purpose>
13
+ Verify the core Pennyfarthing installation exists and is intact. This checks the manifest, core framework directories, symlinks, and file integrity — the foundation everything else depends on.
14
+ </purpose>
15
+
16
+ <prerequisites>
17
+ - Project has been initialized with `pennyfarthing init`
18
+ - Running from the project root directory
19
+ </prerequisites>
20
+
21
+ <instructions>
22
+ 1. Run the doctor command for the installation category
23
+ 2. For each result, explain what it checks and why it matters:
24
+ - **manifest/exists**: The manifest tracks installed version and file hashes. Without it, Pennyfarthing can't detect drift or apply updates.
25
+ - **core/* directories**: These contain agents, commands, guides, skills, personas, and scripts. Missing directories mean broken agent invocation.
26
+ - **symlink/* checks** (symlink mode only): Symlinks to node_modules keep files in sync with the installed package version.
27
+ - **core/integrity**: Detects locally modified framework files that may conflict with updates.
28
+ - **core/completeness**: Flags missing files that should have been installed.
29
+ 3. For any failures, explain the impact and offer remediation
30
+ 4. Present the collaboration menu
31
+ </instructions>
32
+
33
+ <actions>
34
+ - Run: `pennyfarthing doctor --json --category installation`
35
+ - Check: manifest.json exists at `.pennyfarthing/manifest.json`
36
+ - Check: Core directories exist under `.claude/pennyfarthing/` or via symlinks
37
+ </actions>
38
+
39
+ <output>
40
+ Present results in a clear table format:
41
+
42
+ ```markdown
43
+ ## Foundation Check Results
44
+
45
+ | Check | Status | Detail |
46
+ |-------|--------|--------|
47
+ | manifest | ... | ... |
48
+ | core files | ... | ... |
49
+ | symlinks | ... | ... |
50
+
51
+ ### Issues Found
52
+ [Explain each failure/warning with remediation steps]
53
+ ```
54
+ </output>
55
+
56
+ <collaboration-menu>
57
+ - **[F] Fix** - Run `pennyfarthing doctor --fix --category installation` to auto-repair
58
+ - **[E] Explain** - Deep dive on a specific check result
59
+ - **[C] Continue** - Proceed to Commands & Skills check
60
+ - **[R] Recheck** - Re-run after manual changes
61
+ </collaboration-menu>
62
+
63
+ <next-step>
64
+ After reviewing foundation results, proceed to step-02-commands.md for Commands & Skills verification.
65
+ </next-step>
66
+
67
+ ## Failure Modes
68
+
69
+ - Running from wrong directory (not project root)
70
+ - Manifest missing entirely (needs `pennyfarthing init`)
71
+ - Broken symlinks after `node_modules` cleanup without reinstall
72
+
73
+ ## Success Metrics
74
+
75
+ - All manifest and core file checks pass
76
+ - User understands each check's purpose
77
+ - Any failures have clear remediation path