This commit is contained in:
Federico Altepost 2026-07-19 02:40:44 -07:00 committed by GitHub
commit 96eff96556
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 527 additions and 15 deletions

View File

@ -1,5 +1,28 @@
# Changelog
## [1.60.2.0] - 2026-07-19
## **Every `/ship` handoff now starts by reminding you what the work was actually about.**
## **Installed hosts now receive the shared runtime modules their gstack commands import.**
Long ship sessions used to end with a technically complete status report that could still be hard to understand after the conversation had scrolled away: summaries could begin with "Before" and "Now" without naming the product or problem. The completion contract now opens with a short, self-contained orientation before the engineering summary, and its final plain-language section must name the concrete subject. Separately, host-specific installs copied or linked `bin/` without the sibling `lib/` modules many commands load at runtime, leaving otherwise-correct installations vulnerable to missing-module failures.
### What this means for builders
You can return to a `/ship` result later and immediately recover the context, motivation, and intended outcome before reading implementation details. Codex, Factory, OpenCode, Kiro, and agent-sidecar installations also carry a complete runtime: command scripts and their shared modules travel together.
### Itemized changes
#### Fixed
- `/ship` completion reports now begin with `What this work was about`, naming the product, prior behavior, concrete problem, and intended outcome before the engineering summary. The final `Put simply` section must also stand alone instead of relying on context-free pronouns.
- The setup paths for agent sidecars, Codex, Factory, OpenCode, and Kiro now link or copy `lib/` beside `bin/`, preserving the relative imports used by shared runtime commands.
#### For contributors
- Added a completion-report contract test across the source template, generated skill, and Claude/Codex/Factory golden fixtures.
- Extended setup assertions across every affected host runtime and regenerated the ship skill fixtures.
## [1.60.1.0] - 2026-07-09
## **The /autoplan dual-voice eval is back on the board, catching real regressions.**

View File

@ -1 +1 @@
1.60.1.0
1.60.2.0

View File

