@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.
Files changed (115) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/README.md +1 -2
  3. package/dist/application/capability/design-handler.js +94 -0
  4. package/dist/application/capability/design-handler.js.map +1 -1
  5. package/dist/application/capability/dispatcher.js +178 -18
  6. package/dist/application/capability/dispatcher.js.map +1 -1
  7. package/dist/application/capability/durable-effect.js.map +1 -1
  8. package/dist/application/capability/readiness.js +8 -54
  9. package/dist/application/capability/readiness.js.map +1 -1
  10. package/dist/application/capability/resolution.js +124 -192
  11. package/dist/application/capability/resolution.js.map +1 -1
  12. package/dist/application/doctor/prepare.js +0 -3
  13. package/dist/application/doctor/prepare.js.map +1 -1
  14. package/dist/application/doctor/provider-skills.js +21 -132
  15. package/dist/application/doctor/provider-skills.js.map +1 -1
  16. package/dist/application/doctor/repair-runner.js +0 -47
  17. package/dist/application/doctor/repair-runner.js.map +1 -1
  18. package/dist/application/flow/submit.js +1 -1
  19. package/dist/application/flow/submit.js.map +1 -1
  20. package/dist/application/plan-lint-service.js +31 -5
  21. package/dist/application/plan-lint-service.js.map +1 -1
  22. package/dist/application/retirement/attribution.js +1 -2
  23. package/dist/application/retirement/attribution.js.map +1 -1
  24. package/dist/application/self/clean-legacy.js +1 -2
  25. package/dist/application/self/clean-legacy.js.map +1 -1
  26. package/dist/application/self/install-skill.js +5 -49
  27. package/dist/application/self/install-skill.js.map +1 -1
  28. package/dist/application/self/skill-files.js +29 -0
  29. package/dist/application/self/skill-files.js.map +1 -0
  30. package/dist/application/skills-resolver-service.js +5 -91
  31. package/dist/application/skills-resolver-service.js.map +1 -1
  32. package/dist/application/source-boundary-policy.js +10 -2
  33. package/dist/application/source-boundary-policy.js.map +1 -1
  34. package/dist/cli/commands/capability.js +12 -4
  35. package/dist/cli/commands/capability.js.map +1 -1
  36. package/dist/cli/commands/index.js +0 -4
  37. package/dist/cli/commands/index.js.map +1 -1
  38. package/dist/cli/commands/self.js +1 -22
  39. package/dist/cli/commands/self.js.map +1 -1
  40. package/dist/cli/commands/skills.js +4 -11
  41. package/dist/cli/commands/skills.js.map +1 -1
  42. package/dist/cli/help-groups.js +1 -3
  43. package/dist/cli/help-groups.js.map +1 -1
  44. package/dist/cli/tui/app.js +2 -3
  45. package/dist/cli/tui/app.js.map +1 -1
  46. package/dist/cli/tui/components/host-admin-section.js +2 -13
  47. package/dist/cli/tui/components/host-admin-section.js.map +1 -1
  48. package/dist/cli/tui/components/tabs-config.js +1 -2
  49. package/dist/cli/tui/components/tabs-config.js.map +1 -1
  50. package/dist/cli/tui/tui-prefs.js +2 -0
  51. package/dist/cli/tui/tui-prefs.js.map +1 -1
  52. package/dist/dist-manifest.json +60 -204
  53. package/dist/domain/capability/protocol.js +3 -1
  54. package/dist/domain/capability/protocol.js.map +1 -1
  55. package/dist/domain/doctor/operations.js +0 -18
  56. package/dist/domain/doctor/operations.js.map +1 -1
  57. package/dist/domain/flow/authority.js +1 -3
  58. package/dist/domain/flow/authority.js.map +1 -1
  59. package/dist/domain/skills.js +2 -6
  60. package/dist/domain/skills.js.map +1 -1
  61. package/package.json +2 -2
  62. package/skills/w/SKILL.md +9 -16
  63. package/skills/w/exports/README.md +4 -4
  64. package/skills/w/exports/export-diagrams/EXPORT.md +1 -1
  65. package/skills/w/exports/export-scripts/EXPORT.md +1 -1
  66. package/skills/w/harness/HARNESS.md +2 -5
  67. package/skills/w/loops/CHASSIS.md +1 -1
  68. package/skills/w/loops/CODE-POLICIES.md +1 -1
  69. package/skills/w/loops/README.md +2 -2
  70. package/skills/w/loops/quick-loop/LOOP.md +1 -1
  71. package/skills/w/loops/spec-refine-loop/LOOP.md +1 -1
  72. package/skills/w/roles/README.md +11 -47
  73. package/skills/w/roles/design/ROLE.md +3 -1
  74. package/skills/w/roles/diagrams/ROLE.md +1 -1
  75. package/skills/w/roles/git/ROLE.md +1 -1
  76. package/skills/w/roles/research/ROLE.md +1 -1
  77. package/skills/w/roles/sql/ROLE.md +1 -1
  78. package/dist/application/capability/descriptor-loader.js +0 -109
  79. package/dist/application/capability/descriptor-loader.js.map +0 -1
  80. package/dist/application/capability/installed-inventory.js +0 -168
  81. package/dist/application/capability/installed-inventory.js.map +0 -1
  82. package/dist/application/doctor/skills-toml-migrate.js +0 -76
  83. package/dist/application/doctor/skills-toml-migrate.js.map +0 -1
  84. package/dist/application/self/install-plugin-skills-git.js +0 -226
  85. package/dist/application/self/install-plugin-skills-git.js.map +0 -1
  86. package/dist/application/self/install-plugin-skills.js +0 -203
  87. package/dist/application/self/install-plugin-skills.js.map +0 -1
  88. package/dist/application/self/plugin-cache-clear.js +0 -133
  89. package/dist/application/self/plugin-cache-clear.js.map +0 -1
  90. package/dist/application/self/plugin-cache-reload.js +0 -141
  91. package/dist/application/self/plugin-cache-reload.js.map +0 -1
  92. package/dist/application/self/skills-apply.js +0 -623
  93. package/dist/application/self/skills-apply.js.map +0 -1
  94. package/dist/application/self/skills-catalog.js +0 -35
  95. package/dist/application/self/skills-catalog.js.map +0 -1
  96. package/dist/application/self/skills-change.js +0 -479
  97. package/dist/application/self/skills-change.js.map +0 -1
  98. package/dist/application/self/skills-discovery.js +0 -275
  99. package/dist/application/self/skills-discovery.js.map +0 -1
  100. package/dist/application/self/skills-manager.js +0 -253
  101. package/dist/application/self/skills-manager.js.map +0 -1
  102. package/dist/application/self/skills-payload.js +0 -566
  103. package/dist/application/self/skills-payload.js.map +0 -1
  104. package/dist/application/self/skills-registry.js +0 -107
  105. package/dist/application/self/skills-registry.js.map +0 -1
  106. package/dist/application/skill-index-service.js +0 -78
  107. package/dist/application/skill-index-service.js.map +0 -1
  108. package/dist/cli/commands/plugin-cache.js +0 -25
  109. package/dist/cli/commands/plugin-cache.js.map +0 -1
  110. package/dist/cli/commands/skill-index.js +0 -19
  111. package/dist/cli/commands/skill-index.js.map +0 -1
  112. package/dist/cli/tui/data/recommended-skills.js +0 -482
  113. package/dist/cli/tui/data/recommended-skills.js.map +0 -1
  114. package/dist/cli/tui/tabs/skills-tab.js +0 -664
  115. 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. A task creating a tool has it documented in `docs/tools` by the ambient `creating-tools` skill (auto-discovered; Workline does not bind it).
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`): did the run create **reusable auxiliary tooling** (support scripts/CLIs/generators/reusable configs — not product code, not session probes)? → the host applies the **ambient `creating-tools` skill** (auto-discovered; Workline does not bind it), which homes it under `docs/tools/<slug>/` per its contract. Host without such a skill → the loop still **never writes `docs/tools` itself**: **declare the gap** — the homeless tool goes to the plan's `Open questions` + `BACKLOG` (in quick, `BACKLOG`) — never silent.
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.
@@ -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); the 5 loops — including `spec-refine-loop` — are **heirs** of that engine. The canonical heirs list and their deltas live in the chassis itself (§ *Heirs*). The chassis is **not a bindable capability**: it is the loop engine; what is pluggable are the **capabilities** a loop composes (e.g. `design`, `sql`, `git`), resolved via `.workflow/skills.toml`.
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
- Loops compose **capabilities by role**, never concrete skills; the skill fulfilling the role is resolved via `.workflow/skills.toml` (cascade: built-in → global → workspace; `off` = disabled — the loop continues and says so if it was needed). Catalog, defaults and ambient-conventions doctrine: [../roles/README.md](../roles/README.md).
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
- `git` · `sql` (DB rule) · `research` (inline). Resolved via `.workflow/skills.toml`.
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 standards and `creating-tools` are standalone skills the host auto-discovers by `description` — Workline neither binds nor depends on them. Full doctrine: [../../roles/README.md](../../roles/README.md).
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
 
@@ -1,31 +1,25 @@
1
1
  # roles/ — Capability role catalog
2
2
 
3
- > Built-in default implementations of the **capability roles** that loops and exports compose.
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
- All 6 roles, their built-in defaults, their tier, and which loops/exports compose them:
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 conventions (not roles).** Code, testing and writing standards **and tool authoring** (`creating-tools`, which writes `docs/tools`) are **not Workline roles** and are never bound: they are **standalone skills the host auto-discovers by `description`** and applies when relevant. Workline is **indifferent** (it neither reads nor looks for them). Useful families live in marketplace plugins (`dev-conventions`, `tool-builder`), but Workline does **not depend** on them.
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.** Installing one adds a technique the host may apply when it is relevant; it moves no boundary this system already fixed. Concretely: a skill recommending a validation library does not override the repo's own decision; a reference to subagents is not delegation authority; one that writes documents of its own still lands where the work's custody says; an interview or a checklist it proposes does not become a step of SPEC, PLAN or QUICK; and none of them authorizes a dependency, an agent, an architecture change or an extra validation. **Absence is not a blocker either:** a flow whose optional skill is missing, refused or incompatible runs its base behavior, and says so instead of reporting a check it never ran — a real dependency of the task is named as such. What Workline controls is its **recommendation** and its **managed installation**; a host that discovers instructions by another route is outside that control, so neither a catalog filter nor a `skills.toml` `off` is ever announced as a universal switch.
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. **Role with a binding** (workspace, or global if not workspace) → use that skill name.
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
- **A role whose skill declares a capability descriptor is stricter**, because there the binding decides what RUNS and not just which name is written: unset or the canonical name enables the built-in floor plus whatever compatible improvements the host selected; `off` applies the descriptor's per-operation policy and no host, wrapper or legacy name reverts it; anything else is `misconfigured` — a replacement binding does not select an improvement, and the file is never rewritten for you. Existing workspaces are not migrated: `aw skills --detail` explains the reclassification and the owner adopts unset, the canonical name or `off`.
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
- # Override examples:
73
- design = "acme/figma-spec" # third-party skill installed via skills.sh
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
- sql = "off"
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
- Only meaningful if multiple built-ins for the same role are registered. Currently each role has exactly one built-in default.
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 [`research/ROLE.md`](research/ROLE.md) as a reference implementation.
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
- Rebindable in `.workflow/skills.toml` to a third-party skill or `off`.
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
- `diagrams` — built-in default implementation. Rebindable to another skill (third-party or `off`) in `.workflow/skills.toml`.
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
- `git` — built-in default. Rebindable in `.workflow/skills.toml` (third-party skill or `off`). This skill encodes invariant 5: **safe git**.
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
- `research` — built-in default implementation. Rebindable to another skill (third-party or `off`) in `.workflow/skills.toml`.
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
- `sql` — built-in default. Rebindable in `.workflow/skills.toml` (third-party skill or `off`). When `off`, the loop continues without DB authoring help and says so if the task needed it.
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":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGzC,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAGlE,OAAO,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AACnE,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAsCvE,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,EAAkB,EAClB,GAAY,EACZ,aAAsB;IAEtB,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC;IAC7C,MAAM,UAAU,GAAgB,EAAE,CAAC;IACnC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;IACjD,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC;AACpD,CAAC;AAED,KAAK,UAAU,QAAQ,CAAC,EAAkB,EAAE,IAAY;IACtD,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAAE,OAAO,EAAE,CAAC;IACxC,IAAI,OAAoD,CAAC;IACzD,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,KAAK,GAAgB,EAAE,CAAC;IAC9B,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,KAAK,CAAC,IAAI,KAAK,KAAK;YAAE,SAAS;QACnC,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC,EAAE,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAC7D,6EAA6E;QAC7E,mEAAmE;QACnE,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,CAAC,YAAY,KAAK,IAAI;YAAE,SAAS;QAC1D,KAAK,CAAC,IAAI,CAAC,MAAM,YAAY,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;IAC7D,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,KAAK,UAAU,YAAY,CACzB,EAAkB,EAClB,IAAY,EACZ,QAAgB,EAChB,IAAe;IAEf,MAAM,QAAQ,GAAqB;QACjC,KAAK,EAAE,IAAI;QACX,QAAQ;QACR,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,cAAc,EAAE,IAAI;KACrB,CAAC;IACF,MAAM,IAAI,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,IAAI,EAAW,CAAC;IAE7F,8EAA8E;IAC9E,4EAA4E;IAC5E,gCAAgC;IAChC,MAAM,OAAO,GAAG,wBAAwB,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;IACtE,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,OAAO;YACL,GAAG,IAAI;YACP,MAAM,EAAE,IAAI;YACZ,OAAO,EAAE;gBACP,IAAI,EAAE,yBAAyB;gBAC/B,OAAO,EAAE,IAAI,IAAI,CAAC,IAAI,qBAAqB,OAAO,EAAE;gBACpD,MAAM,EAAE,mEAAmE;aAC5E;SACF,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,cAAc,CAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;IACtD,IAAI,IAAI,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC5B,OAAO;YACL,GAAG,IAAI;YACP,MAAM,EAAE,IAAI;YACZ,OAAO,EAAE,IAAI,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI;SACxD,CAAC;IACJ,CAAC;IACD,OAAO;QACL,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,MAAM,EAAE,MAAM,cAAc,CAAC,EAAE,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;QAClE,QAAQ,EAAE,EAAE,GAAG,QAAQ,EAAE,cAAc,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE;QAC3D,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,UAAU;QAClC,OAAO,EAAE,IAAI;KACd,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,KAAK,UAAU,cAAc,CAC3B,EAAkB,EAClB,OAAe,EACf,gBAAwB;IAExB,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QACxC,OAAO,cAAc,CAAC;YACpB,QAAQ,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;YACjE,UAAU,EAAE,gBAAgB;SAC7B,CAAC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,KAAK,CAAC,UAAuB;IACpC,MAAM,MAAM,GAAG,IAAI,GAAG,EAAuB,CAAC;IAC9C,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC;IACjF,CAAC;IAED,MAAM,GAAG,GAA0B,EAAE,CAAC;IACtC,KAAK,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACpC,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;QAChD,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,IAAI,CAAC,CAAC;QACtD,IAAI,MAAM,EAAE,OAAO,IAAI,IAAI,EAAE,CAAC;YAC5B,GAAG,CAAC,IAAI,CAAC;gBACP,IAAI;gBACJ,OAAO,EAAE,MAAM,CAAC,OAAO;gBACvB,MAAM,EAAE,IAAI;gBACZ,SAAS;gBACT,UAAU,EAAE,IAAI;gBAChB,KAAK,EAAE,eAAe;gBACtB,OAAO,EAAE,MAAM,CAAC,OAAO;aACxB,CAAC,CAAC;YACH,SAAS;QACX,CAAC;QAED,MAAM,OAAO,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAC1D,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAc,CAAC;QACrC,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvB,GAAG,CAAC,IAAI,CAAC;gBACP,IAAI;gBACJ,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,MAAM,EAAE,IAAI;gBACZ,SAAS;gBACT,UAAU,EAAE,IAAI;gBAChB,KAAK,EAAE,eAAe;gBACtB,OAAO,EAAE;oBACP,IAAI,EAAE,+BAA+B;oBACrC,OAAO,EAAE,OAAO,MAAM,CAAC,MAAM,qBAAqB,IAAI,0BAA0B,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;oBAC7H,MAAM,EACJ,2GAA2G;iBAC9G;aACF,CAAC,CAAC;YACH,SAAS;QACX,CAAC;QACD,GAAG,CAAC,IAAI,CAAC;YACP,IAAI;YACJ,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,SAAS;YACT,UAAU,EAAE,KAAK,CAAC,UAAU;YAC5B,KAAK,EAAE,OAAO;YACd,OAAO,EAAE,IAAI;SACd,CAAC,CAAC;IACL,CAAC;IACD,OAAO,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC9E,CAAC;AAED,MAAM,UAAU,aAAa,CAC3B,SAA8B,EAC9B,IAAY;IAEZ,OAAO,SAAS,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,IAAI,CAAC;AACrE,CAAC"}
@@ -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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"}