Skip to content

Commit de7c48f

Browse files
authored
Make installed skills self-contained (#2)
* Make output handoffs preserve source state * Make clear-ask self-contained * Make decision-brief self-contained * Make meeting-to-actions self-contained * Make follow-up-draft self-contained * Make status-update self-contained * Make brief-me self-contained * Make reduce-to-facts self-contained * Enforce portable self-contained skills * Smoke test portable installed skills * Clarify portable install behavior * Document portable skill hardening
1 parent 0584f79 commit de7c48f

12 files changed

Lines changed: 180 additions & 48 deletions

File tree

.github/workflows/validate.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ jobs:
3434
HOME="$tmp_home" ./install.sh --claude-user --only reduce-to-facts,clear-ask
3535
test -f "$tmp_home/.claude/skills/reduce-to-facts/SKILL.md"
3636
test -f "$tmp_home/.claude/skills/clear-ask/SKILL.md"
37+
grep -q "Portable Output Contract" "$tmp_home/.claude/skills/reduce-to-facts/SKILL.md"
38+
grep -q "without new source support" "$tmp_home/.claude/skills/clear-ask/SKILL.md"
39+
! grep -R -E '\.\./\.\./(references|templates)' "$tmp_home/.claude/skills"
3740
HOME="$tmp_home" ./install.sh --claude-user --only reduce-to-facts,clear-ask
3841
HOME="$tmp_home" ./install.sh --claude-user --only reduce-to-facts,clear-ask --dry-run
3942
@@ -46,6 +49,7 @@ jobs:
4649
./install.sh --codex-project "$tmp_project" --only status-update --include-templates
4750
test -f "$tmp_project/.agents/skills/status-update/SKILL.md"
4851
test -f "$tmp_project/docs/context-to-action-skills/templates/ACTIONS.md"
52+
grep -q "Portable Output Contract" "$tmp_project/.agents/skills/status-update/SKILL.md"
4953
5054
tmp_home="$(mktemp -d)"
5155
HOME="$tmp_home" ./install.sh --claude-user --only reduce-to-facts

CHANGELOG.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,17 @@
77
- `LLM.md` as a compact agent-readable guide to the repo.
88
- README front-door cleanup, including the routing table and compatibility/control matrix.
99
- A clearer repo-specific `AGENTS.md`.
10+
- A portable output contract inside every installed skill.
11+
- Validation that rejects skill links escaping the installed skill folder.
1012

1113
### Changed
1214

1315
- README sections were consolidated for faster scanning.
16+
- The quickstart now asks users to choose one install target instead of running both installers.
17+
- Downstream skills now accept fact ledgers or conversation-state records explicitly and preserve their source classifications.
18+
- Optional template references no longer use repository-relative paths that break after installation.
1419

15-
### Notes
20+
### Fixed
1621

17-
- This branch is documentation and productization only; skill behavior is unchanged.
22+
- Installed skills no longer depend on `../../references` or `../../templates` paths that are absent from the installed layout.
23+
- Assumptions, open questions, proposed actions, and stakeholder positions may not be promoted into facts, decisions, commitments, owners, or deadlines without new source support.

README.md

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ It is not a deterministic workflow engine, ticketing system, MCP server, or proj
2727

2828
The skills provide reusable instruction contracts and examples. They help an assistant preserve uncertainty, identify asks, surface owners, draft replies, and avoid unsafe action.
2929

30+
Each installed `SKILL.md` is self-contained: the critical uncertainty, handoff, and mutation rules travel with the skill folder rather than depending on repository-only links.
31+
3032
Slack threads, email chains, doc comments, tickets, and transcripts can all carry the same source state as a live meeting. Treat them as async collaboration: extract facts first, then move to the next clear action.
3133

3234
For machine-validated workflows, use the optional schemas and examples as a stricter handoff layer.
@@ -35,10 +37,24 @@ For machine-validated workflows, use the optional schemas and examples as a stri
3537

3638
No coding is required.
3739

40+
Clone the repo:
41+
3842
```sh
3943
git clone https://github.com/tmusser/context-to-action-skills.git
4044
cd context-to-action-skills
45+
```
46+
47+
Then choose one install target.
48+
49+
Claude Code:
50+
51+
```sh
4152
./install.sh --claude-user --only reduce-to-facts,clear-ask,decision-brief,follow-up-draft
53+
```
54+
55+
Codex:
56+
57+
```sh
4258
./install.sh --codex-user --only reduce-to-facts,clear-ask,decision-brief,follow-up-draft
4359
```
4460

@@ -115,9 +131,9 @@ Choose the mode that gives you the right control.
115131
| Mode | What it uses | Default behavior | Validation confidence | Caveat |
116132
| --- | --- | --- | --- | --- |
117133
| Pasted-context mode | Pasted notes, transcripts, docs, or thread text | Read and draft from pasted source only | High | This is the primary validated usage pattern. |
118-
| Claude/Cowork-style skills | Local `SKILL.md` files plus pasted context | Read and draft through the hosted skill pack | Medium | Validated mainly when used with pasted context; host UI behavior is outside this repo. |
119-
| Codex install path | `install.sh` or copied skill folders | Places the same skill pack in Codex-friendly paths | Medium | Install layout is validated; host features are not. |
120-
| Other assistants / manual prompt reuse | Copied `SKILL.md` text or pasted prompts | Same output contract when the host follows it | Low | Compatibility target, not a tested integration. |
134+
| Claude/Cowork-style skills | Local self-contained `SKILL.md` files plus pasted context | Read and draft through the hosted skill pack | Medium | Validated mainly when used with pasted context; host UI behavior is outside this repo. |
135+
| Codex install path | `install.sh` or copied skill folders | Places the same self-contained skill pack in Codex-friendly paths | Medium | Install layout is validated; host features are not. |
136+
| Other assistants / manual prompt reuse | Copied `SKILL.md` text or skill folders | Same output contract when the host follows it | Low | Compatibility target, not a tested integration. |
121137
| Connected-context mode | Approved tools the user explicitly authorizes | Reads only approved tools | Low | This repo does not grant connector access. |
122138
| Action mode | Host tool invocation plus user approval | Mutates systems only when explicitly asked | Low | This repo provides guardrails, not mutation rights. |
123139

@@ -133,7 +149,7 @@ Connector and action-mode behavior depends on the host assistant and the tools t
133149

134150
For why MCP stays out of scope for now, see [integration roadmap](docs/integration-roadmap.md).
135151

136-
Shared guidance for mixed-source inputs lives in [source-packet.md](references/source-packet.md).
152+
Shared authoring guidance for mixed-source inputs lives in [source-packet.md](references/source-packet.md). The installed skills carry their critical output contract inline.
137153

138154
## Privacy and control
139155

references/shared-output-contract.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,11 @@ Rules:
1717
- Use the smallest useful output.
1818
- Label assumptions.
1919
- Preserve source gaps.
20+
- Preserve source anchors and confidence labels when they are available.
21+
- When consuming a fact ledger or conversation state, do not promote an
22+
assumption, inference, open question, proposed action, or stakeholder position
23+
into a fact, decision, commitment, owner, or deadline without new source support.
24+
- If new source changes a classification, name the new source and explain the
25+
change.
26+
- Keep unresolved approvals, owners, timing, and blockers explicit in drafts.
2027
- Do not send, publish, update tickets, create events, or mutate systems unless explicitly asked.

scripts/validate_repo.py

Lines changed: 55 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,18 @@
5252
]
5353

