claude-harness/dsh/tests/sdd-skill.test.mjs
Andrey Epifancev f714426b11 feat(dsh): skill sdd — асинхронный протокол исполнения плана (#41)
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>
2026-10-24 17:40:24 +04:00

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)
})