fix(dsh): sync — полный набор transform-ов (16), фикстура 15 скиллов (T1.1-T1.2, #69)
This commit is contained in:
parent
fce88f04d9
commit
6c003d1d86
@ -29,7 +29,10 @@
|
||||
* skill registry addresses skills by bare name.
|
||||
*
|
||||
* A missing anchor fails the run loudly: upstream rewrote text this port
|
||||
* depends on, so a human must decide what the DSH wording becomes.
|
||||
* depends on, so a human must decide what the DSH wording becomes. The one
|
||||
* exception is `optional: true` — a transform whose upstream text v7.0.1 has
|
||||
* already dropped: it is reported as a warning, not a failure, so the port
|
||||
* keeps the transform ready for the release that brings the text back.
|
||||
*
|
||||
* Usage:
|
||||
* node dsh/sync/sync-from-upstream.mjs <upstream-checkout> [--out <dir>] [--ref <tag>]
|
||||
@ -80,12 +83,15 @@ const SKIP = [
|
||||
'using-superpowers/references/pi-tools.md'
|
||||
]
|
||||
|
||||
/** Optional manifest of a reduced checkout (test fixtures); absent upstream. */
|
||||
const FIXTURE_MANIFEST = '.sync-fixture.json'
|
||||
const DSH_HOME = '$DSH_HOME'
|
||||
|
||||
/**
|
||||
* Explicit rewrites applied before the namespace strip. Each entry must match
|
||||
* exactly `expect` times, or the sync aborts.
|
||||
* exactly `expect` times, or the sync aborts — unless it is `optional: true`,
|
||||
* in which case an absent anchor is reported as a warning. Optional entries
|
||||
* exist for upstream deletions: v7.0.1 dropped the subagent hook example, but
|
||||
* an upstream release may bring it back, and the adaptation must then return
|
||||
* automatically instead of being silently absent from the transform list.
|
||||
*/
|
||||
const TRANSFORMS = [
|
||||
{
|
||||
@ -124,6 +130,142 @@ const TRANSFORMS = [
|
||||
' `subagent-driven-development`, `dispatching-parallel-agents`, and the rest.',
|
||||
'- `using-superpowers` itself is discoverable the same way.'
|
||||
].join('\n')
|
||||
},
|
||||
{
|
||||
name: 'brainstorming: DSH platform note for the visual companion',
|
||||
file: 'brainstorming/visual-companion.md',
|
||||
find: 'Browser-based visual brainstorming companion for showing mockups, diagrams, and options.\n',
|
||||
replace: [
|
||||
'Browser-based visual brainstorming companion for showing mockups, diagrams, and options.',
|
||||
'',
|
||||
'## Platform notes (DeepSeek Harness port)',
|
||||
'',
|
||||
'The companion server is `scripts/server.cjs` (plain Node.js, runs anywhere',
|
||||
'Node runs, including Windows). The `start-server.sh` / `stop-server.sh`',
|
||||
'helpers are bash-only: on Windows, start the server directly with',
|
||||
'`node scripts/server.cjs --project-dir <path> --open` and stop it by killing',
|
||||
'the process. All other guidance below is platform-neutral.',
|
||||
''
|
||||
].join('\n')
|
||||
},
|
||||
{
|
||||
name: 'executing-plans: DSH availability of subagents',
|
||||
file: 'executing-plans/SKILL.md',
|
||||
find: [
|
||||
'- You have a plan from superpowers:writing-plans and your human partner',
|
||||
' chose inline execution at the handoff.',
|
||||
'- Your harness has no subagent tool (see the per-platform references in',
|
||||
' `../using-superpowers/references/`). Never fabricate a dispatch; run',
|
||||
' the plan here.'
|
||||
].join('\n'),
|
||||
replace: [
|
||||
'- You have a plan from writing-plans and your human partner chose inline',
|
||||
' (Native) execution at the handoff.',
|
||||
'- No subagent tool is available in this session, or your human partner',
|
||||
' chose Native. On the DeepSeek Harness `subagent` / `subagent_fork`',
|
||||
' normally ARE available (see `../using-superpowers/references/dsh-tools.md`),',
|
||||
' so prefer subagent-driven-development; run the plan here when the work',
|
||||
' must stay in one context. Never fabricate a dispatch.'
|
||||
].join('\n')
|
||||
},
|
||||
{
|
||||
name: 'executing-plans: invoke sdd-workspace through bash',
|
||||
file: 'executing-plans/SKILL.md',
|
||||
find: '`../subagent-driven-development/scripts/sdd-workspace PLAN_FILE`',
|
||||
replace: '`bash ../subagent-driven-development/scripts/sdd-workspace PLAN_FILE`'
|
||||
},
|
||||
{
|
||||
name: 'executing-plans: invoke task-start through bash',
|
||||
file: 'executing-plans/SKILL.md',
|
||||
find: "Run this skill's `scripts/task-start PLAN_FILE N`.",
|
||||
replace: "Run this skill's `bash scripts/task-start PLAN_FILE N`."
|
||||
},
|
||||
{
|
||||
name: 'executing-plans: invoke task-done through bash',
|
||||
file: 'executing-plans/SKILL.md',
|
||||
find: "Run this skill's `scripts/task-done PLAN_FILE N BASE -- <test command>`",
|
||||
replace: "Run this skill's `bash scripts/task-done PLAN_FILE N BASE -- <test command>`"
|
||||
},
|
||||
{
|
||||
name: 'executing-plans: invoke review-package through bash',
|
||||
file: 'executing-plans/SKILL.md',
|
||||
find: 'Run `../subagent-driven-development/scripts/review-package PLAN_FILE MERGE_BASE HEAD`',
|
||||
replace: 'Run `bash ../subagent-driven-development/scripts/review-package PLAN_FILE MERGE_BASE HEAD`'
|
||||
},
|
||||
{
|
||||
name: 'executing-plans: task-start calls task-brief through bash',
|
||||
file: 'executing-plans/scripts/task-start',
|
||||
find: 'out=$("$sdd/task-brief" "$plan" "$n")',
|
||||
replace: 'out=$("${BASH:-bash}" "$sdd/task-brief" "$plan" "$n")'
|
||||
},
|
||||
{
|
||||
name: 'executing-plans: task-done calls sdd-workspace through bash',
|
||||
file: 'executing-plans/scripts/task-done',
|
||||
find: 'dir=$("$sdd/sdd-workspace" "$plan")',
|
||||
replace: 'dir=$("${BASH:-bash}" "$sdd/sdd-workspace" "$plan")'
|
||||
},
|
||||
{
|
||||
name: 'writing-skills: DSH skills directory replaces the cross-harness paths',
|
||||
file: 'writing-skills/SKILL.md',
|
||||
find: "**Personal skills live in your runtime's skills directory** (`~/.claude/skills/` on Claude Code) — see [codex-tools.md](../using-superpowers/references/codex-tools.md) or [gemini-tools.md](../using-superpowers/references/gemini-tools.md) for the path on those runtimes. Codex, Copilot CLI, and Gemini CLI all also recognize `~/.agents/skills/` as a cross-runtime alias.",
|
||||
replace: "**Personal skills live in your runtime's skills directory**: on the DeepSeek Harness, that is `" +
|
||||
DSH_HOME + "/skills/` (user level, discovered automatically by `skill-filesystem`), the project `.dsh/skills/` / " +
|
||||
'`.agents/skills/` roots, or — for packaged skills — the `skills/` directory inside a plugin bundle like this ' +
|
||||
'one. See [dsh-tools.md](../using-superpowers/references/dsh-tools.md) for the full mechanism.'
|
||||
},
|
||||
{
|
||||
// optional: upstream v7.0.1 dropped the hook example this transform rewrites.
|
||||
name: 'subagent-driven-development: hook example uses the DSH home',
|
||||
file: 'subagent-driven-development/SKILL.md',
|
||||
find: 'You: "User level (~/.config/superpowers/hooks/)"',
|
||||
replace: 'You: "Install the hook at the user level (' + DSH_HOME + ')"',
|
||||
optional: true
|
||||
},
|
||||
{
|
||||
name: 'diagnosing-superpowers: case workspace lives under the DSH home',
|
||||
file: 'diagnosing-superpowers/SKILL.md',
|
||||
find: '`~/.superpowers/diagnosing-superpowers/<session-id>/`',
|
||||
replace: '`' + DSH_HOME + '/diagnosing-superpowers/<session-id>/`'
|
||||
},
|
||||
{
|
||||
name: 'diagnosing-superpowers: case template uses the DSH home',
|
||||
file: 'diagnosing-superpowers/templates/case.md',
|
||||
find: 'Workspace: ~/.superpowers/diagnosing-superpowers/<session-id>/',
|
||||
replace: 'Workspace: ' + DSH_HOME + '/diagnosing-superpowers/<session-id>/'
|
||||
},
|
||||
{
|
||||
name: 'diagnosing-superpowers: report template uses the DSH home',
|
||||
file: 'diagnosing-superpowers/templates/report.md',
|
||||
find: 'Report path: ~/.superpowers/diagnosing-superpowers/<session-id>/report.md',
|
||||
replace: 'Report path: ' + DSH_HOME + '/diagnosing-superpowers/<session-id>/report.md'
|
||||
},
|
||||
{
|
||||
name: 'diagnosing-superpowers: DSH session discovery facts',
|
||||
file: 'diagnosing-superpowers/references/session-discovery.md',
|
||||
find: 'limitation and ask for the missing path, export, or identifying detail.',
|
||||
replace: [
|
||||
'limitation and ask for the missing path, export, or identifying detail.',
|
||||
'',
|
||||
'## DeepSeek Harness',
|
||||
'',
|
||||
'Verified in this environment; confirm it against the records you actually read.',
|
||||
'',
|
||||
'- Transcripts: `' + DSH_HOME + '/sessions/<slugified-cwd>/session-<uuid>/session*.jsonl.zstd`',
|
||||
' (`' + DSH_HOME + '` defaults to `~/.dsh`). The slug is the working directory with',
|
||||
' separators and non-alphanumeric characters folded to `-`, wrapped in `--`.',
|
||||
'- Child sessions — work dispatched through `subagent` / `subagent_fork` — are',
|
||||
' peer directories under the same slug whose header record carries',
|
||||
' `delegationDepth: 1`.',
|
||||
'- The schema version is in the filename (`session.v4.jsonl.zstd`; older files',
|
||||
' are `session.v3.jsonl.zstd` or `session.jsonl.zstd`). Read the header',
|
||||
" record's `version` instead of guessing from the name.",
|
||||
'- Each file is a concatenation of independent zstd frames, and the `zstd` CLI',
|
||||
' is usually absent. See `../using-superpowers/references/dsh-tools.md` for the',
|
||||
' frame-by-frame Node decompression command.',
|
||||
'- Records are JSON lines carrying `type`, `seq`, `time`, and `data`. Establish',
|
||||
' what each type means from the records themselves — never import a meaning',
|
||||
' from another harness.'
|
||||
].join('\n')
|
||||
}
|
||||
]
|
||||
|
||||
@ -198,13 +340,22 @@ function isTextFile(rel) {
|
||||
return TEXT_EXTENSIONS.has(rel.slice(dot))
|
||||
}
|
||||
|
||||
/** Apply every transform whose `file` matches, asserting the anchor exists. */
|
||||
function applyTransforms(rel, text, applied) {
|
||||
/**
|
||||
* Apply every transform whose `file` matches, asserting the anchor exists.
|
||||
* Optional transforms whose anchor is gone are collected for a warning.
|
||||
*/
|
||||
function applyTransforms(rel, text, applied, optionalMisses) {
|
||||
for (const t of TRANSFORMS) {
|
||||
if (t.file !== rel) continue
|
||||
if (t.find === t.replace) continue
|
||||
const count = text.split(t.find).length - 1
|
||||
if (count === 0) fail(`anchor missing in ${rel} for "${t.name}"\n find: ${JSON.stringify(t.find.slice(0, 120))}`)
|
||||
if (count === 0) {
|
||||
if (t.optional) {
|
||||
optionalMisses.push(t)
|
||||
continue
|
||||
}
|
||||
fail(`anchor missing in ${rel} for "${t.name}"\n find: ${JSON.stringify(t.find.slice(0, 120))}`)
|
||||
}
|
||||
if (count > 1) fail(`anchor matched ${count} times in ${rel} for "${t.name}"`)
|
||||
text = text.replace(t.find, t.replace)
|
||||
applied.add(t.name)
|
||||
@ -212,25 +363,6 @@ function applyTransforms(rel, text, applied) {
|
||||
return text
|
||||
}
|
||||
|
||||
/**
|
||||
* A real obra/superpowers checkout ships the 15 skills above; the minimal test
|
||||
* fixture ships two and declares them in `.sync-fixture.json`. The skill-set
|
||||
* assertion runs in both cases, against the declared set when one exists.
|
||||
*
|
||||
* @returns {Promise<{expected: string[], source: string}>}
|
||||
*/
|
||||
async function expectedSkillNames(upstreamRoot) {
|
||||
try {
|
||||
const manifest = JSON.parse(await readFile(join(upstreamRoot, FIXTURE_MANIFEST), 'utf8'))
|
||||
if (Array.isArray(manifest.expectedSkills) && manifest.expectedSkills.length > 0) {
|
||||
return { expected: manifest.expectedSkills, source: FIXTURE_MANIFEST }
|
||||
}
|
||||
} catch {
|
||||
/* real checkouts have no fixture manifest */
|
||||
}
|
||||
return { expected: UPSTREAM_SKILLS, source: 'UPSTREAM_SKILLS' }
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const args = parseArgs(process.argv.slice(2))
|
||||
const upstreamRoot = args.upstream
|
||||
@ -244,17 +376,16 @@ async function main() {
|
||||
// A new (or removed) upstream skill must be a deliberate decision: it
|
||||
// changes the skill catalog, the README tables, and possibly the DSH
|
||||
// adaptations.
|
||||
const { expected, source } = await expectedSkillNames(upstreamRoot)
|
||||
const upstreamSkillDirs = (await readdir(upstreamSkills, { withFileTypes: true }))
|
||||
.filter((entry) => entry.isDirectory())
|
||||
.map((entry) => entry.name)
|
||||
.sort()
|
||||
const expectedSorted = [...expected].sort()
|
||||
const expectedSorted = [...UPSTREAM_SKILLS].sort()
|
||||
if (upstreamSkillDirs.join('\n') !== expectedSorted.join('\n')) {
|
||||
const added = upstreamSkillDirs.filter((name) => !expectedSorted.includes(name))
|
||||
const removed = expectedSorted.filter((name) => !upstreamSkillDirs.includes(name))
|
||||
fail(
|
||||
`the upstream skill set changed (expected ${expectedSorted.length} skills from ${source}) — decide before syncing:\n` +
|
||||
`the upstream skill set changed (expected ${expectedSorted.length} skills from UPSTREAM_SKILLS) — decide before syncing:\n` +
|
||||
(added.length > 0 ? ` added upstream: ${added.join(', ')}\n` : '') +
|
||||
(removed.length > 0 ? ` removed upstream: ${removed.join(', ')}\n` : '') +
|
||||
' Update UPSTREAM_SKILLS in this script and the README skill tables.'
|
||||
@ -280,6 +411,7 @@ async function main() {
|
||||
await mkdir(staging, { recursive: true })
|
||||
|
||||
const applied = new Set()
|
||||
const optionalMisses = []
|
||||
let copied = 0
|
||||
let stripped = 0
|
||||
|
||||
@ -296,7 +428,7 @@ async function main() {
|
||||
}
|
||||
|
||||
let text = await readFile(sourceFile, 'utf8')
|
||||
text = applyTransforms(rel, text, applied)
|
||||
text = applyTransforms(rel, text, applied, optionalMisses)
|
||||
|
||||
const namespaced = text.split('superpowers:').length - 1
|
||||
if (namespaced > 0) {
|
||||
@ -314,12 +446,15 @@ async function main() {
|
||||
await cp(dshToolsOverride, overrideTarget)
|
||||
copied++
|
||||
|
||||
// Every transform that names a file must have fired; one that silently
|
||||
// stopped matching would drop a DSH adaptation from the next release's sync.
|
||||
const unfired = TRANSFORMS.filter((t) => t.find !== t.replace && !applied.has(t.name))
|
||||
// Every required transform must have fired; one that silently stopped
|
||||
// matching would drop a DSH adaptation from the next release's sync.
|
||||
const unfired = TRANSFORMS.filter((t) => t.find !== t.replace && !t.optional && !applied.has(t.name))
|
||||
if (unfired.length > 0) {
|
||||
fail(`transform(s) never matched a copied file: ${unfired.map((t) => `${t.name} (${t.file})`).join('; ')}`)
|
||||
}
|
||||
for (const t of optionalMisses) {
|
||||
console.warn(`[warn] optional transform did not match, anchor gone upstream: "${t.name}" (${t.file})`)
|
||||
}
|
||||
|
||||
await writeFile(
|
||||
join(staging, '.sync-meta.json'),
|
||||
|
||||
@ -1,4 +0,0 @@
|
||||
{
|
||||
"comment": "Reduced upstream checkout for tests. The skill-set assertion still runs, against this declared set instead of the 15 skills of a real obra/superpowers tree.",
|
||||
"expectedSkills": ["brainstorming", "using-superpowers"]
|
||||
}
|
||||
5
dsh/tests/fixtures/superpowers-min/skills/brainstorming/visual-companion.md
vendored
Normal file
5
dsh/tests/fixtures/superpowers-min/skills/brainstorming/visual-companion.md
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
# Visual companion
|
||||
|
||||
Browser-based visual brainstorming companion for showing mockups, diagrams, and options.
|
||||
|
||||
Minimal upstream stub for sync tests.
|
||||
10
dsh/tests/fixtures/superpowers-min/skills/diagnosing-superpowers/SKILL.md
vendored
Normal file
10
dsh/tests/fixtures/superpowers-min/skills/diagnosing-superpowers/SKILL.md
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
---
|
||||
name: diagnosing-superpowers
|
||||
description: Upstream stub for diagnosing-superpowers used by sync tests.
|
||||
---
|
||||
|
||||
# Diagnosing superpowers
|
||||
|
||||
Case workspace: `~/.superpowers/diagnosing-superpowers/<session-id>/`
|
||||
|
||||
Minimal upstream stub for sync tests.
|
||||
@ -0,0 +1,3 @@
|
||||
# Session discovery
|
||||
|
||||
When a record is missing, state the limitation and ask for the missing path, export, or identifying detail.
|
||||
3
dsh/tests/fixtures/superpowers-min/skills/diagnosing-superpowers/templates/case.md
vendored
Normal file
3
dsh/tests/fixtures/superpowers-min/skills/diagnosing-superpowers/templates/case.md
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
# Case
|
||||
|
||||
Workspace: ~/.superpowers/diagnosing-superpowers/<session-id>/
|
||||
3
dsh/tests/fixtures/superpowers-min/skills/diagnosing-superpowers/templates/report.md
vendored
Normal file
3
dsh/tests/fixtures/superpowers-min/skills/diagnosing-superpowers/templates/report.md
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
# Report
|
||||
|
||||
Report path: ~/.superpowers/diagnosing-superpowers/<session-id>/report.md
|
||||
8
dsh/tests/fixtures/superpowers-min/skills/dispatching-parallel-agents/SKILL.md
vendored
Normal file
8
dsh/tests/fixtures/superpowers-min/skills/dispatching-parallel-agents/SKILL.md
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
---
|
||||
name: dispatching-parallel-agents
|
||||
description: Upstream stub for dispatching-parallel-agents used by sync tests.
|
||||
---
|
||||
|
||||
# Dispatching parallel agents
|
||||
|
||||
Minimal upstream stub for sync tests. No DSH-specific text is rewritten here.
|
||||
20
dsh/tests/fixtures/superpowers-min/skills/executing-plans/SKILL.md
vendored
Normal file
20
dsh/tests/fixtures/superpowers-min/skills/executing-plans/SKILL.md
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
---
|
||||
name: executing-plans
|
||||
description: Upstream stub for executing-plans used by sync tests.
|
||||
---
|
||||
|
||||
# Executing plans
|
||||
|
||||
- You have a plan from superpowers:writing-plans and your human partner
|
||||
chose inline execution at the handoff.
|
||||
- Your harness has no subagent tool (see the per-platform references in
|
||||
`../using-superpowers/references/`). Never fabricate a dispatch; run
|
||||
the plan here.
|
||||
|
||||
Run this skill's `scripts/task-start PLAN_FILE N`.
|
||||
|
||||
Run this skill's `scripts/task-done PLAN_FILE N BASE -- <test command>`.
|
||||
|
||||
Use `../subagent-driven-development/scripts/sdd-workspace PLAN_FILE`.
|
||||
|
||||
Run `../subagent-driven-development/scripts/review-package PLAN_FILE MERGE_BASE HEAD`.
|
||||
6
dsh/tests/fixtures/superpowers-min/skills/executing-plans/scripts/task-done
vendored
Normal file
6
dsh/tests/fixtures/superpowers-min/skills/executing-plans/scripts/task-done
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
sdd=$(dirname "$0")
|
||||
plan=$1
|
||||
dir=$("$sdd/sdd-workspace" "$plan")
|
||||
printf '%s\n' "$dir"
|
||||
7
dsh/tests/fixtures/superpowers-min/skills/executing-plans/scripts/task-start
vendored
Normal file
7
dsh/tests/fixtures/superpowers-min/skills/executing-plans/scripts/task-start
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
sdd=$(dirname "$0")
|
||||
plan=$1
|
||||
n=$2
|
||||
out=$("$sdd/task-brief" "$plan" "$n")
|
||||
printf '%s\n' "$out"
|
||||
8
dsh/tests/fixtures/superpowers-min/skills/finishing-a-development-branch/SKILL.md
vendored
Normal file
8
dsh/tests/fixtures/superpowers-min/skills/finishing-a-development-branch/SKILL.md
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
---
|
||||
name: finishing-a-development-branch
|
||||
description: Upstream stub for finishing-a-development-branch used by sync tests.
|
||||
---
|
||||
|
||||
# Finishing a development branch
|
||||
|
||||
Minimal upstream stub for sync tests. No DSH-specific text is rewritten here.
|
||||
8
dsh/tests/fixtures/superpowers-min/skills/receiving-code-review/SKILL.md
vendored
Normal file
8
dsh/tests/fixtures/superpowers-min/skills/receiving-code-review/SKILL.md
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
---
|
||||
name: receiving-code-review
|
||||
description: Upstream stub for receiving-code-review used by sync tests.
|
||||
---
|
||||
|
||||
# Receiving code review
|
||||
|
||||
Minimal upstream stub for sync tests. No DSH-specific text is rewritten here.
|
||||
8
dsh/tests/fixtures/superpowers-min/skills/requesting-code-review/SKILL.md
vendored
Normal file
8
dsh/tests/fixtures/superpowers-min/skills/requesting-code-review/SKILL.md
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
---
|
||||
name: requesting-code-review
|
||||
description: Upstream stub for requesting-code-review used by sync tests.
|
||||
---
|
||||
|
||||
# Requesting code review
|
||||
|
||||
Minimal upstream stub for sync tests. No DSH-specific text is rewritten here.
|
||||
14
dsh/tests/fixtures/superpowers-min/skills/subagent-driven-development/SKILL.md
vendored
Normal file
14
dsh/tests/fixtures/superpowers-min/skills/subagent-driven-development/SKILL.md
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
---
|
||||
name: subagent-driven-development
|
||||
description: Upstream stub for subagent-driven-development used by sync tests.
|
||||
---
|
||||
|
||||
# Subagent-driven development
|
||||
|
||||
Setup example (upstream v7.0.0 wording, kept so the port exercises its
|
||||
home-dir transform; v7.0.1 dropped the example):
|
||||
|
||||
You: "User level (~/.config/superpowers/hooks/)"
|
||||
Human: "Project level"
|
||||
|
||||
Minimal upstream stub for sync tests.
|
||||
8
dsh/tests/fixtures/superpowers-min/skills/systematic-debugging/SKILL.md
vendored
Normal file
8
dsh/tests/fixtures/superpowers-min/skills/systematic-debugging/SKILL.md
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
---
|
||||
name: systematic-debugging
|
||||
description: Upstream stub for systematic-debugging used by sync tests.
|
||||
---
|
||||
|
||||
# Systematic debugging
|
||||
|
||||
Minimal upstream stub for sync tests. No DSH-specific text is rewritten here.
|
||||
8
dsh/tests/fixtures/superpowers-min/skills/test-driven-development/SKILL.md
vendored
Normal file
8
dsh/tests/fixtures/superpowers-min/skills/test-driven-development/SKILL.md
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
---
|
||||
name: test-driven-development
|
||||
description: Upstream stub for test-driven-development used by sync tests.
|
||||
---
|
||||
|
||||
# Test-driven development
|
||||
|
||||
Minimal upstream stub for sync tests. No DSH-specific text is rewritten here.
|
||||
8
dsh/tests/fixtures/superpowers-min/skills/using-git-worktrees/SKILL.md
vendored
Normal file
8
dsh/tests/fixtures/superpowers-min/skills/using-git-worktrees/SKILL.md
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
---
|
||||
name: using-git-worktrees
|
||||
description: Upstream stub for using-git-worktrees used by sync tests.
|
||||
---
|
||||
|
||||
# Using git worktrees
|
||||
|
||||
Minimal upstream stub for sync tests. No DSH-specific text is rewritten here.
|
||||
8
dsh/tests/fixtures/superpowers-min/skills/verification-before-completion/SKILL.md
vendored
Normal file
8
dsh/tests/fixtures/superpowers-min/skills/verification-before-completion/SKILL.md
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
---
|
||||
name: verification-before-completion
|
||||
description: Upstream stub for verification-before-completion used by sync tests.
|
||||
---
|
||||
|
||||
# Verification before completion
|
||||
|
||||
Minimal upstream stub for sync tests. No DSH-specific text is rewritten here.
|
||||
8
dsh/tests/fixtures/superpowers-min/skills/writing-plans/SKILL.md
vendored
Normal file
8
dsh/tests/fixtures/superpowers-min/skills/writing-plans/SKILL.md
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
---
|
||||
name: writing-plans
|
||||
description: Upstream stub for writing-plans used by sync tests.
|
||||
---
|
||||
|
||||
# Writing plans
|
||||
|
||||
Minimal upstream stub for sync tests. No DSH-specific text is rewritten here.
|
||||
10
dsh/tests/fixtures/superpowers-min/skills/writing-skills/SKILL.md
vendored
Normal file
10
dsh/tests/fixtures/superpowers-min/skills/writing-skills/SKILL.md
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
---
|
||||
name: writing-skills
|
||||
description: Upstream stub for writing-skills used by sync tests.
|
||||
---
|
||||
|
||||
# Writing skills
|
||||
|
||||
**Personal skills live in your runtime's skills directory** (`~/.claude/skills/` on Claude Code) — see [codex-tools.md](../using-superpowers/references/codex-tools.md) or [gemini-tools.md](../using-superpowers/references/gemini-tools.md) for the path on those runtimes. Codex, Copilot CLI, and Gemini CLI all also recognize `~/.agents/skills/` as a cross-runtime alias.
|
||||
|
||||
Minimal upstream stub for sync tests.
|
||||
@ -32,6 +32,10 @@ test('sync happy path: transforms, namespace strip, override, meta', () => {
|
||||
|
||||
assert.equal(result.status, 0, `stderr: ${result.stderr}`)
|
||||
assert.match(result.stdout, /synced \d+ files/)
|
||||
assert.match(result.stdout, /transforms applied: 16/)
|
||||
|
||||
const skillDirs = readdirSync(out).filter((name) => name !== '.sync-meta.json')
|
||||
assert.equal(skillDirs.length, 15, `expected all 15 upstream skills, got ${skillDirs.join(', ')}`)
|
||||
|
||||
const using = readFileSync(join(out, 'using-superpowers', 'SKILL.md'), 'utf8')
|
||||
assert.match(using, /references\/dsh-tools\.md/)
|
||||
@ -83,6 +87,26 @@ test('sync fails loud on a broken transform anchor and leaves --out untouched',
|
||||
}
|
||||
})
|
||||
|
||||
test('sync fails loud on a broken anchor of another transform', () => {
|
||||
const work = tempDir('dsh-sync-anchor-executing-plans-')
|
||||
try {
|
||||
const upstream = fixtureCopy(work)
|
||||
const skillPath = join(upstream, 'skills', 'executing-plans', 'SKILL.md')
|
||||
const anchor = 'Run `../subagent-driven-development/scripts/review-package PLAN_FILE MERGE_BASE HEAD`'
|
||||
const original = readFileSync(skillPath, 'utf8')
|
||||
assert.ok(original.includes(anchor), 'fixture must carry the review-package anchor verbatim')
|
||||
write(skillPath, original.replace(anchor, 'Run `../subagent-driven-development/scripts/review-package PLAN_FILE HEAD`'))
|
||||
|
||||
const result = runSync([upstream, '--out', join(work, 'out'), '--ref', 'v7.0.1'])
|
||||
|
||||
assert.equal(result.status, 1)
|
||||
assert.match(result.stderr, /invoke review-package through bash/)
|
||||
assert.equal(existsSync(join(work, 'out')), false)
|
||||
} finally {
|
||||
cleanup(work)
|
||||
}
|
||||
})
|
||||
|
||||
test('sync fails on a changed skill set', () => {
|
||||
const work = tempDir('dsh-sync-skill-set-')
|
||||
try {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user