5454

55+
PORTABLE_CONTRACT_PHRASES = [
56+
"portable output contract",
57+
"use the smallest useful output",
58+
"label assumptions",
59+
"preserve source gaps",
60+
"source anchors",
61+
"confidence labels",
62+
"without new source support",
63+
"do not send, publish, update tickets, create events, or mutate systems unless explicitly asked",
64+
]
65+
66+
5567
def fail(message: str) -> None:
5668
print(f"FAIL: {message}", file=sys.stderr)
5769
raise SystemExit(1)
@@ -99,6 +111,45 @@ def line_has_allowed_former_name(path: Path, line: str) -> bool:
99111
return "Formerly ai-business-skills" in normalized or "Formerly ai-business-skills." in normalized
100112

101113

114+
def resolve_link(source_file: Path, link: str) -> Path | None:
115+
target = link.strip()
116+
if not target:
117+
return None
118+
if target.startswith(("http://", "https://", "mailto:", "#")):
119+
return None
120+
if target.startswith("<") and target.endswith(">"):
121+
target = target[1:-1]
122+
target = target.split("#", 1)[0].split("?", 1)[0]
123+
if not target:
124+
return None
125+
path = Path(target)
126+
if path.is_absolute():
127+
return path
128+
return (source_file.parent / path).resolve()
129+
130+
131+
def validate_skill_portability(skill_file: Path, skill_dir: Path, text: str) -> None:
132+
lowered = text.lower()
133+
for phrase in PORTABLE_CONTRACT_PHRASES:
134+
if phrase not in lowered:
135+
fail(f"{skill_file.relative_to(ROOT)} is missing portable contract phrase: {phrase}")
136+
137+
link_pattern = re.compile(r"\[[^\]]+\]\(([^)]+)\)")
138+
skill_root = skill_dir.resolve()
139+
for match in link_pattern.finditer(text):
140+
link = match.group(1)
141+
resolved = resolve_link(skill_file, link)
142+
if resolved is None:
143+
continue
144+
if not resolved.is_relative_to(skill_root):
145+
fail(
146+
f"{skill_file.relative_to(ROOT)} has a non-portable relative link: {link}. "
147+
"Installed skill folders must be self-contained."
148+
)
149+
if not resolved.exists():
150+
fail(f"{skill_file.relative_to(ROOT)} has a broken local link: {link}")
151+
152+
102153
def validate_repo_identity() -> None:
103154
if not README.exists():
104155
fail("README.md is missing")
@@ -125,6 +176,9 @@ def validate_repo_identity() -> None:
125176
"use the smallest useful output",
126177
"label assumptions",
127178
"preserve source gaps",
179+
"preserve source anchors and confidence labels",
180+
"without new source support",
181+
"keep unresolved approvals, owners, timing, and blockers explicit",
128182
"do not send, publish, update tickets, create events, or mutate systems unless explicitly asked",
129183
]
130184
for phrase in shared_required:
@@ -152,8 +206,7 @@ def validate_repo_identity() -> None:
152206
fail(f"{skill_file.relative_to(ROOT)} frontmatter name {name!r} does not match folder {skill_dir.name!r}")
153207
if "Read before write" not in text:
154208
fail(f"{skill_file.relative_to(ROOT)} is missing read-before-write guardrail")
155-
if "shared-output-contract.md" not in text:
156-
fail(f"{skill_file.relative_to(ROOT)} does not reference shared-output-contract.md")
209+
validate_skill_portability(skill_file, skill_dir, text)
157210

