agent-skillboard 0.3.1 → 0.3.3
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 +41 -0
- package/README.md +27 -10
- package/docs/ai-skill-routing-goal.md +19 -7
- package/docs/install.md +15 -4
- package/docs/policy-model.md +12 -3
- package/docs/positioning.md +4 -2
- package/docs/reference.md +20 -9
- package/docs/routing.md +19 -8
- package/docs/user-flow.md +14 -6
- package/docs/value-proof.md +7 -2
- package/docs/variant-lifecycle.md +2 -1
- package/docs/versioning.md +9 -4
- package/package.json +1 -1
- package/src/advisor/guidance.mjs +20 -2
- package/src/agent-integration-cli.mjs +31 -48
- package/src/agent-integration-command.mjs +38 -0
- package/src/agent-integration-content.mjs +6 -6
- package/src/brief-renderer.mjs +1 -1
- package/src/cli.mjs +70 -43
- package/src/inventory-refresh.mjs +1 -0
- package/src/lifecycle-cli.mjs +1 -1
- package/src/lifecycle-content.mjs +8 -6
- package/src/migration/automatic-v2.mjs +14 -0
- package/src/migration/v2-projection.mjs +2 -1
- package/src/migration/v2-transaction.mjs +4 -0
- package/src/route-advisory.mjs +0 -44
- package/src/route-renderer.mjs +9 -2
- package/src/route-selection.mjs +11 -33
- package/src/route-tokens.mjs +20 -2
- package/src/route.mjs +35 -52
- package/src/setup-policy-migration.mjs +43 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,47 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.3.3 — 2026-07-15
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Added deterministic Unicode intent tokenization with whole-run and character
|
|
10
|
+
bigram matching for legacy v1 compatibility routing.
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- Removed v2 request tokenization, metadata scoring, ranked hints, and
|
|
15
|
+
deterministic recommendations. Route and brief now return raw eligible skill
|
|
16
|
+
descriptions and saved preferences for the active model to interpret.
|
|
17
|
+
- Made route, can-use, and guard errors explain whether the detected policy
|
|
18
|
+
expects v2 `--agent` or v1 `--workflow`, including the v1 migration preview.
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
|
|
22
|
+
- Preserved legacy v1 explicit skill-id selection when an ASCII id is
|
|
23
|
+
immediately followed by a Hangul or CJK particle, without allowing Latin
|
|
24
|
+
prefix matches.
|
|
25
|
+
|
|
26
|
+
## 0.3.2 — 2026-07-14
|
|
27
|
+
|
|
28
|
+
### Changed
|
|
29
|
+
|
|
30
|
+
- Made global npm updates and `skillboard setup` automatically upgrade a valid
|
|
31
|
+
version 1 user policy when every migration choice is already understood.
|
|
32
|
+
- Kept the explicit `migrate v2` preview, apply, and rollback commands for
|
|
33
|
+
project policies, audits, and recovery.
|
|
34
|
+
|
|
35
|
+
### Fixed
|
|
36
|
+
|
|
37
|
+
- Removed the hidden manual migration step left after a 0.3.1 update while
|
|
38
|
+
preserving explicit terminal denials as disabled and review-only quarantine
|
|
39
|
+
states as enabled, agent-local skills.
|
|
40
|
+
- Kept automatic migration non-mutating for unknown future ambiguity kinds or
|
|
41
|
+
policy skills that are not currently observed, and restored exact version 1
|
|
42
|
+
bytes after any transactional failure.
|
|
43
|
+
- Restored invoking-user ownership for migration backups, manifests, and
|
|
44
|
+
generated inventory during sudo-driven global updates.
|
|
45
|
+
|
|
5
46
|
## 0.3.1 — 2026-07-14
|
|
6
47
|
|
|
7
48
|
### Added
|
package/README.md
CHANGED
|
@@ -6,10 +6,11 @@ SkillBoard gives AI agents one small user-level policy for installed skills:
|
|
|
6
6
|
2. Keep an enabled skill agent-local or shared across agents.
|
|
7
7
|
|
|
8
8
|
Valid installed skills default to enabled and agent-local. Sharing is opt-in per
|
|
9
|
-
skill.
|
|
10
|
-
and
|
|
9
|
+
skill. The model makes semantic skill choices from the request, eligible skill
|
|
10
|
+
descriptions, and raw saved preferences. SkillBoard does not tokenize, score,
|
|
11
|
+
match, or recommend from v2 request text.
|
|
11
12
|
|
|
12
|
-
Status: public alpha. Package 0.3.
|
|
13
|
+
Status: public alpha. Package 0.3.3 writes policy schema v2.
|
|
13
14
|
|
|
14
15
|
<p align="center">
|
|
15
16
|
<img src="https://raw.githubusercontent.com/NyXXiR/skillboard/main/skillboard.png" alt="SkillBoard architecture diagram" width="100%">
|
|
@@ -56,6 +57,14 @@ prefix, activate the Node environment that owns each stale copy, and run
|
|
|
56
57
|
uninstall another prefix. Restart or refresh agents after an update because
|
|
57
58
|
some agents cache user skills.
|
|
58
59
|
|
|
60
|
+
When an update finds a valid version 1 user policy, setup automatically migrates
|
|
61
|
+
it only when all reported choices are understood. It creates an adjacent exact
|
|
62
|
+
backup, keeps explicit terminal denials disabled, and maps review-only
|
|
63
|
+
quarantine states to enabled and agent-local. Unknown future ambiguity leaves
|
|
64
|
+
the policy unchanged and prints the explicit preview command instead. The same
|
|
65
|
+
review path is used when a v1 policy skill is not currently observed, avoiding
|
|
66
|
+
an unhealthy generated inventory or silently forgetting a denial.
|
|
67
|
+
|
|
59
68
|
`setup` is safe to rerun. It refreshes managed guidance and inventory, discovers
|
|
60
69
|
late standard agent homes and Hermes profiles, and fills already-selected
|
|
61
70
|
`shared: true` skills into newly active roots. It does not make every skill
|
|
@@ -120,8 +129,9 @@ destructive actions, and secrets.
|
|
|
120
129
|
From any working directory, an agent can:
|
|
121
130
|
|
|
122
131
|
1. Read `skillboard brief --intent <request> --agent <agent> --json`.
|
|
123
|
-
2. Select
|
|
124
|
-
|
|
132
|
+
2. Select the best eligible skill from the full request, descriptions, local
|
|
133
|
+
instructions, and raw saved preferences, or use no skill. The model itself
|
|
134
|
+
interprets explicit user direction and preference semantics.
|
|
125
135
|
3. Run `skillboard guard use <skill-id> --agent <agent> --json` before use.
|
|
126
136
|
4. Work without another approval when the guard allows use.
|
|
127
137
|
5. Ask after completion only if remembering a preference would help.
|
|
@@ -143,8 +153,8 @@ current action, runs `skillboard apply-action <action-id> --agent <agent> --yes
|
|
|
143
153
|
rereads the returned post-apply brief.
|
|
144
154
|
|
|
145
155
|
This is the distinction from a pure distribution tool: skills stay local by
|
|
146
|
-
default, users promote only selected skills to shared use, and
|
|
147
|
-
can be remembered without changing installation or availability.
|
|
156
|
+
default, users promote only selected skills to shared use, and a model-facing
|
|
157
|
+
preference can be remembered without changing installation or availability.
|
|
148
158
|
|
|
149
159
|
## Migrate version 1
|
|
150
160
|
|
|
@@ -157,9 +167,16 @@ skillboard migrate v2 --config <path> --yes --json
|
|
|
157
167
|
skillboard migrate v2 --config <path> --rollback <backup> --json
|
|
158
168
|
```
|
|
159
169
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
170
|
+
Starting in 0.3.2, setup and global package updates automatically migrate a
|
|
171
|
+
valid version 1 user policy when the report contains only understood choices.
|
|
172
|
+
The transaction creates an adjacent exact backup. Explicit terminal denials
|
|
173
|
+
remain disabled; review-only quarantine becomes enabled and agent-local. An
|
|
174
|
+
unknown future ambiguity leaves the policy unchanged and prints the preview
|
|
175
|
+
command. A policy skill that is not currently observed also stays on v1 for an
|
|
176
|
+
explicit decision, because forgetting a disabled entry could enable it if it
|
|
177
|
+
later reappears. The explicit commands remain available for project policies,
|
|
178
|
+
audits, and rollback. Other v1 mutations still refuse and point to migration.
|
|
179
|
+
v0.4.0 removes the v1 reader.
|
|
163
180
|
|
|
164
181
|
## Cleanup
|
|
165
182
|
|
|
@@ -7,16 +7,23 @@ cross-agent sharing, and overlap routing. It asks only two policy questions:
|
|
|
7
7
|
2. Should SkillBoard share this skill with other supported agents?
|
|
8
8
|
|
|
9
9
|
Installed, valid skills default to enabled and agent-local. A user may disable
|
|
10
|
-
a skill or opt that individual skill into sharing. An optional preference
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
a skill or opt that individual skill into sharing. An optional preference is
|
|
11
|
+
returned as raw context beside eligible skills; it never changes availability
|
|
12
|
+
or copies files.
|
|
13
|
+
|
|
14
|
+
The active model owns all v2 semantic skill selection. SkillBoard returns the
|
|
15
|
+
request unchanged with enabled skills installed for the current agent, their
|
|
16
|
+
descriptions, and raw saved preferences. It does not tokenize, normalize,
|
|
17
|
+
score, match, or recommend from v2 request text. The model interprets Korean,
|
|
18
|
+
explicit user direction, and preferences directly, and may choose no skill.
|
|
13
19
|
|
|
14
20
|
## Product loop
|
|
15
21
|
|
|
16
22
|
Preserve `observe → route → work → explain briefly → ask after → remember`.
|
|
17
23
|
Ordinary work must not stop for source review or pre-task configuration. Read
|
|
18
|
-
the current brief when skills overlap,
|
|
19
|
-
once only before a persistent policy
|
|
24
|
+
the current brief when skills overlap, make the semantic choice in the active
|
|
25
|
+
model, run the guard before use, and ask once only before a persistent policy
|
|
26
|
+
change.
|
|
20
27
|
|
|
21
28
|
## Boundaries
|
|
22
29
|
|
|
@@ -45,13 +52,18 @@ inventory, and materializes missing copies only for skills already marked
|
|
|
45
52
|
discovery state. They must not introduce project scope, source trust gates, or
|
|
46
53
|
another authorization layer.
|
|
47
54
|
|
|
55
|
+
When setup encounters version 1 user policy, it may converge that policy to v2
|
|
56
|
+
only if every migration ambiguity is a known review-only quarantine mapping.
|
|
57
|
+
It must preserve terminal denials, create an exact recoverable backup, and leave
|
|
58
|
+
unknown future ambiguity unchanged for an explicit decision.
|
|
59
|
+
|
|
48
60
|
## Development rule
|
|
49
61
|
|
|
50
62
|
Every route, brief, guard, dashboard, generated bridge, and policy mutation must
|
|
51
63
|
project the same v2 meaning. Normal commands use one home control plane from any
|
|
52
64
|
working directory; project initialization is not part of the v2 flow. Never
|
|
53
|
-
reintroduce source reputation, workflow scope,
|
|
54
|
-
authorization checks.
|
|
65
|
+
reintroduce source reputation, workflow scope, v2 tokenizers or metadata scores,
|
|
66
|
+
or legacy state fields as hidden authorization or semantic-selection checks.
|
|
55
67
|
|
|
56
68
|
Version 1 is migration input only. It has a one-release read-only window in the
|
|
57
69
|
v0.3 release and is removed in v0.4.0.
|
package/docs/install.md
CHANGED
|
@@ -35,6 +35,15 @@ keep. Activate the Node environment that owns each stale prefix, confirm it with
|
|
|
35
35
|
SkillBoard does not automatically uninstall another prefix or request elevated
|
|
36
36
|
permissions for cleanup.
|
|
37
37
|
|
|
38
|
+
From 0.3.2, setup and global postinstall automatically migrate a valid version
|
|
39
|
+
1 user policy when every reported migration choice is understood. Migration
|
|
40
|
+
creates an adjacent exact backup, preserves explicit terminal denials as
|
|
41
|
+
disabled, and makes review-only quarantine states enabled and agent-local. An
|
|
42
|
+
unknown future ambiguity leaves the policy unchanged and prints the explicit
|
|
43
|
+
preview command; no migration files are changed. A v1 policy skill that is not
|
|
44
|
+
currently observed uses the same review path so setup neither invents inventory
|
|
45
|
+
nor silently forgets its policy.
|
|
46
|
+
|
|
38
47
|
Run setup later when lifecycle scripts were skipped, another agent or Hermes
|
|
39
48
|
profile was added, or a managed root needs to be repaired:
|
|
40
49
|
|
|
@@ -104,10 +113,12 @@ skillboard migrate v2 --config <path> --yes --json
|
|
|
104
113
|
skillboard migrate v2 --config <path> --rollback <backup> --json
|
|
105
114
|
```
|
|
106
115
|
|
|
107
|
-
Version 1 is read-only during v0.3.x. v0.4.0 removes the v1 reader.
|
|
108
|
-
|
|
109
|
-
the
|
|
110
|
-
|
|
116
|
+
Version 1 is read-only during v0.3.x. v0.4.0 removes the v1 reader. Setup and
|
|
117
|
+
global postinstall automatically migrate an understood version 1 user policy
|
|
118
|
+
through the same backup and validation transaction. Unknown future ambiguity
|
|
119
|
+
or a policy skill that is not currently observed leaves it unchanged and prints
|
|
120
|
+
the preview command. Explicit preview, apply, and rollback remain available for
|
|
121
|
+
project policies, audits, and recovery.
|
|
111
122
|
|
|
112
123
|
## Uninstall
|
|
113
124
|
|
package/docs/policy-model.md
CHANGED
|
@@ -24,7 +24,7 @@ compatible copies for other supported agents.
|
|
|
24
24
|
|
|
25
25
|
## Optional routing preference
|
|
26
26
|
|
|
27
|
-
Preference
|
|
27
|
+
Preference is raw context shown to the model for an eligible skill. It never
|
|
28
28
|
changes availability and never shares files.
|
|
29
29
|
|
|
30
30
|
```yaml
|
|
@@ -38,8 +38,10 @@ changes availability and never shares files.
|
|
|
38
38
|
priority: 100
|
|
39
39
|
```
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
The model interprets explicit user selection and saved preference semantics from
|
|
42
|
+
the full request. SkillBoard does not match the `intents` strings or use
|
|
43
|
+
`priority` as a score in v2. A high priority cannot enable a disabled skill or
|
|
44
|
+
make a skill appear on an agent where it is absent.
|
|
43
45
|
|
|
44
46
|
## Generated inventory
|
|
45
47
|
|
|
@@ -71,3 +73,10 @@ skillboard migrate v2 --config <path> --rollback <backup> --json
|
|
|
71
73
|
```
|
|
72
74
|
|
|
73
75
|
v0.4.0 removes the v1 reader.
|
|
76
|
+
|
|
77
|
+
Setup and global postinstall automatically upgrade a valid version 1 user
|
|
78
|
+
policy when its migration report contains only understood choices. The
|
|
79
|
+
transaction keeps an exact adjacent backup. An unknown future ambiguity leaves
|
|
80
|
+
the policy unchanged and requires the explicit preview/apply flow. Policy skills
|
|
81
|
+
that are not currently observed also require review rather than being silently
|
|
82
|
+
forgotten.
|
package/docs/positioning.md
CHANGED
|
@@ -8,8 +8,10 @@ Its durable policy answers two questions:
|
|
|
8
8
|
1. Is this skill enabled?
|
|
9
9
|
2. Should this one skill remain agent-local or be shared across agents?
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
The active model chooses the best enabled skill installed for the current
|
|
12
|
+
agent, or no skill, from raw descriptions and optional saved preferences.
|
|
13
|
+
SkillBoard does not tokenize, score, or match v2 request text. Preference never
|
|
14
|
+
changes availability.
|
|
13
15
|
|
|
14
16
|
## Difference from distribution tools
|
|
15
17
|
|
package/docs/reference.md
CHANGED
|
@@ -16,9 +16,9 @@ Source tree: replace `skillboard ` with `node bin/skillboard.mjs `.
|
|
|
16
16
|
skillboard setup [--yes] [--agent codex[,claude,opencode,hermes]] [--skill-root <path>]
|
|
17
17
|
skillboard inventory refresh [--config <path>] [--dry-run] [--json]
|
|
18
18
|
skillboard brief [--agent codex|claude|opencode|hermes] [--intent <request>] [--include-actions] [--json]
|
|
19
|
-
skillboard route <intent> --agent
|
|
20
|
-
skillboard can-use <skill-id> --agent
|
|
21
|
-
skillboard guard use <skill-id> --agent
|
|
19
|
+
skillboard route <intent> --agent <name> (v2 policy) | --workflow <name> (v1 policy) [--json]
|
|
20
|
+
skillboard can-use <skill-id> --agent <name> (v2 policy) | --workflow <name> (v1 policy) [--json]
|
|
21
|
+
skillboard guard use <skill-id> --agent <name> (v2 policy) | --workflow <name> (v1 policy) [--json]
|
|
22
22
|
skillboard skill enable <skill-id> [--dry-run] [--json]
|
|
23
23
|
skillboard skill disable <skill-id> [--dry-run] [--json]
|
|
24
24
|
skillboard skill share <skill-id> [--dry-run] [--json]
|
|
@@ -50,12 +50,18 @@ non-symlinked path inside the invoking user's home, and persists the mapping in
|
|
|
50
50
|
not authorization or policy. One root cannot be registered to two agents.
|
|
51
51
|
|
|
52
52
|
Guard requires a valid inventory record, `enabled: true`, and the selected agent
|
|
53
|
-
in `installed_on`.
|
|
54
|
-
|
|
53
|
+
in `installed_on`. For v2 routing, SkillBoard returns the request plus raw
|
|
54
|
+
eligible skill descriptions and saved preferences. It does not tokenize, score,
|
|
55
|
+
match, or recommend from request text. The active model interprets explicit
|
|
56
|
+
direction and preferences, chooses a skill or no skill, then runs guard.
|
|
57
|
+
Preference never changes availability.
|
|
55
58
|
|
|
56
59
|
Version 2 route, can-use, and guard require `--agent`; generated agent guidance
|
|
57
60
|
passes it automatically. This prevents one agent from selecting another
|
|
58
61
|
agent's local-only skill without adding a user prompt to the normal flow.
|
|
62
|
+
Version 1 compatibility policy uses `--workflow` instead. Passing the selector
|
|
63
|
+
for the other policy version exits with guidance for the detected version and,
|
|
64
|
+
for v1, the exact `migrate v2` preview command.
|
|
59
65
|
|
|
60
66
|
## Config schema v2
|
|
61
67
|
|
|
@@ -79,8 +85,8 @@ skills:
|
|
|
79
85
|
- `enabled` and `shared` are required Booleans.
|
|
80
86
|
- `shared: false` means agent-local; `shared: true` enables managed cross-agent
|
|
81
87
|
copies while preserving the original.
|
|
82
|
-
- `preference` is optional
|
|
83
|
-
agent
|
|
88
|
+
- `preference` is optional raw context for model selection when the skill is
|
|
89
|
+
enabled and installed for the current agent. SkillBoard does not score it.
|
|
84
90
|
- Unknown policy keys are rejected.
|
|
85
91
|
- Skill ids use letters, numbers, `.`, `_`, `:`, and `-`; path-like ids are rejected.
|
|
86
92
|
- A valid newly discovered skill defaults to enabled and agent-local.
|
|
@@ -153,8 +159,13 @@ Preview changes no bytes. Apply creates an adjacent byte-for-byte backup and
|
|
|
153
159
|
writes v2 policy plus generated inventory atomically. Rollback restores the
|
|
154
160
|
selected backup. v0.4.0 removes the v1 reader.
|
|
155
161
|
|
|
156
|
-
Setup and npm postinstall
|
|
157
|
-
|
|
162
|
+
Setup and global npm postinstall automatically migrate a valid version 1 user
|
|
163
|
+
policy when all reported choices are understood. They create an adjacent exact
|
|
164
|
+
backup, preserve terminal denials as disabled, and map review-only quarantine
|
|
165
|
+
to enabled and agent-local. An unknown future ambiguity leaves the policy
|
|
166
|
+
unchanged, changes no migration files, and prints the preview form. The same
|
|
167
|
+
review path names policy skills that are not currently observed. Explicit
|
|
168
|
+
commands remain available for project policies, audit, and recovery.
|
|
158
169
|
|
|
159
170
|
Legacy fields are interpreted only by migration and never become hidden v2
|
|
160
171
|
authorization. Primary examples are `examples/v2-multi-source.config.yaml` and
|
package/docs/routing.md
CHANGED
|
@@ -4,16 +4,22 @@ Routing chooses among skills already available to the current agent. Guard
|
|
|
4
4
|
decides availability from valid generated inventory, `enabled`, and
|
|
5
5
|
`installed_on`; routing cannot override that verdict.
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## v2 resolution order
|
|
8
8
|
|
|
9
9
|
1. Remove skills missing valid inventory records.
|
|
10
10
|
2. Remove disabled skills.
|
|
11
11
|
3. Remove skills not installed for the selected agent.
|
|
12
|
-
4.
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
4. Return every remaining skill's id, name, description, path, and raw optional
|
|
13
|
+
preference beside the request.
|
|
14
|
+
5. Let the active model interpret the full request, explicit user direction,
|
|
15
|
+
descriptions, instructions, and preferences and choose a skill or no skill.
|
|
16
|
+
6. Guard the model-selected skill immediately before use.
|
|
17
|
+
|
|
18
|
+
V2 has no intent tokenizer, metadata score, request matcher, ranked candidates,
|
|
19
|
+
or deterministic recommendation. Korean and other languages are handled by the
|
|
20
|
+
foundation model. Preference is raw model context and never changes
|
|
21
|
+
availability. Version 1 compatibility routing retains its deterministic
|
|
22
|
+
tokenizer until the v1 reader is removed in v0.4.0.
|
|
17
23
|
|
|
18
24
|
```bash
|
|
19
25
|
skillboard brief --intent "write tests" --agent codex --json
|
|
@@ -26,8 +32,13 @@ These commands use `~/skillboard.config.yaml` and
|
|
|
26
32
|
`--config` and `--skills` overrides remain available for migration, testing,
|
|
27
33
|
and legacy workspaces.
|
|
28
34
|
|
|
29
|
-
When guard allows use, continue without another approval.
|
|
30
|
-
|
|
35
|
+
When guard allows use, continue without another approval. If the model-selected
|
|
36
|
+
choice was ambiguous, finish first and ask afterward only when remembering a
|
|
37
|
+
preference would reduce future ambiguity.
|
|
38
|
+
|
|
39
|
+
Version 1 compatibility routing remains workflow-driven and may return a
|
|
40
|
+
deterministic capability route. It asks for clarification when no workflow
|
|
41
|
+
route matches.
|
|
31
42
|
|
|
32
43
|
Source and provenance findings are optional audit metadata and never determine
|
|
33
44
|
availability. Runtime and action authorization are outside SkillBoard's scope.
|
package/docs/user-flow.md
CHANGED
|
@@ -41,8 +41,11 @@ skillboard guard use <skill-id> --agent codex --json
|
|
|
41
41
|
```
|
|
42
42
|
|
|
43
43
|
The guard allows an enabled skill only when generated inventory records it on
|
|
44
|
-
the selected agent.
|
|
45
|
-
|
|
44
|
+
the selected agent. SkillBoard returns raw eligible descriptions and saved
|
|
45
|
+
preferences without tokenizing, scoring, or matching the request. The model
|
|
46
|
+
interprets the full request, explicit direction, and preferences and chooses a
|
|
47
|
+
skill or no skill. Preference never changes availability. Allowed use does not
|
|
48
|
+
require another confirmation.
|
|
46
49
|
|
|
47
50
|
## 3. Change one decision
|
|
48
51
|
|
|
@@ -65,9 +68,10 @@ returned post-apply brief. Cached action ids are not reused.
|
|
|
65
68
|
|
|
66
69
|
## 4. Ask after, then remember
|
|
67
70
|
|
|
68
|
-
When a route was ambiguous, the agent finishes first. It may then
|
|
69
|
-
remember an intent preference. Preference
|
|
70
|
-
share, enable, disable, install, or
|
|
71
|
+
When a model-selected route was ambiguous, the agent finishes first. It may then
|
|
72
|
+
ask whether to remember an intent preference. Preference becomes raw context
|
|
73
|
+
for later model selection; it does not share, enable, disable, install, or
|
|
74
|
+
remove a skill.
|
|
71
75
|
|
|
72
76
|
## 5. Audit separately
|
|
73
77
|
|
|
@@ -111,4 +115,8 @@ skillboard migrate v2 --config <path> --rollback <backup> --json
|
|
|
111
115
|
```
|
|
112
116
|
|
|
113
117
|
Version 1 remains readable but immutable for the v0.3.x one-release read-only
|
|
114
|
-
window.
|
|
118
|
+
window. Setup and global package updates automatically migrate an understood
|
|
119
|
+
version 1 user policy with an exact adjacent backup. Unknown future ambiguity
|
|
120
|
+
or a policy skill that is not currently observed leaves it unchanged and prints
|
|
121
|
+
the preview command. Project policies and other ordinary commands still require
|
|
122
|
+
explicit migration. v0.4.0 removes the v1 reader.
|
package/docs/value-proof.md
CHANGED
|
@@ -12,10 +12,15 @@ node --test test/v2-agent-sharing.test.mjs test/v2-onboarding-behavior.test.mjs
|
|
|
12
12
|
- Valid discovered skills default to enabled and agent-local.
|
|
13
13
|
- Disabled skills and skills absent from the selected agent are denied.
|
|
14
14
|
- Share and unshare preserve agent-owned originals.
|
|
15
|
-
-
|
|
15
|
+
- V2 returns raw eligible descriptions and preferences without interpreting
|
|
16
|
+
request text or producing a recommendation.
|
|
17
|
+
- Korean, explicit skill direction, and saved preference semantics remain owned
|
|
18
|
+
by the active model.
|
|
19
|
+
- Optional preference never changes availability.
|
|
16
20
|
- Source and provenance audits do not change guard results.
|
|
17
21
|
- Commands produce the same result from different working directories.
|
|
18
|
-
- Version 1
|
|
22
|
+
- Version 1 project policy remains read-only until explicit migration; setup
|
|
23
|
+
automatically migrates an understood user policy with an exact backup.
|
|
19
24
|
|
|
20
25
|
## Reproduce the user surface
|
|
21
26
|
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
A variant is a manual content adaptation with snapshot and digest history. The
|
|
4
4
|
lifecycle does not authorize availability. A registered variant is usable only
|
|
5
5
|
according to its ordinary v2 `enabled` entry and generated installation
|
|
6
|
-
presence; optional preference
|
|
6
|
+
presence; optional preference is raw model context and never changes
|
|
7
|
+
availability.
|
|
7
8
|
|
|
8
9
|
## Current v2 boundary
|
|
9
10
|
|
package/docs/versioning.md
CHANGED
|
@@ -22,9 +22,13 @@ Preview is non-mutating, apply creates an adjacent byte-for-byte backup, and
|
|
|
22
22
|
rollback restores the selected backup. Old action ids, hooks, and lock
|
|
23
23
|
projections are invalid after migration.
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
Starting in 0.3.2, setup and global package updates automatically migrate a
|
|
26
|
+
valid version 1 user policy when all migration choices are understood. They use
|
|
27
|
+
the same exact-backup, atomic-write, validation, and recovery transaction as
|
|
28
|
+
the explicit command. Unknown future ambiguity leaves the policy unchanged and
|
|
29
|
+
prints the preview command. A policy skill that is not currently observed also
|
|
30
|
+
requires review, preserving future denial semantics. Doctor and project-local
|
|
31
|
+
commands remain non-mutating.
|
|
28
32
|
|
|
29
33
|
## Versioned v2 contract
|
|
30
34
|
|
|
@@ -39,7 +43,8 @@ schema.
|
|
|
39
43
|
1. Run `npm run check`.
|
|
40
44
|
2. Run `npm pack --dry-run --json` and inspect public contents.
|
|
41
45
|
3. Install the tarball into an isolated prefix and run
|
|
42
|
-
`skillboard doctor --summary`; verify fresh setup, v1
|
|
46
|
+
`skillboard doctor --summary`; verify fresh setup, safe v1 auto-migration,
|
|
47
|
+
exact backup preservation, and a
|
|
43
48
|
late-agent shared-skill reconciliation.
|
|
44
49
|
4. Confirm `CHANGELOG.md` includes the package version.
|
|
45
50
|
5. Push `main` and wait for the complete cross-platform check matrix.
|
package/package.json
CHANGED
package/src/advisor/guidance.mjs
CHANGED
|
@@ -3,7 +3,7 @@ import { command } from "./action-core.mjs";
|
|
|
3
3
|
const GUARD_WHEN = "immediately before skill use";
|
|
4
4
|
const GOAL_DOCUMENT = Object.freeze({
|
|
5
5
|
path: "docs/ai-skill-routing-goal.md",
|
|
6
|
-
purpose: "Preserve SkillBoard v2 as a user-level control plane: enable or disable a skill, opt individual skills into cross-agent sharing, and
|
|
6
|
+
purpose: "Preserve SkillBoard v2 as a user-level control plane: enable or disable a skill, opt individual skills into cross-agent sharing, and expose optional preference as raw context for the active model.",
|
|
7
7
|
loop: Object.freeze([
|
|
8
8
|
"observe",
|
|
9
9
|
"route",
|
|
@@ -140,14 +140,22 @@ function recommendedNextStep(status, brief, choices, route = null) {
|
|
|
140
140
|
switch (status) {
|
|
141
141
|
case "ready":
|
|
142
142
|
if (route !== null) {
|
|
143
|
+
if (route.model_selection_required === true) {
|
|
144
|
+
return modelSelectionStep(route);
|
|
145
|
+
}
|
|
143
146
|
return route.recommended_skill === null
|
|
144
|
-
?
|
|
147
|
+
? route.workflow === null
|
|
148
|
+
? "No enabled skill is available for this request."
|
|
149
|
+
: "Ask a clarifying question; no workflow capability matched this request."
|
|
145
150
|
: `Use ${route.recommended_skill} for this request after the guard check passes${postUsePolicyStep(route)}.`;
|
|
146
151
|
}
|
|
147
152
|
return availableSkillCount(brief) === 0
|
|
148
153
|
? "No policy change is required; valid installed skills default to enabled and agent-local."
|
|
149
154
|
: "Run the guard check immediately before using any selected skill.";
|
|
150
155
|
case "needs-decision":
|
|
156
|
+
if (route?.model_selection_required === true) {
|
|
157
|
+
return `${modelSelectionStep(route)} Handle pending review decisions after the task unless a policy-changing action is needed now.`;
|
|
158
|
+
}
|
|
151
159
|
if (route?.recommended_skill !== null && route?.guard_allowed === true) {
|
|
152
160
|
return route.post_use_policy_suggestion === null
|
|
153
161
|
? `Use ${route.recommended_skill} for this request after the guard check passes; handle pending review decisions after the task unless a policy-changing action is needed now.`
|
|
@@ -180,6 +188,10 @@ function recommendedNextStep(status, brief, choices, route = null) {
|
|
|
180
188
|
}
|
|
181
189
|
}
|
|
182
190
|
|
|
191
|
+
function modelSelectionStep(route) {
|
|
192
|
+
return "Choose the best enabled, installed skill from the request's semantic context, skill descriptions, and raw saved preferences. Run its guard before use, or continue without a skill when none fits.";
|
|
193
|
+
}
|
|
194
|
+
|
|
183
195
|
function postUsePolicyStep(route) {
|
|
184
196
|
return route.post_use_policy_suggestion === null
|
|
185
197
|
? ""
|
|
@@ -197,6 +209,8 @@ function routeGuidance(route) {
|
|
|
197
209
|
matched_terms: route.matched_terms,
|
|
198
210
|
recommendation_reason: route.recommendation_reason,
|
|
199
211
|
recommended_skill: route.recommended_skill,
|
|
212
|
+
selection_mode: route.selection_mode ?? null,
|
|
213
|
+
model_selection_required: route.model_selection_required ?? false,
|
|
200
214
|
fallback_skills: route.fallback_skills,
|
|
201
215
|
route_candidates: (route.route_candidates ?? []).map((candidate) => ({
|
|
202
216
|
skill: candidate.skill,
|
|
@@ -216,6 +230,10 @@ function routeGuidance(route) {
|
|
|
216
230
|
guard_reasons: route.guard?.reasons ?? [],
|
|
217
231
|
possible_skills: route.possible_skills.map((skill) => ({
|
|
218
232
|
id: skill.id,
|
|
233
|
+
name: skill.name,
|
|
234
|
+
description: skill.description,
|
|
235
|
+
path: skill.path,
|
|
236
|
+
preference: skill.preference,
|
|
219
237
|
category: skill.category,
|
|
220
238
|
allowed: skill.allowed
|
|
221
239
|
}))
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { resolve } from "node:path";
|
|
2
2
|
import { mkdir } from "node:fs/promises";
|
|
3
3
|
import { createInterface } from "node:readline";
|
|
4
|
+
import { commandPrefix, shellQuote } from "./agent-integration-command.mjs";
|
|
4
5
|
import { installAgentIntegration, uninstallAgentIntegration } from "./agent-integration-files.mjs";
|
|
5
6
|
import { applyOwnership, applyOwnershipTree, resolveSetupHome, setupOwnership } from "./agent-integration-home.mjs";
|
|
6
7
|
import { setupAgentSkillTargets, supportedAgentNames } from "./agent-skill-roots.mjs";
|
|
@@ -13,6 +14,7 @@ import {
|
|
|
13
14
|
} from "./agent-root-registry.mjs";
|
|
14
15
|
import { refreshAgentInventory } from "./inventory-refresh.mjs";
|
|
15
16
|
import { reconcileSharedSkills } from "./shared-skill-reconcile.mjs";
|
|
17
|
+
import { upgradeLegacyUserPolicy } from "./setup-policy-migration.mjs";
|
|
16
18
|
|
|
17
19
|
export async function runSetupCommand(options, stdout, runtime = defaultRuntime()) {
|
|
18
20
|
assertSetupOptions(options);
|
|
@@ -52,7 +54,21 @@ export async function runSetupCommand(options, stdout, runtime = defaultRuntime(
|
|
|
52
54
|
preserveLegacyPolicy: true
|
|
53
55
|
});
|
|
54
56
|
const configPath = resolve(home, inventory.configPath);
|
|
55
|
-
|
|
57
|
+
let inventoryPath = inventory.inventoryPath === null ? null : resolve(home, inventory.inventoryPath);
|
|
58
|
+
const policyUpgrade = await upgradeLegacyUserPolicy({
|
|
59
|
+
home,
|
|
60
|
+
configPath,
|
|
61
|
+
inventoryPath,
|
|
62
|
+
observedSkillIds: inventory.observedSkillIds,
|
|
63
|
+
failpoint: runtime.migrationFailpoint
|
|
64
|
+
});
|
|
65
|
+
if (policyUpgrade.status === "upgraded") {
|
|
66
|
+
inventoryPath = policyUpgrade.inventoryPath;
|
|
67
|
+
await applyOwnership(configPath, ownership);
|
|
68
|
+
await applyOwnership(inventoryPath, ownership);
|
|
69
|
+
for (const artifact of policyUpgrade.artifacts) await applyOwnership(artifact, ownership);
|
|
70
|
+
inventory = await refreshAgentInventory({ root: home, home, env, registeredRoots });
|
|
71
|
+
}
|
|
56
72
|
const shared = inventoryPath === null
|
|
57
73
|
? { created: [], unchanged: [], preserved: [], blocked: [] }
|
|
58
74
|
: await reconcileSharedSkills({ home, env, targets, configPath, inventoryPath });
|
|
@@ -80,14 +96,24 @@ export async function runSetupCommand(options, stdout, runtime = defaultRuntime(
|
|
|
80
96
|
writeList(stdout, "Blocked shared copies", shared.blocked.map(formatBlockedEntry));
|
|
81
97
|
stdout.write(`User policy: ${inventory.configPath}\n`);
|
|
82
98
|
stdout.write(`Observed skills: ${inventory.scan.scannedSkills}\n`);
|
|
83
|
-
if (
|
|
84
|
-
stdout.write("
|
|
99
|
+
if (policyUpgrade.status === "upgraded") {
|
|
100
|
+
stdout.write("User policy upgraded automatically to version 2.\n");
|
|
101
|
+
stdout.write(`Backup: ${policyUpgrade.backupPath}\n`);
|
|
102
|
+
} else if (policyUpgrade.status === "decision-required") {
|
|
103
|
+
stdout.write("Policy version 1 needs review before migration; no migration files were changed.\n");
|
|
104
|
+
if (policyUpgrade.unobservedSkillIds.length > 0) {
|
|
105
|
+
stdout.write(`Policy skills not currently observed: ${formatList(policyUpgrade.unobservedSkillIds)}\n`);
|
|
106
|
+
}
|
|
85
107
|
stdout.write(`Preview migration: ${commandPrefix(runtime)} migrate v2 --config ${shellQuote(configPath, runtime.platform)} --json\n`);
|
|
86
108
|
}
|
|
87
109
|
stdout.write("Next:\n");
|
|
88
110
|
stdout.write("- Restart or refresh agents that cache user skills.\n");
|
|
89
111
|
stdout.write("- Run skillboard doctor --summary to check policy and executable paths.\n");
|
|
90
|
-
|
|
112
|
+
if (policyUpgrade.status === "decision-required") {
|
|
113
|
+
stdout.write("- User-level policy was preserved and installed skills were rescanned; no project was initialized.\n");
|
|
114
|
+
} else {
|
|
115
|
+
stdout.write("- User-level policy and inventory were refreshed; no project was initialized.\n");
|
|
116
|
+
}
|
|
91
117
|
stdout.write('- Ask the agent in a workspace: "Review this plan and point out weak assumptions."\n');
|
|
92
118
|
stdout.write("- SkillBoard will step in when skills overlap, routing is ambiguous, or you ask for a skill decision.\n");
|
|
93
119
|
return 0;
|
|
@@ -222,46 +248,3 @@ function formatSharedEntry(entry) {
|
|
|
222
248
|
function formatBlockedEntry(entry) {
|
|
223
249
|
return `${entry.agent ?? "unknown"}:${entry.skill}:${entry.reason}`;
|
|
224
250
|
}
|
|
225
|
-
|
|
226
|
-
function commandPrefix(runtime) {
|
|
227
|
-
const entrypoint = runtime.entrypointPath ?? "";
|
|
228
|
-
const normalized = entrypoint.replace(/\\/g, "/");
|
|
229
|
-
if (normalized.includes("/_npx/")) {
|
|
230
|
-
const packageSpec = runtime.packageSpec ?? "agent-skillboard";
|
|
231
|
-
return `npx --yes --package ${shellQuote(packageSpec, runtime.platform)} skillboard`;
|
|
232
|
-
}
|
|
233
|
-
if (isSourceTreeEntrypoint(entrypoint)) {
|
|
234
|
-
return `node ${sourceTreeEntrypoint(entrypoint, runtime.cwd ?? process.cwd(), runtime.platform)}`;
|
|
235
|
-
}
|
|
236
|
-
return "skillboard";
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
function isSourceTreeEntrypoint(entrypoint) {
|
|
240
|
-
if (entrypoint === "") {
|
|
241
|
-
return false;
|
|
242
|
-
}
|
|
243
|
-
const normalized = entrypoint.replace(/\\/g, "/");
|
|
244
|
-
return (normalized === "bin/skillboard.mjs" || normalized.endsWith("/bin/skillboard.mjs"))
|
|
245
|
-
&& !normalized.includes("/node_modules/")
|
|
246
|
-
&& !normalized.includes("/_npx/")
|
|
247
|
-
&& !normalized.includes("/.npm/");
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
function sourceTreeEntrypoint(entrypoint, cwd, platform) {
|
|
251
|
-
const absoluteEntrypoint = isAbsolute(entrypoint) ? entrypoint : resolve(cwd, entrypoint);
|
|
252
|
-
const relativeEntrypoint = relative(cwd, absoluteEntrypoint).replace(/\\/g, "/");
|
|
253
|
-
if (!relativeEntrypoint.startsWith("../") && relativeEntrypoint !== ".." && !isAbsolute(relativeEntrypoint)) {
|
|
254
|
-
return shellQuote(relativeEntrypoint, platform);
|
|
255
|
-
}
|
|
256
|
-
return shellQuote(absoluteEntrypoint, platform);
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
function shellQuote(value, platform = process.platform) {
|
|
260
|
-
if (/^[A-Za-z0-9_./:@%+=,-]+$/.test(value)) {
|
|
261
|
-
return value;
|
|
262
|
-
}
|
|
263
|
-
if (platform === "win32") {
|
|
264
|
-
return `"${value.replace(/"/g, '""')}"`;
|
|
265
|
-
}
|
|
266
|
-
return `'${value.replace(/'/g, "'\\''")}'`;
|
|
267
|
-
}
|