@pieerry/harness-kit 3.3.1 → 4.0.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 (87) hide show
  1. package/.claude/{plugins → agents}/product-manager/README.md +32 -30
  2. package/.claude/{plugins → agents}/product-manager/guides/examples/good-prp-example.md +2 -2
  3. package/.claude/{plugins → agents}/product-manager/guides/pipeline.md +7 -7
  4. package/.claude/{plugins → agents}/product-manager/sensors/prp-links.md +1 -1
  5. package/.claude/{plugins → agents}/product-manager/skills/prd/SKILL.md +2 -2
  6. package/.claude/{plugins → agents}/product-manager/skills/prp/SKILL.md +4 -4
  7. package/.claude/agents/product-manager.md +2 -2
  8. package/.claude/agents/staff-software-engineer/README.md +87 -0
  9. package/.claude/{plugins → agents}/staff-software-engineer/guides/conventions-override.md +3 -3
  10. package/.claude/{plugins → agents}/staff-software-engineer/guides/pipeline.md +4 -4
  11. package/.claude/{plugins → agents}/staff-software-engineer/sensors/dev-structure.md +2 -2
  12. package/.claude/{plugins → agents}/staff-software-engineer/sensors/pr-structure.md +3 -3
  13. package/.claude/{plugins → agents}/staff-software-engineer/sensors/test-structure.md +2 -2
  14. package/.claude/agents/staff-software-engineer.md +4 -4
  15. package/.claude/commands/pipeline/reset.md +1 -1
  16. package/.claude/commands/product-manager/prd.md +11 -11
  17. package/.claude/commands/product-manager/prp.md +12 -12
  18. package/.claude/commands/product-manager/run.md +4 -4
  19. package/.claude/commands/sse/dev.md +11 -11
  20. package/.claude/commands/sse/plan.md +11 -12
  21. package/.claude/commands/sse/pr.md +6 -7
  22. package/.claude/commands/sse/run.md +4 -4
  23. package/.claude/commands/sse/test.md +5 -5
  24. package/.claude/conventions/README.md +1 -1
  25. package/.claude/hooks/activity-pre-read.sh +4 -4
  26. package/.claude/hooks/status-line.sh +11 -11
  27. package/.claude/{plugins/product-manager/hooks → runtime/hooks/product-manager}/post-eval-prd.sh +11 -9
  28. package/.claude/{plugins/product-manager/hooks → runtime/hooks/product-manager}/post-eval-prp.sh +11 -9
  29. package/.claude/{plugins/product-manager/hooks → runtime/hooks/product-manager}/post-write-prd.sh +7 -5
  30. package/.claude/{plugins/product-manager/hooks → runtime/hooks/product-manager}/post-write-prp.sh +8 -6
  31. package/.claude/{plugins/product-manager/hooks → runtime/hooks/product-manager}/pre-prp-check.sh +5 -3
  32. package/.claude/{plugins/staff-software-engineer/hooks → runtime/hooks/staff-software-engineer}/post-eval-sse.sh +13 -11
  33. package/.claude/{plugins/staff-software-engineer/hooks → runtime/hooks/staff-software-engineer}/post-write-sse.sh +11 -9
  34. package/.claude/runtime/scripts/product-manager/__pycache__/confluence-publish.cpython-314.pyc +0 -0
  35. package/.claude/runtime/scripts/product-manager/__pycache__/link-validator.cpython-314.pyc +0 -0
  36. package/.claude/runtime/scripts/product-manager/__pycache__/sensor-runner.cpython-314.pyc +0 -0
  37. package/.claude/runtime/scripts/product-manager/__pycache__/token-phase.cpython-314.pyc +0 -0
  38. package/.claude/runtime/scripts/product-manager/confluence-publish.py +206 -0
  39. package/.claude/{plugins/product-manager/scripts → runtime/scripts/product-manager}/link-validator.py +1 -1
  40. package/.claude/{plugins/product-manager/scripts → runtime/scripts/product-manager}/token-phase.py +2 -2
  41. package/.claude/scripts/__pycache__/activity.cpython-314.pyc +0 -0
  42. package/.claude/scripts/__pycache__/pipeline.cpython-314.pyc +0 -0
  43. package/.claude/scripts/__pycache__/pr-monitor.cpython-314.pyc +0 -0
  44. package/.claude/scripts/pipeline.py +6 -6
  45. package/.claude/settings.json +7 -7
  46. package/.claude/settings.local.json +11 -3
  47. package/AGENTS.md +141 -0
  48. package/CLAUDE.md +9 -7
  49. package/README.md +88 -290
  50. package/VERSION +1 -1
  51. package/bin/hk.js +16 -8
  52. package/package.json +5 -3
  53. package/setup/install.sh +59 -40
  54. package/setup/update.sh +5 -0
  55. package/.claude/plugins/product-manager/scripts/confluence-publish.py +0 -205
  56. package/.claude/plugins/staff-software-engineer/README.md +0 -90
  57. /package/.claude/{plugins → agents}/product-manager/evals/prd-quality.md +0 -0
  58. /package/.claude/{plugins → agents}/product-manager/evals/prd-readiness.md +0 -0
  59. /package/.claude/{plugins → agents}/product-manager/evals/prp-context-readiness.md +0 -0
  60. /package/.claude/{plugins → agents}/product-manager/evals/prp-quality.md +0 -0
  61. /package/.claude/{plugins → agents}/product-manager/guides/examples/good-prd-example.md +0 -0
  62. /package/.claude/{plugins → agents}/product-manager/guides/prd-guidelines.md +0 -0
  63. /package/.claude/{plugins → agents}/product-manager/guides/product-guidelines.md +0 -0
  64. /package/.claude/{plugins → agents}/product-manager/guides/prp-guidelines.md +0 -0
  65. /package/.claude/{plugins → agents}/product-manager/guides/templates/prd.md +0 -0
  66. /package/.claude/{plugins → agents}/product-manager/guides/templates/prp.md +0 -0
  67. /package/.claude/{plugins → agents}/product-manager/guides/writing-style.md +0 -0
  68. /package/.claude/{plugins → agents}/product-manager/sensors/prd-acceptance-criteria.md +0 -0
  69. /package/.claude/{plugins → agents}/product-manager/sensors/prd-structure.md +0 -0
  70. /package/.claude/{plugins → agents}/product-manager/sensors/prp-context-quality.md +0 -0
  71. /package/.claude/{plugins → agents}/product-manager/sensors/prp-structure.md +0 -0
  72. /package/.claude/{plugins → agents}/staff-software-engineer/evals/dev-quality.md +0 -0
  73. /package/.claude/{plugins → agents}/staff-software-engineer/evals/plan-quality.md +0 -0
  74. /package/.claude/{plugins → agents}/staff-software-engineer/evals/pr-quality.md +0 -0
  75. /package/.claude/{plugins → agents}/staff-software-engineer/evals/test-quality.md +0 -0
  76. /package/.claude/{plugins → agents}/staff-software-engineer/guides/coding-style.md +0 -0
  77. /package/.claude/{plugins → agents}/staff-software-engineer/guides/commit-style.md +0 -0
  78. /package/.claude/{plugins → agents}/staff-software-engineer/sensors/code-conventions.md +0 -0
  79. /package/.claude/{plugins → agents}/staff-software-engineer/sensors/plan-structure.md +0 -0
  80. /package/.claude/{plugins → agents}/staff-software-engineer/sensors/test-coverage.md +0 -0
  81. /package/.claude/{plugins → agents}/staff-software-engineer/skills/backend/SKILL.md +0 -0
  82. /package/.claude/{plugins → agents}/staff-software-engineer/skills/devops/SKILL.md +0 -0
  83. /package/.claude/{plugins → agents}/staff-software-engineer/skills/mobile/SKILL.md +0 -0
  84. /package/.claude/{plugins → agents}/staff-software-engineer/skills/web/SKILL.md +0 -0
  85. /package/.claude/{plugins/product-manager/outputs → runtime/outputs/pm}/.markers/.gitkeep +0 -0
  86. /package/.claude/{plugins/staff-software-engineer/outputs → runtime/outputs/sse}/.markers/.gitkeep +0 -0
  87. /package/.claude/{plugins/product-manager/scripts → runtime/scripts/product-manager}/sensor-runner.py +0 -0
