sisyphi 1.2.18 → 1.2.19
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/dist/cli.js +165 -158
- package/dist/cli.js.map +1 -1
- package/dist/daemon.js +32 -0
- package/dist/daemon.js.map +1 -1
- package/dist/templates/agent-plugin/agents/review/CLAUDE.md +0 -1
- package/dist/templates/agent-suffix.md +9 -1
- package/dist/templates/orchestrator-base.md +13 -0
- package/dist/templates/orchestrator-plugin/hooks/goal-length-guard.sh +60 -0
- package/dist/templates/orchestrator-plugin/hooks/goal-read-advisory.sh +54 -0
- package/dist/templates/orchestrator-plugin/hooks/hooks.json +20 -0
- package/package.json +1 -1
- package/templates/agent-plugin/agents/review/CLAUDE.md +0 -1
- package/templates/agent-suffix.md +9 -1
- package/templates/orchestrator-base.md +13 -0
- package/templates/orchestrator-plugin/hooks/goal-length-guard.sh +60 -0
- package/templates/orchestrator-plugin/hooks/goal-read-advisory.sh +54 -0
- package/templates/orchestrator-plugin/hooks/hooks.json +20 -0
|
@@ -1,3 +1,2 @@
|
|
|
1
|
-
- **`reuse` dismissed entries cite `existing-file:line`** (the existing utility evaluated), not `file:line` (the new code) — the validation wave parses reuse dismissals differently from all other sub-agents.
|
|
2
1
|
- **No output ≠ clean**: a sub-agent that produces no output is treated as failed. The explicit clean sentence ("No X concerns — ...") is the signal the validation wave uses to skip spawning a validator.
|
|
3
2
|
- **Adding a sub-agent**: create `{name}.md` with frontmatter, add `subagent_type: {name}` to the scaling table in `review.md` step 4, and update the scaling guidance table if conditionally spawned — without the registration, the sub-agent is silently never spawned.
|
|
@@ -14,9 +14,17 @@ You are an agent in a sisyphus session.
|
|
|
14
14
|
|
|
15
15
|
If you're blocked by ambiguity, contradictions, or unclear requirements — **don't guess**. Submit what you found instead. A clear report is more valuable than a wrong implementation.
|
|
16
16
|
|
|
17
|
+
## The sis CLI
|
|
18
|
+
|
|
19
|
+
You operate inside a sisyphus session driven by the `sis` CLI. Run `sis <group> -h` to drill into any command.
|
|
20
|
+
|
|
21
|
+
{{HELP:.}}
|
|
22
|
+
|
|
17
23
|
## The User
|
|
18
24
|
|
|
19
|
-
A human may interact with you directly in your pane — if they do, prioritize their input over your original instruction. Otherwise, communicate through the orchestrator via reports.
|
|
25
|
+
A human may interact with you directly in your pane — if they do, prioritize their input over your original instruction. Otherwise, communicate through the orchestrator via reports.
|
|
26
|
+
|
|
27
|
+
**If the user complains about sisyphus itself** — a crash, a CLI that misbehaved, a confusing or broken workflow, behavior they disliked — file it with `sis feedback "<summary>"` (run `sis feedback -h`). Low-cost side-action; do it without asking. It's for the tool, not your task.
|
|
20
28
|
|
|
21
29
|
## Context
|
|
22
30
|
|
|
@@ -101,6 +101,16 @@ goal.md is a plain statement of what "done" looks like — scope boundaries and
|
|
|
101
101
|
**What belongs in goal.md:** the desired end state, what's in scope, what's out of scope.
|
|
102
102
|
**What doesn't:** approach decisions, technical choices, stage plans — those belong in strategy.md and context docs.
|
|
103
103
|
|
|
104
|
+
**Scope files keep goal.md lean.** goal.md is inlined into every wakeup and capped at 100 lines, so concrete detail about one slice of the goal does not belong inline — it taxes every cycle, including ones abstracted far away from that slice. When a part of the goal needs maintained detail (a subsystem, a workstream, a newly-authorized expansion), write `context/scope-<topic>.md` for it and add a one-line pointer under a `## Scope` list in goal.md:
|
|
105
|
+
|
|
106
|
+
```
|
|
107
|
+
## Scope
|
|
108
|
+
- context/scope-backend.md — DB + API-layer refactors for X
|
|
109
|
+
- context/scope-frontend.md — render-path cleanup for X
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
This is how scope *grows* without rewriting the goal: a mid-session "let's also do the microservices" becomes a new scope file linked from goal.md, never a condensed or deleted goal. Scope files are maintained like other context docs (current understanding, not history) and read on demand; strategy.md and roadmap.md point at the scope file a stage is focused on rather than restating it. A hook rejects any goal.md edit that leaves the file over 100 lines and tells you to offload into scope files.
|
|
113
|
+
|
|
104
114
|
### strategy.md — Your problem-solving map
|
|
105
115
|
|
|
106
116
|
strategy.md defines **how to approach this problem** — the stages, gates, backtrack edges, and behavioral style for this session. It is generated during discovery and progressively updated as the goal crystallizes or shifts.
|
|
@@ -225,6 +235,7 @@ Context dir contents are listed in your prompt each cycle. Read files when you n
|
|
|
225
235
|
- Roadmap items should **reference** context files: `"See context/{plan-lead-agent-id}/plan-stage-1-auth.md for detail."` Copy the path from the plan lead's submission report; don't reconstruct it.
|
|
226
236
|
- Agents writing requirements and designs save to the context dir with descriptive filenames: `requirements-auth.md`, `design-auth.md`. Plan agents save plans under their own subdirectory `context/{agent-id}/plan-*.md`; treat those paths as authoritative from the plan lead's report.
|
|
227
237
|
- **Implementation plans belong here**, not in roadmap.md
|
|
238
|
+
- **Scope files** (`context/scope-<topic>.md`) hold maintained detail for one slice of the goal, linked from goal.md's `## Scope` list — see the goal.md section. You write and maintain them directly, like strategy.md.
|
|
228
239
|
|
|
229
240
|
### Session Directory
|
|
230
241
|
|
|
@@ -284,6 +295,8 @@ You have unlimited cycles. Failed implementations, deferred issues, and skipped
|
|
|
284
295
|
|
|
285
296
|
## CLI Reference
|
|
286
297
|
|
|
298
|
+
{{HELP:.}}
|
|
299
|
+
|
|
287
300
|
{{HELP:session clone}}
|
|
288
301
|
|
|
289
302
|
## File Conflicts
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# PostToolUse(Write|Edit|MultiEdit) hook for the orchestrator: enforce the
|
|
3
|
+
# 100-line cap on goal.md. The edit has already landed (PostToolUse runs after
|
|
4
|
+
# success); if goal.md is now over the cap, emit a decision:block so the
|
|
5
|
+
# orchestrator must trim it and move the detail into context/scope-*.md before
|
|
6
|
+
# proceeding. Under the cap → silent passthrough.
|
|
7
|
+
|
|
8
|
+
if [ -z "$SISYPHUS_SESSION_ID" ] || [ -z "$SISYPHUS_SESSION_DIR" ]; then exit 0; fi
|
|
9
|
+
|
|
10
|
+
STDIN_JSON=$(cat)
|
|
11
|
+
|
|
12
|
+
FP=$(printf '%s' "$STDIN_JSON" | python3 -c "
|
|
13
|
+
import json, sys
|
|
14
|
+
try:
|
|
15
|
+
d = json.load(sys.stdin)
|
|
16
|
+
print((d.get('tool_input') or {}).get('file_path') or '')
|
|
17
|
+
except Exception:
|
|
18
|
+
pass
|
|
19
|
+
" 2>/dev/null)
|
|
20
|
+
|
|
21
|
+
[ -z "$FP" ] && exit 0
|
|
22
|
+
|
|
23
|
+
GOAL_FILE="$SISYPHUS_SESSION_DIR/goal.md"
|
|
24
|
+
|
|
25
|
+
SAME=$(python3 -c "
|
|
26
|
+
import os, sys
|
|
27
|
+
try:
|
|
28
|
+
print('1' if os.path.realpath(sys.argv[1]) == os.path.realpath(sys.argv[2]) else '0')
|
|
29
|
+
except Exception:
|
|
30
|
+
print('0')
|
|
31
|
+
" "$FP" "$GOAL_FILE" 2>/dev/null)
|
|
32
|
+
|
|
33
|
+
[ "$SAME" = "1" ] || exit 0
|
|
34
|
+
[ -f "$GOAL_FILE" ] || exit 0
|
|
35
|
+
|
|
36
|
+
LINES=$(python3 -c "
|
|
37
|
+
import sys
|
|
38
|
+
try:
|
|
39
|
+
with open(sys.argv[1], encoding='utf-8') as f:
|
|
40
|
+
print(sum(1 for _ in f))
|
|
41
|
+
except Exception:
|
|
42
|
+
print(0)
|
|
43
|
+
" "$GOAL_FILE" 2>/dev/null)
|
|
44
|
+
|
|
45
|
+
[ -z "$LINES" ] && exit 0
|
|
46
|
+
if [ "$LINES" -le 100 ]; then exit 0; fi
|
|
47
|
+
|
|
48
|
+
REASON=$(cat <<TXT
|
|
49
|
+
goal.md is now ${LINES} lines — over the 100-line cap. Trim it back to the north-star paragraph plus a "## Scope" reference list before continuing.
|
|
50
|
+
|
|
51
|
+
Move the detail you just added into context/scope-<topic>.md (the maintained home for one slice of the goal) and leave only a one-line pointer in goal.md:
|
|
52
|
+
- context/scope-<topic>.md — one-line description
|
|
53
|
+
|
|
54
|
+
Why the cap: goal.md is inlined into every orchestrator wakeup, so length here taxes every future cycle, even ones working far from this detail. Scope files are read on demand and can be referenced from strategy.md / roadmap.md. Restructure the over-cap detail into scope files rather than deleting still-relevant scope to fit.
|
|
55
|
+
TXT
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
ESCAPED=$(printf '%s' "$REASON" | python3 -c "import json,sys; print(json.dumps(sys.stdin.read()))")
|
|
59
|
+
echo "{\"decision\":\"block\",\"reason\":$ESCAPED,\"hookSpecificOutput\":{\"hookEventName\":\"PostToolUse\"}}"
|
|
60
|
+
exit 0
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# PostToolUse(Read) hook for the orchestrator: when the orchestrator reads
|
|
3
|
+
# goal.md, surface the scope-file convention. goal.md is inlined into every
|
|
4
|
+
# wakeup, so the orchestrator only Reads it when it intends to edit — that's
|
|
5
|
+
# the moment to remind it to push concrete detail into context/scope-*.md
|
|
6
|
+
# rather than into the goal. Neutral guidance (additionalContext), not a block.
|
|
7
|
+
|
|
8
|
+
if [ -z "$SISYPHUS_SESSION_ID" ] || [ -z "$SISYPHUS_SESSION_DIR" ]; then exit 0; fi
|
|
9
|
+
|
|
10
|
+
STDIN_JSON=$(cat)
|
|
11
|
+
|
|
12
|
+
FP=$(printf '%s' "$STDIN_JSON" | python3 -c "
|
|
13
|
+
import json, sys
|
|
14
|
+
try:
|
|
15
|
+
d = json.load(sys.stdin)
|
|
16
|
+
print((d.get('tool_input') or {}).get('file_path') or '')
|
|
17
|
+
except Exception:
|
|
18
|
+
pass
|
|
19
|
+
" 2>/dev/null)
|
|
20
|
+
|
|
21
|
+
[ -z "$FP" ] && exit 0
|
|
22
|
+
|
|
23
|
+
GOAL_FILE="$SISYPHUS_SESSION_DIR/goal.md"
|
|
24
|
+
|
|
25
|
+
# Only fire for the session's own goal.md (compare resolved paths).
|
|
26
|
+
SAME=$(python3 -c "
|
|
27
|
+
import os, sys
|
|
28
|
+
try:
|
|
29
|
+
print('1' if os.path.realpath(sys.argv[1]) == os.path.realpath(sys.argv[2]) else '0')
|
|
30
|
+
except Exception:
|
|
31
|
+
print('0')
|
|
32
|
+
" "$FP" "$GOAL_FILE" 2>/dev/null)
|
|
33
|
+
|
|
34
|
+
[ "$SAME" = "1" ] || exit 0
|
|
35
|
+
|
|
36
|
+
ADVISORY=$(cat <<'TXT'
|
|
37
|
+
Editing goal.md? Keep it to the north-star paragraph plus a `## Scope` list of references — nothing more. Put any concrete detail about one slice of the goal (a subsystem, a workstream, a newly-authorized expansion) in `context/scope-<topic>.md`, and link it from goal.md with a one-liner:
|
|
38
|
+
- context/scope-backend.md — DB + API-layer refactors for X
|
|
39
|
+
- context/scope-frontend.md — render-path cleanup for X
|
|
40
|
+
|
|
41
|
+
Why: goal.md is inlined into every orchestrator wakeup and capped at 100 lines, so per-slice detail here taxes every future cycle — even ones working far from that slice. Routing detail into scope files lets scope grow without rewriting the goal: a mid-session "let's also do the microservices" becomes a new scope file linked from goal.md, never a condensed or deleted goal. Maintain scope files like other context docs (current understanding, not history); they are read on demand, and strategy.md/roadmap.md point at whichever scope a stage is focused on.
|
|
42
|
+
TXT
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
printf '%s' "$ADVISORY" | python3 -c "
|
|
46
|
+
import json, sys
|
|
47
|
+
print(json.dumps({
|
|
48
|
+
'hookSpecificOutput': {
|
|
49
|
+
'hookEventName': 'PostToolUse',
|
|
50
|
+
'additionalContext': sys.stdin.read(),
|
|
51
|
+
}
|
|
52
|
+
}))
|
|
53
|
+
"
|
|
54
|
+
exit 0
|
|
@@ -9,6 +9,26 @@
|
|
|
9
9
|
}
|
|
10
10
|
]
|
|
11
11
|
}
|
|
12
|
+
],
|
|
13
|
+
"PostToolUse": [
|
|
14
|
+
{
|
|
15
|
+
"matcher": "Read",
|
|
16
|
+
"hooks": [
|
|
17
|
+
{
|
|
18
|
+
"type": "command",
|
|
19
|
+
"command": "bash ${CLAUDE_PLUGIN_ROOT}/hooks/goal-read-advisory.sh"
|
|
20
|
+
}
|
|
21
|
+
]
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"matcher": "Write|Edit|MultiEdit",
|
|
25
|
+
"hooks": [
|
|
26
|
+
{
|
|
27
|
+
"type": "command",
|
|
28
|
+
"command": "bash ${CLAUDE_PLUGIN_ROOT}/hooks/goal-length-guard.sh"
|
|
29
|
+
}
|
|
30
|
+
]
|
|
31
|
+
}
|
|
12
32
|
]
|
|
13
33
|
}
|
|
14
34
|
}
|
package/package.json
CHANGED
|
@@ -1,3 +1,2 @@
|
|
|
1
|
-
- **`reuse` dismissed entries cite `existing-file:line`** (the existing utility evaluated), not `file:line` (the new code) — the validation wave parses reuse dismissals differently from all other sub-agents.
|
|
2
1
|
- **No output ≠ clean**: a sub-agent that produces no output is treated as failed. The explicit clean sentence ("No X concerns — ...") is the signal the validation wave uses to skip spawning a validator.
|
|
3
2
|
- **Adding a sub-agent**: create `{name}.md` with frontmatter, add `subagent_type: {name}` to the scaling table in `review.md` step 4, and update the scaling guidance table if conditionally spawned — without the registration, the sub-agent is silently never spawned.
|
|
@@ -14,9 +14,17 @@ You are an agent in a sisyphus session.
|
|
|
14
14
|
|
|
15
15
|
If you're blocked by ambiguity, contradictions, or unclear requirements — **don't guess**. Submit what you found instead. A clear report is more valuable than a wrong implementation.
|
|
16
16
|
|
|
17
|
+
## The sis CLI
|
|
18
|
+
|
|
19
|
+
You operate inside a sisyphus session driven by the `sis` CLI. Run `sis <group> -h` to drill into any command.
|
|
20
|
+
|
|
21
|
+
{{HELP:.}}
|
|
22
|
+
|
|
17
23
|
## The User
|
|
18
24
|
|
|
19
|
-
A human may interact with you directly in your pane — if they do, prioritize their input over your original instruction. Otherwise, communicate through the orchestrator via reports.
|
|
25
|
+
A human may interact with you directly in your pane — if they do, prioritize their input over your original instruction. Otherwise, communicate through the orchestrator via reports.
|
|
26
|
+
|
|
27
|
+
**If the user complains about sisyphus itself** — a crash, a CLI that misbehaved, a confusing or broken workflow, behavior they disliked — file it with `sis feedback "<summary>"` (run `sis feedback -h`). Low-cost side-action; do it without asking. It's for the tool, not your task.
|
|
20
28
|
|
|
21
29
|
## Context
|
|
22
30
|
|
|
@@ -101,6 +101,16 @@ goal.md is a plain statement of what "done" looks like — scope boundaries and
|
|
|
101
101
|
**What belongs in goal.md:** the desired end state, what's in scope, what's out of scope.
|
|
102
102
|
**What doesn't:** approach decisions, technical choices, stage plans — those belong in strategy.md and context docs.
|
|
103
103
|
|
|
104
|
+
**Scope files keep goal.md lean.** goal.md is inlined into every wakeup and capped at 100 lines, so concrete detail about one slice of the goal does not belong inline — it taxes every cycle, including ones abstracted far away from that slice. When a part of the goal needs maintained detail (a subsystem, a workstream, a newly-authorized expansion), write `context/scope-<topic>.md` for it and add a one-line pointer under a `## Scope` list in goal.md:
|
|
105
|
+
|
|
106
|
+
```
|
|
107
|
+
## Scope
|
|
108
|
+
- context/scope-backend.md — DB + API-layer refactors for X
|
|
109
|
+
- context/scope-frontend.md — render-path cleanup for X
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
This is how scope *grows* without rewriting the goal: a mid-session "let's also do the microservices" becomes a new scope file linked from goal.md, never a condensed or deleted goal. Scope files are maintained like other context docs (current understanding, not history) and read on demand; strategy.md and roadmap.md point at the scope file a stage is focused on rather than restating it. A hook rejects any goal.md edit that leaves the file over 100 lines and tells you to offload into scope files.
|
|
113
|
+
|
|
104
114
|
### strategy.md — Your problem-solving map
|
|
105
115
|
|
|
106
116
|
strategy.md defines **how to approach this problem** — the stages, gates, backtrack edges, and behavioral style for this session. It is generated during discovery and progressively updated as the goal crystallizes or shifts.
|
|
@@ -225,6 +235,7 @@ Context dir contents are listed in your prompt each cycle. Read files when you n
|
|
|
225
235
|
- Roadmap items should **reference** context files: `"See context/{plan-lead-agent-id}/plan-stage-1-auth.md for detail."` Copy the path from the plan lead's submission report; don't reconstruct it.
|
|
226
236
|
- Agents writing requirements and designs save to the context dir with descriptive filenames: `requirements-auth.md`, `design-auth.md`. Plan agents save plans under their own subdirectory `context/{agent-id}/plan-*.md`; treat those paths as authoritative from the plan lead's report.
|
|
227
237
|
- **Implementation plans belong here**, not in roadmap.md
|
|
238
|
+
- **Scope files** (`context/scope-<topic>.md`) hold maintained detail for one slice of the goal, linked from goal.md's `## Scope` list — see the goal.md section. You write and maintain them directly, like strategy.md.
|
|
228
239
|
|
|
229
240
|
### Session Directory
|
|
230
241
|
|
|
@@ -284,6 +295,8 @@ You have unlimited cycles. Failed implementations, deferred issues, and skipped
|
|
|
284
295
|
|
|
285
296
|
## CLI Reference
|
|
286
297
|
|
|
298
|
+
{{HELP:.}}
|
|
299
|
+
|
|
287
300
|
{{HELP:session clone}}
|
|
288
301
|
|
|
289
302
|
## File Conflicts
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# PostToolUse(Write|Edit|MultiEdit) hook for the orchestrator: enforce the
|
|
3
|
+
# 100-line cap on goal.md. The edit has already landed (PostToolUse runs after
|
|
4
|
+
# success); if goal.md is now over the cap, emit a decision:block so the
|
|
5
|
+
# orchestrator must trim it and move the detail into context/scope-*.md before
|
|
6
|
+
# proceeding. Under the cap → silent passthrough.
|
|
7
|
+
|
|
8
|
+
if [ -z "$SISYPHUS_SESSION_ID" ] || [ -z "$SISYPHUS_SESSION_DIR" ]; then exit 0; fi
|
|
9
|
+
|
|
10
|
+
STDIN_JSON=$(cat)
|
|
11
|
+
|
|
12
|
+
FP=$(printf '%s' "$STDIN_JSON" | python3 -c "
|
|
13
|
+
import json, sys
|
|
14
|
+
try:
|
|
15
|
+
d = json.load(sys.stdin)
|
|
16
|
+
print((d.get('tool_input') or {}).get('file_path') or '')
|
|
17
|
+
except Exception:
|
|
18
|
+
pass
|
|
19
|
+
" 2>/dev/null)
|
|
20
|
+
|
|
21
|
+
[ -z "$FP" ] && exit 0
|
|
22
|
+
|
|
23
|
+
GOAL_FILE="$SISYPHUS_SESSION_DIR/goal.md"
|
|
24
|
+
|
|
25
|
+
SAME=$(python3 -c "
|
|
26
|
+
import os, sys
|
|
27
|
+
try:
|
|
28
|
+
print('1' if os.path.realpath(sys.argv[1]) == os.path.realpath(sys.argv[2]) else '0')
|
|
29
|
+
except Exception:
|
|
30
|
+
print('0')
|
|
31
|
+
" "$FP" "$GOAL_FILE" 2>/dev/null)
|
|
32
|
+
|
|
33
|
+
[ "$SAME" = "1" ] || exit 0
|
|
34
|
+
[ -f "$GOAL_FILE" ] || exit 0
|
|
35
|
+
|
|
36
|
+
LINES=$(python3 -c "
|
|
37
|
+
import sys
|
|
38
|
+
try:
|
|
39
|
+
with open(sys.argv[1], encoding='utf-8') as f:
|
|
40
|
+
print(sum(1 for _ in f))
|
|
41
|
+
except Exception:
|
|
42
|
+
print(0)
|
|
43
|
+
" "$GOAL_FILE" 2>/dev/null)
|
|
44
|
+
|
|
45
|
+
[ -z "$LINES" ] && exit 0
|
|
46
|
+
if [ "$LINES" -le 100 ]; then exit 0; fi
|
|
47
|
+
|
|
48
|
+
REASON=$(cat <<TXT
|
|
49
|
+
goal.md is now ${LINES} lines — over the 100-line cap. Trim it back to the north-star paragraph plus a "## Scope" reference list before continuing.
|
|
50
|
+
|
|
51
|
+
Move the detail you just added into context/scope-<topic>.md (the maintained home for one slice of the goal) and leave only a one-line pointer in goal.md:
|
|
52
|
+
- context/scope-<topic>.md — one-line description
|
|
53
|
+
|
|
54
|
+
Why the cap: goal.md is inlined into every orchestrator wakeup, so length here taxes every future cycle, even ones working far from this detail. Scope files are read on demand and can be referenced from strategy.md / roadmap.md. Restructure the over-cap detail into scope files rather than deleting still-relevant scope to fit.
|
|
55
|
+
TXT
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
ESCAPED=$(printf '%s' "$REASON" | python3 -c "import json,sys; print(json.dumps(sys.stdin.read()))")
|
|
59
|
+
echo "{\"decision\":\"block\",\"reason\":$ESCAPED,\"hookSpecificOutput\":{\"hookEventName\":\"PostToolUse\"}}"
|
|
60
|
+
exit 0
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# PostToolUse(Read) hook for the orchestrator: when the orchestrator reads
|
|
3
|
+
# goal.md, surface the scope-file convention. goal.md is inlined into every
|
|
4
|
+
# wakeup, so the orchestrator only Reads it when it intends to edit — that's
|
|
5
|
+
# the moment to remind it to push concrete detail into context/scope-*.md
|
|
6
|
+
# rather than into the goal. Neutral guidance (additionalContext), not a block.
|
|
7
|
+
|
|
8
|
+
if [ -z "$SISYPHUS_SESSION_ID" ] || [ -z "$SISYPHUS_SESSION_DIR" ]; then exit 0; fi
|
|
9
|
+
|
|
10
|
+
STDIN_JSON=$(cat)
|
|
11
|
+
|
|
12
|
+
FP=$(printf '%s' "$STDIN_JSON" | python3 -c "
|
|
13
|
+
import json, sys
|
|
14
|
+
try:
|
|
15
|
+
d = json.load(sys.stdin)
|
|
16
|
+
print((d.get('tool_input') or {}).get('file_path') or '')
|
|
17
|
+
except Exception:
|
|
18
|
+
pass
|
|
19
|
+
" 2>/dev/null)
|
|
20
|
+
|
|
21
|
+
[ -z "$FP" ] && exit 0
|
|
22
|
+
|
|
23
|
+
GOAL_FILE="$SISYPHUS_SESSION_DIR/goal.md"
|
|
24
|
+
|
|
25
|
+
# Only fire for the session's own goal.md (compare resolved paths).
|
|
26
|
+
SAME=$(python3 -c "
|
|
27
|
+
import os, sys
|
|
28
|
+
try:
|
|
29
|
+
print('1' if os.path.realpath(sys.argv[1]) == os.path.realpath(sys.argv[2]) else '0')
|
|
30
|
+
except Exception:
|
|
31
|
+
print('0')
|
|
32
|
+
" "$FP" "$GOAL_FILE" 2>/dev/null)
|
|
33
|
+
|
|
34
|
+
[ "$SAME" = "1" ] || exit 0
|
|
35
|
+
|
|
36
|
+
ADVISORY=$(cat <<'TXT'
|
|
37
|
+
Editing goal.md? Keep it to the north-star paragraph plus a `## Scope` list of references — nothing more. Put any concrete detail about one slice of the goal (a subsystem, a workstream, a newly-authorized expansion) in `context/scope-<topic>.md`, and link it from goal.md with a one-liner:
|
|
38
|
+
- context/scope-backend.md — DB + API-layer refactors for X
|
|
39
|
+
- context/scope-frontend.md — render-path cleanup for X
|
|
40
|
+
|
|
41
|
+
Why: goal.md is inlined into every orchestrator wakeup and capped at 100 lines, so per-slice detail here taxes every future cycle — even ones working far from that slice. Routing detail into scope files lets scope grow without rewriting the goal: a mid-session "let's also do the microservices" becomes a new scope file linked from goal.md, never a condensed or deleted goal. Maintain scope files like other context docs (current understanding, not history); they are read on demand, and strategy.md/roadmap.md point at whichever scope a stage is focused on.
|
|
42
|
+
TXT
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
printf '%s' "$ADVISORY" | python3 -c "
|
|
46
|
+
import json, sys
|
|
47
|
+
print(json.dumps({
|
|
48
|
+
'hookSpecificOutput': {
|
|
49
|
+
'hookEventName': 'PostToolUse',
|
|
50
|
+
'additionalContext': sys.stdin.read(),
|
|
51
|
+
}
|
|
52
|
+
}))
|
|
53
|
+
"
|
|
54
|
+
exit 0
|
|
@@ -9,6 +9,26 @@
|
|
|
9
9
|
}
|
|
10
10
|
]
|
|
11
11
|
}
|
|
12
|
+
],
|
|
13
|
+
"PostToolUse": [
|
|
14
|
+
{
|
|
15
|
+
"matcher": "Read",
|
|
16
|
+
"hooks": [
|
|
17
|
+
{
|
|
18
|
+
"type": "command",
|
|
19
|
+
"command": "bash ${CLAUDE_PLUGIN_ROOT}/hooks/goal-read-advisory.sh"
|
|
20
|
+
}
|
|
21
|
+
]
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"matcher": "Write|Edit|MultiEdit",
|
|
25
|
+
"hooks": [
|
|
26
|
+
{
|
|
27
|
+
"type": "command",
|
|
28
|
+
"command": "bash ${CLAUDE_PLUGIN_ROOT}/hooks/goal-length-guard.sh"
|
|
29
|
+
}
|
|
30
|
+
]
|
|
31
|
+
}
|
|
12
32
|
]
|
|
13
33
|
}
|
|
14
34
|
}
|