158211
reduce_to_facts = SKILLS_DIR / "reduce-to-facts" / "SKILL.md"
159212
reduce_text = read_text(reduce_to_facts)
@@ -207,23 +260,6 @@ def validate_readme() -> None:
207260
fail(f"{template.relative_to(ROOT)} is missing the schema mapping note")
208261

209262

210-
def resolve_link(source_file: Path, link: str) -> Path | None:
211-
target = link.strip()
212-
if not target:
213-
return None
214-
if target.startswith(("http://", "https://", "mailto:", "#")):
215-
return None
216-
if target.startswith("<") and target.endswith(">"):
217-
target = target[1:-1]
218-
target = target.split("#", 1)[0].split("?", 1)[0]
219-
if not target:
220-
return None
221-
path = Path(target)
222-
if path.is_absolute():
223-
return path
224-
return (source_file.parent / path).resolve()
225-
226-
227263
def validate_markdown_links() -> None:
228264
link_pattern = re.compile(r"\[[^\]]+\]\(([^)]+)\)")
229265
for path in markdown_files():

skills/brief-me/SKILL.md

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ Turn messy connected or pasted context into a short conversation-state brief the
2626
- Hex or other data output
2727
- Pasted notes
2828
- Any combination of the above
29+
- A `reduce-to-facts` ledger or conversation-state record
2930

