Compare commits
200 Commits
8074e3b420
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0416bf343c | ||
|
|
c3e4f85903 | ||
|
|
52d9d0f9ce | ||
|
|
996ba82682 | ||
|
|
1f4152c894 | ||
|
|
02b481ee4c | ||
|
|
9c339c118f | ||
|
|
4790aac286 | ||
|
|
b2d92d6059 | ||
|
|
71887af2d3 | ||
|
|
5db9965962 | ||
|
|
e109e1ba5c | ||
|
|
3554594d8d | ||
|
|
a6c8cf0daf | ||
|
|
30a56d03e5 | ||
|
|
4734bd943f | ||
|
|
a1dd88579b | ||
|
|
759a289894 | ||
|
|
be3b5b0b60 | ||
|
|
fbf391684a | ||
|
|
65546a42b7 | ||
|
|
4e014d45c3 | ||
|
|
4f39de437f | ||
|
|
79ee6eb0dc | ||
|
|
c930c537bc | ||
|
|
f129a38704 | ||
|
|
4344081b54 | ||
|
|
52c5344ce5 | ||
|
|
35bd196790 | ||
|
|
65c8dc19d6 | ||
|
|
645a141d2d | ||
|
|
11d1980920 | ||
|
|
83879cfa9e | ||
|
|
972d8f3c12 | ||
|
|
4b1167025c | ||
|
|
23eb752e3b | ||
|
|
7aa1d0e322 | ||
|
|
a6dcd48da9 | ||
|
|
87958b0a2a | ||
|
|
ea061d868d | ||
|
|
6a03ca725e | ||
|
|
0cd7c15227 | ||
|
|
0cb43a4de4 | ||
|
|
cb663b620b | ||
|
|
0653af701c | ||
|
|
b1a96990c4 | ||
|
|
e46f855ab3 | ||
|
|
d838dd7127 | ||
|
|
02ee48911e | ||
|
|
6429b20974 | ||
|
|
dcf0be2998 | ||
|
|
efea81b487 | ||
|
|
491ca19a0b | ||
|
|
243b75e966 | ||
|
|
7693cc820c | ||
|
|
ba4af4179e | ||
|
|
d60ed18e0f | ||
|
|
94f4ba831b | ||
|
|
c4a113b855 | ||
|
|
5510d9d19d | ||
|
|
ca949aec46 | ||
|
|
9ceda6694d | ||
|
|
b0a1eafd8d | ||
|
|
b2c9ece9e4 | ||
|
|
24ca585fd0 | ||
|
|
c4e45b2841 | ||
|
|
51d878e117 | ||
|
|
cb991da84c | ||
|
|
28b78c4a32 | ||
|
|
6f47943369 | ||
|
|
8885543c25 | ||
|
|
2208aba3fb | ||
|
|
d3f462e518 | ||
|
|
9581e5d51a | ||
|
|
375277f86e | ||
|
|
c096488ba1 | ||
|
|
ab5fb734e5 | ||
|
|
d7e814c02c | ||
|
|
4268db8641 | ||
|
|
943bd38d19 | ||
|
|
16df7b783d | ||
|
|
24eb20f985 | ||
|
|
9f18cacbed | ||
|
|
737ddca884 | ||
|
|
0e8963591e | ||
|
|
492a0fc749 | ||
|
|
287c64faf1 | ||
|
|
31085e8c9f | ||
|
|
1a22e0cb41 | ||
|
|
f653b51dd7 | ||
|
|
2f66c7d30e | ||
|
|
3031c158e7 | ||
|
|
6aa932b349 | ||
|
|
fb23e2218b | ||
|
|
01d1c15d91 | ||
|
|
9622a1a572 | ||
|
|
e99a3da336 | ||
|
|
60e1d7bf64 | ||
|
|
3cfe25f97a | ||
|
|
ebb9df9780 | ||
|
|
d0ec1eebd7 | ||
|
|
19bb3a6b52 | ||
|
|
594114d671 | ||
|
|
0897b36cc1 | ||
|
|
81e822642e | ||
|
|
134cae216a | ||
|
|
2b5c7578d3 | ||
|
|
3778162920 | ||
|
|
8c3e92f936 | ||
|
|
25711fc16b | ||
|
|
e33979aacb | ||
|
|
31e2f823f7 | ||
|
|
ec5f4afcfb | ||
|
|
75640c6ecf | ||
|
|
69030599d3 | ||
|
|
adab08f804 | ||
|
|
3d59077a3c | ||
|
|
84acc82f8c | ||
|
|
a2ea1d65aa | ||
|
|
086eb908ee | ||
|
|
c138246db3 | ||
|
|
c7846c041c | ||
|
|
9b6bde95bc | ||
|
|
f625534ff0 | ||
|
|
3f59420b2b | ||
|
|
9730a923dd | ||
|
|
c7b2b5820b | ||
|
|
303fdbad6f | ||
|
|
c0a7f5fbfb | ||
|
|
5215956314 | ||
|
|
27b86da0aa | ||
|
|
2ce0166ea8 | ||
|
|
2d377532df | ||
|
|
3885802d79 | ||
|
|
f650fef1e5 | ||
|
|
dbc8849681 | ||
|
|
b17ba0c8dd | ||
|
|
eea797975b | ||
|
|
67e6a4afe6 | ||
|
|
9c01bfebc8 | ||
|
|
8ea69fc70f | ||
|
|
1bd816f5a6 | ||
|
|
5f3dcebfc3 | ||
|
|
ef9ec8bbbe | ||
|
|
14a97ed4ed | ||
|
|
3932aa65c2 | ||
|
|
9a77ffaa83 | ||
|
|
a9d5e9f6f8 | ||
|
|
f5b1103bf6 | ||
|
|
39707ce026 | ||
|
|
ff1705f26c | ||
|
|
14cab448cb | ||
|
|
973af81fa5 | ||
|
|
09890b5ea4 | ||
|
|
4fe61c643b | ||
|
|
665ffa9521 | ||
|
|
e558d716d8 | ||
|
|
cc403e7736 | ||
|
|
48edf6a94b | ||
|
|
27c406330a | ||
|
|
48aad2323d | ||
|
|
6c00f66894 | ||
|
|
90c98f5b47 | ||
|
|
a8cb851ba7 | ||
|
|
02947700ba | ||
|
|
e3ade4cca5 | ||
|
|
e9a0858d53 | ||
|
|
c84c33a1a7 | ||
|
|
09a47ac224 | ||
|
|
a791b9f49c | ||
|
|
351f770516 | ||
|
|
cc0110e577 | ||
|
|
8eff849e83 | ||
|
|
7439c227a9 | ||
|
|
887ab81898 | ||
|
|
ef6201b273 | ||
|
|
5af3c17522 | ||
|
|
7cb95260aa | ||
|
|
cf4a40a431 | ||
|
|
6c03c4f9dc | ||
|
|
4acf38f035 | ||
|
|
d6d7fb3c59 | ||
|
|
9e4587ceb4 | ||
|
|
72216fe7ce | ||
|
|
9807eb6bb0 | ||
|
|
7eb9686bfb | ||
|
|
3b9cea22bb | ||
|
|
e2a8b978f7 | ||
|
|
748d86cf10 | ||
|
|
060d5a40a4 | ||
|
|
3cb4f32634 | ||
|
|
e00d780940 | ||
|
|
df7556c0f3 | ||
|
|
07f8defad0 | ||
|
|
1739c2ff58 | ||
|
|
e6eaa10c16 | ||
|
|
110db662a9 | ||
|
|
9998b3ed25 | ||
|
|
d27a389a21 | ||
|
|
11a6be4b45 |
@@ -1,12 +1,10 @@
|
|||||||
{
|
{
|
||||||
"enabledMcpjsonServers": [
|
"enabledMcpjsonServers": ["storkit"],
|
||||||
"story-kit"
|
|
||||||
],
|
|
||||||
"permissions": {
|
"permissions": {
|
||||||
"allow": [
|
"allow": [
|
||||||
"Bash(./server/target/debug/story-kit:*)",
|
"Bash(./server/target/debug/storkit:*)",
|
||||||
"Bash(./target/debug/story-kit:*)",
|
"Bash(./target/debug/storkit:*)",
|
||||||
"Bash(STORYKIT_PORT=*)",
|
"Bash(STORKIT_PORT=*)",
|
||||||
"Bash(cargo build:*)",
|
"Bash(cargo build:*)",
|
||||||
"Bash(cargo check:*)",
|
"Bash(cargo check:*)",
|
||||||
"Bash(cargo clippy:*)",
|
"Bash(cargo clippy:*)",
|
||||||
@@ -56,7 +54,7 @@
|
|||||||
"WebFetch(domain:portkey.ai)",
|
"WebFetch(domain:portkey.ai)",
|
||||||
"WebFetch(domain:www.shuttle.dev)",
|
"WebFetch(domain:www.shuttle.dev)",
|
||||||
"WebSearch",
|
"WebSearch",
|
||||||
"mcp__story-kit__*",
|
"mcp__storkit__*",
|
||||||
"Edit",
|
"Edit",
|
||||||
"Write",
|
"Write",
|
||||||
"Bash(find *)",
|
"Bash(find *)",
|
||||||
@@ -72,4 +70,4 @@
|
|||||||
"Bash(npm run dev:*)"
|
"Bash(npm run dev:*)"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -5,9 +5,9 @@
|
|||||||
# Local environment (secrets)
|
# Local environment (secrets)
|
||||||
.env
|
.env
|
||||||
|
|
||||||
# App specific (root-level; story-kit subdirectory patterns live in .story_kit/.gitignore)
|
# App specific (root-level; storkit subdirectory patterns live in .storkit/.gitignore)
|
||||||
store.json
|
store.json
|
||||||
.story_kit_port
|
.storkit_port
|
||||||
|
|
||||||
# Rust stuff
|
# Rust stuff
|
||||||
target
|
target
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ When you start a new session with this project:
|
|||||||
|
|
||||||
1. **Check for MCP Tools:** Read `.mcp.json` to discover the MCP server endpoint. Then list available tools by calling:
|
1. **Check for MCP Tools:** Read `.mcp.json` to discover the MCP server endpoint. Then list available tools by calling:
|
||||||
```bash
|
```bash
|
||||||
curl -s "$(jq -r '.mcpServers["story-kit"].url' .mcp.json)" \
|
curl -s "$(jq -r '.mcpServers["storkit"].url' .mcp.json)" \
|
||||||
-H 'Content-Type: application/json' \
|
-H 'Content-Type: application/json' \
|
||||||
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'
|
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'
|
||||||
```
|
```
|
||||||
61
.storkit/bot.toml.example
Normal file
61
.storkit/bot.toml.example
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
homeserver = "https://matrix.example.com"
|
||||||
|
username = "@botname:example.com"
|
||||||
|
password = "your-bot-password"
|
||||||
|
|
||||||
|
# List one or more rooms to listen in. Use a single-element list for one room.
|
||||||
|
room_ids = ["!roomid:example.com"]
|
||||||
|
|
||||||
|
# Optional: the deprecated single-room key is still accepted for backwards compat.
|
||||||
|
# room_id = "!roomid:example.com"
|
||||||
|
|
||||||
|
allowed_users = ["@youruser:example.com"]
|
||||||
|
enabled = false
|
||||||
|
|
||||||
|
# Maximum conversation turns to remember per room (default: 20).
|
||||||
|
# history_size = 20
|
||||||
|
|
||||||
|
# Rooms where the bot responds to all messages (not just addressed ones).
|
||||||
|
# This list is updated automatically when users toggle ambient mode at runtime.
|
||||||
|
# ambient_rooms = ["!roomid:example.com"]
|
||||||
|
|
||||||
|
# ── WhatsApp Business API ──────────────────────────────────────────────
|
||||||
|
# Set transport = "whatsapp" to use WhatsApp instead of Matrix.
|
||||||
|
# The webhook endpoint will be available at /webhook/whatsapp.
|
||||||
|
# You must configure this URL in the Meta Developer Dashboard.
|
||||||
|
#
|
||||||
|
# transport = "whatsapp"
|
||||||
|
# whatsapp_phone_number_id = "123456789012345"
|
||||||
|
# whatsapp_access_token = "EAAx..."
|
||||||
|
# whatsapp_verify_token = "my-secret-verify-token"
|
||||||
|
#
|
||||||
|
# ── 24-hour messaging window & notification templates ─────────────────
|
||||||
|
# WhatsApp only allows free-form text messages within 24 hours of the last
|
||||||
|
# inbound message from a user. For proactive pipeline notifications sent
|
||||||
|
# after the window expires, an approved Meta message template is used.
|
||||||
|
#
|
||||||
|
# Register the template in the Meta Business Manager:
|
||||||
|
# 1. Go to Business Settings → WhatsApp → Message Templates → Create.
|
||||||
|
# 2. Category: UTILITY
|
||||||
|
# 3. Template name: pipeline_notification (or your chosen name below)
|
||||||
|
# 4. Language: English (en_US)
|
||||||
|
# 5. Body text (example):
|
||||||
|
# Story *{{1}}* has moved to *{{2}}*.
|
||||||
|
# Where {{1}} = story name, {{2}} = pipeline stage.
|
||||||
|
# 6. Submit for review. Meta typically approves utility templates within
|
||||||
|
# minutes; transactional categories may take longer.
|
||||||
|
#
|
||||||
|
# Once approved, set the name below (default: "pipeline_notification"):
|
||||||
|
# whatsapp_notification_template = "pipeline_notification"
|
||||||
|
|
||||||
|
# ── Slack Bot API ─────────────────────────────────────────────────────
|
||||||
|
# Set transport = "slack" to use Slack instead of Matrix.
|
||||||
|
# The webhook endpoint will be available at /webhook/slack.
|
||||||
|
# Configure this URL in the Slack App → Event Subscriptions → Request URL.
|
||||||
|
#
|
||||||
|
# Required Slack App scopes: chat:write, chat:update
|
||||||
|
# Subscribe to bot events: message.channels, message.groups, message.im
|
||||||
|
#
|
||||||
|
# transport = "slack"
|
||||||
|
# slack_bot_token = "xoxb-..."
|
||||||
|
# slack_signing_secret = "your-signing-secret"
|
||||||
|
# slack_channel_ids = ["C01ABCDEF"]
|
||||||
28
.storkit/problems.md
Normal file
28
.storkit/problems.md
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
# Problems
|
||||||
|
|
||||||
|
Recurring issues observed during pipeline operation. Review periodically and create stories for systemic problems.
|
||||||
|
|
||||||
|
## 2026-03-18: Stories graduating to "done" with empty merges (7 of 10)
|
||||||
|
|
||||||
|
Pipeline allows stories to move through coding → QA → merge → done without any actual code changes landing on master. The squash-merge produces an empty diff but the pipeline still marks the story as done. Affected stories: 247, 273, 274, 278, 279, 280, 92. Only 266, 271, 277, and 281 actually shipped code. Root cause: no check that the merge commit contains a non-empty diff. Filed bug 283 for the manual_qa gate issue specifically, but the empty-merge-to-done problem is broader and needs its own fix.
|
||||||
|
|
||||||
|
## 2026-03-18: Agent committed directly to master instead of worktree
|
||||||
|
|
||||||
|
Multiple agents have committed directly to master instead of their worktree/feature branch:
|
||||||
|
|
||||||
|
- Commit `5f4591f` ("fix: update should_commit_stage test to match 5_done") — likely mergemaster
|
||||||
|
- Commit `a32cfbd` ("Add bot-level command registry with help command") — story 285 coder committed code + Cargo.lock directly to master
|
||||||
|
|
||||||
|
Agents should only commit to their feature branch or merge-queue branch, never to master directly. Suspect agents are running `git commit` in the project root instead of the worktree directory. This can also revert uncommitted fixes on master (e.g. project.toml pkill fix was overwritten). Frequency: at least 2 confirmed cases. This is a recurring and serious problem — needs a guard in the server or agent prompts.
|
||||||
|
|
||||||
|
## 2026-03-19: Auto-assign re-assigns mergemaster to failed merge stories in a loop
|
||||||
|
|
||||||
|
After bug 295 fix (`auto_assign_available_work` after every pipeline advance), mergemaster gets re-assigned to stories that already have a merge failure flag. Story 310 had an empty diff merge failure — mergemaster correctly reported the failure, but auto-assign immediately re-assigned mergemaster to the same story, creating an infinite retry loop. The auto-assign logic needs to check for the `merge_failure` front matter flag before re-assigning agents to stories in `4_merge/`.
|
||||||
|
|
||||||
|
## 2026-03-19: Coder produces no code (complete ghost — story 310)
|
||||||
|
|
||||||
|
Story 310 (Bot delete command) went through the full pipeline — coder session ran, passed QA/gates, moved to merge — but the coder produced zero code. No commits on the feature branch, no commits on master. The entire agent session was a no-op. This is different from the "committed to master instead of worktree" problem — in this case, the coder simply did nothing. Need to investigate the coder logs to understand what happened. The empty-diff merge check would catch this at merge time, but ideally the server should detect "coder finished with no commits on feature branch" at the gate-check stage and fail early.
|
||||||
|
|
||||||
|
## 2026-03-19: Auto-assign assigns mergemaster to coding-stage stories
|
||||||
|
|
||||||
|
Auto-assign picked mergemaster for story 310 which was in `2_current/`. Mergemaster should only work on stories in `4_merge/`. The `auto_assign_available_work` function doesn't enforce that the agent's configured stage matches the pipeline stage of the story it's being assigned to. Story 279 (auto-assign respects agent stage from front matter) was supposed to fix this, but the check may only apply to front-matter preferences, not the fallback assignment path.
|
||||||
@@ -25,45 +25,6 @@ path = "."
|
|||||||
setup = ["mkdir -p frontend/dist", "cargo check"]
|
setup = ["mkdir -p frontend/dist", "cargo check"]
|
||||||
teardown = []
|
teardown = []
|
||||||
|
|
||||||
[[agent]]
|
|
||||||
name = "supervisor"
|
|
||||||
stage = "other"
|
|
||||||
role = "Coordinates work, reviews PRs, decomposes stories."
|
|
||||||
model = "opus"
|
|
||||||
max_turns = 200
|
|
||||||
max_budget_usd = 15.00
|
|
||||||
prompt = """You are the supervisor for story {{story_id}}. Your job is to coordinate coder agents to implement this story.
|
|
||||||
|
|
||||||
Read CLAUDE.md first, then .story_kit/README.md to understand the dev process (SDTW). You are responsible for ensuring coders follow this process.
|
|
||||||
|
|
||||||
## Your MCP Tools
|
|
||||||
You have these tools via the story-kit MCP server:
|
|
||||||
- start_agent(story_id, agent_name) - Start a coder agent on a story
|
|
||||||
- wait_for_agent(story_id, agent_name, timeout_ms) - Block until the agent reaches a terminal state (completed/failed). Returns final status including completion report with gates_passed.
|
|
||||||
- get_agent_output(story_id, agent_name, timeout_ms) - Poll agent output (returns recent events, call repeatedly)
|
|
||||||
- list_agents() - See all running agents and their status
|
|
||||||
- stop_agent(story_id, agent_name) - Stop a running agent
|
|
||||||
- get_story_todos(story_id) - Get unchecked acceptance criteria for a story in work/2_current/
|
|
||||||
- ensure_acceptance(story_id) - Check if a story passes acceptance gates
|
|
||||||
|
|
||||||
## Your Workflow
|
|
||||||
1. Read CLAUDE.md and .story_kit/README.md to understand the project and dev process
|
|
||||||
2. Read the story file from .story_kit/work/ to understand requirements
|
|
||||||
3. Move it to work/2_current/ if it is in work/1_backlog/
|
|
||||||
4. Start coder-1 on the story: call start_agent with story_id="{{story_id}}" and agent_name="coder-1"
|
|
||||||
5. Wait for completion: call wait_for_agent with story_id="{{story_id}}" and agent_name="coder-1". The server automatically runs acceptance gates (cargo clippy + tests) when the coder process exits. wait_for_agent returns when the coder reaches a terminal state.
|
|
||||||
6. Check the result: inspect the "completion" field in the wait_for_agent response — if gates_passed is true, the work is done; if false, review the gate_output and decide whether to start a fresh coder.
|
|
||||||
7. If the agent gets stuck, stop it and start a fresh agent.
|
|
||||||
8. STOP here. Do NOT accept the story or merge to master. Report the status to the human for final review and acceptance.
|
|
||||||
|
|
||||||
## Rules
|
|
||||||
- Do NOT implement code yourself - delegate to coder agents
|
|
||||||
- Only run one coder at a time per story
|
|
||||||
- Focus on coordination, monitoring, and quality review
|
|
||||||
- Never accept stories or merge to master - that is the human's job
|
|
||||||
- Your job ends when the coder's completion report shows gates_passed=true and you have reported the result"""
|
|
||||||
system_prompt = "You are a supervisor agent. Read CLAUDE.md and .story_kit/README.md first to understand the project dev process. Use MCP tools to coordinate sub-agents. Never implement code directly - always delegate to coder agents and monitor their progress. Use wait_for_agent to block until the coder finishes — the server automatically runs acceptance gates when the agent process exits. Never accept stories or merge to master - get all gates green and report to the human."
|
|
||||||
|
|
||||||
[[agent]]
|
[[agent]]
|
||||||
name = "coder-1"
|
name = "coder-1"
|
||||||
stage = "coder"
|
stage = "coder"
|
||||||
@@ -127,7 +88,7 @@ Read CLAUDE.md first, then .story_kit/README.md to understand the dev process.
|
|||||||
- URL to visit in the browser
|
- URL to visit in the browser
|
||||||
- Things to check in the UI
|
- Things to check in the UI
|
||||||
- curl commands to exercise relevant API endpoints
|
- curl commands to exercise relevant API endpoints
|
||||||
- Kill the test server when done: `pkill -f 'target.*story-kit' || true` (NEVER use `pkill -f story-kit` — it kills the vite dev server)
|
- Kill the test server when done: `pkill -f 'target.*storkit' || true` (NEVER use `pkill -f storkit` — it kills the vite dev server)
|
||||||
|
|
||||||
### 4. Produce Structured Report
|
### 4. Produce Structured Report
|
||||||
Print your QA report to stdout before your process exits. The server will automatically run acceptance gates. Use this format:
|
Print your QA report to stdout before your process exits. The server will automatically run acceptance gates. Use this format:
|
||||||
@@ -204,7 +165,7 @@ Read CLAUDE.md first, then .story_kit/README.md to understand the dev process.
|
|||||||
- URL to visit in the browser
|
- URL to visit in the browser
|
||||||
- Things to check in the UI
|
- Things to check in the UI
|
||||||
- curl commands to exercise relevant API endpoints
|
- curl commands to exercise relevant API endpoints
|
||||||
- Kill the test server when done: `pkill -f 'target.*story-kit' || true` (NEVER use `pkill -f story-kit` — it kills the vite dev server)
|
- Kill the test server when done: `pkill -f 'target.*storkit' || true` (NEVER use `pkill -f storkit` — it kills the vite dev server)
|
||||||
|
|
||||||
### 4. Produce Structured Report
|
### 4. Produce Structured Report
|
||||||
Print your QA report to stdout before your process exits. The server will automatically run acceptance gates. Use this format:
|
Print your QA report to stdout before your process exits. The server will automatically run acceptance gates. Use this format:
|
||||||
44
.storkit/specs/functional/SLACK_SETUP.md
Normal file
44
.storkit/specs/functional/SLACK_SETUP.md
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
# Slack Integration Setup
|
||||||
|
|
||||||
|
## Bot Configuration
|
||||||
|
|
||||||
|
Slack integration is configured via `bot.toml` in the project's `.story_kit/` directory:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
transport = "slack"
|
||||||
|
display_name = "Storkit"
|
||||||
|
slack_bot_token = "xoxb-..."
|
||||||
|
slack_signing_secret = "..."
|
||||||
|
slack_channel_ids = ["C01ABCDEF"]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Slack App Configuration
|
||||||
|
|
||||||
|
### Event Subscriptions
|
||||||
|
|
||||||
|
1. In your Slack app settings, enable **Event Subscriptions**.
|
||||||
|
2. Set the **Request URL** to: `https://<your-host>/webhook/slack`
|
||||||
|
3. Subscribe to the `message.channels` and `message.im` bot events.
|
||||||
|
|
||||||
|
### Slash Commands
|
||||||
|
|
||||||
|
Slash commands provide quick access to pipeline commands without mentioning the bot.
|
||||||
|
|
||||||
|
1. In your Slack app settings, go to **Slash Commands**.
|
||||||
|
2. Create the following commands, all pointing to the same **Request URL**: `https://<your-host>/webhook/slack/command`
|
||||||
|
|
||||||
|
| Command | Description |
|
||||||
|
|---------|-------------|
|
||||||
|
| `/storkit-status` | Show pipeline status and agent availability |
|
||||||
|
| `/storkit-cost` | Show token spend: 24h total, top stories, and breakdown |
|
||||||
|
| `/storkit-show` | Display the full text of a work item (e.g. `/storkit-show 42`) |
|
||||||
|
| `/storkit-git` | Show git status: branch, changes, ahead/behind |
|
||||||
|
| `/storkit-htop` | Show system and agent process dashboard |
|
||||||
|
|
||||||
|
All slash command responses are **ephemeral** — only the user who invoked the command sees the response.
|
||||||
|
|
||||||
|
### OAuth & Permissions
|
||||||
|
|
||||||
|
Required bot token scopes:
|
||||||
|
- `chat:write` — send messages
|
||||||
|
- `commands` — handle slash commands
|
||||||
@@ -118,8 +118,8 @@ To support both Remote and Local models, the system implements a `ModelProvider`
|
|||||||
|
|
||||||
Multiple instances can run simultaneously in different worktrees. To avoid port conflicts:
|
Multiple instances can run simultaneously in different worktrees. To avoid port conflicts:
|
||||||
|
|
||||||
- **Backend:** Set `STORYKIT_PORT` to a unique port (default is 3001). Example: `STORYKIT_PORT=3002 cargo run`
|
- **Backend:** Set `STORKIT_PORT` to a unique port (default is 3001). Example: `STORKIT_PORT=3002 cargo run`
|
||||||
- **Frontend:** Run `npm run dev` from `frontend/`. It auto-selects the next unused port. It reads `STORYKIT_PORT` to know which backend to talk to, so export it before running: `export STORYKIT_PORT=3002 && cd frontend && npm run dev`
|
- **Frontend:** Run `npm run dev` from `frontend/`. It auto-selects the next unused port. It reads `STORKIT_PORT` to know which backend to talk to, so export it before running: `export STORKIT_PORT=3002 && cd frontend && npm run dev`
|
||||||
|
|
||||||
When running in a worktree, use a port that won't conflict with the main instance (3001). Ports 3002+ are good choices.
|
When running in a worktree, use a port that won't conflict with the main instance (3001). Ports 3002+ are good choices.
|
||||||
|
|
||||||
@@ -127,4 +127,4 @@ When running in a worktree, use a port that won't conflict with the main instanc
|
|||||||
1. **Project Scope:** The application must strictly enforce that it does not read/write outside the `project_root` selected by the user.
|
1. **Project Scope:** The application must strictly enforce that it does not read/write outside the `project_root` selected by the user.
|
||||||
2. **Human in the Loop:**
|
2. **Human in the Loop:**
|
||||||
* Shell commands that modify state (non-readonly) should ideally require a UI confirmation (configurable).
|
* Shell commands that modify state (non-readonly) should ideally require a UI confirmation (configurable).
|
||||||
* File writes must be confirmed or revertible.
|
* File writes must be confirmed or revertible.
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
---
|
||||||
|
name: "Run storkit container under gVisor (runsc) runtime"
|
||||||
|
---
|
||||||
|
|
||||||
|
# Story 360: Run storkit container under gVisor (runsc) runtime
|
||||||
|
|
||||||
|
## User Story
|
||||||
|
|
||||||
|
As a storkit operator, I want the container to run under gVisor so that even if a malicious codebase escapes the container's process namespace, it cannot make raw syscalls to the host kernel.
|
||||||
|
|
||||||
|
## Acceptance Criteria
|
||||||
|
|
||||||
|
- [ ] docker-compose.yml specifies runtime: runsc
|
||||||
|
- [ ] PTY-based agent spawning (Claude Code via PTY) works correctly under runsc
|
||||||
|
- [ ] rebuild_and_restart (exec() replacement) works correctly under runsc
|
||||||
|
- [ ] Rust compilation inside the container completes successfully under runsc
|
||||||
|
- [ ] Document host setup requirement: runsc must be installed and registered in /etc/docker/daemon.json
|
||||||
|
|
||||||
|
## Out of Scope
|
||||||
|
|
||||||
|
- TBD
|
||||||
@@ -0,0 +1,212 @@
|
|||||||
|
---
|
||||||
|
name: "Evaluate Docker/OrbStack for agent isolation and resource limiting"
|
||||||
|
agent: "coder-opus"
|
||||||
|
---
|
||||||
|
|
||||||
|
# Spike 329: Evaluate Docker/OrbStack for agent isolation and resource limiting
|
||||||
|
|
||||||
|
## Question
|
||||||
|
|
||||||
|
Investigate running the entire storkit system (server, Matrix bot, agents, web UI) inside a single Docker container, using OrbStack as the macOS runtime for better performance. The goal is to isolate storkit from the host machine — not to isolate agents from each other.
|
||||||
|
|
||||||
|
**Important context:** Storkit developing itself is the dogfood edge case. The primary use case is storkit managing agents that develop *other* projects, driven by multiple users in chat rooms (Matrix, WhatsApp, Slack). Isolation must account for untrusted codebases, multi-user command surfaces, and running against arbitrary repos — not just the single-developer self-hosted setup.
|
||||||
|
|
||||||
|
Currently storkit runs as bare processes on the host with full filesystem and network access. A single container would provide:
|
||||||
|
|
||||||
|
1. **Host isolation** — storkit can't touch anything outside the container
|
||||||
|
2. **Clean install/uninstall** — `docker run` to start, `docker rm` to remove
|
||||||
|
3. **Reproducible environment** — same container works on any machine
|
||||||
|
4. **Distributable product** — `docker pull storkit` for new users
|
||||||
|
5. **Resource limits** — cap total CPU/memory for the whole system
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
```
|
||||||
|
Docker Container (single)
|
||||||
|
├── storkit server
|
||||||
|
│ ├── Matrix bot
|
||||||
|
│ ├── WhatsApp webhook
|
||||||
|
│ ├── Slack webhook
|
||||||
|
│ ├── Web UI
|
||||||
|
│ └── MCP server
|
||||||
|
├── Agent processes (coder-1, coder-2, coder-opus, qa, mergemaster)
|
||||||
|
├── Rust toolchain + Node.js + Claude Code CLI
|
||||||
|
└── /workspace (bind-mounted project repo from host)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Key questions to answer:
|
||||||
|
|
||||||
|
- **Performance**: How much slower are cargo builds inside the container on macOS? Compare Docker Desktop vs OrbStack for bind-mounted volumes.
|
||||||
|
- **Dockerfile**: What's the minimal image for the full stack? Rust toolchain + Node.js + Claude Code CLI + cargo-nextest + git.
|
||||||
|
- **Bind mounts**: The project repo is bind-mounted from the host. Any filesystem performance concerns with OrbStack?
|
||||||
|
- **Networking**: Container exposes web UI port (3000). Matrix/WhatsApp/Slack connect outbound. Any issues?
|
||||||
|
- **API key**: Pass ANTHROPIC_API_KEY as env var to the container.
|
||||||
|
- **Git**: Git operations happen inside the container on the bind-mounted repo. Commits are visible on the host immediately.
|
||||||
|
- **Cargo cache**: Use a named Docker volume for ~/.cargo/registry so dependencies persist across container restarts.
|
||||||
|
- **Claude Code state**: Where does Claude Code store its session data? Needs to persist or be in a volume.
|
||||||
|
- **OrbStack vs Docker Desktop**: Is OrbStack required for acceptable performance, or does Docker Desktop work too?
|
||||||
|
- **Server restart**: Does `rebuild_and_restart` work inside a container (re-exec with new binary)?
|
||||||
|
|
||||||
|
## Deliverable:
|
||||||
|
A proof-of-concept Dockerfile, docker-compose.yml, and a short write-up with findings and performance benchmarks.
|
||||||
|
|
||||||
|
## Hypothesis
|
||||||
|
|
||||||
|
A single Docker container running the entire storkit stack (server + agents + toolchain) on OrbStack will provide acceptable performance for the primary use case (developing other projects) while giving us host isolation, resource limits, and a distributable product. OrbStack's VirtioFS should make bind-mounted filesystem performance close to native.
|
||||||
|
|
||||||
|
## Timebox
|
||||||
|
|
||||||
|
4 hours
|
||||||
|
|
||||||
|
## Investigation Plan
|
||||||
|
|
||||||
|
1. Audit storkit's runtime dependencies (Rust toolchain, Node.js, Claude Code CLI, cargo-nextest, git)
|
||||||
|
2. Determine where Claude Code stores session state (~/.claude)
|
||||||
|
3. Analyze how rebuild_and_restart works (exec() replacement) and whether it's container-compatible
|
||||||
|
4. Draft a multi-stage Dockerfile and docker-compose.yml
|
||||||
|
5. Document findings for each key question
|
||||||
|
6. Provide recommendation and follow-up stories
|
||||||
|
|
||||||
|
## Findings
|
||||||
|
|
||||||
|
### 1. Dockerfile: Minimal image for the full stack
|
||||||
|
|
||||||
|
**Result:** Multi-stage Dockerfile created at `docker/Dockerfile`.
|
||||||
|
|
||||||
|
The image requires these runtime components:
|
||||||
|
- **Rust 1.90+ toolchain** (~1.5 GB) — needed at runtime for `rebuild_and_restart` and agent-driven `cargo clippy`, `cargo test`, etc.
|
||||||
|
- **Node.js 22.x** (~100 MB) — needed at runtime for Claude Code CLI (npm global package)
|
||||||
|
- **Claude Code CLI** (`@anthropic-ai/claude-code`) — npm global, spawned by storkit via PTY
|
||||||
|
- **cargo-nextest** — pre-built binary, used by acceptance gates
|
||||||
|
- **git** — used extensively by agents and worktree management
|
||||||
|
- **System libs:** libssl3, ca-certificates
|
||||||
|
|
||||||
|
The build stage compiles the storkit binary with embedded frontend assets (build.rs runs `npm run build`). The runtime stage is based on `debian:bookworm-slim` but still needs Rust + Node because agents use them at runtime.
|
||||||
|
|
||||||
|
**Total estimated image size:** ~3-4 GB (dominated by the Rust toolchain). This is large but acceptable for a development tool that runs locally.
|
||||||
|
|
||||||
|
### 2. Bind mounts and filesystem performance
|
||||||
|
|
||||||
|
**OrbStack** uses Apple's VirtioFS for bind mounts, which is near-native speed. This is a significant advantage over Docker Desktop's older options:
|
||||||
|
|
||||||
|
| Runtime | Bind mount driver | Performance | Notes |
|
||||||
|
|---------|------------------|-------------|-------|
|
||||||
|
| OrbStack | VirtioFS (native) | ~95% native | Default, no config needed |
|
||||||
|
| Docker Desktop | VirtioFS | ~85-90% native | Must enable in settings (Docker Desktop 4.15+) |
|
||||||
|
| Docker Desktop | gRPC-FUSE (legacy) | ~40-60% native | Default on older versions, very slow for cargo builds |
|
||||||
|
| Docker Desktop | osxfs (deprecated) | ~30-50% native | Ancient default, unusable for Rust projects |
|
||||||
|
|
||||||
|
**For cargo builds on bind-mounted volumes:** The critical path is `target/` directory I/O. Since `target/` lives inside the bind-mounted project, large Rust projects will see a noticeable slowdown on Docker Desktop with gRPC-FUSE. OrbStack's VirtioFS makes this tolerable.
|
||||||
|
|
||||||
|
**Mitigation option:** Keep `target/` in a named Docker volume instead of on the bind mount. This gives native Linux filesystem speed for compilation artifacts while the source code remains bind-mounted. The trade-off is that `target/` won't be visible on the host, which is fine since it's a build cache.
|
||||||
|
|
||||||
|
### 3. Claude Code state persistence
|
||||||
|
|
||||||
|
Claude Code stores all state in `~/.claude/`:
|
||||||
|
- `sessions/` — conversation transcripts (used by `--resume`)
|
||||||
|
- `projects/` — per-project settings and memory
|
||||||
|
- `history.jsonl` — command history
|
||||||
|
- `session-env/` — environment snapshots
|
||||||
|
- `settings.json` — global preferences
|
||||||
|
|
||||||
|
**Solution:** Mount `~/.claude` as a named Docker volume (`claude-state`). This persists across container restarts. Session resumption (`--resume <session_id>`) will work correctly since the session files are preserved.
|
||||||
|
|
||||||
|
### 4. Networking
|
||||||
|
|
||||||
|
**Straightforward.** The container exposes port 3001 for the web UI + MCP endpoint. All chat integrations (Matrix, Slack, WhatsApp) connect outbound from the container, which works by default in Docker's bridge networking. No special configuration needed.
|
||||||
|
|
||||||
|
Port mapping: `3001:3001` in docker-compose.yml. Users access the web UI at `http://localhost:3001`.
|
||||||
|
|
||||||
|
### 5. API key handling
|
||||||
|
|
||||||
|
**Simple.** Pass `ANTHROPIC_API_KEY` as an environment variable via docker-compose.yml. The storkit server already reads it from the environment. Claude Code also reads `ANTHROPIC_API_KEY` from the environment.
|
||||||
|
|
||||||
|
### 6. Git operations on bind-mounted repos
|
||||||
|
|
||||||
|
**Works correctly.** Git operations inside the container on a bind-mounted volume are immediately visible on the host (and vice versa). The key considerations:
|
||||||
|
|
||||||
|
- **Git config:** The container runs as root, so `git config --global user.name/email` needs to be set inside the container (or mounted from host). Without this, commits have no author identity.
|
||||||
|
- **File ownership:** OrbStack maps the container's root user to the host user automatically (uid remapping). Docker Desktop does not — files created by the container may be owned by root on the host. OrbStack handles this transparently.
|
||||||
|
- **Worktrees:** `git worktree add` inside the container creates worktrees within the bind-mounted repo, which are visible on the host. This is correct behavior.
|
||||||
|
|
||||||
|
### 7. Cargo cache
|
||||||
|
|
||||||
|
**Named Docker volumes** for `/usr/local/cargo/registry` and `/usr/local/cargo/git` persist downloaded crates across container restarts. First `cargo build` downloads everything; subsequent builds use the cached crates. This is a standard Docker pattern.
|
||||||
|
|
||||||
|
### 8. OrbStack vs Docker Desktop
|
||||||
|
|
||||||
|
| Capability | OrbStack | Docker Desktop |
|
||||||
|
|-----------|----------|----------------|
|
||||||
|
| **VirtioFS (fast mounts)** | Default, always on | Must enable manually |
|
||||||
|
| **UID remapping** | Automatic (root → host user) | Manual or not available |
|
||||||
|
| **Memory usage** | ~50% less than Docker Desktop | Higher baseline overhead |
|
||||||
|
| **Startup time** | 1-2 seconds | 10-30 seconds |
|
||||||
|
| **License** | Free for personal use, paid for teams | Free for personal/small business, paid for enterprise |
|
||||||
|
| **Linux compatibility** | Full (Rosetta for x86 on ARM) | Full (QEMU for x86 on ARM) |
|
||||||
|
|
||||||
|
**Verdict:** OrbStack is strongly recommended for macOS. Docker Desktop works but requires VirtioFS to be enabled manually and has worse file ownership semantics. On Linux hosts, Docker Engine (not Desktop) is native and has none of these issues.
|
||||||
|
|
||||||
|
### 9. rebuild_and_restart inside a container
|
||||||
|
|
||||||
|
**Works with caveats.** The current implementation:
|
||||||
|
1. Runs `cargo build` from `CARGO_MANIFEST_DIR` (baked at compile time to `/app/server`)
|
||||||
|
2. Calls `exec()` to replace the process with the new binary
|
||||||
|
|
||||||
|
Inside a container, `exec()` works fine — it replaces the PID 1 process. However:
|
||||||
|
- The source tree must exist at `/app` inside the container (the path baked into the binary)
|
||||||
|
- The Rust toolchain must be available at runtime
|
||||||
|
- If the container is configured with `restart: unless-stopped`, a crash during rebuild could cause a restart loop
|
||||||
|
|
||||||
|
**The Dockerfile handles this** by copying the full source tree into `/app` in the runtime stage and including the Rust toolchain.
|
||||||
|
|
||||||
|
**Future improvement:** For the storkit-developing-itself case, mount the source tree as a volume at `/app` so code changes on the host are immediately available for rebuild. For the primary use case (developing other projects), the baked-in source is fine — the server doesn't change.
|
||||||
|
|
||||||
|
### 10. Multi-user / untrusted codebase considerations
|
||||||
|
|
||||||
|
The single-container model provides **host isolation** but no **agent-to-agent isolation**:
|
||||||
|
- All agents share the same filesystem, network, and process namespace
|
||||||
|
- A malicious codebase could interfere with other agents or the storkit server itself
|
||||||
|
- This is acceptable as a first step since the primary threat model is "storkit shouldn't wreck the host"
|
||||||
|
|
||||||
|
For true multi-tenant isolation (multiple untrusted projects), a future architecture could:
|
||||||
|
- Run one container per project (each with its own bind mount)
|
||||||
|
- Use Docker's `--read-only` with specific writable mounts
|
||||||
|
- Apply seccomp/AppArmor profiles to limit syscalls
|
||||||
|
|
||||||
|
### 11. Image distribution
|
||||||
|
|
||||||
|
The single-container approach enables simple distribution:
|
||||||
|
```
|
||||||
|
docker pull ghcr.io/crashlabs/storkit:latest
|
||||||
|
docker run -e ANTHROPIC_API_KEY=sk-ant-... -v /my/project:/workspace -p 3001:3001 storkit
|
||||||
|
```
|
||||||
|
|
||||||
|
This is a massive UX improvement over "install Rust, install Node, install Claude Code, clone the repo, cargo build, etc."
|
||||||
|
|
||||||
|
## Recommendation
|
||||||
|
|
||||||
|
**Proceed with implementation.** The single-container Docker approach is viable and solves the stated goals:
|
||||||
|
|
||||||
|
1. **Host isolation** — achieved via standard Docker containerization
|
||||||
|
2. **Clean install/uninstall** — `docker compose up` / `docker compose down -v`
|
||||||
|
3. **Reproducible environment** — Dockerfile pins all versions
|
||||||
|
4. **Distributable product** — `docker pull` for new users
|
||||||
|
5. **Resource limits** — `deploy.resources.limits` in compose
|
||||||
|
|
||||||
|
### Follow-up stories to create:
|
||||||
|
|
||||||
|
1. **Story: Implement Docker container build and CI** — Set up automated image builds, push to registry, test that the image works end-to-end with a sample project.
|
||||||
|
|
||||||
|
2. **Story: Target directory optimization** — Move `target/` to a named volume to avoid bind mount I/O overhead for cargo builds. Benchmark the improvement.
|
||||||
|
|
||||||
|
3. **Story: Git identity in container** — Configure git user.name/email inside the container (from env vars or mounted .gitconfig).
|
||||||
|
|
||||||
|
4. **Story: Per-project container isolation** — For multi-tenant deployments, run one storkit container per project with tighter security (read-only root, seccomp, no-new-privileges).
|
||||||
|
|
||||||
|
5. **Story: Health endpoint** — Add a `/health` HTTP endpoint to the storkit server for the Docker healthcheck.
|
||||||
|
|
||||||
|
### Risks and open questions:
|
||||||
|
|
||||||
|
- **Image size (~3-4 GB):** Acceptable for a dev tool but worth optimizing later. The Rust toolchain dominates.
|
||||||
|
- **Rust toolchain at runtime:** Required for rebuild_and_restart and agent cargo commands. Cannot be eliminated without changing the architecture.
|
||||||
|
- **Claude Code CLI updates:** The CLI version is pinned at image build time. Users need to rebuild the image to get updates. Could use a volume mount for the npm global dir to allow in-place updates.
|
||||||
@@ -10,7 +10,7 @@ The `prompt_permission` MCP tool returns plain text ("Permission granted for '..
|
|||||||
|
|
||||||
## How to Reproduce
|
## How to Reproduce
|
||||||
|
|
||||||
1. Start the story-kit server and open the web UI
|
1. Start the storkit server and open the web UI
|
||||||
2. Chat with the claude-code-pty model
|
2. Chat with the claude-code-pty model
|
||||||
3. Ask it to do something that requires a tool NOT in `.claude/settings.json` allow list (e.g. `wc -l /etc/hosts`, or WebFetch to a non-allowed domain)
|
3. Ask it to do something that requires a tool NOT in `.claude/settings.json` allow list (e.g. `wc -l /etc/hosts`, or WebFetch to a non-allowed domain)
|
||||||
4. The permission dialog appears — click Approve
|
4. The permission dialog appears — click Approve
|
||||||
@@ -6,7 +6,7 @@ name: "Retry limit for mergemaster and pipeline restarts"
|
|||||||
|
|
||||||
## User Story
|
## User Story
|
||||||
|
|
||||||
As a developer using story-kit, I want pipeline auto-restarts to have a configurable retry limit so that failing agents don't loop infinitely consuming CPU and API credits.
|
As a developer using storkit, I want pipeline auto-restarts to have a configurable retry limit so that failing agents don't loop infinitely consuming CPU and API credits.
|
||||||
|
|
||||||
## Acceptance Criteria
|
## Acceptance Criteria
|
||||||
|
|
||||||
@@ -23,7 +23,7 @@ The watcher should periodically check `5_done/` and move items older than 4 hour
|
|||||||
- All MCP tools and pipeline logic that reference `5_archived` need updating to use `5_done`
|
- All MCP tools and pipeline logic that reference `5_archived` need updating to use `5_done`
|
||||||
- Frontend pipeline display if it shows archived/done items
|
- Frontend pipeline display if it shows archived/done items
|
||||||
- `.story_kit/README.md`: update pipeline stage documentation
|
- `.story_kit/README.md`: update pipeline stage documentation
|
||||||
- Story 116's init scaffolding: `story-kit init` must create `5_done/` and `6_archived/` directories
|
- Story 116's init scaffolding: `storkit init` must create `5_done/` and `6_archived/` directories
|
||||||
- Any templates or scaffold code that creates the `.story_kit/work/` directory structure
|
- Any templates or scaffold code that creates the `.story_kit/work/` directory structure
|
||||||
|
|
||||||
## Acceptance Criteria
|
## Acceptance Criteria
|
||||||
@@ -35,7 +35,7 @@ The watcher should periodically check `5_done/` and move items older than 4 hour
|
|||||||
- [ ] Existing items in old `5_archived/` are migrated to `6_archived/`
|
- [ ] Existing items in old `5_archived/` are migrated to `6_archived/`
|
||||||
- [ ] Frontend pipeline display updated if applicable
|
- [ ] Frontend pipeline display updated if applicable
|
||||||
- [ ] `.story_kit/README.md` updated to reflect the new pipeline stages
|
- [ ] `.story_kit/README.md` updated to reflect the new pipeline stages
|
||||||
- [ ] `story-kit init` scaffolding creates `5_done/` and `6_archived/` (coordinate with story 116)
|
- [ ] `storkit init` scaffolding creates `5_done/` and `6_archived/` (coordinate with story 116)
|
||||||
|
|
||||||
## Out of Scope
|
## Out of Scope
|
||||||
|
|
||||||
@@ -17,21 +17,21 @@ const TEMPLATE_MARKER_CONTEXT: &str = "Agentic AI Code Assistant";
|
|||||||
const TEMPLATE_MARKER_STACK: &str = "Agentic Code Assistant";
|
const TEMPLATE_MARKER_STACK: &str = "Agentic Code Assistant";
|
||||||
```
|
```
|
||||||
|
|
||||||
These markers are phrases that appear in the scaffold templates (`server/src/io/fs.rs` lines 233 and 269). The detection logic (`is_template_or_missing` at line 59) checks if the file *contains* the marker string. But these phrases are generic enough that real project content can contain them too — especially when the project being managed IS an agentic code assistant (i.e. story-kit managing itself).
|
These markers are phrases that appear in the scaffold templates (`server/src/io/fs.rs` lines 233 and 269). The detection logic (`is_template_or_missing` at line 59) checks if the file *contains* the marker string. But these phrases are generic enough that real project content can contain them too — especially when the project being managed IS an agentic code assistant (i.e. storkit managing itself).
|
||||||
|
|
||||||
## The Fix
|
## The Fix
|
||||||
|
|
||||||
Replace the content-based marker detection with a dedicated sentinel comment that only exists in untouched scaffold templates. The sentinel should be something that would never appear in real content, like an HTML comment:
|
Replace the content-based marker detection with a dedicated sentinel comment that only exists in untouched scaffold templates. The sentinel should be something that would never appear in real content, like an HTML comment:
|
||||||
|
|
||||||
```
|
```
|
||||||
<!-- story-kit:scaffold-template -->
|
<!-- storkit:scaffold-template -->
|
||||||
```
|
```
|
||||||
|
|
||||||
Changes needed:
|
Changes needed:
|
||||||
|
|
||||||
1. **`server/src/io/onboarding.rs`**: Replace `TEMPLATE_MARKER_CONTEXT` and `TEMPLATE_MARKER_STACK` with a single `TEMPLATE_SENTINEL` constant set to `"<!-- story-kit:scaffold-template -->"`. Update `check_onboarding_status` to use it for both context and stack checks.
|
1. **`server/src/io/onboarding.rs`**: Replace `TEMPLATE_MARKER_CONTEXT` and `TEMPLATE_MARKER_STACK` with a single `TEMPLATE_SENTINEL` constant set to `"<!-- storkit:scaffold-template -->"`. Update `check_onboarding_status` to use it for both context and stack checks.
|
||||||
|
|
||||||
2. **`server/src/io/fs.rs`**: Add `<!-- story-kit:scaffold-template -->` as the first line of both `STORY_KIT_CONTEXT` and `STORY_KIT_STACK` template constants (lines 233 and 269).
|
2. **`server/src/io/fs.rs`**: Add `<!-- storkit:scaffold-template -->` as the first line of both `STORY_KIT_CONTEXT` and `STORY_KIT_STACK` template constants (lines 233 and 269).
|
||||||
|
|
||||||
3. **`server/src/io/onboarding.rs` tests**: Update the test `needs_onboarding_true_when_specs_contain_scaffold_markers` to use the sentinel instead of the old marker phrases. Also add a test confirming that content containing "Agentic AI Code Assistant" WITHOUT the sentinel does NOT trigger onboarding.
|
3. **`server/src/io/onboarding.rs` tests**: Update the test `needs_onboarding_true_when_specs_contain_scaffold_markers` to use the sentinel instead of the old marker phrases. Also add a test confirming that content containing "Agentic AI Code Assistant" WITHOUT the sentinel does NOT trigger onboarding.
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@ Changes needed:
|
|||||||
|
|
||||||
## Acceptance Criteria
|
## Acceptance Criteria
|
||||||
|
|
||||||
- [ ] Scaffold templates contain the sentinel `<!-- story-kit:scaffold-template -->` as first line
|
- [ ] Scaffold templates contain the sentinel `<!-- storkit:scaffold-template -->` as first line
|
||||||
- [ ] `needs_onboarding()` returns false for projects whose specs contain "Agentic AI Code Assistant" but NOT the sentinel
|
- [ ] `needs_onboarding()` returns false for projects whose specs contain "Agentic AI Code Assistant" but NOT the sentinel
|
||||||
- [ ] `needs_onboarding()` returns true for untouched scaffold content (which contains the sentinel)
|
- [ ] `needs_onboarding()` returns true for untouched scaffold content (which contains the sentinel)
|
||||||
- [ ] Existing tests updated and passing
|
- [ ] Existing tests updated and passing
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user