dsh/skills/sdd/SKILL.md: два режима контроллера (главная сессия / фоновый субагент), проверка глубины и маршрутов моделей, диспатч и отчёт файлами, контракт DONE/DONE_WITH_CONCERNS/NEEDS_CONTEXT/BLOCKED, ожидание через завершение хода и уведомление, ревью задачи и fix-loop 5 раундов, ledger с ## Findings, таблица отличий от Claude-SDD. Тесты: frontmatter, режимы, инструменты, маршруты, ledger, отсутствие job_output как ожидания; install.test.mjs ждёт два локальных skill. Co-Authored-By: DeepSeek Harness <noreply@deepseek.com>
65 lines
2.3 KiB
JavaScript
65 lines
2.3 KiB
JavaScript
import assert from 'node:assert/strict'
|
|
import { readFileSync } from 'node:fs'
|
|
import { dirname, join } from 'node:path'
|
|
import test from 'node:test'
|
|
import { fileURLToPath } from 'node:url'
|
|
|
|
const here = dirname(fileURLToPath(import.meta.url))
|
|
const skillPath = join(here, '..', 'skills', 'sdd', 'SKILL.md')
|
|
const text = () => readFileSync(skillPath, 'utf8')
|
|
|
|
test('sdd skill is model-invocable', () => {
|
|
const body = text()
|
|
assert.match(body, /^---\nname: sdd\n/)
|
|
assert.match(body, /\ndescription: .+/)
|
|
assert.ok(Buffer.byteLength(body) < 12288, 'skill is over the 12 KiB budget')
|
|
})
|
|
|
|
test('sdd skill describes both controller modes and the depth check', () => {
|
|
const body = text()
|
|
assert.match(body, /Режим 1/)
|
|
assert.match(body, /Режим 2/)
|
|
assert.match(body, /maxDepth: 2/)
|
|
assert.match(body, /глубин/)
|
|
assert.match(body, /откат/i)
|
|
})
|
|
|
|
test('sdd skill names the asynchronous tools and never job_output', () => {
|
|
const body = text()
|
|
for (const tool of ['subagent', 'send_message', 'list_agents', 'interrupt_agent']) {
|
|
assert.ok(body.includes(tool), `missing ${tool}`)
|
|
}
|
|
for (const line of body.split('\n').filter((l) => l.includes('job_output'))) {
|
|
assert.match(line, /не /i, `job_output proposed as a wait mechanism: ${line}`)
|
|
}
|
|
assert.match(body, /закончи ход/)
|
|
assert.match(body, /уведомлен/)
|
|
})
|
|
|
|
test('sdd skill fixes the report contract and the model routes', () => {
|
|
const body = text()
|
|
for (const status of ['DONE_WITH_CONCERNS', 'NEEDS_CONTEXT', 'BLOCKED']) {
|
|
assert.ok(body.includes(status), `missing status ${status}`)
|
|
}
|
|
assert.match(body, /deepseek-official\/deepseek-flash/)
|
|
assert.match(body, /deepseek-official\/deepseek-v4-pro/)
|
|
assert.match(body, /модель сессии/)
|
|
})
|
|
|
|
test('sdd skill requires the ledger with findings and statuses', () => {
|
|
const body = text()
|
|
assert.match(body, /## Findings/)
|
|
assert.match(body, /fixed <commit>/)
|
|
assert.match(body, /T<n>\.<k>/)
|
|
assert.match(body, /deferred/)
|
|
assert.match(body, /rejected <причина>/)
|
|
})
|
|
|
|
test('sdd skill states the difference from Claude SDD without claiming parity', () => {
|
|
const body = text()
|
|
assert.match(body, /синхронн/i)
|
|
assert.match(body, /асинхронн/i)
|
|
assert.match(body, /subagent-driven-development/)
|
|
assert.match(body, /не паритет/i)
|
|
})
|