@ancleto/spec 0.6.2 → 0.6.5
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/README.md +184 -91
- package/agents/coder.md +11 -11
- package/agents/documenter.md +27 -27
- package/agents/orchestrator.md +8 -8
- package/agents/reviewer.md +13 -13
- package/agents/spec-writer.md +11 -11
- package/agents/technical-discovery.md +5 -5
- package/agents/technical-seed-writer.md +1 -1
- package/agents/tester.md +9 -9
- package/commands/{opsx-apply.md → cleto-apply.md} +9 -9
- package/commands/{opsx-archive.md → cleto-archive.md} +16 -16
- package/commands/{opsx-bulk-archive.md → cleto-bulk-archive.md} +8 -8
- package/commands/{opsx-continue.md → cleto-continue.md} +8 -8
- package/commands/{opsx-explore.md → cleto-explore.md} +9 -9
- package/commands/{opsx-ff.md → cleto-ff.md} +10 -12
- package/commands/{opsx-new.md → cleto-new.md} +12 -14
- package/commands/{opsx-onboard.md → cleto-onboard.md} +45 -57
- package/commands/{opsx-propose.md → cleto-propose.md} +11 -13
- package/commands/{opsx-recall.md → cleto-recall.md} +6 -6
- package/commands/{opsx-sync.md → cleto-sync.md} +6 -6
- package/commands/{opsx-verify.md → cleto-verify.md} +5 -5
- package/package.json +2 -2
- package/skills/{openspec-apply → ancleto-apply}/SKILL.md +6 -6
- package/skills/{openspec-archive → ancleto-archive}/SKILL.md +10 -10
- package/skills/{openspec-bulk-archive → ancleto-bulk-archive}/SKILL.md +8 -8
- package/skills/{openspec-continue → ancleto-continue}/SKILL.md +7 -7
- package/skills/{openspec-explore → ancleto-explore}/SKILL.md +6 -6
- package/skills/{openspec-ff → ancleto-ff}/SKILL.md +4 -4
- package/skills/{openspec-new → ancleto-new}/SKILL.md +6 -6
- package/skills/{openspec-onboard → ancleto-onboard}/SKILL.md +20 -20
- package/skills/{openspec-propose → ancleto-propose}/SKILL.md +6 -6
- package/skills/{openspec-recall → ancleto-recall}/SKILL.md +3 -3
- package/skills/{openspec-sync-specs → ancleto-sync-specs}/SKILL.md +7 -7
- package/skills/ancleto-upgrade/SKILL.md +11 -13
- package/skills/ancleto-upgrade/references/templates.md +1 -1
- package/skills/{openspec-verify → ancleto-verify}/SKILL.md +5 -5
- package/skills/{openspec-workflow → ancleto-workflow}/SKILL.md +19 -19
- package/skills/triage-clarifier/SKILL.md +1 -1
- package/src/cli/index.js +40 -20
- package/templates/AGENTS.md +4 -4
- package/templates/PRODUCT.md +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
2
|
+
name: ancleto-verify
|
|
3
3
|
description: Verify an implementation against its change artifacts (completeness, correctness, coherence). Use before archiving a change. Captures architectural findings into persistent memory. No external binaries required.
|
|
4
4
|
license: MIT
|
|
5
5
|
compatibility: No external binaries required. Works with any agent runtime.
|
|
@@ -8,11 +8,11 @@ metadata:
|
|
|
8
8
|
version: '1.0'
|
|
9
9
|
---
|
|
10
10
|
|
|
11
|
-
#
|
|
11
|
+
# aspec Verify
|
|
12
12
|
|
|
13
13
|
Verify that an implementation matches its change artifacts (proposal, design, tasks, delta specs) by reading the files directly. No external binaries are invoked.
|
|
14
14
|
|
|
15
|
-
**Input**: Optionally specify a change name (e.g., `add-auth`). If omitted, check if it can be inferred from conversation context. If vague or ambiguous, list the directories under `
|
|
15
|
+
**Input**: Optionally specify a change name (e.g., `add-auth`). If omitted, check if it can be inferred from conversation context. If vague or ambiguous, list the directories under `aspec/changes/` that contain a `tasks.md` file and ask the user to select. Mark changes with incomplete tasks as "(In Progress)".
|
|
16
16
|
|
|
17
17
|
**IMPORTANT**: Do NOT guess or auto-select a change. Always let the user choose.
|
|
18
18
|
|
|
@@ -20,7 +20,7 @@ Verify that an implementation matches its change artifacts (proposal, design, ta
|
|
|
20
20
|
|
|
21
21
|
### 1. Load the change artifacts
|
|
22
22
|
|
|
23
|
-
Read everything under `
|
|
23
|
+
Read everything under `aspec/changes/<name>/`:
|
|
24
24
|
|
|
25
25
|
- `tasks.md` — the checklist (required)
|
|
26
26
|
- `proposal.md`, `design.md` — intent and decisions (if present)
|
|
@@ -36,7 +36,7 @@ Read everything under `openspec/changes/<name>/`:
|
|
|
36
36
|
|
|
37
37
|
**Spec Coverage:**
|
|
38
38
|
|
|
39
|
-
- If delta specs exist in `
|
|
39
|
+
- If delta specs exist in `aspec/changes/<name>/specs/`:
|
|
40
40
|
- Extract all requirements (marked with `### Requirement:`).
|
|
41
41
|
- For each requirement, search the codebase for keywords related to it and assess whether implementation likely exists.
|
|
42
42
|
- If a requirement appears unimplemented, add a CRITICAL issue: "Requirement not found: `<requirement name>`" with the recommendation "Implement requirement: `<description>`".
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
2
|
+
name: ancleto-workflow
|
|
3
3
|
description: Router for the spec-driven lifecycle — know which stage you're in and which skill runs next. Use when unsure where a request fits, or to explain the full cycle. No external binaries required.
|
|
4
4
|
license: MIT
|
|
5
5
|
compatibility: No external binaries required. Works with any agent runtime.
|
|
@@ -8,7 +8,7 @@ metadata:
|
|
|
8
8
|
version: '1.0'
|
|
9
9
|
---
|
|
10
10
|
|
|
11
|
-
#
|
|
11
|
+
# aspec Workflow
|
|
12
12
|
|
|
13
13
|
This skill is the map of the spec-driven lifecycle. It does not execute work itself — it routes: given where the user (or the current change) stands, it names the skill that runs next and hands over the required context.
|
|
14
14
|
|
|
@@ -28,28 +28,28 @@ explore → new/propose/ff → continue* → apply → verify → archive
|
|
|
28
28
|
|
|
29
29
|
| User wants to… | Run |
|
|
30
30
|
|---|---|
|
|
31
|
-
| Think through an idea or problem, no commitment yet | `
|
|
32
|
-
| Start structured work on something new | `
|
|
33
|
-
| Skip straight to a full draft when the path is clear | `
|
|
34
|
-
| Resume a change with missing artifacts | `
|
|
35
|
-
| Implement tasks from ready artifacts | `
|
|
36
|
-
| Check implementation against artifacts before closing | `
|
|
37
|
-
| Close one finished change (syncing its specs) | `
|
|
38
|
-
| Close several finished changes at once | `
|
|
39
|
-
| Learn the whole cycle hands-on | `
|
|
31
|
+
| Think through an idea or problem, no commitment yet | `ancleto-explore` |
|
|
32
|
+
| Start structured work on something new | `ancleto-new` (step by step) or `ancleto-propose` (all artifacts at once) |
|
|
33
|
+
| Skip straight to a full draft when the path is clear | `ancleto-ff` |
|
|
34
|
+
| Resume a change with missing artifacts | `ancleto-continue` (repeat until complete) |
|
|
35
|
+
| Implement tasks from ready artifacts | `ancleto-apply` |
|
|
36
|
+
| Check implementation against artifacts before closing | `ancleto-verify` |
|
|
37
|
+
| Close one finished change (syncing its specs) | `ancleto-archive` |
|
|
38
|
+
| Close several finished changes at once | `ancleto-bulk-archive` |
|
|
39
|
+
| Learn the whole cycle hands-on | `ancleto-onboard` |
|
|
40
40
|
| Recall what the team learned about a topic | `searchMemory` directly (or the recall contract) |
|
|
41
41
|
|
|
42
|
-
**By change state** (read `
|
|
42
|
+
**By change state** (read `aspec/changes/<name>/`):
|
|
43
43
|
|
|
44
44
|
| State | Run |
|
|
45
45
|
|---|---|
|
|
46
|
-
| Directory missing → nothing to continue | `
|
|
47
|
-
| `proposal.md` missing | `
|
|
48
|
-
| `specs/` or `design.md` missing | `
|
|
49
|
-
| `tasks.md` missing | `
|
|
50
|
-
| All artifacts present, tasks unchecked | `
|
|
51
|
-
| All tasks checked | `
|
|
52
|
-
| Several changes complete | `
|
|
46
|
+
| Directory missing → nothing to continue | `ancleto-new` (or propose/ff) |
|
|
47
|
+
| `proposal.md` missing | `ancleto-continue` |
|
|
48
|
+
| `specs/` or `design.md` missing | `ancleto-continue` |
|
|
49
|
+
| `tasks.md` missing | `ancleto-continue` |
|
|
50
|
+
| All artifacts present, tasks unchecked | `ancleto-apply` |
|
|
51
|
+
| All tasks checked | `ancleto-verify`, then `ancleto-archive` |
|
|
52
|
+
| Several changes complete | `ancleto-bulk-archive` |
|
|
53
53
|
|
|
54
54
|
## Handoff Contract
|
|
55
55
|
|
|
@@ -96,6 +96,6 @@ If option 4 happened and the answer still does not remove the main ambiguity, cl
|
|
|
96
96
|
## What not to do
|
|
97
97
|
|
|
98
98
|
- do not create specs, design, tasks, or proposals
|
|
99
|
-
- do not trigger
|
|
99
|
+
- do not trigger cleto or any workflow handoff
|
|
100
100
|
- do not ask more than one clarification question
|
|
101
101
|
- do not replace the orchestrator's final responsibility for classification
|
package/src/cli/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
2
|
+
import { existsSync } from 'node:fs'
|
|
3
|
+
import { cp, mkdir, access, writeFile, readFile, readdir, rename } from 'node:fs/promises'
|
|
3
4
|
import { spawnSync } from 'node:child_process'
|
|
4
5
|
import { createHash } from 'node:crypto'
|
|
5
6
|
import { createInterface } from 'node:readline'
|
|
@@ -86,17 +87,21 @@ function globalConfigDir() {
|
|
|
86
87
|
: join(homedir(), '.config', 'opencode')
|
|
87
88
|
}
|
|
88
89
|
|
|
90
|
+
function binName(base) {
|
|
91
|
+
return process.platform === 'win32' ? `${base}.exe` : base
|
|
92
|
+
}
|
|
93
|
+
|
|
89
94
|
function resolveBin(name, fallbacks = []) {
|
|
90
95
|
const probe = process.platform === 'win32' ? 'where' : 'which'
|
|
91
96
|
const r = spawnSync(probe, [name], { encoding: 'utf8' })
|
|
92
97
|
if (r.status === 0 && r.stdout) {
|
|
93
|
-
const
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
98
|
+
for (const line of r.stdout.split(/\r?\n/)) {
|
|
99
|
+
const candidate = line.trim()
|
|
100
|
+
if (candidate && !/^informacion:/i.test(candidate)) return candidate
|
|
101
|
+
}
|
|
97
102
|
}
|
|
98
103
|
for (const fb of fallbacks) {
|
|
99
|
-
if (fb) return fb
|
|
104
|
+
if (fb && existsSync(fb)) return fb
|
|
100
105
|
}
|
|
101
106
|
return null
|
|
102
107
|
}
|
|
@@ -104,16 +109,21 @@ function resolveBin(name, fallbacks = []) {
|
|
|
104
109
|
function buildDefaultMcp() {
|
|
105
110
|
const mcp = {}
|
|
106
111
|
|
|
107
|
-
const
|
|
112
|
+
const engramFallbacks = [
|
|
113
|
+
join(homedir(), 'go', 'bin', binName('engram')),
|
|
114
|
+
join(homedir(), '.local', 'bin', binName('engram'))
|
|
115
|
+
]
|
|
116
|
+
const engramBin = resolveBin('engram', engramFallbacks)
|
|
108
117
|
if (engramBin) {
|
|
109
118
|
mcp.engram = { type: 'local', enabled: true, command: [engramBin, 'mcp', '--tools=agent'] }
|
|
110
119
|
} else {
|
|
111
120
|
console.warn('ancleto: no se encontro engram (memoria) en PATH; se omitio su MCP')
|
|
112
121
|
}
|
|
113
122
|
|
|
114
|
-
const
|
|
115
|
-
join(homedir(), '.caveman', 'bin', 'caveman-mcp
|
|
116
|
-
]
|
|
123
|
+
const cavemanFallbacks = [
|
|
124
|
+
join(homedir(), '.caveman', 'bin', binName('caveman-mcp'))
|
|
125
|
+
]
|
|
126
|
+
const cavemanBin = resolveBin('caveman-mcp', cavemanFallbacks)
|
|
117
127
|
if (cavemanBin) {
|
|
118
128
|
mcp.caveman = { type: 'local', enabled: true, command: [cavemanBin] }
|
|
119
129
|
} else {
|
|
@@ -280,13 +290,13 @@ const AGENT_SKILLS_DIR = {
|
|
|
280
290
|
roo: '.roo/skills'
|
|
281
291
|
}
|
|
282
292
|
|
|
283
|
-
const
|
|
293
|
+
const ANCLETO_SKILLS = ['ancleto-new', 'ancleto-propose', 'ancleto-apply', 'ancleto-verify', 'ancleto-archive', 'ancleto-bulk-archive', 'ancleto-continue', 'ancleto-explore', 'ancleto-ff', 'ancleto-onboard', 'ancleto-workflow']
|
|
284
294
|
|
|
285
295
|
async function installAgentSkills(projectDir, agent) {
|
|
286
296
|
const dir = AGENT_SKILLS_DIR[agent] || AGENT_SKILLS_DIR.opencode
|
|
287
297
|
const dest = join(projectDir, dir)
|
|
288
298
|
await mkdir(dest, { recursive: true })
|
|
289
|
-
for (const name of
|
|
299
|
+
for (const name of ANCLETO_SKILLS) {
|
|
290
300
|
const src = join(ROOT, 'skills', name)
|
|
291
301
|
if (!(await exists(src))) {
|
|
292
302
|
console.warn(`ancleto: skill no encontrada en el paquete: ${name}`)
|
|
@@ -300,17 +310,19 @@ async function installAgentSkills(projectDir, agent) {
|
|
|
300
310
|
return dir.replace(/\\/g, '/')
|
|
301
311
|
}
|
|
302
312
|
|
|
303
|
-
const
|
|
313
|
+
const CHANGES_ROOT = 'aspec'
|
|
314
|
+
|
|
315
|
+
const DEFAULT_ASPEC_CONFIG = `# OpenSpec project configuration
|
|
304
316
|
# Generado por @ancleto/spec (G5) — editalo libremente, no se sobrescribe en reinstalaciones.
|
|
305
317
|
schema: spec-driven-development
|
|
306
318
|
`
|
|
307
319
|
|
|
308
|
-
async function
|
|
309
|
-
const changesDir = join(projectDir,
|
|
320
|
+
async function scaffoldAspec(projectDir) {
|
|
321
|
+
const changesDir = join(projectDir, CHANGES_ROOT, 'changes')
|
|
310
322
|
await mkdir(changesDir, { recursive: true })
|
|
311
|
-
const configPath = join(projectDir,
|
|
323
|
+
const configPath = join(projectDir, CHANGES_ROOT, 'config.yaml')
|
|
312
324
|
if (!(await exists(configPath))) {
|
|
313
|
-
await writeFile(configPath,
|
|
325
|
+
await writeFile(configPath, DEFAULT_ASPEC_CONFIG)
|
|
314
326
|
}
|
|
315
327
|
}
|
|
316
328
|
|
|
@@ -382,7 +394,7 @@ async function install(args) {
|
|
|
382
394
|
|
|
383
395
|
if (project) {
|
|
384
396
|
await copyTemplates(resolve(project))
|
|
385
|
-
await
|
|
397
|
+
await scaffoldAspec(resolve(project))
|
|
386
398
|
const existingRc = await readAncletorc(resolve(project))
|
|
387
399
|
const agent = await resolveAgent(args, existingRc?.agent)
|
|
388
400
|
const agentSkillsDir = await installAgentSkills(resolve(project), agent)
|
|
@@ -436,6 +448,14 @@ async function upgradeCmd(args) {
|
|
|
436
448
|
console.error("Error: No se encontro .ancletorc. Ejecuta 'ancleto init' primero.")
|
|
437
449
|
process.exit(1)
|
|
438
450
|
}
|
|
451
|
+
const legacyChanges = join(projectDir, 'openspec')
|
|
452
|
+
const changesRoot = join(projectDir, CHANGES_ROOT)
|
|
453
|
+
if ((await exists(legacyChanges)) && !(await exists(changesRoot))) {
|
|
454
|
+
await rename(legacyChanges, changesRoot)
|
|
455
|
+
console.log('ancleto: changes migrados de openspec/ a aspec/')
|
|
456
|
+
} else if ((await exists(legacyChanges)) && (await exists(changesRoot))) {
|
|
457
|
+
console.warn('ancleto: existen openspec/ y aspec/ — no se migro nada (revisar manualmente)')
|
|
458
|
+
}
|
|
439
459
|
const agent = await resolveAgent(args, rc.agent)
|
|
440
460
|
await copyTemplates(projectDir)
|
|
441
461
|
const agentSkillsDir = await installAgentSkills(projectDir, agent)
|
|
@@ -450,7 +470,7 @@ async function upgradeCmd(args) {
|
|
|
450
470
|
})
|
|
451
471
|
console.log(`ancleto: upgrade completo (v${manifest.version}, agente: ${agent})`)
|
|
452
472
|
console.log(' ✔ templates re-aplicados (bloques LOCKED actualizados, EXTENSIBLE intacto)')
|
|
453
|
-
console.log(` ✔ skills actualizadas en ${agentSkillsDir} (${
|
|
473
|
+
console.log(` ✔ skills actualizadas en ${agentSkillsDir} (${ANCLETO_SKILLS.length} skills)`)
|
|
454
474
|
console.log(' ✔ manifiesto .ancletorc actualizado')
|
|
455
475
|
}
|
|
456
476
|
|
|
@@ -491,7 +511,7 @@ async function initProject(args) {
|
|
|
491
511
|
}
|
|
492
512
|
|
|
493
513
|
const manifest = await writeManifest(projectDir, { azure, discovery, agent })
|
|
494
|
-
await
|
|
514
|
+
await scaffoldAspec(projectDir)
|
|
495
515
|
if (azure.enabled) console.log(AZURE_MCP_NOTICE)
|
|
496
516
|
console.log(`ancleto: .ancletorc actualizado en ${projectDir} (v${manifest.version})${azure.enabled ? ' (Azure habilitado)' : ' (Azure desactivado)'} (Agente: ${agent})${tier ? ` (Tier: ${tier})` : ''}`)
|
|
497
517
|
}
|
package/templates/AGENTS.md
CHANGED
|
@@ -50,16 +50,16 @@ conflicto, prevalece el diseño vigente.
|
|
|
50
50
|
- Si la memoria contradice el estado actual del código o los guardrails de este archivo,
|
|
51
51
|
reportá la discrepancia en lugar de aplicarla a ciegas.
|
|
52
52
|
|
|
53
|
-
## Flujo Spec-Driven (
|
|
53
|
+
## Flujo Spec-Driven (aspec)
|
|
54
54
|
|
|
55
|
-
- **Cambios con scope incierto / arquitectura**: Crear artifacts en `
|
|
55
|
+
- **Cambios con scope incierto / arquitectura**: Crear artifacts en `aspec/changes/<name>/`.
|
|
56
56
|
- **Cambios menores / fixes**: Implementación directa.
|
|
57
|
-
- **Cierre**: Archivar con
|
|
57
|
+
- **Cierre**: Archivar con `/cleto-archive` al finalizar.
|
|
58
58
|
|
|
59
59
|
## Tools de Soporte
|
|
60
60
|
|
|
61
61
|
- `ancleto`: Descubrimiento técnico e inicialización.
|
|
62
|
-
- `
|
|
62
|
+
- `cleto-*`: Comandos del ciclo de vida del cambio en el IDE (proposal, specs, design, tasks, archive).
|
|
63
63
|
|
|
64
64
|
<!-- LOCKED: test-block -->
|
|
65
65
|
Contexto gestionado por @ancleto/spec — no editar: se re-aplica en cada actualizacion.
|