Align skills with frozen Ink contracts

This commit is contained in:
tmk241
2026-08-11 16:42:45 +02:00
parent 284cf5ec90
commit 5552014329
5 changed files with 115 additions and 52 deletions
+2 -1
View File
@@ -15,4 +15,5 @@
- Keep skill names lowercase and hyphenated; directory and frontmatter name must match. - Keep skill names lowercase and hyphenated; directory and frontmatter name must match.
- The installer only creates symlinks and must refuse collisions. Do not add a registry, - The installer only creates symlinks and must refuse collisions. Do not add a registry,
network calls, package-manager dependency, prompts, copies, or hidden state. network calls, package-manager dependency, prompts, copies, or hidden state.
- Run `sh -n bin/ink-skills` and `sh test/install-smoke.sh` after changes. - Run `sh -n bin/ink-skills`, `sh test/install-smoke.sh`, and
`sh test/skills-smoke.sh` after changes.
+14 -11
View File
@@ -36,9 +36,11 @@ ink-skills install --project /path/to/project configure-ink-agent
The installer is intentionally smaller than `npx skills`: no registry, package The installer is intentionally smaller than `npx skills`: no registry, package
manager, network access, copies, prompts, lockfile, or hidden state. It creates manager, network access, copies, prompts, lockfile, or hidden state. It creates
absolute symlinks from `$HOME/.ink/skills` (or `$INK_SKILLS_HOME`) to this absolute symlinks from `$HOME/.ink/skills` (or the installer-only
checkout. Pulling the repository updates installed skills; restarting Ink freezes `$INK_SKILLS_HOME` target override) to this checkout. Pulling the repository
the new bytes into the next startup snapshot. updates installed skills; restarting Ink freezes the new bytes into the next
startup snapshot. Ink itself discovers `$HOME/.ink/skills`, `$CWD/.ink/skills`,
and colon-separated `INK_SKILLS_DIRS`.
`ink-skills list` emits TSV. `ink-skills --help` is the complete command manual. `ink-skills list` emits TSV. `ink-skills --help` is the complete command manual.
Existing paths and foreign symlinks are refused rather than overwritten. Existing paths and foreign symlinks are refused rather than overwritten.
@@ -48,13 +50,13 @@ Existing paths and foreign symlinks are refused rather than overwritten.
| Skill | Job | | Skill | Job |
|---|---| |---|---|
| `ink-cli` | Audit and explain the Ink host without crossing the host/guest boundary. | | `ink-cli` | Audit and explain the Ink host without crossing the host/guest boundary. |
| `configure-ink-agent` | Create or audit one Ink agent definition, access class, and relative policy conjunct. | | `configure-ink-agent` | Create or audit one Ink agent definition, access class, and effective-policy boundary. |
| `create-ink-agent-cli-tool` | Build one inspectable permission-bearing executable suitable for Ink policy admission. | | `create-ink-agent-cli-tool` | Build one inspectable permission-bearing executable suitable for Ink policy admission. |
## Agent definitions and policy ## Agent definitions and policy
Agent definitions live in `$INK_AGENT_HOME` (default `$HOME/.ink/agents`) or Agent definitions live in `$HOME/.ink/agents` or the exact current project's
project `.ink/agents` directories: `.ink/agents` directory:
```text ```text
name: Frontend specialist name: Frontend specialist
@@ -65,18 +67,19 @@ policy: frontend.policy
Implement the bounded frontend task and return proof. Implement the bounded frontend task and return proof.
``` ```
The policy path is relative to the definition. It is a normal Ink policy file and `access: read|write` selects reader/writer scheduling; it does not grant commands
narrows the frozen parent snapshot conjunctively. `access: read|write` selects or tools. Definitions are frozen at startup, so restart Ink after changing one.
reader/writer scheduling; it does not grant commands or tools. Definitions and
policy files are frozen at startup, so restart Ink after changing either.
Use the `configure-ink-agent` skill for the complete decision boundary. Current caveat: Ink records `policy:` as frozen metadata but does not yet read the
named relative file into the child effective policy. Do not treat it as enforced.
Use the `configure-ink-agent` skill for the exact boundary and blocker.
## Verify ## Verify
```sh ```sh
sh -n bin/ink-skills sh -n bin/ink-skills
sh test/install-smoke.sh sh test/install-smoke.sh
sh test/skills-smoke.sh
``` ```
## Refusals ## Refusals
+55 -35
View File
@@ -2,10 +2,10 @@
name: configure-ink-agent name: configure-ink-agent
description: >- description: >-
Use when the user asks to create, configure, audit, or explain an Ink subagent Use when the user asks to create, configure, audit, or explain an Ink subagent
definition, including its model, read/write scheduling class, or conjunctive definition, including its model, read/write scheduling class, or named policy
policy file. Produce the smallest startup-frozen agent definition and policy boundary. Produce the smallest startup-frozen definition and verify the real
boundary. Do not use for ordinary delegation, Ink implementation work, or effective child policy. Do not use for ordinary delegation, Ink implementation
generic prompt/role authoring outside Ink. work, or generic prompt/role authoring outside Ink.
--- ---
# Configure an Ink agent # Configure an Ink agent
@@ -16,23 +16,22 @@ Define one inspectable Ink subagent identity without confusing scheduling class,
model choice, and authority. model choice, and authority.
```text ```text
agent definition -> access class -> relative policy conjunct -> frozen child snapshot agent definition -> access class -> effective child policy -> frozen child snapshot
``` ```
## Trigger boundary ## Trigger boundary
Use for explicit requests about files in `$INK_AGENT_HOME` (default Use for explicit requests about agent files in `$HOME/.ink/agents` or the current
`$HOME/.ink/agents`) or a project `.ink/agents` directory, or when deciding the project's `.ink/agents` directory, or when deciding the policy of a named Ink
policy of a named Ink child. child.
Do not load for launching an existing child, editing Ink source, installing Do not load for launching an existing child, editing Ink source, installing
skills, or creating an external executable. `ink-cli` owns host audits; skills, or creating an external executable. `ink-cli` owns host audits;
`create-ink-agent-cli-tool` owns permission-bearing external tools. `create-ink-agent-cli-tool` owns permission-bearing external tools.
## Contract ## Current definition contract
An agent definition is a plain text file with headers followed by one prompt An agent definition is a plain text file whose filename stem is the catalog key:
body:
```text ```text
name: Frontend specialist name: Frontend specialist
@@ -44,54 +43,75 @@ Implement the bounded frontend task and return proof.
``` ```
- `name` is the human-facing identity. - `name` is the human-facing identity.
- `model` is a startup-resolved alias such as `default`, `cheap`, `think`, or a - `model` defaults to `default`; `default`, `cheap`, `think`, and `design` may be
configured alias. resolved through `INK_MODEL_DEFAULT`, `INK_MODEL_CHEAP`, `INK_MODEL_THINK`, and
`INK_MODEL_DESIGN`. Other values are literal model names.
- `access` is mandatory: `read` or `write`. - `access` is mandatory: `read` or `write`.
- `policy` is optional and relative to the definition file. Its bytes become an - `policy` is optional metadata intended to name a role-specific policy.
additional conjunct; it can narrow inherited authority but never broaden it. - Unknown headers, missing/unknown access, an empty prompt, and duplicate catalog
- Unknown headers, unknown access values, and unreadable policy files fail keys within one directory fail visibly.
visibly.
Ink loads built-ins, then `$HOME/.ink/agents`, then `$CWD/.ink/agents`; later
files replace earlier definitions with the same filename stem. The resulting
catalog is frozen at startup. There is currently no `INK_AGENT_HOME` contract and
no ancestor-chain project-agent discovery.
## Authority versus scheduling
`access` schedules actors; it does not grant tools: `access` schedules actors; it does not grant tools:
- `read` children may overlap and receive an immutable host floor with no command, - `read` children may overlap and receive an immutable host floor with no command,
file-mutation, lifecycle-mutation, or delegation authority. file-mutation, lifecycle-mutation, or delegation authority.
- `write` children are exclusive, operate in the canonical parent cwd, pause - `write` children are exclusive, operate in the canonical parent cwd, pause
parent effects, and still receive only their inherited-and-narrowed effective parent effects, and still receive only their effective frozen policy.
policy.
Agent definitions and referenced policy files are frozen at orchestrator startup. Never infer effective authority from `access`, prompt text, or a `policy:` label.
Editing either requires restarting Ink before the change can take effect. Child Use the child policy snapshot and a real allowed/denied smoke.
snapshots never reread cwd policy, and nested delegation is removed by the host.
## Named-policy enforcement gate
The current Ink source parses and freezes the `policy:` string as catalog
metadata, but does not yet read that relative file into the child's effective
policy. Therefore:
- do not claim a relative per-agent policy is enforced merely because `agent
resolve` or child metadata names it;
- do not use a named policy to justify launching a writer;
- report **blocked: named agent policy is metadata-only** when the requested
safety boundary depends on it;
- use inherited frozen parent policy plus the immutable reader floor only when
those are already sufficient.
This gate may be removed only after the provider launch path proves that the
referenced bytes are pinned and conjoined into the child effective policy.
## Decision loop ## Decision loop
1. Choose `read` unless the child must produce a real effect. 1. Choose `read` unless the child must produce a real effect.
2. Choose the smallest model alias that fits the specialist job. 2. Choose the smallest model alias that fits the specialist job.
3. Omit `policy` when the inherited parent policy is already the exact boundary. 3. Put the definition in user scope or exact project cwd according to intended
4. Otherwise write one nearby policy file using ordinary Ink policy rows; include precedence.
only authority the role needs and rely on conjunctive narrowing. 4. Restart Ink after definition changes.
5. Inspect the startup-frozen catalog with the operator surface before relying on 5. Inspect the frozen operator catalog and child metadata.
the role. Restart Ink after definition or policy changes.
6. Prove one allowed path and one denied near miss through the actual child path. 6. Prove one allowed path and one denied near miss through the actual child path.
7. If safety depends on `policy:`, stop at the named-policy enforcement gate.
## Refusals ## Refusals
- Do not put policy rows in the prompt body. - Do not put policy rows in the prompt body.
- Do not use `access: write` as a substitute for command/tool policy. - Do not use `access: write` as a substitute for command/tool policy.
- Do not grant `tool delegate` to a child; Ink removes nested delegation anyway. - Do not grant `tool delegate` to a child; Ink removes nested delegation.
- Do not create worktrees, copied workspaces, merge protocols, or per-role policy - Do not create worktrees, copied workspaces, merge protocols, or a per-role DSL.
DSLs. - Do not invent `INK_AGENT_HOME`, ancestor discovery, or mutable session policy.
- Do not use environment variables as a second mutable agent-policy channel.
## Behavior smoke ## Behavior smoke
Positive: “Create a frontend writer child with only the admitted formatter and Positive: “Create a frontend writer child with only formatter and file mutation
file mutation tools” loads this skill and separates `access: write` from its authority” loads this skill and blocks until the named policy is actually
relative policy conjunct. conjoined or the parent frozen policy already supplies that exact boundary.
Negative: “Ask the existing reviewer to inspect this diff” does not load this Negative: “Ask the existing reviewer to inspect this diff” does not load this
skill; it is ordinary delegation. skill; it is ordinary delegation.
Safety: a reader request that asks for `run` or file writes remains denied even if Safety: a reader request that asks for `run` or file writes remains denied even if
its role policy mentions them. its prompt or `policy:` metadata says otherwise.
+9 -5
View File
@@ -49,14 +49,17 @@ changes belong to Ink's repository authority and implementation workflow.
Distinguish three surfaces explicitly: Distinguish three surfaces explicitly:
1. **Operator CLI commands** such as top-level `ink sessions` or `ink context`. 1. **Operator CLI commands** such as top-level `ink sessions`, `ink skills`,
`ink agent catalog`, and `ink policy help`.
2. **Model-callable Ink built-ins** exposed directly to the hosted agent. 2. **Model-callable Ink built-ins** exposed directly to the hosted agent.
3. **External executables** admitted through Ink's `run` policy. 3. **External executables** admitted through Ink's `run` policy.
A command may exist on the first surface while being intentionally unreachable on A command may exist on the first surface while being intentionally unreachable on
the other two. Current source exposing flat `ink sessions` does not imply nested the other two. Current source exposing flat `ink sessions`, `ink skills`, and
`sessions list/tree/inspect/resume`, and a policy rejection does not prove the `ink tools` does not imply invented nested verbs, and a policy rejection does not
operator command is absent. prove the operator command is absent. The current operator agent catalogue uses
`ink agent catalog` and `ink agent resolve NAME`; role launch remains governed by
the frozen `tool delegate` subject.
## Decision loop ## Decision loop
@@ -77,7 +80,8 @@ operator command is absent.
- Do not edit policy to admit `ink`, call Ink recursively, log in, approve a - Do not edit policy to admit `ink`, call Ink recursively, log in, approve a
digest, resume or clear a session, or dump host context from the agent. digest, resume or clear a session, or dump host context from the agent.
- Do not infer command absence from policy denial or command existence from a - Do not infer command absence from policy denial or command existence from a
handover. In particular, challenge invented nested session verbs. handover. Challenge invented nested session or tool-verification verbs and
verify current public help/source before suggesting operator argv.
- Do not expose raw conversation or context when bounded metadata answers the - Do not expose raw conversation or context when bounded metadata answers the
operator's question; prompts and tool results may contain secrets. operator's question; prompts and tool results may contain secrets.
- Do not weaken path, origin, account, or repository selectors merely to make an - Do not weaken path, origin, account, or repository selectors merely to make an
+35
View File
@@ -0,0 +1,35 @@
#!/bin/sh
set -eu
repo=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd -P)
count=0
for skill in "$repo"/skills/*/SKILL.md; do
[ -f "$skill" ] || continue
directory=$(basename -- "$(dirname -- "$skill")")
name=$(sed -n 's/^name:[[:space:]]*//p' "$skill" | sed -n '1p')
[ "$name" = "$directory" ] || {
printf 'name mismatch: %s != %s\n' "$name" "$directory" >&2
exit 1
}
grep '^description:' "$skill" >/dev/null
count=$((count + 1))
done
[ "$count" -eq 3 ] || {
printf 'expected 3 skills, found %s\n' "$count" >&2
exit 1
}
configure=$repo/skills/configure-ink-agent/SKILL.md
grep 'access.*read.*write' "$configure" >/dev/null
grep 'named agent policy is metadata-only' "$configure" >/dev/null
grep 'no `INK_AGENT_HOME` contract' "$configure" >/dev/null
ink_cli=$repo/skills/ink-cli/SKILL.md
grep 'ink agent catalog' "$ink_cli" >/dev/null
grep 'frozen `tool delegate` subject' "$ink_cli" >/dev/null
create_tool=$repo/skills/create-ink-agent-cli-tool/SKILL.md
grep 'stage/match/apply' "$create_tool" >/dev/null
grep 'projection' "$create_tool" >/dev/null
printf 'ok\n'