@ -1,6 +1,6 @@
{
"name": "gstack",
"version": "1.60.1.0",
"version": "1.60.2.0",
"description": "Garry's Stack — Claude Code skills + fast headless browser. One repo, one install, entire AI engineering workflow.",
"license": "MIT",
"type": "module",

15
setup
View File

@ -748,8 +748,9 @@ create_agents_sidecar() {
local agents_gstack="$repo_root/.agents/skills/gstack"
mkdir -p "$agents_gstack"
# Sidecar directories that skills reference at runtime
for asset in bin browse review qa; do
# Sidecar directories that skills reference at runtime. bin scripts import
# shared modules via ../lib, so bin and lib must always travel together.
for asset in bin lib browse review qa; do
local src="$SOURCE_GSTACK_DIR/$asset"
local dst="$agents_gstack/$asset"
if [ -d "$src" ] || [ -f "$src" ]; then
@ -796,6 +797,9 @@ create_codex_runtime_root() {
if [ -d "$gstack_dir/bin" ]; then
_link_or_copy "$gstack_dir/bin" "$codex_gstack/bin"
fi
if [ -d "$gstack_dir/lib" ]; then
_link_or_copy "$gstack_dir/lib" "$codex_gstack/lib"
fi
if [ -d "$gstack_dir/browse/dist" ]; then
_link_or_copy "$gstack_dir/browse/dist" "$codex_gstack/browse/dist"
fi
@ -836,6 +840,9 @@ create_factory_runtime_root() {
if [ -d "$gstack_dir/bin" ]; then
_link_or_copy "$gstack_dir/bin" "$factory_gstack/bin"
fi
if [ -d "$gstack_dir/lib" ]; then
_link_or_copy "$gstack_dir/lib" "$factory_gstack/lib"
fi
if [ -d "$gstack_dir/browse/dist" ]; then
_link_or_copy "$gstack_dir/browse/dist" "$factory_gstack/browse/dist"
fi
@ -874,6 +881,9 @@ create_opencode_runtime_root() {
if [ -d "$gstack_dir/bin" ]; then
_link_or_copy "$gstack_dir/bin" "$opencode_gstack/bin"
fi
if [ -d "$gstack_dir/lib" ]; then
_link_or_copy "$gstack_dir/lib" "$opencode_gstack/lib"
fi
if [ -d "$gstack_dir/browse/dist" ]; then
_link_or_copy "$gstack_dir/browse/dist" "$opencode_gstack/browse/dist"
fi
@ -1115,6 +1125,7 @@ if [ "$INSTALL_KIRO" -eq 1 ]; then
[ -L "$KIRO_GSTACK" ] && rm -f "$KIRO_GSTACK"
mkdir -p "$KIRO_GSTACK" "$KIRO_GSTACK/browse" "$KIRO_GSTACK/gstack-upgrade" "$KIRO_GSTACK/review"
_link_or_copy "$SOURCE_GSTACK_DIR/bin" "$KIRO_GSTACK/bin"
_link_or_copy "$SOURCE_GSTACK_DIR/lib" "$KIRO_GSTACK/lib"
_link_or_copy "$SOURCE_GSTACK_DIR/browse/dist" "$KIRO_GSTACK/browse/dist"
_link_or_copy "$SOURCE_GSTACK_DIR/browse/bin" "$KIRO_GSTACK/browse/bin"
# ETHOS.md — referenced by "Search Before Building" in all skill preambles

View File

@ -843,7 +843,7 @@ branch name wherever the instructions say "the base branch" or `<default>`.
# Ship: Fully Automated Ship Workflow
You are running the `/ship` workflow. This is a **non-interactive, fully automated** workflow. Do NOT ask for confirmation at any step. The user said `/ship` which means DO IT. Run straight through and output the PR URL at the end.
You are running the `/ship` workflow. This is a **non-interactive, fully automated** workflow. Do NOT ask for confirmation at any step. The user said `/ship` which means DO IT. Run straight through and include the PR URL in the final engineering handoff.
**Only stop for:**
- On the base branch (abort)
@ -1246,7 +1246,11 @@ Before pushing, re-verify if code changed during Steps 4-6:
2. **Build verification:** If the project has a build step, run it. Paste output.
3. **Rationalization prevention:**
3. **UI evidence gate:** For a user-visible UI diff, produce the matched
Before/After evidence from Step 22 before push. If unavailable, STOP; do not
push or create/update the PR/MR.
4. **Rationalization prevention:**
- "Should work now" → RUN IT.
- "I'm confident" → Confidence is not evidence.
- "I already tested earlier" → Code changed since then. Test again.
@ -1415,3 +1419,74 @@ through `gstack-version-bump`; never hand-roll the VERSION/package.json write.
- **Never push without fresh verification evidence.** If code changed after Step 5 tests, re-run before pushing.
- **Step 7 generates coverage tests.** They must pass before committing. Never commit failing tests.
- **The goal is: user says `/ship`, next thing they see is the review + PR URL + auto-synced docs.**
---
## Step 22: Full engineering handoff
End every ship attempt with this self-contained report, even when stopped. Use each heading;
write `Not applicable` briefly when a category does not apply.
Open with orientation, not status. Assume the reader remembers nothing from the
earlier conversation.
```markdown
## What this work was about
Name the product, system, or feature being changed. In 2-4 sentences, state what it did before,
the concrete problem that motivated the work, and the intended outcome. Assume the reader remembers nothing from the earlier conversation.
Keep implementation, verification, and ship status in the sections below.
## Engineering summary
### Outcome
What shipped (version, branch, commit, PR/MR URL), or what blocked it.
### Problem and root cause
What was wrong or missing, why, and the supporting evidence.
### Investigation and decisions
Key findings, alternatives, decisions, and why this approach won.
### Implementation
Changed behavior, components, data paths, APIs, migrations, infrastructure, and docs.
### Verification
Fresh test/build/typecheck/lint/behavior/review/CI/deploy evidence; mark pass/fail/skipped.
### Risks and operational impact
Tradeoffs, compatibility, rollout/migration, observability, rollback.
### Remaining work
Unfinished work. Write `None` when the completion contract is fully satisfied.
### Decision required
The user's next decision. Write `None` when no decision is required.
```
### UI before/after evidence
For user-visible UI changes, include matched **Before** and **After** screenshots:
1. Use a pre-change capture only if it faithfully represents the base; otherwise run the merge-base/base revision in an isolated worktree or use its known deployment.
2. Capture the current branch after implementation and verification.
3. Match route, application state, data, viewport, theme, and zoom. Use safe test data; never expose credentials, customer data, or private information.
4. Show `![Before](path)` and `![After](path)` inline; include both artifact paths.
5. Do not commit screenshot artifacts unless the repository explicitly requires it.
If a faithful comparison is impossible, use the same report with Outcome blocked,
mark UI evidence incomplete, and STOP before Step 17. Do not push, create/update
the PR/MR, claim UI completion, or offer a waiver.
### Put simply
Final response section; nothing follows. It must stand on its own. Be intuitive,
extremely concise, and precise. Name the concrete subject before describing the
change. Never rely only on `it`, `this`, or `the change` to carry context.
```markdown
### Put simply
- **Why:** Why the named product, system, or feature needed to change.
- **What:** Its relevant before-and-now behavior.
- **How:** The essential mechanism, without unnecessary implementation detail.
```

View File

@ -34,7 +34,7 @@ triggers:
# Ship: Fully Automated Ship Workflow
You are running the `/ship` workflow. This is a **non-interactive, fully automated** workflow. Do NOT ask for confirmation at any step. The user said `/ship` which means DO IT. Run straight through and output the PR URL at the end.
You are running the `/ship` workflow. This is a **non-interactive, fully automated** workflow. Do NOT ask for confirmation at any step. The user said `/ship` which means DO IT. Run straight through and include the PR URL in the final engineering handoff.
**Only stop for:**
- On the base branch (abort)
@ -367,7 +367,11 @@ Before pushing, re-verify if code changed during Steps 4-6:
2. **Build verification:** If the project has a build step, run it. Paste output.
3. **Rationalization prevention:**
3. **UI evidence gate:** For a user-visible UI diff, produce the matched
Before/After evidence from Step 22 before push. If unavailable, STOP; do not
push or create/update the PR/MR.
4. **Rationalization prevention:**
- "Should work now" → RUN IT.
- "I'm confident" → Confidence is not evidence.
- "I already tested earlier" → Code changed since then. Test again.
@ -535,3 +539,74 @@ through `gstack-version-bump`; never hand-roll the VERSION/package.json write.
- **Never push without fresh verification evidence.** If code changed after Step 5 tests, re-run before pushing.
- **Step 7 generates coverage tests.** They must pass before committing. Never commit failing tests.
- **The goal is: user says `/ship`, next thing they see is the review + PR URL + auto-synced docs.**
---
## Step 22: Full engineering handoff
End every ship attempt with this self-contained report, even when stopped. Use each heading;
write `Not applicable` briefly when a category does not apply.
Open with orientation, not status. Assume the reader remembers nothing from the
earlier conversation.
```markdown
## What this work was about
Name the product, system, or feature being changed. In 2-4 sentences, state what it did before,
the concrete problem that motivated the work, and the intended outcome. Assume the reader remembers nothing from the earlier conversation.
Keep implementation, verification, and ship status in the sections below.
## Engineering summary
### Outcome
What shipped (version, branch, commit, PR/MR URL), or what blocked it.
### Problem and root cause
What was wrong or missing, why, and the supporting evidence.
### Investigation and decisions
Key findings, alternatives, decisions, and why this approach won.
### Implementation
Changed behavior, components, data paths, APIs, migrations, infrastructure, and docs.
### Verification
Fresh test/build/typecheck/lint/behavior/review/CI/deploy evidence; mark pass/fail/skipped.
### Risks and operational impact
Tradeoffs, compatibility, rollout/migration, observability, rollback.
### Remaining work
Unfinished work. Write `None` when the completion contract is fully satisfied.
### Decision required
The user's next decision. Write `None` when no decision is required.
```
### UI before/after evidence
For user-visible UI changes, include matched **Before** and **After** screenshots:
1. Use a pre-change capture only if it faithfully represents the base; otherwise run the merge-base/base revision in an isolated worktree or use its known deployment.
2. Capture the current branch after implementation and verification.
3. Match route, application state, data, viewport, theme, and zoom. Use safe test data; never expose credentials, customer data, or private information.
4. Show `![Before](path)` and `![After](path)` inline; include both artifact paths.
5. Do not commit screenshot artifacts unless the repository explicitly requires it.
If a faithful comparison is impossible, use the same report with Outcome blocked,
mark UI evidence incomplete, and STOP before Step 17. Do not push, create/update
the PR/MR, claim UI completion, or offer a waiver.
### Put simply
Final response section; nothing follows. It must stand on its own. Be intuitive,
extremely concise, and precise. Name the concrete subject before describing the
change. Never rely only on `it`, `this`, or `the change` to carry context.
```markdown
### Put simply
- **Why:** Why the named product, system, or feature needed to change.
- **What:** Its relevant before-and-now behavior.
- **How:** The essential mechanism, without unnecessary implementation detail.
```

View File

@ -843,7 +843,7 @@ branch name wherever the instructions say "the base branch" or `<default>`.
# Ship: Fully Automated Ship Workflow
You are running the `/ship` workflow. This is a **non-interactive, fully automated** workflow. Do NOT ask for confirmation at any step. The user said `/ship` which means DO IT. Run straight through and output the PR URL at the end.
You are running the `/ship` workflow. This is a **non-interactive, fully automated** workflow. Do NOT ask for confirmation at any step. The user said `/ship` which means DO IT. Run straight through and include the PR URL in the final engineering handoff.
**Only stop for:**
- On the base branch (abort)
@ -1246,7 +1246,11 @@ Before pushing, re-verify if code changed during Steps 4-6:
2. **Build verification:** If the project has a build step, run it. Paste output.
3. **Rationalization prevention:**
3. **UI evidence gate:** For a user-visible UI diff, produce the matched
Before/After evidence from Step 22 before push. If unavailable, STOP; do not
push or create/update the PR/MR.
4. **Rationalization prevention:**
- "Should work now" → RUN IT.
- "I'm confident" → Confidence is not evidence.
- "I already tested earlier" → Code changed since then. Test again.
@ -1415,3 +1419,74 @@ through `gstack-version-bump`; never hand-roll the VERSION/package.json write.
- **Never push without fresh verification evidence.** If code changed after Step 5 tests, re-run before pushing.
- **Step 7 generates coverage tests.** They must pass before committing. Never commit failing tests.
- **The goal is: user says `/ship`, next thing they see is the review + PR URL + auto-synced docs.**
---
## Step 22: Full engineering handoff
End every ship attempt with this self-contained report, even when stopped. Use each heading;
write `Not applicable` briefly when a category does not apply.
Open with orientation, not status. Assume the reader remembers nothing from the
earlier conversation.
```markdown
## What this work was about
Name the product, system, or feature being changed. In 2-4 sentences, state what it did before,
the concrete problem that motivated the work, and the intended outcome. Assume the reader remembers nothing from the earlier conversation.
Keep implementation, verification, and ship status in the sections below.
## Engineering summary
### Outcome
What shipped (version, branch, commit, PR/MR URL), or what blocked it.
### Problem and root cause
What was wrong or missing, why, and the supporting evidence.
### Investigation and decisions
Key findings, alternatives, decisions, and why this approach won.
### Implementation
Changed behavior, components, data paths, APIs, migrations, infrastructure, and docs.
### Verification
Fresh test/build/typecheck/lint/behavior/review/CI/deploy evidence; mark pass/fail/skipped.
### Risks and operational impact
Tradeoffs, compatibility, rollout/migration, observability, rollback.
### Remaining work
Unfinished work. Write `None` when the completion contract is fully satisfied.
### Decision required
The user's next decision. Write `None` when no decision is required.
```
### UI before/after evidence
For user-visible UI changes, include matched **Before** and **After** screenshots:
1. Use a pre-change capture only if it faithfully represents the base; otherwise run the merge-base/base revision in an isolated worktree or use its known deployment.
2. Capture the current branch after implementation and verification.
3. Match route, application state, data, viewport, theme, and zoom. Use safe test data; never expose credentials, customer data, or private information.
4. Show `![Before](path)` and `![After](path)` inline; include both artifact paths.
5. Do not commit screenshot artifacts unless the repository explicitly requires it.
If a faithful comparison is impossible, use the same report with Outcome blocked,
mark UI evidence incomplete, and STOP before Step 17. Do not push, create/update
the PR/MR, claim UI completion, or offer a waiver.
### Put simply
Final response section; nothing follows. It must stand on its own. Be intuitive,
extremely concise, and precise. Name the concrete subject before describing the
change. Never rely only on `it`, `this`, or `the change` to carry context.
```markdown
### Put simply
- **Why:** Why the named product, system, or feature needed to change.
- **What:** Its relevant before-and-now behavior.
- **How:** The essential mechanism, without unnecessary implementation detail.
```

View File

@ -829,7 +829,7 @@ branch name wherever the instructions say "the base branch" or `<default>`.
# Ship: Fully Automated Ship Workflow
You are running the `/ship` workflow. This is a **non-interactive, fully automated** workflow. Do NOT ask for confirmation at any step. The user said `/ship` which means DO IT. Run straight through and output the PR URL at the end.
You are running the `/ship` workflow. This is a **non-interactive, fully automated** workflow. Do NOT ask for confirmation at any step. The user said `/ship` which means DO IT. Run straight through and include the PR URL in the final engineering handoff.
**Only stop for:**
- On the base branch (abort)
@ -2429,7 +2429,11 @@ Before pushing, re-verify if code changed during Steps 4-6:
2. **Build verification:** If the project has a build step, run it. Paste output.
3. **Rationalization prevention:**
3. **UI evidence gate:** For a user-visible UI diff, produce the matched
Before/After evidence from Step 22 before push. If unavailable, STOP; do not
push or create/update the PR/MR.
4. **Rationalization prevention:**
- "Should work now" → RUN IT.
- "I'm confident" → Confidence is not evidence.
- "I already tested earlier" → Code changed since then. Test again.
@ -2801,3 +2805,74 @@ through `gstack-version-bump`; never hand-roll the VERSION/package.json write.
- **Never push without fresh verification evidence.** If code changed after Step 5 tests, re-run before pushing.
- **Step 7 generates coverage tests.** They must pass before committing. Never commit failing tests.
- **The goal is: user says `/ship`, next thing they see is the review + PR URL + auto-synced docs.**
---
## Step 22: Full engineering handoff
End every ship attempt with this self-contained report, even when stopped. Use each heading;
write `Not applicable` briefly when a category does not apply.
Open with orientation, not status. Assume the reader remembers nothing from the
earlier conversation.
```markdown
## What this work was about
Name the product, system, or feature being changed. In 2-4 sentences, state what it did before,
the concrete problem that motivated the work, and the intended outcome. Assume the reader remembers nothing from the earlier conversation.
Keep implementation, verification, and ship status in the sections below.
## Engineering summary
### Outcome
What shipped (version, branch, commit, PR/MR URL), or what blocked it.
### Problem and root cause
What was wrong or missing, why, and the supporting evidence.
### Investigation and decisions
Key findings, alternatives, decisions, and why this approach won.
### Implementation
Changed behavior, components, data paths, APIs, migrations, infrastructure, and docs.
### Verification
Fresh test/build/typecheck/lint/behavior/review/CI/deploy evidence; mark pass/fail/skipped.
### Risks and operational impact
Tradeoffs, compatibility, rollout/migration, observability, rollback.
### Remaining work
Unfinished work. Write `None` when the completion contract is fully satisfied.
### Decision required
The user's next decision. Write `None` when no decision is required.
```
### UI before/after evidence
For user-visible UI changes, include matched **Before** and **After** screenshots:
1. Use a pre-change capture only if it faithfully represents the base; otherwise run the merge-base/base revision in an isolated worktree or use its known deployment.
2. Capture the current branch after implementation and verification.
3. Match route, application state, data, viewport, theme, and zoom. Use safe test data; never expose credentials, customer data, or private information.
4. Show `![Before](path)` and `![After](path)` inline; include both artifact paths.
5. Do not commit screenshot artifacts unless the repository explicitly requires it.
If a faithful comparison is impossible, use the same report with Outcome blocked,
mark UI evidence incomplete, and STOP before Step 17. Do not push, create/update
the PR/MR, claim UI completion, or offer a waiver.
### Put simply
Final response section; nothing follows. It must stand on its own. Be intuitive,
extremely concise, and precise. Name the concrete subject before describing the
change. Never rely only on `it`, `this`, or `the change` to carry context.
```markdown
### Put simply
- **Why:** Why the named product, system, or feature needed to change.
- **What:** Its relevant before-and-now behavior.
- **How:** The essential mechanism, without unnecessary implementation detail.
```

View File

@ -831,7 +831,7 @@ branch name wherever the instructions say "the base branch" or `<default>`.
# Ship: Fully Automated Ship Workflow
You are running the `/ship` workflow. This is a **non-interactive, fully automated** workflow. Do NOT ask for confirmation at any step. The user said `/ship` which means DO IT. Run straight through and output the PR URL at the end.
You are running the `/ship` workflow. This is a **non-interactive, fully automated** workflow. Do NOT ask for confirmation at any step. The user said `/ship` which means DO IT. Run straight through and include the PR URL in the final engineering handoff.
**Only stop for:**
- On the base branch (abort)
@ -2835,7 +2835,11 @@ Before pushing, re-verify if code changed during Steps 4-6:
2. **Build verification:** If the project has a build step, run it. Paste output.
3. **Rationalization prevention:**
3. **UI evidence gate:** For a user-visible UI diff, produce the matched
Before/After evidence from Step 22 before push. If unavailable, STOP; do not
push or create/update the PR/MR.
4. **Rationalization prevention:**
- "Should work now" → RUN IT.
- "I'm confident" → Confidence is not evidence.
- "I already tested earlier" → Code changed since then. Test again.
@ -3207,3 +3211,74 @@ through `gstack-version-bump`; never hand-roll the VERSION/package.json write.
- **Never push without fresh verification evidence.** If code changed after Step 5 tests, re-run before pushing.
- **Step 7 generates coverage tests.** They must pass before committing. Never commit failing tests.
- **The goal is: user says `/ship`, next thing they see is the review + PR URL + auto-synced docs.**
---
## Step 22: Full engineering handoff
End every ship attempt with this self-contained report, even when stopped. Use each heading;
write `Not applicable` briefly when a category does not apply.
Open with orientation, not status. Assume the reader remembers nothing from the
earlier conversation.
```markdown
## What this work was about
Name the product, system, or feature being changed. In 2-4 sentences, state what it did before,
the concrete problem that motivated the work, and the intended outcome. Assume the reader remembers nothing from the earlier conversation.
Keep implementation, verification, and ship status in the sections below.
## Engineering summary
### Outcome
What shipped (version, branch, commit, PR/MR URL), or what blocked it.
### Problem and root cause
What was wrong or missing, why, and the supporting evidence.
### Investigation and decisions
Key findings, alternatives, decisions, and why this approach won.
### Implementation
Changed behavior, components, data paths, APIs, migrations, infrastructure, and docs.
### Verification
Fresh test/build/typecheck/lint/behavior/review/CI/deploy evidence; mark pass/fail/skipped.
### Risks and operational impact
Tradeoffs, compatibility, rollout/migration, observability, rollback.
### Remaining work
Unfinished work. Write `None` when the completion contract is fully satisfied.
### Decision required
The user's next decision. Write `None` when no decision is required.
```
### UI before/after evidence
For user-visible UI changes, include matched **Before** and **After** screenshots:
1. Use a pre-change capture only if it faithfully represents the base; otherwise run the merge-base/base revision in an isolated worktree or use its known deployment.
2. Capture the current branch after implementation and verification.
3. Match route, application state, data, viewport, theme, and zoom. Use safe test data; never expose credentials, customer data, or private information.
4. Show `![Before](path)` and `![After](path)` inline; include both artifact paths.
5. Do not commit screenshot artifacts unless the repository explicitly requires it.
If a faithful comparison is impossible, use the same report with Outcome blocked,
mark UI evidence incomplete, and STOP before Step 17. Do not push, create/update
the PR/MR, claim UI completion, or offer a waiver.
### Put simply
Final response section; nothing follows. It must stand on its own. Be intuitive,
extremely concise, and precise. Name the concrete subject before describing the
change. Never rely only on `it`, `this`, or `the change` to carry context.
```markdown
### Put simply
- **Why:** Why the named product, system, or feature needed to change.
- **What:** Its relevant before-and-now behavior.
- **How:** The essential mechanism, without unnecessary implementation detail.
```

View File

@ -2406,6 +2406,7 @@ describe('setup script validation', () => {
expect(setupContent).toContain('kiro-cli');
expect(setupContent).toContain('KIRO_SKILLS=');
expect(setupContent).toContain('~/.kiro/skills/gstack');
expect(setupContent).toContain('$KIRO_GSTACK/lib');
});
test('setup supports --host opencode with install section and OpenCode skill path vars', () => {
@ -2421,14 +2422,16 @@ describe('setup script validation', () => {
expect(setupContent).toContain('qa/templates');
expect(setupContent).toContain('qa/references');
expect(setupContent).toContain('dx-hall-of-fame.md');
expect(setupContent).toContain('$opencode_gstack/lib');
});
test('create_agents_sidecar links runtime assets', () => {
// Sidecar must link bin, browse, review, qa
// Sidecar must link bin with its shared lib modules, plus browse, review, qa
const fnStart = setupContent.indexOf('create_agents_sidecar()');
const fnEnd = setupContent.indexOf('}', setupContent.indexOf('done', fnStart));
const fnBody = setupContent.slice(fnStart, fnEnd);
expect(fnBody).toContain('bin');
expect(fnBody).toContain('lib');
expect(fnBody).toContain('browse');
expect(fnBody).toContain('review');
expect(fnBody).toContain('qa');
@ -2439,6 +2442,7 @@ describe('setup script validation', () => {
const fnEnd = setupContent.indexOf('}', setupContent.indexOf('done', setupContent.indexOf('review/', fnStart)));
const fnBody = setupContent.slice(fnStart, fnEnd);
expect(fnBody).toContain('gstack/SKILL.md');
expect(fnBody).toContain('$codex_gstack/lib');
expect(fnBody).toContain('browse/dist');
expect(fnBody).toContain('browse/bin');
expect(fnBody).toContain('gstack-upgrade/SKILL.md');
@ -2450,6 +2454,14 @@ describe('setup script validation', () => {
expect(fnBody).not.toContain('_link_or_copy "$gstack_dir" "$codex_gstack"');
});
test('create_factory_runtime_root links shared lib modules beside bin', () => {
const fnStart = setupContent.indexOf('create_factory_runtime_root()');
const fnEnd = setupContent.indexOf('create_opencode_runtime_root()', fnStart);
const fnBody = setupContent.slice(fnStart, fnEnd);
expect(fnBody).toContain('$factory_gstack/bin');
expect(fnBody).toContain('$factory_gstack/lib');
});
test('direct Codex installs are migrated out of ~/.codex/skills/gstack', () => {
expect(setupContent).toContain('migrate_direct_codex_install');
expect(setupContent).toContain('$HOME/.gstack/repos/gstack');

View File

@ -0,0 +1,91 @@
import { describe, expect, test } from 'bun:test';
import { readFileSync } from 'node:fs';
import { join } from 'node:path';
const root = join(import.meta.dir, '..');
const skillPaths = [
'ship/SKILL.md.tmpl',
'ship/SKILL.md',
'test/fixtures/golden/claude-ship-SKILL.md',
'test/fixtures/golden/codex-ship-SKILL.md',
'test/fixtures/golden/factory-ship-SKILL.md',
];
const engineeringHeadings = [
'### Outcome',
'### Problem and root cause',
'### Investigation and decisions',
'### Implementation',
'### Verification',
'### Risks and operational impact',
'### Remaining work',
'### Decision required',
];
describe('ship completion report', () => {
for (const relativePath of skillPaths) {
test(`${relativePath} requires a self-contained engineering handoff`, () => {
const skill = readFileSync(join(root, relativePath), 'utf8');
const handoff = skill.indexOf('## Step 22: Full engineering handoff');
const workContext = skill.indexOf('## What this work was about', handoff);
const engineeringSummary = skill.indexOf('## Engineering summary', handoff);
const uiEvidence = skill.indexOf('### UI before/after evidence', handoff);
const putSimply = skill.lastIndexOf('### Put simply');
const uiEvidenceGate = skill.indexOf('3. **UI evidence gate:**');
const pushStep = skill.indexOf('## Step 17: Push');
expect(handoff).toBeGreaterThan(-1);
expect(workContext).toBeGreaterThan(handoff);
expect(engineeringSummary).toBeGreaterThan(workContext);
expect(skill).toContain('Use each heading');
expect(skill.slice(workContext, engineeringSummary)).toContain(
'Assume the reader remembers nothing from the earlier conversation.',
);
expect(skill.slice(workContext, engineeringSummary)).toContain(
'Name the product, system, or feature being changed',
);
expect(skill.slice(workContext, engineeringSummary)).toContain(
'what it did before',
);
expect(skill.slice(workContext, engineeringSummary)).toContain(
'the intended outcome',
);
let previousHeading = engineeringSummary;
for (const heading of engineeringHeadings) {
const headingIndex = skill.indexOf(heading, previousHeading);
expect(headingIndex).toBeGreaterThan(previousHeading);
previousHeading = headingIndex;
}
expect(uiEvidence).toBeGreaterThan(previousHeading);
expect(skill).toContain('Write `None` when the completion contract is fully satisfied.');
expect(skill).toContain('Write `None` when no decision is required.');
expect(skill).toContain('matched **Before** and **After** screenshots');
expect(skill).toContain('merge-base/base revision in an isolated worktree');
expect(skill).toContain('current branch after implementation and verification');
expect(skill).toContain('route, application state, data, viewport, theme, and zoom');
expect(skill).toContain('Use safe test data; never expose credentials, customer data, or private information.');
expect(skill).toContain('`![Before](path)` and `![After](path)` inline');
expect(skill).toContain('include both artifact paths');
expect(skill).toContain('Do not commit screenshot artifacts unless the repository explicitly requires it.');
expect(skill).toContain('claim UI completion');
expect(uiEvidenceGate).toBeGreaterThan(-1);
expect(pushStep).toBeGreaterThan(uiEvidenceGate);
expect(skill).toMatch(/do not\s+push or create\/update the PR\/MR/);
expect(skill).toContain('STOP before Step 17');
expect(skill).toContain('or offer a waiver');
expect(putSimply).toBeGreaterThan(uiEvidence);
expect(skill.slice(putSimply)).toContain('- **Why:**');
expect(skill.slice(putSimply)).toContain('- **What:**');
expect(skill.slice(putSimply)).toContain('- **How:**');
expect(skill.slice(uiEvidence)).toContain('must stand on its own');
expect(skill.slice(uiEvidence)).toContain('Name the concrete subject');
expect(skill.slice(uiEvidence)).toContain('Never rely only on `it`, `this`, or `the change`');
expect(skill.slice(handoff).match(/^### .+$/gm)?.at(-1)).toBe('### Put simply');
expect(skill.slice(handoff).match(/^## Step /gm)?.length).toBe(1);
expect(skill).not.toContain('output the PR URL at the end');
});
}
});