@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.
- package/.claude/{plugins → agents}/product-manager/README.md +32 -30
- package/.claude/{plugins → agents}/product-manager/guides/examples/good-prp-example.md +2 -2
- package/.claude/{plugins → agents}/product-manager/guides/pipeline.md +7 -7
- package/.claude/{plugins → agents}/product-manager/sensors/prp-links.md +1 -1
- package/.claude/{plugins → agents}/product-manager/skills/prd/SKILL.md +2 -2
- package/.claude/{plugins → agents}/product-manager/skills/prp/SKILL.md +4 -4
- package/.claude/agents/product-manager.md +2 -2
- package/.claude/agents/staff-software-engineer/README.md +87 -0
- package/.claude/{plugins → agents}/staff-software-engineer/guides/conventions-override.md +3 -3
- package/.claude/{plugins → agents}/staff-software-engineer/guides/pipeline.md +4 -4
- package/.claude/{plugins → agents}/staff-software-engineer/sensors/dev-structure.md +2 -2
- package/.claude/{plugins → agents}/staff-software-engineer/sensors/pr-structure.md +3 -3
- package/.claude/{plugins → agents}/staff-software-engineer/sensors/test-structure.md +2 -2
- package/.claude/agents/staff-software-engineer.md +4 -4
- package/.claude/commands/pipeline/reset.md +1 -1
- package/.claude/commands/product-manager/prd.md +11 -11
- package/.claude/commands/product-manager/prp.md +12 -12
- package/.claude/commands/product-manager/run.md +4 -4
- package/.claude/commands/sse/dev.md +11 -11
- package/.claude/commands/sse/plan.md +11 -12
- package/.claude/commands/sse/pr.md +6 -7
- package/.claude/commands/sse/run.md +4 -4
- package/.claude/commands/sse/test.md +5 -5
- package/.claude/conventions/README.md +1 -1
- package/.claude/hooks/activity-pre-read.sh +4 -4
- package/.claude/hooks/status-line.sh +11 -11
- package/.claude/{plugins/product-manager/hooks → runtime/hooks/product-manager}/post-eval-prd.sh +11 -9
- package/.claude/{plugins/product-manager/hooks → runtime/hooks/product-manager}/post-eval-prp.sh +11 -9
- package/.claude/{plugins/product-manager/hooks → runtime/hooks/product-manager}/post-write-prd.sh +7 -5
- package/.claude/{plugins/product-manager/hooks → runtime/hooks/product-manager}/post-write-prp.sh +8 -6
- package/.claude/{plugins/product-manager/hooks → runtime/hooks/product-manager}/pre-prp-check.sh +5 -3
- package/.claude/{plugins/staff-software-engineer/hooks → runtime/hooks/staff-software-engineer}/post-eval-sse.sh +13 -11
- package/.claude/{plugins/staff-software-engineer/hooks → runtime/hooks/staff-software-engineer}/post-write-sse.sh +11 -9
- package/.claude/runtime/scripts/product-manager/__pycache__/confluence-publish.cpython-314.pyc +0 -0
- package/.claude/runtime/scripts/product-manager/__pycache__/link-validator.cpython-314.pyc +0 -0
- package/.claude/runtime/scripts/product-manager/__pycache__/sensor-runner.cpython-314.pyc +0 -0
- package/.claude/runtime/scripts/product-manager/__pycache__/token-phase.cpython-314.pyc +0 -0
- package/.claude/runtime/scripts/product-manager/confluence-publish.py +206 -0
- package/.claude/{plugins/product-manager/scripts → runtime/scripts/product-manager}/link-validator.py +1 -1
- package/.claude/{plugins/product-manager/scripts → runtime/scripts/product-manager}/token-phase.py +2 -2
- package/.claude/scripts/__pycache__/activity.cpython-314.pyc +0 -0
- package/.claude/scripts/__pycache__/pipeline.cpython-314.pyc +0 -0
- package/.claude/scripts/__pycache__/pr-monitor.cpython-314.pyc +0 -0
- package/.claude/scripts/pipeline.py +6 -6
- package/.claude/settings.json +7 -7
- package/.claude/settings.local.json +11 -3
- package/AGENTS.md +141 -0
- package/CLAUDE.md +9 -7
- package/README.md +88 -290
- package/VERSION +1 -1
- package/bin/hk.js +16 -8
- package/package.json +5 -3
- package/setup/install.sh +59 -40
- package/setup/update.sh +5 -0
- package/.claude/plugins/product-manager/scripts/confluence-publish.py +0 -205
- package/.claude/plugins/staff-software-engineer/README.md +0 -90
- /package/.claude/{plugins → agents}/product-manager/evals/prd-quality.md +0 -0
- /package/.claude/{plugins → agents}/product-manager/evals/prd-readiness.md +0 -0
- /package/.claude/{plugins → agents}/product-manager/evals/prp-context-readiness.md +0 -0
- /package/.claude/{plugins → agents}/product-manager/evals/prp-quality.md +0 -0
- /package/.claude/{plugins → agents}/product-manager/guides/examples/good-prd-example.md +0 -0
- /package/.claude/{plugins → agents}/product-manager/guides/prd-guidelines.md +0 -0
- /package/.claude/{plugins → agents}/product-manager/guides/product-guidelines.md +0 -0
- /package/.claude/{plugins → agents}/product-manager/guides/prp-guidelines.md +0 -0
- /package/.claude/{plugins → agents}/product-manager/guides/templates/prd.md +0 -0
- /package/.claude/{plugins → agents}/product-manager/guides/templates/prp.md +0 -0
- /package/.claude/{plugins → agents}/product-manager/guides/writing-style.md +0 -0
- /package/.claude/{plugins → agents}/product-manager/sensors/prd-acceptance-criteria.md +0 -0
- /package/.claude/{plugins → agents}/product-manager/sensors/prd-structure.md +0 -0
- /package/.claude/{plugins → agents}/product-manager/sensors/prp-context-quality.md +0 -0
- /package/.claude/{plugins → agents}/product-manager/sensors/prp-structure.md +0 -0
- /package/.claude/{plugins → agents}/staff-software-engineer/evals/dev-quality.md +0 -0
- /package/.claude/{plugins → agents}/staff-software-engineer/evals/plan-quality.md +0 -0
- /package/.claude/{plugins → agents}/staff-software-engineer/evals/pr-quality.md +0 -0
- /package/.claude/{plugins → agents}/staff-software-engineer/evals/test-quality.md +0 -0
- /package/.claude/{plugins → agents}/staff-software-engineer/guides/coding-style.md +0 -0
- /package/.claude/{plugins → agents}/staff-software-engineer/guides/commit-style.md +0 -0
- /package/.claude/{plugins → agents}/staff-software-engineer/sensors/code-conventions.md +0 -0
- /package/.claude/{plugins → agents}/staff-software-engineer/sensors/plan-structure.md +0 -0
- /package/.claude/{plugins → agents}/staff-software-engineer/sensors/test-coverage.md +0 -0
- /package/.claude/{plugins → agents}/staff-software-engineer/skills/backend/SKILL.md +0 -0
- /package/.claude/{plugins → agents}/staff-software-engineer/skills/devops/SKILL.md +0 -0
- /package/.claude/{plugins → agents}/staff-software-engineer/skills/mobile/SKILL.md +0 -0
- /package/.claude/{plugins → agents}/staff-software-engineer/skills/web/SKILL.md +0 -0
- /package/.claude/{plugins/product-manager/outputs → runtime/outputs/pm}/.markers/.gitkeep +0 -0
- /package/.claude/{plugins/staff-software-engineer/outputs → runtime/outputs/sse}/.markers/.gitkeep +0 -0
- /package/.claude/{plugins/product-manager/scripts → runtime/scripts/product-manager}/sensor-runner.py +0 -0
package/setup/install.sh
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
-
# harness-kit installer. Copies
|
|
3
|
-
#
|
|
4
|
-
#
|
|
2
|
+
# harness-kit installer (v4). Copies agents, runtime hooks/scripts,
|
|
3
|
+
# root hooks/scripts, slash commands, AGENTS.md/CLAUDE.md, and writes
|
|
4
|
+
# the wiring settings.json into a target repo. Reads VERSION at the
|
|
5
|
+
# repo root and records it in the target.
|
|
5
6
|
#
|
|
6
7
|
# Usage:
|
|
7
8
|
# bash /path/to/harness-kit/setup/install.sh [target-dir]
|
|
@@ -14,8 +15,8 @@ TARGET="${1:-${TARGET:-$(pwd)}}"
|
|
|
14
15
|
|
|
15
16
|
VERSION="$(cat "$SOURCE_ROOT/VERSION" 2>/dev/null || echo "0.0.0")"
|
|
16
17
|
|
|
17
|
-
if [ ! -d "$SOURCE_ROOT/.claude/
|
|
18
|
-
echo "missing
|
|
18
|
+
if [ ! -d "$SOURCE_ROOT/.claude/agents/product-manager" ]; then
|
|
19
|
+
echo "missing agents at $SOURCE_ROOT/.claude/agents/"
|
|
19
20
|
echo "clone the repo first, then re-run: git clone https://github.com/Pierry/harness-kit ~/.harness-kit"
|
|
20
21
|
exit 1
|
|
21
22
|
fi
|
|
@@ -33,47 +34,61 @@ else
|
|
|
33
34
|
echo "harness-kit v$VERSION installing at $TARGET"
|
|
34
35
|
fi
|
|
35
36
|
|
|
36
|
-
#
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
37
|
+
# Migrate legacy v3.x layout if detected. Backs up to .claude/.legacy-v3-backup/.
|
|
38
|
+
if [ -d "$TARGET/.claude/plugins" ]; then
|
|
39
|
+
echo " detected legacy v3.x plugins/ — backing up to .claude/.legacy-v3-backup/"
|
|
40
|
+
STAMP="$(date +%Y%m%d-%H%M%S)"
|
|
41
|
+
mkdir -p "$TARGET/.claude/.legacy-v3-backup"
|
|
42
|
+
mv "$TARGET/.claude/plugins" "$TARGET/.claude/.legacy-v3-backup/plugins.$STAMP"
|
|
43
|
+
fi
|
|
44
|
+
|
|
45
|
+
# 1) AGENTS.md + CLAUDE.md at the repo root.
|
|
46
|
+
cp "$SOURCE_ROOT/AGENTS.md" "$TARGET/AGENTS.md"
|
|
47
|
+
if [ ! -f "$TARGET/CLAUDE.md" ]; then
|
|
48
|
+
cp "$SOURCE_ROOT/CLAUDE.md" "$TARGET/CLAUDE.md"
|
|
49
|
+
fi
|
|
50
|
+
|
|
51
|
+
# 2) Agent definitions (sensors, evals, guides, skills, README + orchestrator .md)
|
|
52
|
+
mkdir -p "$TARGET/.claude/agents"
|
|
53
|
+
for agent in product-manager staff-software-engineer; do
|
|
54
|
+
rm -rf "$TARGET/.claude/agents/$agent"
|
|
55
|
+
cp -R "$SOURCE_ROOT/.claude/agents/$agent" "$TARGET/.claude/agents/$agent"
|
|
56
|
+
cp "$SOURCE_ROOT/.claude/agents/$agent.md" "$TARGET/.claude/agents/$agent.md"
|
|
57
|
+
done
|
|
58
|
+
|
|
59
|
+
# 3) Per-agent runtime hooks + scripts (NOT outputs — that's target-side state)
|
|
60
|
+
mkdir -p "$TARGET/.claude/runtime/hooks" "$TARGET/.claude/runtime/scripts" "$TARGET/.claude/runtime/outputs/pm/.markers" "$TARGET/.claude/runtime/outputs/sse/.markers"
|
|
61
|
+
for agent in product-manager staff-software-engineer; do
|
|
62
|
+
rm -rf "$TARGET/.claude/runtime/hooks/$agent"
|
|
63
|
+
cp -R "$SOURCE_ROOT/.claude/runtime/hooks/$agent" "$TARGET/.claude/runtime/hooks/$agent"
|
|
64
|
+
rm -rf "$TARGET/.claude/runtime/scripts/$agent"
|
|
65
|
+
cp -R "$SOURCE_ROOT/.claude/runtime/scripts/$agent" "$TARGET/.claude/runtime/scripts/$agent"
|
|
41
66
|
done
|
|
42
67
|
|
|
43
|
-
# Re-resolve symlinks in SSE scripts
|
|
44
|
-
for f in "$TARGET/.claude/
|
|
68
|
+
# Re-resolve symlinks in SSE scripts (point at PM's shared utilities)
|
|
69
|
+
for f in "$TARGET/.claude/runtime/scripts/staff-software-engineer/"*; do
|
|
45
70
|
if [ -L "$f" ]; then
|
|
46
71
|
name="$(basename "$f")"
|
|
47
72
|
rm "$f"
|
|
48
|
-
ln -sf "
|
|
73
|
+
ln -sf "../product-manager/$name" "$f"
|
|
49
74
|
fi
|
|
50
75
|
done
|
|
51
76
|
|
|
52
|
-
#
|
|
53
|
-
mkdir -p "$TARGET/.claude/commands"
|
|
77
|
+
# 4) Slash commands
|
|
78
|
+
mkdir -p "$TARGET/.claude/commands"
|
|
54
79
|
for ns in product-manager sse pipeline; do
|
|
55
80
|
rm -rf "$TARGET/.claude/commands/$ns"
|
|
56
81
|
cp -R "$SOURCE_ROOT/.claude/commands/$ns" "$TARGET/.claude/commands/$ns"
|
|
57
82
|
done
|
|
58
|
-
for agent in product-manager staff-software-engineer; do
|
|
59
|
-
cp "$SOURCE_ROOT/.claude/agents/$agent.md" "$TARGET/.claude/agents/$agent.md"
|
|
60
|
-
done
|
|
61
|
-
|
|
62
|
-
# Clean up legacy plugin layout from older installs
|
|
63
|
-
for plugin in product-manager staff-software-engineer; do
|
|
64
|
-
rm -rf "$TARGET/.claude/plugins/$plugin/commands" \
|
|
65
|
-
"$TARGET/.claude/plugins/$plugin/agents" \
|
|
66
|
-
"$TARGET/.claude/plugins/$plugin/.claude-plugin"
|
|
67
|
-
done
|
|
68
83
|
|
|
69
|
-
#
|
|
84
|
+
# 5) Root harness hooks (status-line + pipeline tracking + live activity)
|
|
70
85
|
mkdir -p "$TARGET/.claude/hooks"
|
|
71
86
|
for h in status-line.sh pipeline-prompt.sh pipeline-postwrite.sh pipeline-postedit.sh pipeline-session-start.sh activity-pre-read.sh; do
|
|
72
87
|
cp "$SOURCE_ROOT/.claude/hooks/$h" "$TARGET/.claude/hooks/$h"
|
|
73
88
|
chmod +x "$TARGET/.claude/hooks/$h"
|
|
74
89
|
done
|
|
75
90
|
|
|
76
|
-
#
|
|
91
|
+
# 6) Root harness scripts (pipeline state, activity, PR monitor, stage-card)
|
|
77
92
|
mkdir -p "$TARGET/.claude/scripts"
|
|
78
93
|
for s in pipeline.py activity.py pr-monitor.py; do
|
|
79
94
|
cp "$SOURCE_ROOT/.claude/scripts/$s" "$TARGET/.claude/scripts/$s"
|
|
@@ -81,7 +96,11 @@ for s in pipeline.py activity.py pr-monitor.py; do
|
|
|
81
96
|
done
|
|
82
97
|
cp "$SOURCE_ROOT/.claude/scripts/stage-card.md" "$TARGET/.claude/scripts/stage-card.md"
|
|
83
98
|
|
|
84
|
-
#
|
|
99
|
+
# 6.5) Strip any __pycache__/.pyc that hitched a ride from the source repo
|
|
100
|
+
find "$TARGET/.claude" -name __pycache__ -type d -prune -exec rm -rf {} + 2>/dev/null || true
|
|
101
|
+
find "$TARGET/.claude" -name "*.pyc" -type f -delete 2>/dev/null || true
|
|
102
|
+
|
|
103
|
+
# 7) settings.json (back up existing if content differs)
|
|
85
104
|
if [ -f "$TARGET/.claude/settings.json" ]; then
|
|
86
105
|
STAMP="$(date +%Y%m%d-%H%M%S)"
|
|
87
106
|
BACKUP="$TARGET/.claude/settings.json.bak.$STAMP"
|
|
@@ -99,8 +118,8 @@ cat > "$TARGET/.claude/settings.json" <<'EOF'
|
|
|
99
118
|
"Bash(npm:*)",
|
|
100
119
|
"Bash(gh:*)",
|
|
101
120
|
"Bash(jq:*)",
|
|
102
|
-
"Read(outputs/**)",
|
|
103
|
-
"Write(outputs/**)"
|
|
121
|
+
"Read(.claude/runtime/outputs/**)",
|
|
122
|
+
"Write(.claude/runtime/outputs/**)"
|
|
104
123
|
],
|
|
105
124
|
"deny": [
|
|
106
125
|
"Bash(rm -rf:*)",
|
|
@@ -128,7 +147,7 @@ cat > "$TARGET/.claude/settings.json" <<'EOF'
|
|
|
128
147
|
{
|
|
129
148
|
"matcher": "Write",
|
|
130
149
|
"hooks": [
|
|
131
|
-
{ "type": "command", "command": "[ -x .claude/
|
|
150
|
+
{ "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" }
|
|
132
151
|
]
|
|
133
152
|
},
|
|
134
153
|
{
|
|
@@ -142,18 +161,18 @@ cat > "$TARGET/.claude/settings.json" <<'EOF'
|
|
|
142
161
|
{
|
|
143
162
|
"matcher": "Write",
|
|
144
163
|
"hooks": [
|
|
145
|
-
{ "type": "command", "command": "[ -x .claude/
|
|
146
|
-
{ "type": "command", "command": "[ -x .claude/
|
|
147
|
-
{ "type": "command", "command": "[ -x .claude/
|
|
164
|
+
{ "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" },
|
|
165
|
+
{ "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" },
|
|
166
|
+
{ "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" },
|
|
148
167
|
{ "type": "command", "command": "[ -x .claude/hooks/pipeline-postwrite.sh ] && bash .claude/hooks/pipeline-postwrite.sh; exit 0" }
|
|
149
168
|
]
|
|
150
169
|
},
|
|
151
170
|
{
|
|
152
171
|
"matcher": "Edit",
|
|
153
172
|
"hooks": [
|
|
154
|
-
{ "type": "command", "command": "[ -x .claude/
|
|
155
|
-
{ "type": "command", "command": "[ -x .claude/
|
|
156
|
-
{ "type": "command", "command": "[ -x .claude/
|
|
173
|
+
{ "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" },
|
|
174
|
+
{ "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" },
|
|
175
|
+
{ "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" },
|
|
157
176
|
{ "type": "command", "command": "[ -x .claude/hooks/pipeline-postedit.sh ] && bash .claude/hooks/pipeline-postedit.sh; exit 0" }
|
|
158
177
|
]
|
|
159
178
|
}
|
|
@@ -172,16 +191,16 @@ if [ ! -f "$TARGET/.claude/conventions/README.md" ]; then
|
|
|
172
191
|
cat > "$TARGET/.claude/conventions/README.md" <<'EOF'
|
|
173
192
|
# Project Conventions
|
|
174
193
|
|
|
175
|
-
Override staff-software-engineer
|
|
194
|
+
Override staff-software-engineer defaults for this repo. Create files as needed:
|
|
176
195
|
|
|
177
196
|
- backend.md
|
|
178
197
|
- web.md
|
|
179
198
|
- mobile.md
|
|
180
199
|
- devops.md
|
|
181
200
|
|
|
182
|
-
When a file exists here,
|
|
201
|
+
When a file exists here, the agent reads it on top of defaults. Rules in this folder win.
|
|
183
202
|
|
|
184
|
-
See `.claude/
|
|
203
|
+
See `.claude/agents/staff-software-engineer/guides/conventions-override.md` for the full reference.
|
|
185
204
|
EOF
|
|
186
205
|
fi
|
|
187
206
|
|
package/setup/update.sh
CHANGED
|
@@ -3,6 +3,11 @@
|
|
|
3
3
|
# the installer. For npm installs, you must upgrade the package first:
|
|
4
4
|
# npm i -g @pieerry/harness-kit@latest
|
|
5
5
|
#
|
|
6
|
+
# v3.x → v4.x migration: install.sh detects a legacy .claude/plugins/ tree in
|
|
7
|
+
# the target and backs it up to .claude/.legacy-v3-backup/ before laying down
|
|
8
|
+
# the v4 structure (.claude/agents/, .claude/runtime/, AGENTS.md). Custom
|
|
9
|
+
# edits inside the legacy tree are preserved in the backup for manual merge.
|
|
10
|
+
#
|
|
6
11
|
# Usage:
|
|
7
12
|
# bash /path/to/harness-kit/setup/update.sh [target-dir]
|
|
8
13
|
|
|
@@ -1,205 +0,0 @@
|
|
|
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.request
|
|
26
|
-
from pathlib import Path
|
|
27
|
-
|
|
28
|
-
CONFLUENCE_BASE = "https://YOUR-DOMAIN.atlassian.net/wiki/rest/api/content"
|
|
29
|
-
SPACE_KEY = "TET1"
|
|
30
|
-
|
|
31
|
-
# Parent page IDs per kind. Override via env if needed.
|
|
32
|
-
PARENT_IDS = {
|
|
33
|
-
"prd": os.environ.get("CONFLUENCE_PARENT_PRD", "11351457795"),
|
|
34
|
-
"prp": os.environ.get("CONFLUENCE_PARENT_PRP", "11351457795"),
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
def md_to_storage(md: str) -> str:
|
|
39
|
-
"""Minimal Markdown to Confluence storage XHTML.
|
|
40
|
-
Good enough for headings, paragraphs, fenced code, lists, tables.
|
|
41
|
-
For richer rendering, swap for a real converter later.
|
|
42
|
-
"""
|
|
43
|
-
lines = md.splitlines()
|
|
44
|
-
out: list[str] = []
|
|
45
|
-
in_code = False
|
|
46
|
-
in_list: str | None = None # 'ul' or 'ol'
|
|
47
|
-
in_table = False
|
|
48
|
-
|
|
49
|
-
def close_list():
|
|
50
|
-
nonlocal in_list
|
|
51
|
-
if in_list:
|
|
52
|
-
out.append(f"</{in_list}>")
|
|
53
|
-
in_list = None
|
|
54
|
-
|
|
55
|
-
def close_table():
|
|
56
|
-
nonlocal in_table
|
|
57
|
-
if in_table:
|
|
58
|
-
out.append("</tbody></table>")
|
|
59
|
-
in_table = False
|
|
60
|
-
|
|
61
|
-
for line in lines:
|
|
62
|
-
if line.startswith("```"):
|
|
63
|
-
close_list()
|
|
64
|
-
close_table()
|
|
65
|
-
if not in_code:
|
|
66
|
-
lang = line[3:].strip() or "none"
|
|
67
|
-
out.append(
|
|
68
|
-
f'<ac:structured-macro ac:name="code">'
|
|
69
|
-
f'<ac:parameter ac:name="language">{html.escape(lang)}</ac:parameter>'
|
|
70
|
-
f'<ac:plain-text-body><![CDATA['
|
|
71
|
-
)
|
|
72
|
-
in_code = True
|
|
73
|
-
else:
|
|
74
|
-
out.append("]]></ac:plain-text-body></ac:structured-macro>")
|
|
75
|
-
in_code = False
|
|
76
|
-
continue
|
|
77
|
-
|
|
78
|
-
if in_code:
|
|
79
|
-
out.append(line)
|
|
80
|
-
continue
|
|
81
|
-
|
|
82
|
-
h = re.match(r"^(#{1,6})\s+(.+)$", line)
|
|
83
|
-
if h:
|
|
84
|
-
close_list()
|
|
85
|
-
close_table()
|
|
86
|
-
level = len(h.group(1))
|
|
87
|
-
out.append(f"<h{level}>{html.escape(h.group(2))}</h{level}>")
|
|
88
|
-
continue
|
|
89
|
-
|
|
90
|
-
if re.match(r"^[-*]\s+", line):
|
|
91
|
-
close_table()
|
|
92
|
-
if in_list != "ul":
|
|
93
|
-
close_list()
|
|
94
|
-
out.append("<ul>")
|
|
95
|
-
in_list = "ul"
|
|
96
|
-
item = re.sub(r"^[-*]\s+", "", line)
|
|
97
|
-
out.append(f"<li>{html.escape(item)}</li>")
|
|
98
|
-
continue
|
|
99
|
-
|
|
100
|
-
if re.match(r"^\d+\.\s+", line):
|
|
101
|
-
close_table()
|
|
102
|
-
if in_list != "ol":
|
|
103
|
-
close_list()
|
|
104
|
-
out.append("<ol>")
|
|
105
|
-
in_list = "ol"
|
|
106
|
-
item = re.sub(r"^\d+\.\s+", "", line)
|
|
107
|
-
out.append(f"<li>{html.escape(item)}</li>")
|
|
108
|
-
continue
|
|
109
|
-
|
|
110
|
-
if line.startswith("|") and "|" in line[1:]:
|
|
111
|
-
close_list()
|
|
112
|
-
cells = [c.strip() for c in line.strip("|").split("|")]
|
|
113
|
-
if not in_table:
|
|
114
|
-
out.append("<table><tbody>")
|
|
115
|
-
in_table = True
|
|
116
|
-
out.append(
|
|
117
|
-
"<tr>"
|
|
118
|
-
+ "".join(f"<th>{html.escape(c)}</th>" for c in cells)
|
|
119
|
-
+ "</tr>"
|
|
120
|
-
)
|
|
121
|
-
elif all(re.fullmatch(r":?-+:?", c) for c in cells):
|
|
122
|
-
# separator row, skip
|
|
123
|
-
pass
|
|
124
|
-
else:
|
|
125
|
-
out.append(
|
|
126
|
-
"<tr>"
|
|
127
|
-
+ "".join(f"<td>{html.escape(c)}</td>" for c in cells)
|
|
128
|
-
+ "</tr>"
|
|
129
|
-
)
|
|
130
|
-
continue
|
|
131
|
-
|
|
132
|
-
# paragraph or blank
|
|
133
|
-
close_list()
|
|
134
|
-
close_table()
|
|
135
|
-
if line.strip():
|
|
136
|
-
out.append(f"<p>{html.escape(line)}</p>")
|
|
137
|
-
|
|
138
|
-
close_list()
|
|
139
|
-
close_table()
|
|
140
|
-
return "\n".join(out)
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
def extract_title(md: str) -> str:
|
|
144
|
-
for line in md.splitlines():
|
|
145
|
-
m = re.match(r"^#\s+(.+)$", line)
|
|
146
|
-
if m:
|
|
147
|
-
return m.group(1).strip()
|
|
148
|
-
return "Untitled"
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
def main() -> int:
|
|
152
|
-
parser = argparse.ArgumentParser()
|
|
153
|
-
parser.add_argument("--artifact", required=True, type=Path)
|
|
154
|
-
parser.add_argument("--kind", required=True, choices=["prd", "prp"])
|
|
155
|
-
args = parser.parse_args()
|
|
156
|
-
|
|
157
|
-
username = os.environ.get("JIRA_USERNAME")
|
|
158
|
-
token = os.environ.get("JIRA_API_TOKEN")
|
|
159
|
-
if not username or not token:
|
|
160
|
-
print("[confluence-publish] JIRA_USERNAME/JIRA_API_TOKEN not set", file=sys.stderr)
|
|
161
|
-
return 1
|
|
162
|
-
|
|
163
|
-
md = args.artifact.read_text(encoding="utf-8")
|
|
164
|
-
title = extract_title(md)
|
|
165
|
-
storage = md_to_storage(md)
|
|
166
|
-
|
|
167
|
-
payload = {
|
|
168
|
-
"type": "page",
|
|
169
|
-
"title": title,
|
|
170
|
-
"ancestors": [{"id": PARENT_IDS[args.kind]}],
|
|
171
|
-
"space": {"key": SPACE_KEY},
|
|
172
|
-
"body": {"storage": {"value": storage, "representation": "storage"}},
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
auth = base64.b64encode(f"{username}:{token}".encode()).decode()
|
|
176
|
-
req = urllib.request.Request(
|
|
177
|
-
CONFLUENCE_BASE,
|
|
178
|
-
data=json.dumps(payload).encode("utf-8"),
|
|
179
|
-
method="POST",
|
|
180
|
-
headers={
|
|
181
|
-
"Authorization": f"Basic {auth}",
|
|
182
|
-
"Content-Type": "application/json",
|
|
183
|
-
"Accept": "application/json",
|
|
184
|
-
},
|
|
185
|
-
)
|
|
186
|
-
|
|
187
|
-
try:
|
|
188
|
-
with urllib.request.urlopen(req, timeout=20) as resp:
|
|
189
|
-
data = json.loads(resp.read().decode("utf-8"))
|
|
190
|
-
page_url = data.get("_links", {}).get("base", "") + data.get(
|
|
191
|
-
"_links", {}
|
|
192
|
-
).get("webui", "")
|
|
193
|
-
print(f"[confluence-publish] published: {page_url}", file=sys.stderr)
|
|
194
|
-
return 0
|
|
195
|
-
except urllib.error.HTTPError as e:
|
|
196
|
-
body = e.read().decode("utf-8", errors="replace")
|
|
197
|
-
print(f"[confluence-publish] HTTP {e.code}: {body[:500]}", file=sys.stderr)
|
|
198
|
-
return 1
|
|
199
|
-
except Exception as e:
|
|
200
|
-
print(f"[confluence-publish] error: {e}", file=sys.stderr)
|
|
201
|
-
return 1
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
if __name__ == "__main__":
|
|
205
|
-
sys.exit(main())
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
# Staff Software Engineer Plugin
|
|
2
|
-
|
|
3
|
-
Native Claude Code plugin for the engineering team. Drives plan, dev, test, and pr stages across backend, web, mobile, and devops. Per-project conventions in each repo's `.claude/conventions/` override plugin defaults.
|
|
4
|
-
|
|
5
|
-
## Slash commands
|
|
6
|
-
|
|
7
|
-
- `/sse:plan`: generate an implementation plan from an approved PRP
|
|
8
|
-
- `/sse:dev`: implement the plan in code, run convention gates
|
|
9
|
-
- `/sse:test`: run the project test suite
|
|
10
|
-
- `/sse:pr`: open the draft PR
|
|
11
|
-
- `/sse:run`: full pipeline, plan to pr
|
|
12
|
-
|
|
13
|
-
Also invokable as sub-agent via Task tool with `subagent_type: "staff-software-engineer"`.
|
|
14
|
-
|
|
15
|
-
## Tree
|
|
16
|
-
|
|
17
|
-
```
|
|
18
|
-
.claude/plugins/staff-software-engineer/
|
|
19
|
-
├── .claude-plugin/plugin.json
|
|
20
|
-
├── agents/staff-software-engineer.md sub-agent
|
|
21
|
-
├── commands/
|
|
22
|
-
│ ├── plan.md /sse:plan
|
|
23
|
-
│ ├── dev.md /sse:dev
|
|
24
|
-
│ ├── test.md /sse:test
|
|
25
|
-
│ ├── pr.md /sse:pr
|
|
26
|
-
│ └── run.md /sse:run
|
|
27
|
-
├── skills/
|
|
28
|
-
│ ├── backend/SKILL.md Java/Spring defaults
|
|
29
|
-
│ ├── web/SKILL.md Vue defaults
|
|
30
|
-
│ ├── mobile/SKILL.md iOS/Android defaults
|
|
31
|
-
│ └── devops/SKILL.md CI/IaC defaults
|
|
32
|
-
├── hooks/ phase markers, sensor gates
|
|
33
|
-
├── scripts/ symlinks to product-manager scripts
|
|
34
|
-
├── guides/
|
|
35
|
-
│ ├── pipeline.md retry, approval, token accounting
|
|
36
|
-
│ ├── coding-style.md team code style
|
|
37
|
-
│ ├── commit-style.md Conventional Commits with TICKET
|
|
38
|
-
│ └── conventions-override.md how project overrides work
|
|
39
|
-
├── sensors/ plan structure, code conventions, test coverage
|
|
40
|
-
├── evals/ plan quality rubric
|
|
41
|
-
└── outputs/
|
|
42
|
-
├── plan/ generated plans
|
|
43
|
-
├── dev/ dev summaries
|
|
44
|
-
├── test/ test results
|
|
45
|
-
├── pr/ opened PR records
|
|
46
|
-
├── tokens/ per-feature phase tokens JSON
|
|
47
|
-
└── .markers/ phase start/end markers (transient)
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
## How conventions work
|
|
51
|
-
|
|
52
|
-
The plugin holds team defaults per area. Each project repo can override by adding:
|
|
53
|
-
|
|
54
|
-
```
|
|
55
|
-
{repo-root}/.claude/conventions/{area}.md
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
Example for the `recon-service` repo:
|
|
59
|
-
|
|
60
|
-
```
|
|
61
|
-
recon-service/.claude/conventions/backend.md
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
Plugin skills read both. Project rules win. See `guides/conventions-override.md`.
|
|
65
|
-
|
|
66
|
-
## Where to edit
|
|
67
|
-
|
|
68
|
-
| Change | File |
|
|
69
|
-
|--------|------|
|
|
70
|
-
| Pipeline order | guides/pipeline.md |
|
|
71
|
-
| Retry count | guides/pipeline.md (Max attempts) |
|
|
72
|
-
| Plan template/rules | skills/backend/SKILL.md (etc per area), commands/plan.md |
|
|
73
|
-
| Eval threshold | evals/plan-quality.md (Threshold) |
|
|
74
|
-
| Code style | guides/coding-style.md |
|
|
75
|
-
| Commit format | guides/commit-style.md |
|
|
76
|
-
| Test command detection | commands/test.md |
|
|
77
|
-
| PR template | commands/pr.md, hooks/post-eval-pr.sh |
|
|
78
|
-
| Sensors | sensors/*.md |
|
|
79
|
-
|
|
80
|
-
## Connects to PM plugin
|
|
81
|
-
|
|
82
|
-
`/sse:run` reads the latest approved PRP from `.claude/plugins/product-manager/outputs/prp/`. The feature_id flows through: PM plugin creates `2026-05-12-billing-tz-fix`, SSE plugin reuses the same id and writes its phases to the same `outputs/tokens/{feature_id}.json` file (per `guides/pipeline.md`).
|
|
83
|
-
|
|
84
|
-
Full lifecycle in one JSON: PRD generate, PRD validate, PRP generate, PRP validate, plan generate, plan validate, dev, test, pr.
|
|
85
|
-
|
|
86
|
-
## Setup
|
|
87
|
-
|
|
88
|
-
Hooks registered in `.claude/settings.json` under PostToolUse. Token script reused from the PM plugin via symlinks in `scripts/`.
|
|
89
|
-
|
|
90
|
-
PR opening requires the `gh` CLI authenticated. `pr.md` command details ticket detection and template.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/.claude/{plugins/staff-software-engineer/outputs → runtime/outputs/sse}/.markers/.gitkeep
RENAMED
|
File without changes
|
|
File without changes
|