Align skills with frozen Ink contracts
This commit is contained in:
@@ -15,4 +15,5 @@
|
||||
- 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,
|
||||
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.
|
||||
|
||||
@@ -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
|
||||
manager, network access, copies, prompts, lockfile, or hidden state. It creates
|
||||
absolute symlinks from `$HOME/.ink/skills` (or `$INK_SKILLS_HOME`) to this
|
||||
checkout. Pulling the repository updates installed skills; restarting Ink freezes
|
||||
the new bytes into the next startup snapshot.
|
||||
absolute symlinks from `$HOME/.ink/skills` (or the installer-only
|
||||
`$INK_SKILLS_HOME` target override) to this checkout. Pulling the repository
|
||||
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.
|
||||
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 |
|
||||
|---|---|
|
||||
| `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. |
|
||||
|
||||
## Agent definitions and policy
|
||||
|
||||
Agent definitions live in `$INK_AGENT_HOME` (default `$HOME/.ink/agents`) or
|
||||
project `.ink/agents` directories:
|
||||
Agent definitions live in `$HOME/.ink/agents` or the exact current project's
|
||||
`.ink/agents` directory:
|
||||
|
||||
```text
|
||||
name: Frontend specialist
|
||||
@@ -65,18 +67,19 @@ policy: frontend.policy
|
||||
Implement the bounded frontend task and return proof.
|
||||
```
|
||||
|
||||
The policy path is relative to the definition. It is a normal Ink policy file and
|
||||
narrows the frozen parent snapshot conjunctively. `access: read|write` selects
|
||||
reader/writer scheduling; it does not grant commands or tools. Definitions and
|
||||
policy files are frozen at startup, so restart Ink after changing either.
|
||||
`access: read|write` selects reader/writer scheduling; it does not grant commands
|
||||
or tools. Definitions are frozen at startup, so restart Ink after changing one.
|
||||
|
||||
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
|
||||
|
||||
```sh
|
||||
sh -n bin/ink-skills
|
||||
sh test/install-smoke.sh
|
||||
sh test/skills-smoke.sh
|
||||
```
|
||||
|
||||
## Refusals
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
name: configure-ink-agent
|
||||
description: >-
|
||||
Use when the user asks to create, configure, audit, or explain an Ink subagent
|
||||
definition, including its model, read/write scheduling class, or conjunctive
|
||||
policy file. Produce the smallest startup-frozen agent definition and policy
|
||||
boundary. Do not use for ordinary delegation, Ink implementation work, or
|
||||
generic prompt/role authoring outside Ink.
|
||||
definition, including its model, read/write scheduling class, or named policy
|
||||
boundary. Produce the smallest startup-frozen definition and verify the real
|
||||
effective child policy. Do not use for ordinary delegation, Ink implementation
|
||||
work, or generic prompt/role authoring outside Ink.
|
||||
---
|
||||
|
||||
# Configure an Ink agent
|
||||
@@ -16,23 +16,22 @@ Define one inspectable Ink subagent identity without confusing scheduling class,
|
||||
model choice, and authority.
|
||||
|
||||
```text
|
||||
agent definition -> access class -> relative policy conjunct -> frozen child snapshot
|
||||
agent definition -> access class -> effective child policy -> frozen child snapshot
|
||||
```
|
||||
|
||||
## Trigger boundary
|
||||
|
||||
Use for explicit requests about files in `$INK_AGENT_HOME` (default
|
||||
`$HOME/.ink/agents`) or a project `.ink/agents` directory, or when deciding the
|
||||
policy of a named Ink child.
|
||||
Use for explicit requests about agent files in `$HOME/.ink/agents` or the current
|
||||
project's `.ink/agents` directory, or when deciding the policy of a named Ink
|
||||
child.
|
||||
|
||||
Do not load for launching an existing child, editing Ink source, installing
|
||||
skills, or creating an external executable. `ink-cli` owns host audits;
|
||||
`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
|
||||
body:
|
||||
An agent definition is a plain text file whose filename stem is the catalog key:
|
||||
|
||||
```text
|
||||
name: Frontend specialist
|
||||
@@ -44,54 +43,75 @@ Implement the bounded frontend task and return proof.
|
||||
```
|
||||
|
||||
- `name` is the human-facing identity.
|
||||
- `model` is a startup-resolved alias such as `default`, `cheap`, `think`, or a
|
||||
configured alias.
|
||||
- `model` defaults to `default`; `default`, `cheap`, `think`, and `design` may be
|
||||
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`.
|
||||
- `policy` is optional and relative to the definition file. Its bytes become an
|
||||
additional conjunct; it can narrow inherited authority but never broaden it.
|
||||
- Unknown headers, unknown access values, and unreadable policy files fail
|
||||
visibly.
|
||||
- `policy` is optional metadata intended to name a role-specific policy.
|
||||
- Unknown headers, missing/unknown access, an empty prompt, and duplicate catalog
|
||||
keys within one directory fail 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:
|
||||
|
||||
- `read` children may overlap and receive an immutable host floor with no command,
|
||||
file-mutation, lifecycle-mutation, or delegation authority.
|
||||
- `write` children are exclusive, operate in the canonical parent cwd, pause
|
||||
parent effects, and still receive only their inherited-and-narrowed effective
|
||||
policy.
|
||||
parent effects, and still receive only their effective frozen policy.
|
||||
|
||||
Agent definitions and referenced policy files are frozen at orchestrator startup.
|
||||
Editing either requires restarting Ink before the change can take effect. Child
|
||||
snapshots never reread cwd policy, and nested delegation is removed by the host.
|
||||
Never infer effective authority from `access`, prompt text, or a `policy:` label.
|
||||
Use the child policy snapshot and a real allowed/denied smoke.
|
||||
|
||||
## 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
|
||||
|
||||
1. Choose `read` unless the child must produce a real effect.
|
||||
2. Choose the smallest model alias that fits the specialist job.
|
||||
3. Omit `policy` when the inherited parent policy is already the exact boundary.
|
||||
4. Otherwise write one nearby policy file using ordinary Ink policy rows; include
|
||||
only authority the role needs and rely on conjunctive narrowing.
|
||||
5. Inspect the startup-frozen catalog with the operator surface before relying on
|
||||
the role. Restart Ink after definition or policy changes.
|
||||
3. Put the definition in user scope or exact project cwd according to intended
|
||||
precedence.
|
||||
4. Restart Ink after definition changes.
|
||||
5. Inspect the frozen operator catalog and child metadata.
|
||||
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
|
||||
|
||||
- Do not put policy rows in the prompt body.
|
||||
- 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 create worktrees, copied workspaces, merge protocols, or per-role policy
|
||||
DSLs.
|
||||
- Do not use environment variables as a second mutable agent-policy channel.
|
||||
- Do not grant `tool delegate` to a child; Ink removes nested delegation.
|
||||
- Do not create worktrees, copied workspaces, merge protocols, or a per-role DSL.
|
||||
- Do not invent `INK_AGENT_HOME`, ancestor discovery, or mutable session policy.
|
||||
|
||||
## Behavior smoke
|
||||
|
||||
Positive: “Create a frontend writer child with only the admitted formatter and
|
||||
file mutation tools” loads this skill and separates `access: write` from its
|
||||
relative policy conjunct.
|
||||
Positive: “Create a frontend writer child with only formatter and file mutation
|
||||
authority” loads this skill and blocks until the named policy is actually
|
||||
conjoined or the parent frozen policy already supplies that exact boundary.
|
||||
|
||||
Negative: “Ask the existing reviewer to inspect this diff” does not load this
|
||||
skill; it is ordinary delegation.
|
||||
|
||||
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.
|
||||
|
||||
@@ -49,14 +49,17 @@ changes belong to Ink's repository authority and implementation workflow.
|
||||
|
||||
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.
|
||||
3. **External executables** admitted through Ink's `run` policy.
|
||||
|
||||
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
|
||||
`sessions list/tree/inspect/resume`, and a policy rejection does not prove the
|
||||
operator command is absent.
|
||||
the other two. Current source exposing flat `ink sessions`, `ink skills`, and
|
||||
`ink tools` does not imply invented nested verbs, and a policy rejection does not
|
||||
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
|
||||
|
||||
@@ -77,7 +80,8 @@ operator command is absent.
|
||||
- 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.
|
||||
- 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
|
||||
operator's question; prompts and tool results may contain secrets.
|
||||
- Do not weaken path, origin, account, or repository selectors merely to make an
|
||||
|
||||
Executable
+35
@@ -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'
|
||||
Reference in New Issue
Block a user