3031
## Guardrails
3132

@@ -37,9 +38,17 @@ Turn messy connected or pasted context into a short conversation-state brief the
3738
- Do not dump raw transcript content by default.
3839
- Keep the output workplace-user friendly.
3940

40-
## Shared Output Contract
41+
## Portable Output Contract
4142

42-
See [shared-output-contract.md](../../references/shared-output-contract.md) for the common cross-skill output rules.
43+
- Use only the useful subset of source-backed facts, assumptions, source gaps,
44+
stakeholder sensitivities, potential misreads, and the suggested next action.
45+
- Use the smallest useful output.
46+
- Label assumptions and preserve source gaps, source anchors, and confidence labels.
47+
- When consuming upstream state, do not promote an assumption, inference, open
48+
question, proposed action, or stakeholder position into a fact, decision,
49+
commitment, owner, or deadline without new source support.
50+
- Keep unresolved approvals, owners, timing, and blockers explicit in the brief.
51+
- Do not send, publish, update tickets, create events, or mutate systems unless explicitly asked.
4352

4453
## Output
4554

@@ -53,7 +62,8 @@ See [shared-output-contract.md](../../references/shared-output-contract.md) for
5362
- Suggested follow-ups
5463
- Source gaps
5564

56-
When the user wants a fuller record, map the result into [CONVERSATION_STATE.md](../../templates/CONVERSATION_STATE.md).
65+
When the user wants a fuller record, use the optional `CONVERSATION_STATE.md`
66+
template from this pack when it is available.
5767

5868
## Success Standard
5969

skills/clear-ask/SKILL.md

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ Convert a fuzzy request, thread, or note into a direct ask someone can understan
2121
- Meeting notes
2222
- Project context
2323
- Pasted workplace context
24+
- A `reduce-to-facts` ledger or conversation-state record
2425

2526
## Guardrails
2627

@@ -30,9 +31,17 @@ Convert a fuzzy request, thread, or note into a direct ask someone can understan
3031
- Flag missing owner, timing, or decision context.
3132
- Prefer the smallest useful ask.
3233

33-
## Shared Output Contract
34-
35-
See [shared-output-contract.md](../../references/shared-output-contract.md) for the common cross-skill output rules.
34+
## Portable Output Contract
35+
36+
- Use only the useful subset of source-backed facts, assumptions, source gaps,
37+
stakeholder sensitivities, potential misreads, and the suggested next action.
38+
- Use the smallest useful output.
39+
- Label assumptions and preserve source gaps, source anchors, and confidence labels.
40+
- When consuming upstream state, do not promote an assumption, inference, open
41+
question, proposed action, or stakeholder position into a fact, decision,
42+
commitment, owner, or deadline without new source support.
43+
- Keep unresolved approvals, owners, timing, and blockers explicit in the ask and draft.
44+
- Do not send, publish, update tickets, create events, or mutate systems unless explicitly asked.
3645

3746
## Output
3847

skills/decision-brief/SKILL.md

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ Build a lightweight decision snapshot from mixed workplace context, ticket histo
2121
- Ticket or project context
2222
- Supporting evidence
2323
- Hex or other data output
24+
- A `reduce-to-facts` ledger or conversation-state record
2425

2526
## Guardrails
2627

@@ -30,9 +31,17 @@ Build a lightweight decision snapshot from mixed workplace context, ticket histo
3031
- Make trade-offs and reversal cost visible.
3132
- Surface source gaps and uncertainty.
3233

33-
## Shared Output Contract
34-
35-
See [shared-output-contract.md](../../references/shared-output-contract.md) for the common cross-skill output rules.
34+
## Portable Output Contract
35+
36+
- Use only the useful subset of source-backed facts, assumptions, source gaps,
37+
stakeholder sensitivities, potential misreads, and the suggested next action.
38+
- Use the smallest useful output.
39+
- Label assumptions and preserve source gaps, source anchors, and confidence labels.
40+
- When consuming upstream state, do not promote an assumption, inference, open
41+
question, proposed action, or stakeholder position into a fact, decision,
42+
commitment, owner, or deadline without new source support.
43+
- Keep unresolved approvals, owners, timing, and blockers explicit in the recommendation.
44+
- Do not send, publish, update tickets, create events, or mutate systems unless explicitly asked.
3645

