@tacuchi/agent-workflow-cli 25.9.0 → 26.0.0
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/CHANGELOG.md +26 -0
- package/README.md +1 -2
- package/dist/application/capability/design-handler.js +94 -0
- package/dist/application/capability/design-handler.js.map +1 -1
- package/dist/application/capability/dispatcher.js +178 -18
- package/dist/application/capability/dispatcher.js.map +1 -1
- package/dist/application/capability/durable-effect.js.map +1 -1
- package/dist/application/capability/readiness.js +8 -54
- package/dist/application/capability/readiness.js.map +1 -1
- package/dist/application/capability/resolution.js +124 -192
- package/dist/application/capability/resolution.js.map +1 -1
- package/dist/application/doctor/prepare.js +0 -3
- package/dist/application/doctor/prepare.js.map +1 -1
- package/dist/application/doctor/provider-skills.js +21 -132
- package/dist/application/doctor/provider-skills.js.map +1 -1
- package/dist/application/doctor/repair-runner.js +0 -47
- package/dist/application/doctor/repair-runner.js.map +1 -1
- package/dist/application/flow/submit.js +1 -1
- package/dist/application/flow/submit.js.map +1 -1
- package/dist/application/plan-lint-service.js +31 -5
- package/dist/application/plan-lint-service.js.map +1 -1
- package/dist/application/retirement/attribution.js +1 -2
- package/dist/application/retirement/attribution.js.map +1 -1
- package/dist/application/self/clean-legacy.js +1 -2
- package/dist/application/self/clean-legacy.js.map +1 -1
- package/dist/application/self/install-skill.js +5 -49
- package/dist/application/self/install-skill.js.map +1 -1
- package/dist/application/self/skill-files.js +29 -0
- package/dist/application/self/skill-files.js.map +1 -0
- package/dist/application/skills-resolver-service.js +5 -91
- package/dist/application/skills-resolver-service.js.map +1 -1
- package/dist/application/source-boundary-policy.js +10 -2
- package/dist/application/source-boundary-policy.js.map +1 -1
- package/dist/cli/commands/capability.js +12 -4
- package/dist/cli/commands/capability.js.map +1 -1
- package/dist/cli/commands/index.js +0 -4
- package/dist/cli/commands/index.js.map +1 -1
- package/dist/cli/commands/self.js +1 -22
- package/dist/cli/commands/self.js.map +1 -1
- package/dist/cli/commands/skills.js +4 -11
- package/dist/cli/commands/skills.js.map +1 -1
- package/dist/cli/help-groups.js +1 -3
- package/dist/cli/help-groups.js.map +1 -1
- package/dist/cli/tui/app.js +2 -3
- package/dist/cli/tui/app.js.map +1 -1
- package/dist/cli/tui/components/host-admin-section.js +2 -13
- package/dist/cli/tui/components/host-admin-section.js.map +1 -1
- package/dist/cli/tui/components/tabs-config.js +1 -2
- package/dist/cli/tui/components/tabs-config.js.map +1 -1
- package/dist/cli/tui/tui-prefs.js +2 -0
- package/dist/cli/tui/tui-prefs.js.map +1 -1
- package/dist/dist-manifest.json +60 -204
- package/dist/domain/capability/protocol.js +3 -1
- package/dist/domain/capability/protocol.js.map +1 -1
- package/dist/domain/doctor/operations.js +0 -18
- package/dist/domain/doctor/operations.js.map +1 -1
- package/dist/domain/flow/authority.js +1 -3
- package/dist/domain/flow/authority.js.map +1 -1
- package/dist/domain/skills.js +2 -6
- package/dist/domain/skills.js.map +1 -1
- package/package.json +2 -2
- package/skills/w/SKILL.md +9 -16
- package/skills/w/exports/README.md +4 -4
- package/skills/w/exports/export-diagrams/EXPORT.md +1 -1
- package/skills/w/exports/export-scripts/EXPORT.md +1 -1
- package/skills/w/harness/HARNESS.md +2 -5
- package/skills/w/loops/CHASSIS.md +1 -1
- package/skills/w/loops/CODE-POLICIES.md +1 -1
- package/skills/w/loops/README.md +2 -2
- package/skills/w/loops/quick-loop/LOOP.md +1 -1
- package/skills/w/loops/spec-refine-loop/LOOP.md +1 -1
- package/skills/w/roles/README.md +11 -47
- package/skills/w/roles/design/ROLE.md +3 -1
- package/skills/w/roles/diagrams/ROLE.md +1 -1
- package/skills/w/roles/git/ROLE.md +1 -1
- package/skills/w/roles/research/ROLE.md +1 -1
- package/skills/w/roles/sql/ROLE.md +1 -1
- package/dist/application/capability/descriptor-loader.js +0 -109
- package/dist/application/capability/descriptor-loader.js.map +0 -1
- package/dist/application/capability/installed-inventory.js +0 -168
- package/dist/application/capability/installed-inventory.js.map +0 -1
- package/dist/application/doctor/skills-toml-migrate.js +0 -76
- package/dist/application/doctor/skills-toml-migrate.js.map +0 -1
- package/dist/application/self/install-plugin-skills-git.js +0 -226
- package/dist/application/self/install-plugin-skills-git.js.map +0 -1
- package/dist/application/self/install-plugin-skills.js +0 -203
- package/dist/application/self/install-plugin-skills.js.map +0 -1
- package/dist/application/self/plugin-cache-clear.js +0 -133
- package/dist/application/self/plugin-cache-clear.js.map +0 -1
- package/dist/application/self/plugin-cache-reload.js +0 -141
- package/dist/application/self/plugin-cache-reload.js.map +0 -1
- package/dist/application/self/skills-apply.js +0 -623
- package/dist/application/self/skills-apply.js.map +0 -1
- package/dist/application/self/skills-catalog.js +0 -35
- package/dist/application/self/skills-catalog.js.map +0 -1
- package/dist/application/self/skills-change.js +0 -479
- package/dist/application/self/skills-change.js.map +0 -1
- package/dist/application/self/skills-discovery.js +0 -275
- package/dist/application/self/skills-discovery.js.map +0 -1
- package/dist/application/self/skills-manager.js +0 -253
- package/dist/application/self/skills-manager.js.map +0 -1
- package/dist/application/self/skills-payload.js +0 -566
- package/dist/application/self/skills-payload.js.map +0 -1
- package/dist/application/self/skills-registry.js +0 -107
- package/dist/application/self/skills-registry.js.map +0 -1
- package/dist/application/skill-index-service.js +0 -78
- package/dist/application/skill-index-service.js.map +0 -1
- package/dist/cli/commands/plugin-cache.js +0 -25
- package/dist/cli/commands/plugin-cache.js.map +0 -1
- package/dist/cli/commands/skill-index.js +0 -19
- package/dist/cli/commands/skill-index.js.map +0 -1
- package/dist/cli/tui/data/recommended-skills.js +0 -482
- package/dist/cli/tui/data/recommended-skills.js.map +0 -1
- package/dist/cli/tui/tabs/skills-tab.js +0 -664
- package/dist/cli/tui/tabs/skills-tab.js.map +0 -1
|
@@ -135,7 +135,7 @@ Resume **keys off the `CHECKPOINT`** of the run's session, not the existence of
|
|
|
135
135
|
|
|
136
136
|
## docs/ boundary — no auto-export (hard rule)
|
|
137
137
|
|
|
138
|
-
A loop writes into `docs/` **only** its own flow's doc plus, when it composes a capability whose own deliverable is a `docs/` category, that category — today only the **UI Design Package** under `docs/designs` (`design`). Which folders that is per flow, and refusing any delegated step whose target leaves them, is the CLI's. **Published, never graduated**: the test is the origin, not the folder. No loop **graduates/promotes artifacts** into `docs/` — migrations → `docs/scripts`, manuals → `docs/manuals`, diagrams → `docs/diagrams` are the separate **`export-*`** skills', an explicit later step; artifacts stay in their sessions until then.
|
|
138
|
+
A loop writes into `docs/` **only** its own flow's doc plus, when it composes a capability whose own deliverable is a `docs/` category, that category — today only the **UI Design Package** under `docs/designs` (`design`). Which folders that is per flow, and refusing any delegated step whose target leaves them, is the CLI's. **Published, never graduated**: the test is the origin, not the folder. No loop **graduates/promotes artifacts** into `docs/` — migrations → `docs/scripts`, manuals → `docs/manuals`, diagrams → `docs/diagrams` are the separate **`export-*`** skills', an explicit later step; artifacts stay in their sessions until then. Reusable tooling follows the `docs/tools` contract and closing review; host help is optional.
|
|
139
139
|
|
|
140
140
|
## Conditional modules
|
|
141
141
|
|
|
@@ -36,7 +36,7 @@ same gate before any pending commit.
|
|
|
36
36
|
- **Minimality lens** (floor — holds with **no external skill**; chassis § *Minimality*): re-read the diff for over-building. Flag `delete` (dead/speculative code), `stdlib` (reinvented standard library), `native` (a dep or code doing what the platform already does), `yagni` (one-implementation abstraction, config nobody sets, one-caller layer), `shrink` (same behavior, fewer lines). An installed ambient review skill *raises* this; it never lowers it.
|
|
37
37
|
- **Test-value lens** (floor, next to minimality): every test the diff adds must demonstrate an observable behavior, protect a business rule, verify a contract, exercise a real integration or prevent a known regression. Flag `overtest` for the ones that only mirror structure — a test per class or method, mocked call chains, the same happy path re-asserted at every layer, trivial getters/setters/mappers, cases written for coverage, broad snapshots where a functional assertion is clearer. Bounded by *Gate integrity*: `overtest` prunes redundancy, **never** a check that guards behavior, a trust boundary, security or accessibility.
|
|
38
38
|
- **Temporary simulation check** (only when the change carries one): stubs, fakes and in-memory adapters are **explicit and named as such** (`Stub…` / `Fake…`), they sit at the boundary the plan declares, and no configuration can select them in a production runtime. A simulation still active on the main path with no declared removal is a finding, not a detail.
|
|
39
|
-
- **Tooling check** (`docs/tools`):
|
|
39
|
+
- **Tooling check** (`docs/tools`): reusable support scripts/CLIs/generators/configs (not product code or session probes) belong under `docs/tools/<slug>/`, with README, run/output structure and an index row in `docs/tools/README.md`. Review their usability and evidence before closing. Any host help is optional, from any origin; its absence never defers the tool.
|
|
40
40
|
- **Findings**: **fix** them in the working tree and **re-run validation** (the gate does not replace the tests: it re-verifies after fixing), or **defer them justified** (→ the plan's `Open questions` + `BACKLOG`; in quick, `BACKLOG`); the non-obvious → `DECISION`. Gate integrity (see [`CHASSIS.md`](CHASSIS.md) § *Verification-first*): never weaken a check or lower a convention to pass.
|
|
41
41
|
- **Artifact-first + verification-first**: seed `CHECKPOINT.Next = "review <batch/task>"`; Success
|
|
42
42
|
criteria require the whole diff to pass before commits.
|
package/skills/w/loops/README.md
CHANGED
|
@@ -47,11 +47,11 @@ The **5 loops** are heirs: they use `## Inherits` (a one-line reference to [`CHA
|
|
|
47
47
|
|
|
48
48
|
## Chassis / heirs
|
|
49
49
|
|
|
50
|
-
The **engine lives in [`CHASSIS.md`](CHASSIS.md)** (a referenced doc, not a skill);
|
|
50
|
+
The **engine lives in [`CHASSIS.md`](CHASSIS.md)** (a referenced doc, not a skill); all 5 loops inherit it. It is never a binding. The `design` capability has a Workline-owned floor; other assistance comes from the host when available.
|
|
51
51
|
|
|
52
52
|
## Composed capabilities (roles)
|
|
53
53
|
|
|
54
|
-
|
|
54
|
+
Only Workline-owned roles resolve through `.workflow/skills.toml`. External help is ambient; it is not a prerequisite, binding or gate proof. See [../roles/README.md](../roles/README.md).
|
|
55
55
|
|
|
56
56
|
## Index
|
|
57
57
|
|
|
@@ -42,7 +42,7 @@ Read **[`../CHASSIS.md`](../CHASSIS.md)** — the loop's **full engine** — **a
|
|
|
42
42
|
|
|
43
43
|
## Composes
|
|
44
44
|
|
|
45
|
-
|
|
45
|
+
Git safety, DB scripts-only and inline research are loop rules. Host-native help is optional and does not override them.
|
|
46
46
|
|
|
47
47
|
## QUICK delta — minimal ceremony
|
|
48
48
|
|
|
@@ -75,7 +75,7 @@ The **UI unspecified** gap (when the requirement involves UI; see *Gap taxonomy*
|
|
|
75
75
|
|
|
76
76
|
Other transversal capabilities the engine always uses: `research` (**inline** — chassis § *Research*), `sql` (DB rule inside research — chassis). All resolved by config; `off` → the loop continues without the capability and, if it was needed, says so or asks. The spec's **prose** follows the **ambient** writing conventions (the host auto-applies an installed writing skill if present), not a composed role.
|
|
77
77
|
|
|
78
|
-
> **Ambient conventions (not roles):** code/testing/writing
|
|
78
|
+
> **Ambient conventions (not roles):** host help for code/testing/writing or tooling may come from any origin; Workline neither binds nor depends on it. Full doctrine: [../../roles/README.md](../../roles/README.md).
|
|
79
79
|
|
|
80
80
|
## Current-behavior baseline (brownfield first)
|
|
81
81
|
|
package/skills/w/roles/README.md
CHANGED
|
@@ -1,31 +1,25 @@
|
|
|
1
1
|
# roles/ — Capability role catalog
|
|
2
2
|
|
|
3
|
-
>
|
|
4
|
-
> A role is a slot in the system; a skill is one concrete implementation of that slot.
|
|
5
|
-
> Changing implementation = changing one line in `skills.toml`.
|
|
3
|
+
> Only Workline-owned capabilities are binding roles. Other skills are host-native help, never Workline dependencies.
|
|
6
4
|
|
|
7
5
|
---
|
|
8
6
|
|
|
9
7
|
## Capability catalog
|
|
10
8
|
|
|
11
|
-
|
|
9
|
+
The owned roles and their built-in defaults:
|
|
12
10
|
|
|
13
11
|
| Role | Default built-in | Tier | Composed by |
|
|
14
12
|
|---|---|---|---|
|
|
15
13
|
| `design` | [`design`](design/ROLE.md) | must | `spec-refine-loop` (when requirement involves UI) · `plan-new-loop` / `plan-refine-loop` · `plan-exec-loop` (reads, never redesigns) |
|
|
16
|
-
| `sql` | `sql` | must | inline research · `plan-exec-loop` · `quick-loop` · `export-scripts` |
|
|
17
|
-
| `git` | `git` | must | `plan-exec-loop` · `quick-loop` |
|
|
18
|
-
| `research` | [`research`](research/ROLE.md) | should | all loops (on-demand investigation) |
|
|
19
|
-
| `diagrams` | [`diagrams`](diagrams/ROLE.md) | should | `export-diagrams` |
|
|
20
14
|
| `overview` | `w` | should | any loop (orientation about Workline itself) |
|
|
21
15
|
|
|
22
16
|
**Tiers:**
|
|
23
17
|
- `must` — core to almost every session; built-in always active unless explicitly `off`.
|
|
24
18
|
- `should` — loaded on-demand; active by default but lower priority to override.
|
|
25
19
|
|
|
26
|
-
> **Ambient
|
|
20
|
+
> **Ambient help (not roles).** Code, testing, writing, SQL, Git, research, diagrams and tool authoring are available when the host exposes them. Workline does not bind, inventory, install or require them.
|
|
27
21
|
>
|
|
28
|
-
> **An external skill is a technique, never an authorization.**
|
|
22
|
+
> **An external skill is a technique, never an authorization.** Host help cannot override Workline's gates, permissions, destinations or validated receipts. Its absence never blocks core flows; its mere presence never credits an improvement.
|
|
29
23
|
>
|
|
30
24
|
> **`ui-design` and `ui-spec` are retired names.** The design slot is [`design`](design/ROLE.md), whose only output is the UI Design Package v1. Neither retired name is a role, a binding, an alias or an implementation: they are **rejected**, because two names for one capability are two contracts in disguise. There is no alias, no dual-read, no importer and no migration — a binding that names one is reported as `retired/unsupported`, and a design that is still needed is recreated over the package.
|
|
31
25
|
>
|
|
@@ -47,13 +41,11 @@ built-in default
|
|
|
47
41
|
|
|
48
42
|
**Resolution rules:**
|
|
49
43
|
|
|
50
|
-
1. **
|
|
51
|
-
- If the name exists under `roles/<name>/` → it is a built-in skill.
|
|
52
|
-
- If not → it is a third-party skill installed by name on the host (e.g. via skills.sh).
|
|
44
|
+
1. **Owned role with a binding** → its canonical Workline skill name or `off` applies. Other names are warned as inapplicable, with the file left untouched.
|
|
53
45
|
2. **Role with no binding at any level** → use the built-in default (table above). No config needed for the common case.
|
|
54
46
|
3. **`off`** → capability disabled. The loop continues without it; if the task required it, the loop reports why it cannot proceed or asks the human.
|
|
55
47
|
|
|
56
|
-
|
|
48
|
+
**`design`** uses its built-in floor for required operations. A legacy replacement binding does not select a contributor or disable the floor; `off` follows the descriptor's per-operation policy. `[docs]` is independent and remains supported.
|
|
57
49
|
|
|
58
50
|
---
|
|
59
51
|
|
|
@@ -63,44 +55,20 @@ built-in default
|
|
|
63
55
|
[skills]
|
|
64
56
|
# Built-in defaults (no entry needed — listed here for reference only)
|
|
65
57
|
# design = "design"
|
|
66
|
-
# sql = "sql"
|
|
67
|
-
# git = "git"
|
|
68
|
-
# research = "research"
|
|
69
|
-
# diagrams = "diagrams"
|
|
70
58
|
# overview = "w"
|
|
71
59
|
|
|
72
|
-
#
|
|
73
|
-
design = "
|
|
74
|
-
diagrams = "mermaid-only" # custom built installed locally
|
|
75
|
-
sql = "off" # disable the sql capability
|
|
60
|
+
# Per-operation policy for an owned capability:
|
|
61
|
+
# design = "off"
|
|
76
62
|
```
|
|
77
63
|
|
|
78
|
-
### Override: point to a third-party skill
|
|
79
|
-
|
|
80
|
-
```toml
|
|
81
|
-
[skills]
|
|
82
|
-
design = "acme/figma-spec"
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
`acme/figma-spec` must be installed on the host (e.g. via `skills.sh install acme/figma-spec`). The binding is **advisory**: the resolver emits the name as-is — it does **not** verify the skill is installed and does **not** auto-fall-back to the built-in default. A typo'd name silently leaves the role bound to a skill that does not exist. Verify the resolution with `aw skills`, which warns when a bound skill is not found in the standard skill roots.
|
|
86
|
-
|
|
87
64
|
### Override: disable a capability
|
|
88
65
|
|
|
89
66
|
```toml
|
|
90
67
|
[skills]
|
|
91
|
-
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
The loop that composes `sql` will skip it. If the task required the capability and the role is `off`, the loop should inform the human and ask how to proceed.
|
|
95
|
-
|
|
96
|
-
### Override: use a different built-in
|
|
97
|
-
|
|
98
|
-
```toml
|
|
99
|
-
[skills]
|
|
100
|
-
diagrams = "diagrams-lite" # if a "diagrams-lite" built-in were registered
|
|
68
|
+
design = "off"
|
|
101
69
|
```
|
|
102
70
|
|
|
103
|
-
|
|
71
|
+
The `design` descriptor decides operation by operation: validation retains its own floor while authoring operations are disabled.
|
|
104
72
|
|
|
105
73
|
---
|
|
106
74
|
|
|
@@ -118,10 +86,6 @@ Example output:
|
|
|
118
86
|
Role Resolved skill Source
|
|
119
87
|
----------------- ----------------------- -----------
|
|
120
88
|
design design built-in
|
|
121
|
-
sql sql built-in
|
|
122
|
-
git git built-in
|
|
123
|
-
research research built-in
|
|
124
|
-
diagrams mermaid-only global (~/.workflow/skills.toml)
|
|
125
89
|
overview w built-in
|
|
126
90
|
```
|
|
127
91
|
|
|
@@ -149,4 +113,4 @@ Each `ROLE.md` follows this schema:
|
|
|
149
113
|
| `## Output` | what it produces and where (if any) |
|
|
150
114
|
| `## Source` | recycled from (if applicable) |
|
|
151
115
|
|
|
152
|
-
See [`
|
|
116
|
+
See [`design/ROLE.md`](design/ROLE.md) as a reference implementation.
|
|
@@ -25,7 +25,9 @@ replaces) and `ui-spec` (the skill that used to fill it) are **not** aliases,
|
|
|
25
25
|
for one capability is a second contract in disguise, and the day the two
|
|
26
26
|
disagree there is no way to say which one the package obeys.
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
`skills.toml` accepts the canonical name or `off`; legacy external names are
|
|
29
|
+
reported but cannot select a contributor. The host may contribute independently
|
|
30
|
+
in an attempt, subject to Workline's own validation and permissions.
|
|
29
31
|
Resolution: built-in default → `~/.workflow/skills.toml` (global) →
|
|
30
32
|
`.workflow/skills.toml` (workspace). See [`../README.md`](../README.md).
|
|
31
33
|
|
|
@@ -12,7 +12,7 @@ description: >
|
|
|
12
12
|
|
|
13
13
|
## Role
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
Diagram authoring can use host-native help without a Workline binding; the export retains its own destination and validation rules.
|
|
16
16
|
|
|
17
17
|
## Purpose
|
|
18
18
|
|
|
@@ -14,7 +14,7 @@ description: >-
|
|
|
14
14
|
|
|
15
15
|
## Role
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
Git-safe execution is a Workline invariant, independent of host skills and bindings.
|
|
18
18
|
|
|
19
19
|
## Purpose
|
|
20
20
|
|
|
@@ -14,7 +14,7 @@ description: >
|
|
|
14
14
|
|
|
15
15
|
## Role
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
Research uses the loop's own gap-driven method. Any additional host-native help is optional, not a Workline binding.
|
|
18
18
|
|
|
19
19
|
## Purpose
|
|
20
20
|
|
|
@@ -15,7 +15,7 @@ description: >-
|
|
|
15
15
|
|
|
16
16
|
## Role
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
DB scripts-only is Workline policy. SQL authoring help is ambient, supplied by the host when available and never required to enforce that policy.
|
|
19
19
|
|
|
20
20
|
## Purpose
|
|
21
21
|
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Reading the descriptor an installed skill claims to satisfy.
|
|
3
|
-
*
|
|
4
|
-
* The claim crosses a trust boundary: the frontmatter and the JSON next to it
|
|
5
|
-
* were authored by whoever wrote the skill, and nothing about being installed
|
|
6
|
-
* makes either of them true. So the loader verifies before it believes, in this
|
|
7
|
-
* order, and stops at the first failure:
|
|
8
|
-
*
|
|
9
|
-
* 1. the metadata key exists — its absence is not an error, it means the skill
|
|
10
|
-
* is ambient and gets no Workline surface;
|
|
11
|
-
* 2. the locator is a confined relative path to a `.json`, sealed with a digest;
|
|
12
|
-
* 3. the resolved file is a real file inside the skill's own directory and NOT a
|
|
13
|
-
* symlink — a link is how a confined path reaches outside anyway;
|
|
14
|
-
* 4. the bytes produce the sealed digest;
|
|
15
|
-
* 5. the contract version is one this CLI implements, checked before any other
|
|
16
|
-
* field is read.
|
|
17
|
-
*
|
|
18
|
-
* A failure never loads partially and never touches a binding.
|
|
19
|
-
*/
|
|
20
|
-
import { join } from "node:path";
|
|
21
|
-
import { CAPABILITY_DESCRIPTOR_METADATA_KEY, parseDescriptorLocator, verifyDescriptorPayload, } from "../../domain/capability/descriptor.js";
|
|
22
|
-
import { getSkillVersion, parseSkillFrontmatter } from "../../domain/skill-frontmatter.js";
|
|
23
|
-
/** Read a skill's `SKILL.md` head. Returns null when there is no readable one. */
|
|
24
|
-
export async function readSkillHead(fs, skillDir, dirName) {
|
|
25
|
-
const skillMd = join(skillDir, "SKILL.md");
|
|
26
|
-
if (!(await fs.exists(skillMd)))
|
|
27
|
-
return null;
|
|
28
|
-
let text;
|
|
29
|
-
try {
|
|
30
|
-
text = await fs.readText(skillMd);
|
|
31
|
-
}
|
|
32
|
-
catch {
|
|
33
|
-
return null;
|
|
34
|
-
}
|
|
35
|
-
const fm = parseSkillFrontmatter(text);
|
|
36
|
-
if (fm === null)
|
|
37
|
-
return null;
|
|
38
|
-
return {
|
|
39
|
-
name: fm.fields.name?.trim() || dirName,
|
|
40
|
-
version: getSkillVersion(fm),
|
|
41
|
-
locatorValue: fm.metadata[CAPABILITY_DESCRIPTOR_METADATA_KEY] ?? null,
|
|
42
|
-
skillMd,
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
export async function loadDescriptor(fs, skillDir, head) {
|
|
46
|
-
if (head.locatorValue === null)
|
|
47
|
-
return { state: "absent" };
|
|
48
|
-
const parsed = parseDescriptorLocator(head.locatorValue);
|
|
49
|
-
if (!parsed.ok) {
|
|
50
|
-
return {
|
|
51
|
-
state: "invalid",
|
|
52
|
-
failure: { code: parsed.code, message: parsed.message, action: parsed.action },
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
const absolute = join(skillDir, parsed.locator.path);
|
|
56
|
-
const link = await fs.lstat(absolute);
|
|
57
|
-
if (link === null) {
|
|
58
|
-
return {
|
|
59
|
-
state: "invalid",
|
|
60
|
-
failure: {
|
|
61
|
-
code: "CAPABILITY_DESCRIPTOR_MISSING",
|
|
62
|
-
message: `'${head.name}' declara un descriptor en '${parsed.locator.path}' y ahí no hay nada`,
|
|
63
|
-
action: "publicá el descriptor junto al SKILL.md, o quitá la clave de metadata",
|
|
64
|
-
},
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
// A confined relative path still lands outside if the target is a link. The
|
|
68
|
-
// containment rule is about WHICH BYTES get read, not about how the path looks.
|
|
69
|
-
if (link.isSymlink || link.type !== "file") {
|
|
70
|
-
return {
|
|
71
|
-
state: "invalid",
|
|
72
|
-
failure: {
|
|
73
|
-
code: "CAPABILITY_DESCRIPTOR_NOT_CONFINED",
|
|
74
|
-
message: `'${parsed.locator.path}' no es un archivo dentro del directorio de la skill`,
|
|
75
|
-
action: "publicá el descriptor como archivo real, sin enlaces simbólicos",
|
|
76
|
-
},
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
let bytes;
|
|
80
|
-
try {
|
|
81
|
-
bytes = await fs.readText(absolute);
|
|
82
|
-
}
|
|
83
|
-
catch {
|
|
84
|
-
return {
|
|
85
|
-
state: "invalid",
|
|
86
|
-
failure: {
|
|
87
|
-
code: "CAPABILITY_DESCRIPTOR_UNREADABLE",
|
|
88
|
-
message: `no se pudo leer '${parsed.locator.path}'`,
|
|
89
|
-
action: "revisá permisos del archivo del descriptor",
|
|
90
|
-
},
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
|
-
const verified = verifyDescriptorPayload(parsed.locator, bytes);
|
|
94
|
-
if (!verified.ok) {
|
|
95
|
-
return {
|
|
96
|
-
state: "invalid",
|
|
97
|
-
failure: { code: verified.code, message: verified.message, action: verified.action },
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
return {
|
|
101
|
-
state: "loaded",
|
|
102
|
-
loaded: {
|
|
103
|
-
descriptor: verified.descriptor,
|
|
104
|
-
path: parsed.locator.path,
|
|
105
|
-
digest: parsed.locator.digest,
|
|
106
|
-
},
|
|
107
|
-
};
|
|
108
|
-
}
|
|
109
|
-
//# sourceMappingURL=descriptor-loader.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"descriptor-loader.js","sourceRoot":"","sources":["../../../src/application/capability/descriptor-loader.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,168 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* What is ACTUALLY installed, as exact instances.
|
|
3
|
-
*
|
|
4
|
-
* The advisory check this replaces compared names. A name is not a thing that
|
|
5
|
-
* runs: two directories can both be called `design`, and picking one by scan
|
|
6
|
-
* order is a silent choice nobody made. So the unit here is an instance —
|
|
7
|
-
* name, scope, the locator of its `SKILL.md`, the locator of its descriptor, its
|
|
8
|
-
* version and a digest over its bytes — and the two failure modes are kept
|
|
9
|
-
* apart:
|
|
10
|
-
*
|
|
11
|
-
* - **Same name, same digest, several roots.** Equivalent replicas. Every
|
|
12
|
-
* locator is kept, because "which copy answered" is still a real question.
|
|
13
|
-
* - **Same name, different bytes.** `misconfigured`. Not a precedence puzzle to
|
|
14
|
-
* resolve — two different things are wearing one name, and no scan order makes
|
|
15
|
-
* that safe.
|
|
16
|
-
*
|
|
17
|
-
* Only skills that DECLARE a descriptor enter this inventory. An ambient skill —
|
|
18
|
-
* a linter, a writing convention — is installed and invisible here, which is the
|
|
19
|
-
* whole content of the opt-in.
|
|
20
|
-
*/
|
|
21
|
-
import { createHash } from "node:crypto";
|
|
22
|
-
import { RETIRED_SKILL_IDENTITIES } from "../../domain/skills.js";
|
|
23
|
-
import { semanticDigest } from "../semantic-operation/protocol.js";
|
|
24
|
-
import { skillRoots } from "../skills-resolver-service.js";
|
|
25
|
-
import { loadDescriptor, readSkillHead } from "./descriptor-loader.js";
|
|
26
|
-
export async function buildCapabilityInventory(fs, env, workspaceRoot) {
|
|
27
|
-
const roots = skillRoots(env, workspaceRoot);
|
|
28
|
-
const candidates = [];
|
|
29
|
-
for (const root of roots) {
|
|
30
|
-
candidates.push(...(await scanRoot(fs, root)));
|
|
31
|
-
}
|
|
32
|
-
return { roots, capabilities: group(candidates) };
|
|
33
|
-
}
|
|
34
|
-
async function scanRoot(fs, root) {
|
|
35
|
-
if (!(await fs.exists(root)))
|
|
36
|
-
return [];
|
|
37
|
-
let entries;
|
|
38
|
-
try {
|
|
39
|
-
entries = await fs.list(root);
|
|
40
|
-
}
|
|
41
|
-
catch {
|
|
42
|
-
return [];
|
|
43
|
-
}
|
|
44
|
-
const found = [];
|
|
45
|
-
for (const entry of entries) {
|
|
46
|
-
if (entry.type !== "dir")
|
|
47
|
-
continue;
|
|
48
|
-
const head = await readSkillHead(fs, entry.path, entry.name);
|
|
49
|
-
// No readable head, or no claim at all: an ambient skill. It never becomes a
|
|
50
|
-
// capability by being installed, so it never enters the inventory.
|
|
51
|
-
if (head === null || head.locatorValue === null)
|
|
52
|
-
continue;
|
|
53
|
-
found.push(await candidateFor(fs, root, entry.path, head));
|
|
54
|
-
}
|
|
55
|
-
return found;
|
|
56
|
-
}
|
|
57
|
-
async function candidateFor(fs, root, skillDir, head) {
|
|
58
|
-
const location = {
|
|
59
|
-
scope: root,
|
|
60
|
-
skillDir,
|
|
61
|
-
skillMd: head.skillMd,
|
|
62
|
-
descriptorPath: null,
|
|
63
|
-
};
|
|
64
|
-
const base = { name: head.name, version: head.version, location, descriptor: null };
|
|
65
|
-
// A directory wearing a retired name is refused before its descriptor is even
|
|
66
|
-
// read: the name IS the identity, and honoring it would resurrect the alias
|
|
67
|
-
// the contract exists to close.
|
|
68
|
-
const retired = RETIRED_SKILL_IDENTITIES.get(head.name.toLowerCase());
|
|
69
|
-
if (retired !== undefined) {
|
|
70
|
-
return {
|
|
71
|
-
...base,
|
|
72
|
-
digest: null,
|
|
73
|
-
failure: {
|
|
74
|
-
code: "CAPABILITY_NAME_RETIRED",
|
|
75
|
-
message: `'${head.name}' está retirado — ${retired}`,
|
|
76
|
-
action: "renombrá la skill al nombre vigente de la capacidad; no hay alias",
|
|
77
|
-
},
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
const load = await loadDescriptor(fs, skillDir, head);
|
|
81
|
-
if (load.state !== "loaded") {
|
|
82
|
-
return {
|
|
83
|
-
...base,
|
|
84
|
-
digest: null,
|
|
85
|
-
failure: load.state === "invalid" ? load.failure : null,
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
return {
|
|
89
|
-
name: head.name,
|
|
90
|
-
version: head.version,
|
|
91
|
-
digest: await instanceDigest(fs, head.skillMd, load.loaded.digest),
|
|
92
|
-
location: { ...location, descriptorPath: load.loaded.path },
|
|
93
|
-
descriptor: load.loaded.descriptor,
|
|
94
|
-
failure: null,
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
/**
|
|
98
|
-
* The identity of the bytes that would run: the instruction file AND the
|
|
99
|
-
* contract it points at. Sealing only the descriptor would call two skills
|
|
100
|
-
* identical while their `SKILL.md` told the host to do different things.
|
|
101
|
-
*/
|
|
102
|
-
async function instanceDigest(fs, skillMd, descriptorDigest) {
|
|
103
|
-
try {
|
|
104
|
-
const text = await fs.readText(skillMd);
|
|
105
|
-
return semanticDigest({
|
|
106
|
-
skill_md: createHash("sha256").update(text, "utf8").digest("hex"),
|
|
107
|
-
descriptor: descriptorDigest,
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
catch {
|
|
111
|
-
return null;
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
function group(candidates) {
|
|
115
|
-
const byName = new Map();
|
|
116
|
-
for (const candidate of candidates) {
|
|
117
|
-
byName.set(candidate.name, [...(byName.get(candidate.name) ?? []), candidate]);
|
|
118
|
-
}
|
|
119
|
-
const out = [];
|
|
120
|
-
for (const [name, copies] of byName) {
|
|
121
|
-
const locations = copies.map((c) => c.location);
|
|
122
|
-
const broken = copies.find((c) => c.failure !== null);
|
|
123
|
-
if (broken?.failure != null) {
|
|
124
|
-
out.push({
|
|
125
|
-
name,
|
|
126
|
-
version: broken.version,
|
|
127
|
-
digest: null,
|
|
128
|
-
locations,
|
|
129
|
-
descriptor: null,
|
|
130
|
-
state: "misconfigured",
|
|
131
|
-
failure: broken.failure,
|
|
132
|
-
});
|
|
133
|
-
continue;
|
|
134
|
-
}
|
|
135
|
-
const digests = [...new Set(copies.map((c) => c.digest))];
|
|
136
|
-
const first = copies[0];
|
|
137
|
-
if (digests.length > 1) {
|
|
138
|
-
out.push({
|
|
139
|
-
name,
|
|
140
|
-
version: first.version,
|
|
141
|
-
digest: null,
|
|
142
|
-
locations,
|
|
143
|
-
descriptor: null,
|
|
144
|
-
state: "misconfigured",
|
|
145
|
-
failure: {
|
|
146
|
-
code: "CAPABILITY_INSTANCE_COLLISION",
|
|
147
|
-
message: `hay ${copies.length} skills llamadas '${name}' con bytes distintos: ${locations.map((l) => l.skillDir).join(", ")}`,
|
|
148
|
-
action: "dejá una sola instalación de ese nombre, o renombrá la que no corresponde: no hay precedencia entre roots",
|
|
149
|
-
},
|
|
150
|
-
});
|
|
151
|
-
continue;
|
|
152
|
-
}
|
|
153
|
-
out.push({
|
|
154
|
-
name,
|
|
155
|
-
version: first.version,
|
|
156
|
-
digest: first.digest,
|
|
157
|
-
locations,
|
|
158
|
-
descriptor: first.descriptor,
|
|
159
|
-
state: "ready",
|
|
160
|
-
failure: null,
|
|
161
|
-
});
|
|
162
|
-
}
|
|
163
|
-
return out.sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));
|
|
164
|
-
}
|
|
165
|
-
export function findInstalled(inventory, name) {
|
|
166
|
-
return inventory.capabilities.find((c) => c.name === name) ?? null;
|
|
167
|
-
}
|
|
168
|
-
//# sourceMappingURL=installed-inventory.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"installed-inventory.js","sourceRoot":"","sources":["../../../src/application/capability/installed-inventory.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import { BUILTIN_DEFAULT_SKILLS } from "../../domain/skills.js";
|
|
2
|
-
/** Migrate only active legacy template lines; comments and user bindings keep their bytes. */
|
|
3
|
-
export function migrateSkillsToml(text) {
|
|
4
|
-
const lines = text.match(/[^\n]*\n|[^\n]+$/g) ?? [];
|
|
5
|
-
const hasDesign = hasActiveDesign(lines);
|
|
6
|
-
const output = [];
|
|
7
|
-
let section = "";
|
|
8
|
-
let changed = false;
|
|
9
|
-
for (const line of lines) {
|
|
10
|
-
const heading = /^\s*\[([^\]]+)\]\s*(?:#.*)?(?:\r?\n)?$/.exec(line);
|
|
11
|
-
if (heading !== null) {
|
|
12
|
-
section = heading[1]?.trim() ?? "";
|
|
13
|
-
if (section === "compaction") {
|
|
14
|
-
changed = true;
|
|
15
|
-
continue;
|
|
16
|
-
}
|
|
17
|
-
output.push(line);
|
|
18
|
-
continue;
|
|
19
|
-
}
|
|
20
|
-
if (section === "compaction") {
|
|
21
|
-
if (line.trim().startsWith("#") || line.trim().length === 0)
|
|
22
|
-
output.push(line);
|
|
23
|
-
else
|
|
24
|
-
changed = true;
|
|
25
|
-
continue;
|
|
26
|
-
}
|
|
27
|
-
if (section !== "skills" || line.trim().startsWith("#")) {
|
|
28
|
-
output.push(line);
|
|
29
|
-
continue;
|
|
30
|
-
}
|
|
31
|
-
const rewritten = rewriteBinding(line, hasDesign);
|
|
32
|
-
if (rewritten !== line)
|
|
33
|
-
changed = true;
|
|
34
|
-
if (rewritten.length > 0)
|
|
35
|
-
output.push(rewritten);
|
|
36
|
-
}
|
|
37
|
-
return { text: changed ? output.join("") : text, changed };
|
|
38
|
-
}
|
|
39
|
-
function hasActiveDesign(lines) {
|
|
40
|
-
let skills = false;
|
|
41
|
-
for (const line of lines) {
|
|
42
|
-
const heading = /^\s*\[([^\]]+)\]/.exec(line);
|
|
43
|
-
if (heading !== null)
|
|
44
|
-
skills = heading[1] === "skills";
|
|
45
|
-
else if (skills && /^\s*design\s*=/.test(line))
|
|
46
|
-
return true;
|
|
47
|
-
}
|
|
48
|
-
return false;
|
|
49
|
-
}
|
|
50
|
-
function rewriteBinding(line, hasDesign) {
|
|
51
|
-
const binding = /^(\s*)([a-z][a-z-]*)(\s*=\s*)(["'])([^"']+)\4(\s*(?:#.*)?(?:\r?\n)?)$/.exec(line);
|
|
52
|
-
if (binding === null)
|
|
53
|
-
return line;
|
|
54
|
-
const [, indent, role, equals, quote, value, suffix] = binding;
|
|
55
|
-
if (["coding-standards", "writing", "testing", "tools"].includes(role ?? "")) {
|
|
56
|
-
const comment = /(#.*?)(\r?\n)?$/.exec(suffix ?? "");
|
|
57
|
-
return comment === null ? "" : `${indent}${comment[1]}${comment[2] ?? ""}`;
|
|
58
|
-
}
|
|
59
|
-
if (role === "ui-design" && hasDesign)
|
|
60
|
-
return "";
|
|
61
|
-
const currentRole = role === "ui-design" ? BUILTIN_DEFAULT_SKILLS.design : role;
|
|
62
|
-
const currentValue = value === "ui-spec" && currentRole === BUILTIN_DEFAULT_SKILLS.design
|
|
63
|
-
? BUILTIN_DEFAULT_SKILLS.design
|
|
64
|
-
: value === "workflow" && currentRole === "overview"
|
|
65
|
-
? BUILTIN_DEFAULT_SKILLS.overview
|
|
66
|
-
: value;
|
|
67
|
-
return `${indent}${currentRole}${equals}${quote}${currentValue}${quote}${suffix}`;
|
|
68
|
-
}
|
|
69
|
-
export async function applySkillsTomlMigration(fs, path) {
|
|
70
|
-
const migration = migrateSkillsToml(await fs.readText(path));
|
|
71
|
-
if (!migration.changed)
|
|
72
|
-
return false;
|
|
73
|
-
await fs.writeText(path, migration.text);
|
|
74
|
-
return true;
|
|
75
|
-
}
|
|
76
|
-
//# sourceMappingURL=skills-toml-migrate.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"skills-toml-migrate.js","sourceRoot":"","sources":["../../../src/application/doctor/skills-toml-migrate.ts"],"names":[],"mappings":"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"}
|