@ancleto/spec 0.6.1 → 0.6.4
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/spec-writer.md +2 -2
- package/commands/{opsx-apply.md → cleto-apply.md} +4 -4
- package/commands/{opsx-archive.md → cleto-archive.md} +3 -3
- package/commands/{opsx-bulk-archive.md → cleto-bulk-archive.md} +1 -1
- package/commands/{opsx-continue.md → cleto-continue.md} +3 -3
- package/commands/{opsx-explore.md → cleto-explore.md} +1 -1
- package/commands/{opsx-ff.md → cleto-ff.md} +2 -2
- package/commands/{opsx-new.md → cleto-new.md} +4 -4
- package/commands/{opsx-onboard.md → cleto-onboard.md} +22 -22
- package/commands/{opsx-propose.md → cleto-propose.md} +3 -3
- package/commands/{opsx-recall.md → cleto-recall.md} +6 -6
- package/commands/{opsx-sync.md → cleto-sync.md} +1 -1
- package/commands/{opsx-verify.md → cleto-verify.md} +1 -1
- package/package.json +1 -1
- package/skills/{openspec-apply → ancleto-apply}/SKILL.md +2 -2
- package/skills/{openspec-archive → ancleto-archive}/SKILL.md +1 -1
- package/skills/{openspec-bulk-archive → ancleto-bulk-archive}/SKILL.md +1 -1
- package/skills/{openspec-continue → ancleto-continue}/SKILL.md +4 -4
- package/skills/{openspec-explore → ancleto-explore}/SKILL.md +1 -1
- package/skills/{openspec-ff → ancleto-ff}/SKILL.md +2 -2
- package/skills/{openspec-new → ancleto-new}/SKILL.md +2 -2
- package/skills/{openspec-onboard → ancleto-onboard}/SKILL.md +11 -11
- package/skills/{openspec-propose → ancleto-propose}/SKILL.md +4 -4
- package/skills/{openspec-recall → ancleto-recall}/SKILL.md +3 -3
- package/skills/{openspec-sync-specs → ancleto-sync-specs}/SKILL.md +1 -1
- package/skills/ancleto-upgrade/SKILL.md +2 -2
- package/skills/{openspec-verify → ancleto-verify}/SKILL.md +1 -1
- package/skills/{openspec-workflow → ancleto-workflow}/SKILL.md +17 -17
- package/skills/triage-clarifier/SKILL.md +1 -1
- package/src/cli/index.js +81 -34
- package/src/cli/ui.js +181 -0
|
@@ -4,7 +4,7 @@ description: Verify implementation matches change artifacts before archiving
|
|
|
4
4
|
|
|
5
5
|
Verify that an implementation matches the change artifacts (specs, tasks, design).
|
|
6
6
|
|
|
7
|
-
**Input**: Optionally specify a change name after `/
|
|
7
|
+
**Input**: Optionally specify a change name after `/cleto-verify` (e.g., `/cleto-verify add-auth`). If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes.
|
|
8
8
|
|
|
9
9
|
**Steps**
|
|
10
10
|
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
2
|
+
name: ancleto-apply
|
|
3
3
|
description: Implement tasks from a change step by step, tracking progress in tasks.md. Use when artifacts are ready and implementation should start. No external binaries required.
|
|
4
4
|
license: MIT
|
|
5
5
|
compatibility: No external binaries required. Works with any agent runtime.
|
|
@@ -78,7 +78,7 @@ For each pending task (`- [ ]`):
|
|
|
78
78
|
**Change:** <change-name>
|
|
79
79
|
**Progress:** N/N tasks complete ✓
|
|
80
80
|
|
|
81
|
-
All tasks complete! You can archive this change with `
|
|
81
|
+
All tasks complete! You can archive this change with `ancleto-archive`.
|
|
82
82
|
```
|
|
83
83
|
|
|
84
84
|
**On pause:**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
2
|
+
name: ancleto-archive
|
|
3
3
|
description: Archive a completed change, syncing delta specs first when needed. Use when implementation and verification are done. Captures lessons into persistent memory. No external binaries required.
|
|
4
4
|
license: MIT
|
|
5
5
|
compatibility: No external binaries required. Works with any agent runtime.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
2
|
+
name: ancleto-bulk-archive
|
|
3
3
|
description: Archive multiple completed changes in one batch, resolving spec conflicts by checking the codebase. Use when several changes are done and should be archived together. No external binaries required.
|
|
4
4
|
license: MIT
|
|
5
5
|
compatibility: No external binaries required. Works with any agent runtime.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
2
|
+
name: ancleto-continue
|
|
3
3
|
description: Continue working on an existing change by creating its next missing artifact. Use to resume artifact creation one step at a time. No external binaries required.
|
|
4
4
|
license: MIT
|
|
5
5
|
compatibility: No external binaries required. Works with any agent runtime.
|
|
@@ -29,7 +29,7 @@ Read `openspec/changes/<name>/` and check for artifact files in this fixed depen
|
|
|
29
29
|
|
|
30
30
|
The first item in this order that is absent (or, for `specs/`, contains no `spec.md`) is the next artifact to create.
|
|
31
31
|
|
|
32
|
-
- **If all four are present**: congratulate the user, show the status, and suggest "All artifacts created! You can now implement this change with `
|
|
32
|
+
- **If all four are present**: congratulate the user, show the status, and suggest "All artifacts created! You can now implement this change with `ancleto-apply` or archive it with `ancleto-archive`." STOP.
|
|
33
33
|
- **If the change directory does not exist**: report it and stop.
|
|
34
34
|
|
|
35
35
|
### 2. Load context files
|
|
@@ -38,7 +38,7 @@ Read every artifact that IS present — they constrain what you write next. If a
|
|
|
38
38
|
|
|
39
39
|
### 3. Create exactly ONE artifact
|
|
40
40
|
|
|
41
|
-
Draft the missing artifact using the same templates as `
|
|
41
|
+
Draft the missing artifact using the same templates as `ancleto-propose`:
|
|
42
42
|
|
|
43
43
|
- **proposal.md** (first artifact): problem statement, proposed change, scope, risks. If Work Item context is available, use its title/description as the problem statement, acceptance criteria as the requirements basis, and include a `## Related Work Item` section: `**#{id}** — {title} ({type}) · Project: {project}`.
|
|
44
44
|
- **specs/\<capability\>/spec.md**: one spec file per capability the change touches, with `## ADDED Requirements` / `#### Scenario:` blocks in WHEN/THEN form.
|
|
@@ -54,7 +54,7 @@ Report:
|
|
|
54
54
|
- Which artifact was created.
|
|
55
55
|
- Current progress (N/4 complete).
|
|
56
56
|
- What is unlocked next.
|
|
57
|
-
- Prompt: "Run `
|
|
57
|
+
- Prompt: "Run `ancleto-continue` to create the next artifact."
|
|
58
58
|
|
|
59
59
|
Create ONE artifact per invocation, then STOP.
|
|
60
60
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
2
|
+
name: ancleto-explore
|
|
3
3
|
description: Enter explore mode — think through ideas, investigate problems, and clarify requirements without implementing. Consults prior team memory first. No external binaries required.
|
|
4
4
|
license: MIT
|
|
5
5
|
compatibility: No external binaries required. Works with any agent runtime.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
2
|
+
name: ancleto-ff
|
|
3
3
|
description: Fast-forward artifact creation — create a change and generate everything needed for implementation in one go. Use when the path is clear and no step-by-step guidance is wanted. No external binaries required.
|
|
4
4
|
license: MIT
|
|
5
5
|
compatibility: No external binaries required. Works with any agent runtime.
|
|
@@ -57,7 +57,7 @@ Summarize:
|
|
|
57
57
|
- Change name and location
|
|
58
58
|
- List of artifacts created with brief descriptions
|
|
59
59
|
- What's ready: "All artifacts created! Ready for implementation."
|
|
60
|
-
- Prompt: "Run `
|
|
60
|
+
- Prompt: "Run `ancleto-apply` to start implementing."
|
|
61
61
|
|
|
62
62
|
## Artifact Creation Guidelines
|
|
63
63
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
2
|
+
name: ancleto-new
|
|
3
3
|
description: Start a new spec-driven change without external binaries. Use when the user wants to begin structured work on a feature, fix, or modification. Creates the change directory, recalls prior memory, and shows the first artifact template.
|
|
4
4
|
license: MIT
|
|
5
5
|
compatibility: No external binaries required. Works with any agent runtime.
|
|
@@ -84,7 +84,7 @@ After completing the steps, summarize:
|
|
|
84
84
|
- Change name and location
|
|
85
85
|
- Artifact sequence and current status (0/4 artifacts complete)
|
|
86
86
|
- The template for the first artifact
|
|
87
|
-
- Prompt: "Ready to create the first artifact? Run `
|
|
87
|
+
- Prompt: "Ready to create the first artifact? Run `ancleto-propose` or just describe what this change is about and I'll draft it."
|
|
88
88
|
|
|
89
89
|
## Guardrails
|
|
90
90
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
2
|
+
name: ancleto-onboard
|
|
3
3
|
description: Guided onboarding — walk through a complete spec-driven cycle (idea to archive) on a real small task, with narration. Use for a first-time user of the workflow. No external binaries required.
|
|
4
4
|
license: MIT
|
|
5
5
|
compatibility: No external binaries required. Works with any agent runtime.
|
|
@@ -119,16 +119,16 @@ Congratulate, recap the cycle (Explore → New → Proposal → Specs → Design
|
|
|
119
119
|
|
|
120
120
|
| Command | What it does |
|
|
121
121
|
|---------|--------------|
|
|
122
|
-
| `
|
|
123
|
-
| `
|
|
124
|
-
| `
|
|
125
|
-
| `
|
|
126
|
-
| `
|
|
127
|
-
| `
|
|
128
|
-
| `
|
|
129
|
-
| `
|
|
130
|
-
|
|
131
|
-
**Graceful exits:** if the user wants to stop mid-way, point at the saved change directory and the resume skills (`
|
|
122
|
+
| `ancleto-propose` | Create a change and generate all artifacts |
|
|
123
|
+
| `ancleto-explore` | Think through problems before/during work |
|
|
124
|
+
| `ancleto-apply` | Implement tasks from a change |
|
|
125
|
+
| `ancleto-archive` | Archive a completed change |
|
|
126
|
+
| `ancleto-new` | Start a new change, step by step |
|
|
127
|
+
| `ancleto-continue` | Continue an existing change |
|
|
128
|
+
| `ancleto-ff` | Fast-forward: all artifacts at once |
|
|
129
|
+
| `ancleto-verify` | Verify implementation |
|
|
130
|
+
|
|
131
|
+
**Graceful exits:** if the user wants to stop mid-way, point at the saved change directory and the resume skills (`ancleto-continue`, `ancleto-apply`). If they only want the reference, show the table and exit.
|
|
132
132
|
|
|
133
133
|
## Guardrails
|
|
134
134
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
3
|
-
description: Draft all artifacts for a change in one step (proposal, design, tasks, delta specs). Use after
|
|
2
|
+
name: ancleto-propose
|
|
3
|
+
description: Draft all artifacts for a change in one step (proposal, design, tasks, delta specs). Use after ancleto-new, or directly with a change name or description. No external binaries required.
|
|
4
4
|
license: MIT
|
|
5
5
|
compatibility: No external binaries required. Works with any agent runtime.
|
|
6
6
|
metadata:
|
|
@@ -18,7 +18,7 @@ Create a change and generate all its artifacts in one step, writing files direct
|
|
|
18
18
|
|
|
19
19
|
### 1. Resolve context and derive the change name
|
|
20
20
|
|
|
21
|
-
Same as `
|
|
21
|
+
Same as `ancleto-new` step 1: use in-session Work Item context if available (record id/title/project for traceability, skip entirely when Azure DevOps is not configured), otherwise ask what the user wants to build and derive a kebab-case name.
|
|
22
22
|
|
|
23
23
|
**IMPORTANT**: Do NOT proceed without a change name. If a change with that name already exists, ask whether to continue it or create a new one.
|
|
24
24
|
|
|
@@ -122,7 +122,7 @@ After completing all artifacts, summarize:
|
|
|
122
122
|
- Change name and location
|
|
123
123
|
- List of artifacts created with brief descriptions
|
|
124
124
|
- What's ready: "All artifacts created! Ready for implementation."
|
|
125
|
-
- Prompt: "Run `
|
|
125
|
+
- Prompt: "Run `ancleto-apply` to start implementing."
|
|
126
126
|
|
|
127
127
|
## Artifact Creation Guidelines
|
|
128
128
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
2
|
+
name: ancleto-recall
|
|
3
3
|
description: Recupera memoria episódica del proyecto (.ancleto/memory.db) para precargar contexto de changes anteriores. Se invoca al iniciar un change, antes de generar artifacts. Opcional y no bloqueante.
|
|
4
4
|
license: MIT
|
|
5
5
|
compatibility: Requires the memory engine configured in the repo. Optional — degrades silently when unavailable.
|
|
@@ -10,14 +10,14 @@ metadata:
|
|
|
10
10
|
|
|
11
11
|
Retrieve shared episodic memory for this repository and inject it as starting context for a change.
|
|
12
12
|
|
|
13
|
-
This skill is the **single source of truth** for the recall contract. The change-creation flows (`
|
|
13
|
+
This skill is the **single source of truth** for the recall contract. The change-creation flows (`cleto-new`, `cleto-propose`, `cleto-ff`) carry this step inline; those inline blocks must stay in sync with this file.
|
|
14
14
|
|
|
15
15
|
**Two invocation paths, one contract:**
|
|
16
16
|
|
|
17
17
|
| Path | Trigger | On failure or empty result |
|
|
18
18
|
| --- | --- | --- |
|
|
19
19
|
| **Automatic** | Inside the change-creation flows, before generating artifacts | Silent — omit the section, never block |
|
|
20
|
-
| **Manual** | The `/
|
|
20
|
+
| **Manual** | The `/cleto-recall` command, invoked by the user | **Report it** — the user asked explicitly |
|
|
21
21
|
|
|
22
22
|
Steps 1 to 3 are identical for both. Only the failure behaviour differs, and it differs for a reason: silence is correct when nobody asked, and wrong when somebody did.
|
|
23
23
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
2
|
+
name: ancleto-sync-specs
|
|
3
3
|
description: Sync delta specs from a change to main specs. Use when the user wants to update main specs with changes from a delta spec, without archiving the change.
|
|
4
4
|
license: MIT
|
|
5
5
|
compatibility: Requires openspec CLI.
|
|
@@ -431,7 +431,7 @@ build: sí/no | lint: sí/no | test: sí/no | test:ci: sí/no | typecheck: sí/n
|
|
|
431
431
|
- tasks.md ✅ ({N} tareas en 6 fases)
|
|
432
432
|
- design.md ✅
|
|
433
433
|
|
|
434
|
-
Para implementar: /
|
|
434
|
+
Para implementar: /cleto-apply {CHANGE_NAME}
|
|
435
435
|
```
|
|
436
436
|
|
|
437
437
|
---
|
|
@@ -439,7 +439,7 @@ Para implementar: /opsx-apply {CHANGE_NAME}
|
|
|
439
439
|
## Guardrails
|
|
440
440
|
|
|
441
441
|
Este skill solo genera artefactos OpenSpec — no modifica ningún archivo del repo.
|
|
442
|
-
Todo cambio real lo ejecuta el desarrollador con `/
|
|
442
|
+
Todo cambio real lo ejecuta el desarrollador con `/cleto-apply`, que tiene su propio
|
|
443
443
|
ciclo de revisión. Modificar el repo desde este skill saltearía ese control.
|
|
444
444
|
|
|
445
445
|
- No tocar archivos fuera de `openspec/changes/{CHANGE_NAME}/`
|
|
@@ -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.
|
|
@@ -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.
|
|
@@ -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
42
|
**By change state** (read `openspec/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,4 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { existsSync } from 'node:fs'
|
|
2
3
|
import { cp, mkdir, access, writeFile, readFile, readdir } from 'node:fs/promises'
|
|
3
4
|
import { spawnSync } from 'node:child_process'
|
|
4
5
|
import { createHash } from 'node:crypto'
|
|
@@ -10,6 +11,7 @@ import { createMemoryEngine, defaultMemoryDbPath } from '../core/memory/engine.j
|
|
|
10
11
|
import { memoryDoctor } from '../core/memory/doctor.js'
|
|
11
12
|
import { writeDiscoveryMap } from '../core/discovery.js'
|
|
12
13
|
import { readProjectTier, buildRepomixArgs, tierTokenBudget } from '../core/repomix-tier.js'
|
|
14
|
+
import { showBanner, selectOption, stopBanner } from './ui.js'
|
|
13
15
|
|
|
14
16
|
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
15
17
|
const ROOT = join(__dirname, '..', '..')
|
|
@@ -29,9 +31,9 @@ Uso:
|
|
|
29
31
|
ancleto install --agent <nombre> opencode | vscode | antigravity | cursor | roo (pregunta si no esta guardado)
|
|
30
32
|
ancleto update [--project <dir>] Alias de install (re-instala sobre lo existente)
|
|
31
33
|
ancleto upgrade [--agent <nombre>] Re-aplica templates (LOCKED) y skills sobre el proyecto actual
|
|
32
|
-
ancleto init [--with-azure] [--agent <nombre>]
|
|
34
|
+
ancleto init [--with-azure] [--agent <nombre>] [--tier <nivel>]
|
|
33
35
|
Crea .ancletorc en el repositorio actual
|
|
34
|
-
(Azure desactivado por defecto
|
|
36
|
+
(interactivo en TTY: banner + menu; Azure desactivado por defecto)
|
|
35
37
|
ancleto discovery --check Estado del seed (READY/STALE/PARTIAL/MISSING)
|
|
36
38
|
ancleto discovery [--compress] [--include G] [--ignore G] [--token-budget N]
|
|
37
39
|
Empaca el repo con Repomix y guarda estado
|
|
@@ -85,17 +87,21 @@ function globalConfigDir() {
|
|
|
85
87
|
: join(homedir(), '.config', 'opencode')
|
|
86
88
|
}
|
|
87
89
|
|
|
90
|
+
function binName(base) {
|
|
91
|
+
return process.platform === 'win32' ? `${base}.exe` : base
|
|
92
|
+
}
|
|
93
|
+
|
|
88
94
|
function resolveBin(name, fallbacks = []) {
|
|
89
95
|
const probe = process.platform === 'win32' ? 'where' : 'which'
|
|
90
96
|
const r = spawnSync(probe, [name], { encoding: 'utf8' })
|
|
91
97
|
if (r.status === 0 && r.stdout) {
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
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
|
+
}
|
|
96
102
|
}
|
|
97
103
|
for (const fb of fallbacks) {
|
|
98
|
-
if (fb) return fb
|
|
104
|
+
if (fb && existsSync(fb)) return fb
|
|
99
105
|
}
|
|
100
106
|
return null
|
|
101
107
|
}
|
|
@@ -103,16 +109,21 @@ function resolveBin(name, fallbacks = []) {
|
|
|
103
109
|
function buildDefaultMcp() {
|
|
104
110
|
const mcp = {}
|
|
105
111
|
|
|
106
|
-
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)
|
|
107
117
|
if (engramBin) {
|
|
108
118
|
mcp.engram = { type: 'local', enabled: true, command: [engramBin, 'mcp', '--tools=agent'] }
|
|
109
119
|
} else {
|
|
110
120
|
console.warn('ancleto: no se encontro engram (memoria) en PATH; se omitio su MCP')
|
|
111
121
|
}
|
|
112
122
|
|
|
113
|
-
const
|
|
114
|
-
join(homedir(), '.caveman', 'bin', 'caveman-mcp
|
|
115
|
-
]
|
|
123
|
+
const cavemanFallbacks = [
|
|
124
|
+
join(homedir(), '.caveman', 'bin', binName('caveman-mcp'))
|
|
125
|
+
]
|
|
126
|
+
const cavemanBin = resolveBin('caveman-mcp', cavemanFallbacks)
|
|
116
127
|
if (cavemanBin) {
|
|
117
128
|
mcp.caveman = { type: 'local', enabled: true, command: [cavemanBin] }
|
|
118
129
|
} else {
|
|
@@ -201,18 +212,31 @@ function askAgent() {
|
|
|
201
212
|
})
|
|
202
213
|
}
|
|
203
214
|
|
|
204
|
-
|
|
205
|
-
const
|
|
206
|
-
if (
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
process.exit(1)
|
|
211
|
-
}
|
|
212
|
-
return name
|
|
215
|
+
function scanAgentFlag(args) {
|
|
216
|
+
const name = flagValue(args, '--agent')
|
|
217
|
+
if (!name) return null
|
|
218
|
+
if (!SUPPORTED_AGENTS.includes(name)) {
|
|
219
|
+
console.error(`ancleto: agente invalido: ${name} (${SUPPORTED_AGENTS.join('/')})`)
|
|
220
|
+
process.exit(1)
|
|
213
221
|
}
|
|
222
|
+
return name
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
function scanTierFlag(args) {
|
|
226
|
+
const t = flagValue(args, '--tier')
|
|
227
|
+
if (!t) return null
|
|
228
|
+
if (!TIERS[t]) {
|
|
229
|
+
console.error(`ancleto: tier invalido: ${t} (normal|minimo|gratis)`)
|
|
230
|
+
process.exit(1)
|
|
231
|
+
}
|
|
232
|
+
return t
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
async function resolveAgent(args, existing, allowAsk = Boolean(process.stdin.isTTY)) {
|
|
236
|
+
const flag = scanAgentFlag(args)
|
|
237
|
+
if (flag) return flag
|
|
214
238
|
if (existing && SUPPORTED_AGENTS.includes(existing)) return existing
|
|
215
|
-
if (
|
|
239
|
+
if (allowAsk) return askAgent()
|
|
216
240
|
return DEFAULT_AGENT
|
|
217
241
|
}
|
|
218
242
|
|
|
@@ -266,13 +290,13 @@ const AGENT_SKILLS_DIR = {
|
|
|
266
290
|
roo: '.roo/skills'
|
|
267
291
|
}
|
|
268
292
|
|
|
269
|
-
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']
|
|
270
294
|
|
|
271
295
|
async function installAgentSkills(projectDir, agent) {
|
|
272
296
|
const dir = AGENT_SKILLS_DIR[agent] || AGENT_SKILLS_DIR.opencode
|
|
273
297
|
const dest = join(projectDir, dir)
|
|
274
298
|
await mkdir(dest, { recursive: true })
|
|
275
|
-
for (const name of
|
|
299
|
+
for (const name of ANCLETO_SKILLS) {
|
|
276
300
|
const src = join(ROOT, 'skills', name)
|
|
277
301
|
if (!(await exists(src))) {
|
|
278
302
|
console.warn(`ancleto: skill no encontrada en el paquete: ${name}`)
|
|
@@ -354,12 +378,7 @@ async function install(args) {
|
|
|
354
378
|
const withMcp = !args.includes('--no-mcp')
|
|
355
379
|
let mcpMap = withMcp ? buildDefaultMcp() : {}
|
|
356
380
|
|
|
357
|
-
|
|
358
|
-
let tier = ti >= 0 ? args[ti + 1] : null
|
|
359
|
-
if (tier && !TIERS[tier]) {
|
|
360
|
-
console.error(`ancleto: tier invalido: ${tier} (normal|minimo|gratis)`)
|
|
361
|
-
process.exit(1)
|
|
362
|
-
}
|
|
381
|
+
let tier = scanTierFlag(args)
|
|
363
382
|
|
|
364
383
|
if (project) {
|
|
365
384
|
const dir = resolve(project)
|
|
@@ -441,22 +460,50 @@ async function upgradeCmd(args) {
|
|
|
441
460
|
})
|
|
442
461
|
console.log(`ancleto: upgrade completo (v${manifest.version}, agente: ${agent})`)
|
|
443
462
|
console.log(' ✔ templates re-aplicados (bloques LOCKED actualizados, EXTENSIBLE intacto)')
|
|
444
|
-
console.log(` ✔ skills actualizadas en ${agentSkillsDir} (${
|
|
463
|
+
console.log(` ✔ skills actualizadas en ${agentSkillsDir} (${ANCLETO_SKILLS.length} skills)`)
|
|
445
464
|
console.log(' ✔ manifiesto .ancletorc actualizado')
|
|
446
465
|
}
|
|
447
466
|
|
|
448
467
|
async function initProject(args) {
|
|
449
|
-
const withAzure = args.includes('--with-azure')
|
|
450
468
|
const projectDir = process.cwd()
|
|
469
|
+
const withAzure = args.includes('--with-azure')
|
|
470
|
+
const agentFlag = scanAgentFlag(args)
|
|
471
|
+
const tierFlag = scanTierFlag(args)
|
|
451
472
|
const existing = await readAncletorc(projectDir)
|
|
452
473
|
const azure = existing?.azure ?? { enabled: false }
|
|
453
|
-
if (withAzure) azure.enabled = true
|
|
454
474
|
const discovery = existing?.discovery ?? { outputDir: 'docs/technical-discovery', exclude: [] }
|
|
455
|
-
const
|
|
475
|
+
const tierFile = join(projectDir, '.opencode', '.ancleto-tier')
|
|
476
|
+
|
|
477
|
+
let agent, tier
|
|
478
|
+
const isInteractive = Boolean(process.stdout.isTTY) && (!agentFlag || !tierFlag)
|
|
479
|
+
if (isInteractive) {
|
|
480
|
+
await showBanner()
|
|
481
|
+
const agentIdx = Math.max(0, SUPPORTED_AGENTS.indexOf(existing?.agent))
|
|
482
|
+
const storedTier = (await exists(tierFile)) ? (await readFile(tierFile, 'utf8')).trim() : null
|
|
483
|
+
const tierIdx = Math.max(0, Object.keys(TIERS).indexOf(TIERS[storedTier] ? storedTier : ''))
|
|
484
|
+
agent = agentFlag || await selectOption('Agente/IDE', SUPPORTED_AGENTS, agentIdx)
|
|
485
|
+
tier = tierFlag || await selectOption('Tier de costo', Object.keys(TIERS), tierIdx)
|
|
486
|
+
if (withAzure) {
|
|
487
|
+
azure.enabled = true
|
|
488
|
+
} else {
|
|
489
|
+
azure.enabled = (await selectOption('Habilitar Azure DevOps', ['No', 'Si'], azure.enabled ? 1 : 0)) === 'Si'
|
|
490
|
+
}
|
|
491
|
+
stopBanner()
|
|
492
|
+
} else {
|
|
493
|
+
agent = await resolveAgent(args, existing?.agent, false)
|
|
494
|
+
tier = tierFlag
|
|
495
|
+
if (withAzure) azure.enabled = true
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
if (tier) {
|
|
499
|
+
await mkdir(join(projectDir, '.opencode'), { recursive: true })
|
|
500
|
+
await writeFile(tierFile, tier + '\n')
|
|
501
|
+
}
|
|
502
|
+
|
|
456
503
|
const manifest = await writeManifest(projectDir, { azure, discovery, agent })
|
|
457
504
|
await scaffoldOpenSpec(projectDir)
|
|
458
505
|
if (azure.enabled) console.log(AZURE_MCP_NOTICE)
|
|
459
|
-
console.log(`ancleto: .ancletorc actualizado en ${projectDir} (v${manifest.version})${azure.enabled ? ' (Azure habilitado)' : ' (Azure desactivado)'} (Agente: ${agent})`)
|
|
506
|
+
console.log(`ancleto: .ancletorc actualizado en ${projectDir} (v${manifest.version})${azure.enabled ? ' (Azure habilitado)' : ' (Azure desactivado)'} (Agente: ${agent})${tier ? ` (Tier: ${tier})` : ''}`)
|
|
460
507
|
}
|
|
461
508
|
|
|
462
509
|
const DEFAULT_IGNORES = ['node_modules', '.git', 'dist']
|