3746
## Output
3847

skills/follow-up-draft/SKILL.md

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ Draft a concise follow-up that preserves the ask, owner, timing, context, and ne
2323
- Open ask
2424
- Project context
2525
- Prior thread context
26+
- A `reduce-to-facts` ledger or conversation-state record
2627

2728
## Guardrails
2829

@@ -32,9 +33,17 @@ Draft a concise follow-up that preserves the ask, owner, timing, context, and ne
3233
- Label assumptions or missing details.
3334
- Keep the message concise and workplace-user friendly.
3435

35-
## Shared Output Contract
36+
## Portable Output Contract
3637

37-
See [shared-output-contract.md](../../references/shared-output-contract.md) for the common cross-skill output rules.
38+
- Use only the useful subset of source-backed facts, assumptions, source gaps,
39+
stakeholder sensitivities, potential misreads, and the suggested next action.
40+
- Use the smallest useful output.
41+
- Label assumptions and preserve source gaps, source anchors, and confidence labels.
42+
- When consuming upstream state, do not promote an assumption, inference, open
43+
question, proposed action, or stakeholder position into a fact, decision,
44+
commitment, owner, or deadline without new source support.
45+
- Keep unresolved approvals, owners, timing, and blockers explicit or conditional in the draft.
46+
- Do not send, publish, update tickets, create events, or mutate systems unless explicitly asked.
3847

3948
## Output
4049

@@ -43,7 +52,8 @@ See [shared-output-contract.md](../../references/shared-output-contract.md) for
4352
- Executive concise version
4453
- Context note, when helpful
4554

46-
If the user wants a fuller record before drafting, map the source state into [CONVERSATION_STATE.md](../../templates/CONVERSATION_STATE.md).
55+
If the user wants a fuller record before drafting, use the optional
56+
`CONVERSATION_STATE.md` template from this pack when it is available.
4757

4858
## Success Standard
4959

skills/meeting-to-actions/SKILL.md

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ Turn meeting content into a compact action record without making the user reread
2626
- Notes
2727
- Agenda
2828
- Related ticket or doc context when useful
29+
- A `reduce-to-facts` ledger or conversation-state record
2930

3031
## Guardrails
3132

@@ -36,9 +37,17 @@ Turn meeting content into a compact action record without making the user reread
3637
- Surface missing owners, due dates, and unclear blockers.
3738
- Do not dump raw transcript content by default.
3839

39-
## Shared Output Contract
40+
## Portable Output Contract
4041

41-
See [shared-output-contract.md](../../references/shared-output-contract.md) for the common cross-skill output rules.
42+
- Use only the useful subset of source-backed facts, assumptions, source gaps,
43+
stakeholder sensitivities, potential misreads, and the suggested next action.
44+
- Use the smallest useful output.
45+
- Label assumptions and preserve source gaps, source anchors, and confidence labels.
46+
- When consuming upstream state, do not promote an assumption, inference, open
47+
question, proposed action, or stakeholder position into a fact, decision,
48+
commitment, owner, or deadline without new source support.
49+
- Keep unresolved approvals, owners, timing, and blockers explicit in the action record.
50+
- Do not send, publish, update tickets, create events, or mutate systems unless explicitly asked.
4251

4352
## Output
4453

@@ -50,7 +59,8 @@ See [shared-output-contract.md](../../references/shared-output-contract.md) for
5059
- Tickets/docs to update if applicable
5160
- Source gaps
5261

53-
If the user wants a reusable record, map the result into [CONVERSATION_STATE.md](../../templates/CONVERSATION_STATE.md).
62+
If the user wants a reusable record, use the optional `CONVERSATION_STATE.md`
63+
template from this pack when it is available.
5464

5565
## Success Standard
5666

0 commit comments

Comments
 (0)