@@ -0,0 +1,206 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Publish a PRD or PRP to Confluence.
4
+
5
+ Reads credentials from environment:
6
+ - JIRA_USERNAME (email)
7
+ - JIRA_API_TOKEN (API token)
8
+
9
+ Targets the Confluence at https://YOUR-DOMAIN.atlassian.net.
10
+
11
+ Usage:
12
+ confluence-publish.py --artifact PATH.md --kind {prd|prp}
13
+
14
+ Exit 0 on success, 1 on failure. Stays silent on routine output, prints
15
+ errors to stderr.
16
+ """
17
+
18
+ import argparse
19
+ import base64
20
+ import html
21
+ import json
22
+ import os
23
+ import re
24
+ import sys
25
+ import urllib.error
26
+ import urllib.request
27
+ from pathlib import Path
28
+
29
+ CONFLUENCE_BASE = "https://YOUR-DOMAIN.atlassian.net/wiki/rest/api/content"
30
+ SPACE_KEY = "TET1"
31
+
32
+ # Parent page IDs per kind. Override via env if needed.
33
+ PARENT_IDS = {
34
+ "prd": os.environ.get("CONFLUENCE_PARENT_PRD", "11351457795"),
35
+ "prp": os.environ.get("CONFLUENCE_PARENT_PRP", "11351457795"),
36
+ }
37
+
38
+
39
+ def md_to_storage(md: str) -> str:
40
+ """Minimal Markdown to Confluence storage XHTML.
41
+ Good enough for headings, paragraphs, fenced code, lists, tables.
42
+ For richer rendering, swap for a real converter later.
43
+ """
44
+ lines = md.splitlines()
45
+ out: list[str] = []
46
+ in_code = False
47
+ in_list: str | None = None # 'ul' or 'ol'
48
+ in_table = False
49
+
50
+ def close_list():
51
+ nonlocal in_list
52
+ if in_list:
53
+ out.append(f"</{in_list}>")
54
+ in_list = None
55
+
56
+ def close_table():
57
+ nonlocal in_table
58
+ if in_table:
59
+ out.append("</tbody></table>")
60
+ in_table = False
61
+
62
+ for line in lines:
63
+ if line.startswith("```"):
64
+ close_list()
65
+ close_table()
66
+ if not in_code:
67
+ lang = line[3:].strip() or "none"
68
+ out.append(
69
+ f'<ac:structured-macro ac:name="code">'
70
+ f'<ac:parameter ac:name="language">{html.escape(lang)}</ac:parameter>'
71
+ f'<ac:plain-text-body><![CDATA['
72
+ )
73
+ in_code = True
74
+ else:
75
+ out.append("]]></ac:plain-text-body></ac:structured-macro>")
76
+ in_code = False
77
+ continue
78
+
79
+ if in_code:
80
+ out.append(line)
81
+ continue
82
+
83
+ h = re.match(r"^(#{1,6})\s+(.+)$", line)
84
+ if h:
85
+ close_list()
86
+ close_table()
87
+ level = len(h.group(1))
88
+ out.append(f"<h{level}>{html.escape(h.group(2))}</h{level}>")
89
+ continue
90
+
91
+ if re.match(r"^[-*]\s+", line):
92
+ close_table()
93
+ if in_list != "ul":
94
+ close_list()
95
+ out.append("<ul>")
96
+ in_list = "ul"
97
+ item = re.sub(r"^[-*]\s+", "", line)
98
+ out.append(f"<li>{html.escape(item)}</li>")
99
+ continue
100
+
101
+ if re.match(r"^\d+\.\s+", line):
102
+ close_table()
103
+ if in_list != "ol":
104
+ close_list()
105
+ out.append("<ol>")
106
+ in_list = "ol"
107
+ item = re.sub(r"^\d+\.\s+", "", line)
108
+ out.append(f"<li>{html.escape(item)}</li>")
109
+ continue
110
+
111
+ if line.startswith("|") and "|" in line[1:]:
112
+ close_list()
113
+ cells = [c.strip() for c in line.strip("|").split("|")]
114
+ if not in_table:
115
+ out.append("<table><tbody>")
116
+ in_table = True
117
+ out.append(
118
+ "<tr>"
119
+ + "".join(f"<th>{html.escape(c)}</th>" for c in cells)
120
+ + "</tr>"
121
+ )
122
+ elif all(re.fullmatch(r":?-+:?", c) for c in cells):
123
+ # separator row, skip
124
+ pass
125
+ else:
126
+ out.append(
127
+ "<tr>"
128
+ + "".join(f"<td>{html.escape(c)}</td>" for c in cells)
129
+ + "</tr>"
130
+ )
131
+ continue
132
+
133
+ # paragraph or blank
134
+ close_list()
135
+ close_table()
136
+ if line.strip():
137
+ out.append(f"<p>{html.escape(line)}</p>")
138
+
139
+ close_list()
140
+ close_table()
141
+ return "\n".join(out)
142
+
143
+
144
+ def extract_title(md: str) -> str:
145
+ for line in md.splitlines():
146
+ m = re.match(r"^#\s+(.+)$", line)
147
+ if m:
148
+ return m.group(1).strip()
149
+ return "Untitled"
150
+
151
+
152
+ def main() -> int:
153
+ parser = argparse.ArgumentParser()
154
+ parser.add_argument("--artifact", required=True, type=Path)
155
+ parser.add_argument("--kind", required=True, choices=["prd", "prp"])
156
+ args = parser.parse_args()
157
+
158
+ username = os.environ.get("JIRA_USERNAME")
159
+ token = os.environ.get("JIRA_API_TOKEN")
160
+ if not username or not token:
161
+ print("[confluence-publish] JIRA_USERNAME/JIRA_API_TOKEN not set", file=sys.stderr)
162
+ return 1
163
+
164
+ md = args.artifact.read_text(encoding="utf-8")
165
+ title = extract_title(md)
166
+ storage = md_to_storage(md)
167
+
168
+ payload = {
169
+ "type": "page",
170
+ "title": title,
171
+ "ancestors": [{"id": PARENT_IDS[args.kind]}],
172
+ "space": {"key": SPACE_KEY},
173
+ "body": {"storage": {"value": storage, "representation": "storage"}},
174
+ }
175
+
176
+ auth = base64.b64encode(f"{username}:{token}".encode()).decode()
177
+ req = urllib.request.Request(
178
+ CONFLUENCE_BASE,
179
+ data=json.dumps(payload).encode("utf-8"),
180
+ method="POST",
181
+ headers={
182
+ "Authorization": f"Basic {auth}",
183
+ "Content-Type": "application/json",
184
+ "Accept": "application/json",
185
+ },
186
+ )
187
+
188
+ try:
189
+ with urllib.request.urlopen(req, timeout=20) as resp:
190
+ data = json.loads(resp.read().decode("utf-8"))
191
+ page_url = data.get("_links", {}).get("base", "") + data.get(
192
+ "_links", {}
193
+ ).get("webui", "")
194
+ print(f"[confluence-publish] published: {page_url}", file=sys.stderr)
195
+ return 0
196
+ except urllib.error.HTTPError as e:
197
+ body = e.read().decode("utf-8", errors="replace")
198
+ print(f"[confluence-publish] HTTP {e.code}: {body[:500]}", file=sys.stderr)
199
+ return 1
200
+ except Exception as e:
201
+ print(f"[confluence-publish] error: {e}", file=sys.stderr)
202
+ return 1
203
+
204
+
205
+ if __name__ == "__main__":
206
+ sys.exit(main())
@@ -42,7 +42,7 @@ def main() -> int:
42
42
  candidates = [
43
43
  args.repo_root / prd_rel,
44
44
  args.artifact.parent / prd_rel,
45
- args.repo_root / ".claude/plugins/product-manager" / prd_rel,
45
+ args.repo_root / ".claude/agents/product-manager" / prd_rel,
46
46
  ]
47
47
  if not any(c.exists() for c in candidates):
48
48
  failures.append(f"Source PRD path does not resolve: {prd_rel}")
@@ -137,7 +137,7 @@ def main() -> int:
137
137
  parser.add_argument("--details", default="{}")
138
138
  args = parser.parse_args()
139
139
 
140
- markers_dir = args.plugin_dir / "outputs" / ".markers"
140
+ markers_dir = args.plugin_dir / ".markers"
141
141
  start_marker = markers_dir / f"{args.feature_id}.{args.phase}.start"
142
142
  end_marker = markers_dir / f"{args.feature_id}.{args.phase}.end"
143
143
 
@@ -187,7 +187,7 @@ def main() -> int:
187
187
  files["prp"] = args.prp_path
188
188
 
189
189
  tokens_path = (
190
- args.plugin_dir / "outputs" / "tokens" / f"{args.feature_id}.json"
190
+ args.plugin_dir / "tokens" / f"{args.feature_id}.json"
191
191
  )
192
192
  update_tokens_json(tokens_path, args.feature_id, files, phase_entry)
193
193
 
@@ -55,12 +55,12 @@ STAGE_TO_COMMAND = {
55
55
  }
56
56
 
57
57
  STAGE_TO_OUTPUT_DIR = {
58
- "prd": ".claude/plugins/product-manager/outputs/prd",
59
- "prp": ".claude/plugins/product-manager/outputs/prp",
60
- "plan": ".claude/plugins/staff-software-engineer/outputs/plan",
61
- "dev": ".claude/plugins/staff-software-engineer/outputs/dev",
62
- "test": ".claude/plugins/staff-software-engineer/outputs/test",
63
- "pr": ".claude/plugins/staff-software-engineer/outputs/pr",
58
+ "prd": ".claude/runtime/outputs/pm/prd",
59
+ "prp": ".claude/runtime/outputs/pm/prp",
60
+ "plan": ".claude/runtime/outputs/sse/plan",
61
+ "dev": ".claude/runtime/outputs/sse/dev",
62
+ "test": ".claude/runtime/outputs/sse/test",
63
+ "pr": ".claude/runtime/outputs/sse/pr",
64
64
  }
65
65
 
66
66
 
@@ -36,7 +36,7 @@
36
36
  {
37
37
  "matcher": "Write",
38
38
  "hooks": [
39
- { "type": "command", "command": "[ -x .claude/plugins/product-manager/hooks/pre-prp-check.sh ] && bash .claude/plugins/product-manager/hooks/pre-prp-check.sh; exit 0" }
39
+ { "type": "command", "command": "[ -x .claude/runtime/hooks/product-manager/pre-prp-check.sh ] && bash .claude/runtime/hooks/product-manager/pre-prp-check.sh; exit 0" }
40
40
  ]
41
41
  },
42
42
  {
@@ -50,18 +50,18 @@
50
50
  {
51
51
  "matcher": "Write",
52
52
  "hooks": [
53
- { "type": "command", "command": "[ -x .claude/plugins/product-manager/hooks/post-write-prd.sh ] && bash .claude/plugins/product-manager/hooks/post-write-prd.sh; exit 0" },
54
- { "type": "command", "command": "[ -x .claude/plugins/product-manager/hooks/post-write-prp.sh ] && bash .claude/plugins/product-manager/hooks/post-write-prp.sh; exit 0" },
55
- { "type": "command", "command": "[ -x .claude/plugins/staff-software-engineer/hooks/post-write-sse.sh ] && bash .claude/plugins/staff-software-engineer/hooks/post-write-sse.sh; exit 0" },
53
+ { "type": "command", "command": "[ -x .claude/runtime/hooks/product-manager/post-write-prd.sh ] && bash .claude/runtime/hooks/product-manager/post-write-prd.sh; exit 0" },
54
+ { "type": "command", "command": "[ -x .claude/runtime/hooks/product-manager/post-write-prp.sh ] && bash .claude/runtime/hooks/product-manager/post-write-prp.sh; exit 0" },
55
+ { "type": "command", "command": "[ -x .claude/runtime/hooks/staff-software-engineer/post-write-sse.sh ] && bash .claude/runtime/hooks/staff-software-engineer/post-write-sse.sh; exit 0" },
56
56
  { "type": "command", "command": "[ -x .claude/hooks/pipeline-postwrite.sh ] && bash .claude/hooks/pipeline-postwrite.sh; exit 0" }
57
57
  ]
58
58
  },
59
59
  {
60
60
  "matcher": "Edit",
61
61
  "hooks": [
62
- { "type": "command", "command": "[ -x .claude/plugins/product-manager/hooks/post-eval-prd.sh ] && bash .claude/plugins/product-manager/hooks/post-eval-prd.sh; exit 0" },
63
- { "type": "command", "command": "[ -x .claude/plugins/product-manager/hooks/post-eval-prp.sh ] && bash .claude/plugins/product-manager/hooks/post-eval-prp.sh; exit 0" },
64
- { "type": "command", "command": "[ -x .claude/plugins/staff-software-engineer/hooks/post-eval-sse.sh ] && bash .claude/plugins/staff-software-engineer/hooks/post-eval-sse.sh; exit 0" },
62
+ { "type": "command", "command": "[ -x .claude/runtime/hooks/product-manager/post-eval-prd.sh ] && bash .claude/runtime/hooks/product-manager/post-eval-prd.sh; exit 0" },
63
+ { "type": "command", "command": "[ -x .claude/runtime/hooks/product-manager/post-eval-prp.sh ] && bash .claude/runtime/hooks/product-manager/post-eval-prp.sh; exit 0" },
64
+ { "type": "command", "command": "[ -x .claude/runtime/hooks/staff-software-engineer/post-eval-sse.sh ] && bash .claude/runtime/hooks/staff-software-engineer/post-eval-sse.sh; exit 0" },
65
65
  { "type": "command", "command": "[ -x .claude/hooks/pipeline-postedit.sh ] && bash .claude/hooks/pipeline-postedit.sh; exit 0" }
66
66
  ]
67
67
  }
@@ -74,8 +74,8 @@
74
74
  "Bash(npm publish *)",
75
75
  "Bash(git tag *)",
76
76
  "Bash(sh -n /Users/pierryborges/Development/harness-kit/.claude/hooks/pipeline-session-start.sh)",
77
- "Bash(sh -n .claude/plugins/staff-software-engineer/hooks/post-write-sse.sh)",
78
- "Bash(sh -n .claude/plugins/staff-software-engineer/hooks/post-eval-sse.sh)",
77
+ "Bash(sh -n .claude/runtime/hooks/staff-software-engineer/post-write-sse.sh)",
78
+ "Bash(sh -n .claude/runtime/hooks/staff-software-engineer/post-eval-sse.sh)",
79
79
  "Bash(sh -n .claude/hooks/activity-pre-read.sh)",
80
80
  "Bash(sh -n .claude/hooks/status-line.sh)",
81
81
  "Read(//private/tmp/act-test/**)",
@@ -84,7 +84,15 @@
84
84
  "Bash(cp /Users/pierryborges/Development/harness-kit/.claude/hooks/status-line.sh .claude/hooks/)",
85
85
  "Bash(cp /Users/pierryborges/Development/harness-kit/.claude/scripts/pipeline.py .claude/scripts/)",
86
86
  "Bash(npx --yes tsc --noEmit -p tsconfig.json)",
87
- "Bash(ffmpeg -y -i out/demo.mp4 -vf 'fps=10,scale=720:-1:flags=lanczos,split[s0][s1];[s0]palettegen=max_colors=96[p];[s1][p]paletteuse=dither=bayer:bayer_scale=5' -loop 0 preview.gif)"
87
+ "Bash(ffmpeg -y -i out/demo.mp4 -vf 'fps=10,scale=720:-1:flags=lanczos,split[s0][s1];[s0]palettegen=max_colors=96[p];[s1][p]paletteuse=dither=bayer:bayer_scale=5' -loop 0 preview.gif)",
88
+ "WebFetch(domain:arxiv.org)",
89
+ "WebFetch(domain:openai.com)",
90
+ "Bash(grep -v \"^$\")",
91
+ "Bash(grep \"Error\\\\|^[^:]*:[^:]*:$\")",
92
+ "Bash(echo \"exit=$?\")",
93
+ "Bash(echo \"next exit=$? \\(expect 1, nothing to do\\)\")",
94
+ "Bash(:)",
95
+ "Bash(ffmpeg -y -i out/demo.mp4 -vf \"fps=8,scale=640:-1:flags=lanczos,split[s0][s1];[s0]palettegen=max_colors=64[p];[s1][p]paletteuse=dither=bayer:bayer_scale=5\" -loop 0 preview.gif)"
88
96
  ]
89
97
  }
90
98
  }
package/AGENTS.md ADDED
@@ -0,0 +1,141 @@
1
+ # AGENTS.md — Agent Registry & Routing
2
+
3
+ Source of truth for every agent, skill, and runtime path in this workspace.
4
+
5
+ This file is the **declarative spec**. Execution lives in `.claude/agents/` (definitions), `.claude/runtime/` (state, outputs), and `.claude/shared/` (cross-agent docs). Pipelines like `/sse:run` and `/product-manager:run` consult this registry when dispatching.
6
+
7
+ Portable across tools (Claude Code, Cursor, Codex) — all read `AGENTS.md` at the repo root.
8
+
9
+ ---
10
+
11
+ ## Quick map
12
+
13
+ ```
14
+ AGENTS.md ← this file: registry + routing
15
+ CLAUDE.md ← project context (style, role, conventions)
16
+ .claude/
17
+ ├── agents/ ← per-agent definitions + bundled assets
18
+ │ ├── product-manager/
19
+ │ │ ├── README.md
20
+ │ │ ├── sensors/ deterministic checks
21
+ │ │ ├── evals/ LLM-judge rubrics
22
+ │ │ ├── guides/ pipeline, writing style, templates, examples
23
+ │ │ └── skills/ prd, prp
24
+ │ ├── staff-software-engineer/
25
+ │ │ ├── README.md
26
+ │ │ ├── sensors/
27
+ │ │ ├── evals/
28
+ │ │ ├── guides/ pipeline, coding-style, commit-style, conventions-override
29
+ │ │ └── skills/ backend, web, mobile, devops
30
+ │ ├── product-manager.md orchestrator agent
31
+ │ └── staff-software-engineer.md orchestrator agent
32
+ ├── commands/ ← slash-command entry points
33
+ │ ├── product-manager/ /product-manager:{prd,prp,run}
34
+ │ ├── sse/ /sse:{plan,dev,test,pr,run}
35
+ │ └── pipeline/ /pipeline:{continue,reset}
36
+ ├── conventions/ ← generic conventions (overridable per repo)
37
+ ├── hooks/ ← root lifecycle hooks (session-start, prompt, postedit, postwrite, status-line, activity-pre-read)
38
+ ├── scripts/ ← root utilities (pipeline.py, activity.py, pr-monitor.py)
39
+ └── runtime/ ← generated artifacts + per-agent hooks/scripts
40
+ ├── outputs/
41
+ │ ├── pm/{prd,prp,tokens,.markers}/
42
+ │ └── sse/{plan,dev,test,pr,tokens,.markers}/
43
+ ├── hooks/
44
+ │ ├── product-manager/ phase markers, sensor gates, eval, publish
45
+ │ └── staff-software-engineer/
46
+ └── scripts/
47
+ ├── product-manager/ sensor-runner, token-phase, link-validator, confluence-publish
48
+ └── staff-software-engineer/ token-phase
49
+ ```
50
+
51
+ ---
52
+
53
+ ## Agent registry
54
+
55
+ ### Orchestrators
56
+
57
+ | Agent | When to use | Entry | Definition |
58
+ |---|---|---|---|
59
+ | `product-manager` | Generate PRD then PRP for a squad/feature | `/product-manager:run` | `.claude/agents/product-manager.md` |
60
+ | `staff-software-engineer` | Full engineering pipeline: plan → dev → test → pr | `/sse:run` | `.claude/agents/staff-software-engineer.md` |
61
+
62
+ ---
63
+
64
+ ## Routing
65
+
66
+ When the user types a slash command, the entry point is unambiguous. When the user describes work in natural language, the main session consults this routing table:
67
+
68
+ | User intent | Route |
69
+ |---|---|
70
+ | "ship a new feature end-to-end" | `staff-software-engineer` (`/sse:run` full pipeline) |
71
+ | "draft a PRD" | `product-manager` → `/product-manager:prd` |
72
+ | "draft a PRP" | `product-manager` → `/product-manager:prp` |
73
+ | "full PM pipeline" | `product-manager` → `/product-manager:run` |
74
+ | "make the plan" | `/sse:plan` |
75
+ | "implement the plan" | `/sse:dev` |
76
+ | "run tests" | `/sse:test` |
77
+ | "open the PR" | `/sse:pr` |
78
+ | "continue the active pipeline" | `/pipeline:continue` |
79
+ | "abandon active feature" | `/pipeline:reset` |
80
+
81
+ **Rule of thumb:** if you know the agent, invoke directly. If you only know the intent, this table dispatches.
82
+
83
+ ---
84
+
85
+ ## Pipeline stages
86
+
87
+ Six gated stages, one feature: `prd → prp → plan → dev → test → pr`.
88
+
89
+ Each stage:
90
+ 1. Writes a markdown artifact to `.claude/runtime/outputs/{pm,sse}/{stage}/{feature_id}.md`.
91
+ 2. Triggers deterministic sensors (markdown rules + Python runner) on save.
92
+ 3. Applies an LLM-judge eval rubric, retries on low score (up to 3).
93
+ 4. On approval, records token spend per phase under `.claude/runtime/outputs/{pm,sse}/tokens/{feature_id}.json`.
94
+
95
+ Phase markers under `.claude/runtime/outputs/{pm,sse}/.markers/` track stage boundaries (`{feature}.{phase}.{start,end}`) for token accounting and pipeline status.
96
+
97
+ ---
98
+
99
+ ## Runtime (state, outputs, hooks)
100
+
101
+ Generated artifacts and lifecycle hooks live under `.claude/runtime/`.
102
+
103
+ | Path | Contents |
104
+ |---|---|
105
+ | `runtime/outputs/pm/{prd,prp,tokens,.markers}/` | PRD/PRP artifacts, token JSONs, phase markers |
106
+ | `runtime/outputs/sse/{plan,dev,test,pr,tokens,.markers}/` | Plan/dev/test/pr artifacts, token JSONs, phase markers |
107
+ | `runtime/hooks/<agent>/` | Per-agent lifecycle hooks (post-write, post-eval, pre-prp-check) |
108
+ | `runtime/scripts/<agent>/` | Per-agent utilities (sensor-runner, token-phase, link-validator, confluence-publish) |
109
+
110
+ `settings.json` `hooks` blocks reference these paths. `.claude/scripts/pipeline.py` reads/writes markers and outputs.
111
+
112
+ ---
113
+
114
+ ## Distribution
115
+
116
+ This repo is **harness-kit**, the source-of-truth template. Consumer repos install the harness via `setup/install.sh`, which copies:
117
+
118
+ - `AGENTS.md` and `CLAUDE.md` to the target root
119
+ - `.claude/agents/`, `.claude/commands/`, `.claude/hooks/`, `.claude/scripts/`, `.claude/conventions/` to the target `.claude/`
120
+ - `.claude/runtime/hooks/`, `.claude/runtime/scripts/` to the target (definition-side only; `outputs/`, `state/`, `.markers/` are runtime, not distributed)
121
+ - `.claude/settings.json` `hooks` block, merged with the consumer's existing settings
122
+
123
+ `setup/update.sh` migrates v3.x consumers (which have `.claude/plugins/`) to v4.x layout in place. v3.x consumers were the **plugin-shaped** distribution.
124
+
125
+ ---
126
+
127
+ ## Adding a new agent
128
+
129
+ 1. Create `.claude/agents/<name>.md` (or `.claude/agents/<name>/agent.md` if bundled assets).
130
+ 2. Register here under the right section.
131
+ 3. If invocable via slash command, add `.claude/commands/<name>.md`.
132
+ 4. If it needs lifecycle hooks, add under `.claude/runtime/hooks/<name>/` and wire in `.claude/settings.json`.
133
+
134
+ ---
135
+
136
+ ## See also
137
+
138
+ - [`CLAUDE.md`](./CLAUDE.md) — workspace context, style, role
139
+ - [`.claude/commands/`](./.claude/commands/) — slash command definitions
140
+ - [`setup/install.sh`](./setup/install.sh) — consumer installer
141
+ - [`setup/update.sh`](./setup/update.sh) — v3→v4 migration tool
package/CLAUDE.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  Read by Claude Code on every session. Defines how to work in this harness-kit workspace.
4
4
 
5
+ **See [`AGENTS.md`](./AGENTS.md) for the full agent registry, routing table, and runtime paths.** Consult it whenever you need to decide which agent handles a request, where assets live, or how stages flow.
6
+
5
7
  ## Response Style
6
8
 
7
9
  - **Language:** match the user. Default English. Domain terms stay native.
@@ -29,9 +31,9 @@ AI copilot for product + engineering delivery. Thinking partner and execution as
29
31
 
30
32
  Configurable per consumer. Fill `context-library/business-info.md` and `context-library/squads/{slug}/` with your own structure. Ask which squad the work belongs to when not clear.
31
33
 
32
- ## Plugins
34
+ ## Agents
33
35
 
34
- This workspace ships two Claude Code plugins under `.claude/plugins/`. Both have their own README with full detail.
36
+ Two orchestrator agents, registered in [`AGENTS.md`](./AGENTS.md). Each lives under `.claude/agents/<name>/` with its own README, sensors, evals, guides, and skills.
35
37
 
36
38
  ### product-manager
37
39
 
@@ -40,7 +42,7 @@ PRD and PRP generation. Slash commands:
40
42
  - `/product-manager:prp` draft a PRP (engineering-ready spec)
41
43
  - `/product-manager:run` full PM pipeline
42
44
 
43
- Sub-agent `product-manager` is also Task-tool-invokable for delegation.
45
+ Sub-agent `product-manager` is also Task-tool-invokable for delegation. Assets: `.claude/agents/product-manager/`.
44
46
 
45
47
  ### staff-software-engineer
46
48
 
@@ -51,13 +53,13 @@ Engineering pipeline. Slash commands:
51
53
  - `/sse:pr` open the draft PR
52
54
  - `/sse:run` full SSE pipeline
53
55
 
54
- Sub-agent `staff-software-engineer` is also Task-tool-invokable.
56
+ Sub-agent `staff-software-engineer` is also Task-tool-invokable. Assets: `.claude/agents/staff-software-engineer/`.
55
57
 
56
58
  Full pipeline order: `prd → prp → plan → dev → test → pr`. Each stage gets an approval marker. The status bar tracks the current one.
57
59
 
58
60
  ## Project conventions override
59
61
 
60
- Each target repo can override SSE plugin defaults with files in `.claude/conventions/`:
62
+ Each target repo can override SSE defaults with files in `.claude/conventions/`:
61
63
 
62
64
  ```
63
65
  {repo}/.claude/conventions/
@@ -67,11 +69,11 @@ Each target repo can override SSE plugin defaults with files in `.claude/convent
67
69
  └── devops.md
68
70
  ```
69
71
 
70
- When a file exists, plugin reads it on top of defaults. Project wins. Reference: `.claude/plugins/staff-software-engineer/guides/conventions-override.md`.
72
+ When a file exists, the agent reads it on top of defaults. Project wins. Reference: `.claude/agents/staff-software-engineer/guides/conventions-override.md`.
71
73
 
72
74
  ## Token accounting and status bar
73
75
 
74
- After approval, hooks compute tokens used per phase from the Claude transcript and append to `outputs/tokens/{feature_id}.json` (per plugin). One JSON collects phases across the full lifecycle.
76
+ After approval, hooks compute tokens used per phase from the Claude transcript and append to `.claude/runtime/outputs/{pm,sse}/tokens/{feature_id}.json` (per agent). One JSON per agent collects phases across the full lifecycle.
75
77
 
76
78
  The status bar follows the active feature through the 6-stage pipeline. See `.claude/hooks/status-line.sh`.
77
79