Merge pull request 'DSH: install.sh --roles дописывает DSH-заметку в dev.md (#53)' (#54) from feat/53-dsh-role-notes into main
This commit is contained in:
commit
67ff56190c
@ -224,6 +224,12 @@ bash dsh/install.sh --global --skills --roles
|
||||
# mcp__codegraph__codegraph_explore.
|
||||
```
|
||||
|
||||
`--roles` also appends the DSH SDD note to `~/.dsh/roles/dev.md` (the bullet that
|
||||
points `dev` at the `sdd` skill). The note lives only in the installed copy: the
|
||||
shared `roles/dev.md` stays Claude Code-compatible, so a Claude session never
|
||||
sees DSH-only instructions. The insertion is idempotent — every `--roles` run
|
||||
recopies the role from the repository and re-inserts exactly one note.
|
||||
|
||||
Live checks:
|
||||
|
||||
1. New session: ask "what skills do you have?" — superpowers skills and the
|
||||
|
||||
@ -141,6 +141,11 @@ check() {
|
||||
else
|
||||
echo "WARN: roles not found; /role will fail until --roles is run" >&2
|
||||
fi
|
||||
if [ -f "$DSH_HOME/roles/dev.md" ] && grep -q 'В DSH-сессии исполнение плана' "$DSH_HOME/roles/dev.md"; then
|
||||
echo "ok: role dsh notes"
|
||||
else
|
||||
echo "WARN: role has no DSH SDD notes; run --roles" >&2
|
||||
fi
|
||||
echo "DSH_HOME=$DSH_HOME"
|
||||
return "$failed"
|
||||
}
|
||||
@ -224,6 +229,45 @@ install_roles() {
|
||||
echo "installed $count roles into $DSH_HOME/roles"
|
||||
}
|
||||
|
||||
# The DSH SDD note belongs to the installed role, not to the shared roles/ layer:
|
||||
# in Claude Code the note does not apply, so it is written here, after the copy,
|
||||
# and is idempotent (the source file is overwritten on every --roles run).
|
||||
install_role_dsh_notes() {
|
||||
local role="$DSH_HOME/roles/dev.md"
|
||||
[ -f "$role" ] || return 0
|
||||
python3 - "$role" <<'PY'
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
path = Path(sys.argv[1])
|
||||
text = path.read_text(encoding="utf-8")
|
||||
marker = "В DSH-сессии исполнение плана"
|
||||
if marker in text:
|
||||
print("ok: role dsh notes already present")
|
||||
raise SystemExit(0)
|
||||
note = (
|
||||
"- В DSH-сессии исполнение плана идёт по skill `sdd`, а не "
|
||||
"`subagent-driven-development`: асинхронный `subagent` (бриф и отчёт файлами, "
|
||||
"ожидание завершением хода и уведомлением, ledger "
|
||||
"`.superpowers/sdd/<plan>/progress.md` с `## Findings`, fix-loop до 5 раундов). "
|
||||
"Режим контроллера — по числу параллельных планов: один план — главная сессия, "
|
||||
"несколько — фоновый контроллер (нужен `maxDepth: 2` из "
|
||||
"`dsh/subagent-models.yml`). В Claude Code строка не действует: там исходный "
|
||||
"`subagent-driven-development`."
|
||||
)
|
||||
anchor = "- Режим по умолчанию: subagent-driven-development."
|
||||
lines = text.splitlines(keepends=True)
|
||||
for i, line in enumerate(lines):
|
||||
if line.startswith(anchor):
|
||||
lines.insert(i + 1, note + "\n")
|
||||
break
|
||||
else:
|
||||
lines.append((("" if text.endswith("\n") else "\n") + note + "\n"))
|
||||
path.write_text("".join(lines), encoding="utf-8")
|
||||
print("ok: role dsh notes inserted")
|
||||
PY
|
||||
}
|
||||
|
||||
print_bundle_step() {
|
||||
cat <<EOF
|
||||
|
||||
@ -251,6 +295,7 @@ if [ "$DO_SKILLS" = 1 ]; then
|
||||
fi
|
||||
if [ "$DO_ROLES" = 1 ]; then
|
||||
install_roles
|
||||
install_role_dsh_notes
|
||||
fi
|
||||
if [ "$DO_GLOBAL" = 1 ] || [ "$DO_SKILLS" = 1 ] || [ "$DO_ROLES" = 1 ]; then
|
||||
print_bundle_step
|
||||
|
||||
@ -52,11 +52,27 @@ test('install.sh copies skills and roles instead of linking into ~/.claude', ()
|
||||
assert.ok(existsSync(join(dshHome, 'roles', `${role}.md`)), `missing ${role}.md`)
|
||||
}
|
||||
|
||||
const devRole = join(dshHome, 'roles', 'dev.md')
|
||||
const devText = readFileSync(devRole, 'utf8')
|
||||
assert.match(devText, /В DSH-сессии исполнение плана идёт по skill `sdd`/)
|
||||
assert.match(devText, /`maxDepth: 2`/)
|
||||
assert.match(first.stdout, /role dsh notes/)
|
||||
assert.equal(countNotes(devText), 1, 'note must be inserted once')
|
||||
|
||||
const second = run()
|
||||
assert.equal(second.status, 0, second.stderr)
|
||||
assert.equal(lstatSync(skill).isSymbolicLink(), false)
|
||||
assert.ok(existsSync(roleSkill))
|
||||
assert.match(second.stdout, /role dsh notes/)
|
||||
assert.equal(countNotes(readFileSync(devRole, 'utf8')), 1, 'note must not duplicate')
|
||||
|
||||
const check = spawnSync('bash', [script, '--check'], { env, encoding: 'utf8' })
|
||||
assert.match(check.stdout, /ok: role dsh notes/)
|
||||
} finally {
|
||||
cleanup(home)
|
||||
}
|
||||
})
|
||||
|
||||
function countNotes(text) {
|
||||
return (text.match(/В DSH-сессии исполнение плана/g) ?? []).length
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user