@zyaiting/keelson 0.4.1 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -12
- package/README_CN.md +15 -12
- package/hooks/codebuddy-session.mjs +13 -28
- package/hooks/codex-session.mjs +16 -0
- package/hooks/prompt-state.mjs +5 -29
- package/hooks/session-start.mjs +7 -0
- package/hooks/workflow-guard.mjs +95 -0
- package/package.json +1 -1
- package/registry/platforms.json +4 -4
- package/registry/runtime-hashes.json +41 -0
- package/skills/keelson/SKILL.md +6 -3
- package/skills/keelson/references/build.md +12 -0
- package/skills/keelson/references/discover.md +5 -3
- package/skills/keelson/references/frontend.md +1 -1
- package/skills/keelson/references/interview.md +26 -7
- package/skills/keelson/references/land.md +2 -0
- package/skills/keelson/references/shape.md +3 -3
- package/skills/keelson/references/verify.md +1 -1
- package/skills/keelson/templates/resident-block.md +1 -1
- package/skills/keelson/templates/workflow.md +3 -3
- package/skills/zh/keelson/SKILL.md +6 -3
- package/skills/zh/keelson/references/build.md +12 -0
- package/skills/zh/keelson/references/discover.md +5 -3
- package/skills/zh/keelson/references/frontend.md +1 -1
- package/skills/zh/keelson/references/interview.md +26 -7
- package/skills/zh/keelson/references/land.md +2 -0
- package/skills/zh/keelson/references/shape.md +3 -3
- package/skills/zh/keelson/references/verify.md +2 -0
- package/skills/zh/keelson/templates/resident-block.md +1 -1
- package/skills/zh/keelson/templates/workflow.md +3 -3
- package/src/cli.js +4 -3
- package/src/commands/ablate.js +2 -1
- package/src/commands/ask.js +4 -1
- package/src/commands/context.js +7 -0
- package/src/commands/doctor.js +3 -1
- package/src/commands/hook.js +6 -1
- package/src/commands/init.js +12 -7
- package/src/commands/new.js +1 -1
- package/src/commands/platforms.js +1 -1
- package/src/commands/start.js +33 -0
- package/src/commands/uninstall.js +1 -1
- package/src/lib/decisions.js +3 -1
- package/src/lib/hook-context.js +30 -0
- package/src/lib/markdown.js +1 -1
- package/src/lib/rules.js +10 -2
- package/src/lib/workflow.js +102 -0
- package/src/platforms/integration.js +75 -93
- package/src/platforms/runtime.js +68 -17
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<p align="center"><img src="https://raw.githubusercontent.com/Atingaii/keelson/main/docs/assets/keelson-banner.png" alt="Keelson" width="620"></p>
|
|
2
2
|
|
|
3
|
-
<p align="center"><strong>
|
|
3
|
+
<p align="center"><strong>Clarify the goal. Build to the contract. Keep what you learn.</strong></p>
|
|
4
4
|
<p align="center">Project memory, engineering guidance, and acceptance checks for your coding agent. Describe the outcome; keep decisions and verification alongside the code.</p>
|
|
5
5
|
|
|
6
6
|
<p align="center">
|
|
@@ -16,16 +16,13 @@
|
|
|
16
16
|
<a href="https://github.com/Atingaii/keelson/blob/main/LICENSE"><img src="https://img.shields.io/badge/License-MIT-blue.svg" alt="MIT license"></a>
|
|
17
17
|
</p>
|
|
18
18
|
|
|
19
|
-
<p align="center"><img src="https://raw.githubusercontent.com/Atingaii/keelson/main/docs/assets/keelson-demo.gif" alt="Real agent conversation replay: a task-filter request followed by implementation, verification, and archiving" width="100%"></p>
|
|
20
|
-
<p align="center"><sub>Initialized example repository · Translated excerpts from a real session, with waits shortened · Just describe the task</sub></p>
|
|
21
|
-
|
|
22
19
|
## Why Keelson?
|
|
23
20
|
|
|
24
21
|
Keelson brings software engineering practices into everyday agent conversations: agree on the outcome, preserve the reasoning, and check the result. It addresses four recurring problems.
|
|
25
22
|
|
|
26
23
|
**1. The agent builds the wrong thing.**
|
|
27
24
|
|
|
28
|
-
“Add a filter” leaves room for different defaults, edge cases, and compatibility choices. Keelson guides the agent to inspect the code and turn the request into concrete acceptance examples before implementation. This applies **behaviour-driven development**: use examples to expose disagreement early, asking only about choices that affect the direction.
|
|
25
|
+
“Add a filter” leaves room for different defaults, edge cases, and compatibility choices. Keelson guides the agent to inspect the code, automatically investigate unclear goals and connected decisions, then turn the request into concrete acceptance examples before implementation. This applies **behaviour-driven development**: use examples to expose disagreement early, asking only about choices that affect the direction.
|
|
29
26
|
|
|
30
27
|
**2. Every session needs the same explanation.**
|
|
31
28
|
|
|
@@ -47,7 +44,7 @@ Keelson combines an **Agent Skill + local CLI**. The skill guides the agent's wo
|
|
|
47
44
|
- A coding agent that can read project files, make changes, and run commands.
|
|
48
45
|
- A local project directory; Git is recommended for tracking code and project knowledge.
|
|
49
46
|
|
|
50
|
-
|
|
47
|
+
Claude Code, Codex CLI and CodeBuddy CLI are the primary supported hosts. Keelson also generates integrations for other coding agents. See [Agent support](https://github.com/Atingaii/keelson/blob/main/docs/platforms.md) for capabilities and validation coverage.
|
|
51
48
|
|
|
52
49
|
## Quick start
|
|
53
50
|
|
|
@@ -57,24 +54,30 @@ Keelson generates integrations for Codex, Claude Code, OpenCode, Gemini CLI, and
|
|
|
57
54
|
npm install -g @zyaiting/keelson
|
|
58
55
|
```
|
|
59
56
|
|
|
60
|
-
**2. Initialize your project**,
|
|
57
|
+
**2. Initialize your project**, selecting your CLI:
|
|
61
58
|
|
|
62
59
|
```bash
|
|
63
60
|
cd /path/to/your/project
|
|
64
|
-
keelson init --
|
|
61
|
+
keelson init --claude # Claude Code
|
|
62
|
+
# or: keelson init --codex
|
|
63
|
+
# or: keelson init --codebuddy
|
|
65
64
|
```
|
|
66
65
|
|
|
67
66
|
**3. Open your agent in that directory and describe the task.** Initialize once, then keep working through conversation.
|
|
68
67
|
|
|
69
|
-
> Add a priority filter to the task list
|
|
68
|
+
> Add a priority filter to the task list.
|
|
70
69
|
|
|
71
70
|
To upgrade, run `npm install -g @zyaiting/keelson@latest`, then `keelson update` in your project. See the [setup guide](https://github.com/Atingaii/keelson/blob/main/docs/getting-started.md) and [supported agents](https://github.com/Atingaii/keelson/blob/main/docs/platforms.md).
|
|
72
71
|
|
|
73
72
|
## From request to completion
|
|
74
73
|
|
|
75
|
-
**
|
|
74
|
+
**Investigate → Decide → Implement → Independently review → Verify → Preserve knowledge**
|
|
75
|
+
|
|
76
|
+
After initialization, ordinary requests trigger the relevant workflow automatically: investigate requirements, clarify material choices with recommendations, apply engineering and UI/UX guidance, implement, verify, and preserve the result for later sessions. You do not need to name a skill or manage workflow commands. Clear edits use a minimal change record. A simple gap gets one question; connected uncertainties get the whole ready decision frontier, with recommendations and reasons for each choice. The agent resumes authorized work once those choices are settled.
|
|
77
|
+
|
|
78
|
+
Before implementation, the agent starts the settled change and loads its declared specs and rules. Review gets a separate context pack built from the request and contracts. Verified changes promote durable decisions into project specs, so later work starts with what the project has learned.
|
|
76
79
|
|
|
77
|
-
|
|
80
|
+
Claude Code, Codex and CodeBuddy integrations restore workflow context and gate supported file edits. Codex requires the generated hooks to be trusted in `/hooks` when prompted; other host permissions remain in effect. Disabled hooks fall back to installed guidance and the shared CLI. See [automation and its boundaries](https://github.com/Atingaii/keelson/blob/main/docs/automation.md).
|
|
78
81
|
|
|
79
82
|
You can also ask:
|
|
80
83
|
|
|
@@ -82,7 +85,7 @@ You can also ask:
|
|
|
82
85
|
- **Improve an interface:** “Polish the settings page, keep our brand, preserve input when saving fails, and check the mobile flow.”
|
|
83
86
|
- **Resume:** “Continue the previous change. First check what's left.”
|
|
84
87
|
|
|
85
|
-
|
|
88
|
+
The agent automatically selects from 22 composable [design actions](https://github.com/Atingaii/keelson/blob/main/docs/frontend.md), discoverable with `keelson design`, including critique, simplification, polish, and adaptation when the work affects an interface. Checking the actual interface requires the agent to use a browser.
|
|
86
89
|
|
|
87
90
|
## What stays in your project?
|
|
88
91
|
|
package/README_CN.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<p align="center"><img src="https://raw.githubusercontent.com/Atingaii/keelson/main/docs/assets/keelson-banner.png" alt="Keelson" width="620"></p>
|
|
2
2
|
|
|
3
|
-
<p align="center"><strong
|
|
3
|
+
<p align="center"><strong>让 Agent 先想清楚,再按规范做完,把经验留在仓库。</strong></p>
|
|
4
4
|
<p align="center">为编码 Agent 提供项目记忆、工程方法和验收流程。你描述目标,Agent 推进实现,把决策与验证留在代码旁。</p>
|
|
5
5
|
|
|
6
6
|
<p align="center">
|
|
@@ -16,16 +16,13 @@
|
|
|
16
16
|
<a href="https://github.com/Atingaii/keelson/blob/main/LICENSE"><img src="https://img.shields.io/badge/License-MIT-blue.svg" alt="MIT license"></a>
|
|
17
17
|
</p>
|
|
18
18
|
|
|
19
|
-
<p align="center"><img src="https://raw.githubusercontent.com/Atingaii/keelson/main/docs/assets/keelson-demo-zh.gif" alt="真实 Agent 对话回放:用户提出任务筛选需求,Agent 完成实现、验证与归档" width="100%"></p>
|
|
20
|
-
<p align="center"><sub>已初始化的示例仓库 · 真实会话节选,等待已压缩 · 用户只需提出需求</sub></p>
|
|
21
|
-
|
|
22
19
|
## 为什么选择 Keelson?
|
|
23
20
|
|
|
24
21
|
Keelson 将软件工程中的成熟做法带进日常 Agent 对话:先对齐结果,留下决策依据,再检查实际产出。它围绕四个常见问题展开。
|
|
25
22
|
|
|
26
23
|
**1. Agent 做出来的,并不是你想要的。**
|
|
27
24
|
|
|
28
|
-
“加个筛选”背后,还有默认行为、边界情况和兼容性。Keelson 引导 Agent
|
|
25
|
+
“加个筛选”背后,还有默认行为、边界情况和兼容性。Keelson 引导 Agent 先读代码,自动调查模糊目标和相互关联的选择,把需求变成具体的验收示例,再开始实现。这借鉴了**行为驱动开发(BDD)**:通过例子尽早发现理解偏差,只对影响方向的选择提问。
|
|
29
26
|
|
|
30
27
|
**2. 换个会话,又得解释同一个项目。**
|
|
31
28
|
|
|
@@ -47,7 +44,7 @@ Keelson 由 **Agent Skill + 本地 CLI** 组成:Skill 指导 Agent 如何工
|
|
|
47
44
|
- 一个能读取项目、修改文件并执行命令的编码 Agent。
|
|
48
45
|
- 一个本地项目目录;建议使用 Git 管理代码和项目知识。
|
|
49
46
|
|
|
50
|
-
|
|
47
|
+
重点适配 **Claude Code、Codex CLI 和 CodeBuddy CLI**,也支持其他编码 Agent 的集成入口;各宿主的能力与验证范围见 [Agent 支持](https://github.com/Atingaii/keelson/blob/main/docs/platforms.md)。
|
|
51
48
|
|
|
52
49
|
## 快速开始
|
|
53
50
|
|
|
@@ -57,24 +54,30 @@ Keelson 由 **Agent Skill + 本地 CLI** 组成:Skill 指导 Agent 如何工
|
|
|
57
54
|
npm install -g @zyaiting/keelson
|
|
58
55
|
```
|
|
59
56
|
|
|
60
|
-
**2.
|
|
57
|
+
**2. 在你的项目中初始化**,选择使用的 CLI:
|
|
61
58
|
|
|
62
59
|
```bash
|
|
63
60
|
cd /path/to/your/project
|
|
64
|
-
keelson init --
|
|
61
|
+
keelson init --claude --lang zh # Claude Code
|
|
62
|
+
# 或:keelson init --codex --lang zh
|
|
63
|
+
# 或:keelson init --codebuddy --lang zh
|
|
65
64
|
```
|
|
66
65
|
|
|
67
66
|
**3. 在这个目录启动 Agent,直接提出需求。** 初始化只需一次;后续正常对话即可。
|
|
68
67
|
|
|
69
|
-
>
|
|
68
|
+
> 给任务列表加一个优先级筛选。
|
|
70
69
|
|
|
71
70
|
升级 CLI:`npm install -g @zyaiting/keelson@latest`,然后在项目中运行 `keelson update`。更多设置见[上手教程](https://github.com/Atingaii/keelson/blob/main/docs/zh/getting-started.md);其他宿主见 [Agent 支持](https://github.com/Atingaii/keelson/blob/main/docs/platforms.md)。
|
|
72
71
|
|
|
73
72
|
## 从一句需求到一次完成
|
|
74
73
|
|
|
75
|
-
|
|
74
|
+
**调查 → 决策 → 实现 → 独立复核 → 验证 → 知识回写**
|
|
75
|
+
|
|
76
|
+
初始化后,普通需求自动触发相应流程:调查需求、带着推荐澄清关键选择、应用工程与 UI/UX 指导、实现、验证,并保留结果供后续会话接续。你无需点名 Skill 或管理工作流命令。明确的小修改使用最小变更记录;简单缺口一次问一个,复杂问题一轮问完前提已明确的整组决定,每题给推荐与理由。决定明确后继续已授权的工作。
|
|
77
|
+
|
|
78
|
+
实现前,Agent 自动启动已澄清的变更,加载声明的规范与规则;复核使用从原始需求和契约生成的独立上下文包。验收后,持久决策回写到项目规范,下次开发继续使用这些知识。
|
|
76
79
|
|
|
77
|
-
|
|
80
|
+
Claude Code、Codex 和 CodeBuddy 集成均支持恢复流程上下文,并对受支持的文件修改执行启动门禁。Codex 首次提示时需在 `/hooks` 中信任生成的 hooks;各宿主原有权限确认继续生效。禁用 hooks 时,由已安装指导驱动相同 CLI。详见[自动化机制与边界](https://github.com/Atingaii/keelson/blob/main/docs/zh/automation.md)。
|
|
78
81
|
|
|
79
82
|
你也可以这样说:
|
|
80
83
|
|
|
@@ -82,7 +85,7 @@ Agent 按任务读取需要的指导,维护验收标准并执行项目检查
|
|
|
82
85
|
- **改善界面:**“优化设置页,保留品牌风格,保存失败时不要丢输入,并检查手机端体验。”
|
|
83
86
|
- **接着开发:**“继续上次的改动,先确认还剩什么。”
|
|
84
87
|
|
|
85
|
-
|
|
88
|
+
涉及界面的任务中,Agent 会从 22 个可组合的[设计动作](https://github.com/Atingaii/keelson/blob/main/docs/zh/frontend.md)中按需选择,包括审视、简化、打磨和适配;可通过 `keelson design` 查看。实际界面效果需要 Agent 使用浏览器检查。
|
|
86
89
|
|
|
87
90
|
## 项目里会留下什么?
|
|
88
91
|
|
|
@@ -1,16 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// CodeBuddy session bridge for Keelson.
|
|
3
|
-
// SessionStart/UserPromptSubmit:
|
|
3
|
+
// SessionStart/UserPromptSubmit: restore workflow and declared project contracts.
|
|
4
4
|
// PreToolUse(Bash|PowerShell): deterministically prepend KEELSON_SESSION_ID to the command.
|
|
5
5
|
// Raw CodeBuddy session ids are never written to disk.
|
|
6
|
-
import crypto from 'node:crypto';
|
|
7
6
|
import fs from 'node:fs';
|
|
8
|
-
import
|
|
9
|
-
import {
|
|
7
|
+
import { findProjectRoot } from '../src/lib/paths.js';
|
|
8
|
+
import { hookEnvironment, sessionContext } from '../src/lib/hook-context.js';
|
|
9
|
+
import { writeSession } from '../src/lib/session.js';
|
|
10
10
|
|
|
11
|
-
const hash = (value, n) => crypto.createHash('sha256').update(String(value)).digest('hex').slice(0, n);
|
|
12
|
-
const readJson = (p) => { try { return JSON.parse(fs.readFileSync(p, 'utf8')); } catch { return null; } };
|
|
13
|
-
const writeJson = (p, v) => { fs.mkdirSync(path.dirname(p), { recursive: true }); fs.writeFileSync(p, JSON.stringify(v, null, 2) + '\n'); };
|
|
14
11
|
const shellQuote = (v) => `'${String(v).replace(/'/g, "'\\''")}'`;
|
|
15
12
|
|
|
16
13
|
let input = {};
|
|
@@ -19,17 +16,13 @@ try {
|
|
|
19
16
|
if (raw.trim()) input = JSON.parse(raw);
|
|
20
17
|
} catch {}
|
|
21
18
|
|
|
22
|
-
const root =
|
|
19
|
+
const root = findProjectRoot(process.env.CODEBUDDY_PROJECT_DIR || input.cwd || process.cwd());
|
|
23
20
|
const sessionId = typeof input.session_id === 'string' ? input.session_id.trim() : '';
|
|
24
|
-
if (!sessionId || !
|
|
21
|
+
if (!sessionId || !root) process.exit(0);
|
|
25
22
|
|
|
26
|
-
const
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
const session = readJson(sessionFile) || { schema: 1, change: null, createdAt: new Date().toISOString() };
|
|
30
|
-
session.updatedAt = new Date().toISOString();
|
|
31
|
-
session.source = 'codebuddy';
|
|
32
|
-
writeJson(sessionFile, session);
|
|
23
|
+
const env = hookEnvironment('codebuddy', input);
|
|
24
|
+
const opaque = env.KEELSON_SESSION_ID;
|
|
25
|
+
writeSession(root, { source: 'codebuddy' }, env);
|
|
33
26
|
|
|
34
27
|
const event = input.hook_event_name || '';
|
|
35
28
|
if (event === 'PreToolUse' && ['bash', 'powershell'].includes(String(input.tool_name || '').toLowerCase())) {
|
|
@@ -44,8 +37,6 @@ if (event === 'PreToolUse' && ['bash', 'powershell'].includes(String(input.tool_
|
|
|
44
37
|
continue: true,
|
|
45
38
|
hookSpecificOutput: {
|
|
46
39
|
hookEventName: 'PreToolUse',
|
|
47
|
-
permissionDecision: 'allow',
|
|
48
|
-
permissionDecisionReason: 'Keelson attached the opaque session identity used only for local work-focus routing.',
|
|
49
40
|
modifiedInput: {
|
|
50
41
|
...input.tool_input,
|
|
51
42
|
command: injected,
|
|
@@ -55,13 +46,7 @@ if (event === 'PreToolUse' && ['bash', 'powershell'].includes(String(input.tool_
|
|
|
55
46
|
process.exit(0);
|
|
56
47
|
}
|
|
57
48
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
.map((d) => d.name)
|
|
63
|
-
: [];
|
|
64
|
-
const focused = session.change && active.includes(session.change) ? session.change : null;
|
|
65
|
-
if (focused) process.stdout.write(`[keelson] session focus: ${focused}; use the existing change unless the user requests an independent outcome.\n`);
|
|
66
|
-
else if (active.length === 1) process.stdout.write(`[keelson] resume candidate: ${active[0]}; bind only if this prompt continues that work.\n`);
|
|
67
|
-
else if (active.length > 1) process.stdout.write(`[keelson] active changes: ${active.join(', ')}; no session focus, so do not guess.\n`);
|
|
49
|
+
if (['SessionStart', 'UserPromptSubmit'].includes(event)) {
|
|
50
|
+
try { process.stdout.write(sessionContext(root, env, event, 'codebuddy') + '\n'); }
|
|
51
|
+
catch (error) { process.stdout.write(`[keelson] Context restoration needs attention: ${error.message}\n`); }
|
|
52
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import { findProjectRoot } from '../src/lib/paths.js';
|
|
4
|
+
import { hookEnvironment, sessionContext } from '../src/lib/hook-context.js';
|
|
5
|
+
|
|
6
|
+
let input = {};
|
|
7
|
+
try { input = JSON.parse(fs.readFileSync(0, 'utf8')); } catch { process.exit(0); }
|
|
8
|
+
const root = findProjectRoot(input.cwd || process.cwd());
|
|
9
|
+
if (!root) process.exit(0);
|
|
10
|
+
const event = input.hook_event_name || 'SessionStart';
|
|
11
|
+
try {
|
|
12
|
+
const context = sessionContext(root, hookEnvironment('codex', input), event, 'codex');
|
|
13
|
+
process.stdout.write(JSON.stringify({ hookSpecificOutput: { hookEventName: event, additionalContext: context } }) + '\n');
|
|
14
|
+
} catch (error) {
|
|
15
|
+
process.stdout.write(`[keelson] Context restoration needs attention: ${error.message}\n`);
|
|
16
|
+
}
|
package/hooks/prompt-state.mjs
CHANGED
|
@@ -5,10 +5,10 @@ import crypto from 'node:crypto';
|
|
|
5
5
|
import fs from 'node:fs';
|
|
6
6
|
import path from 'node:path';
|
|
7
7
|
import { runtimeDir } from '../src/lib/runtime-path.js';
|
|
8
|
+
import { workflowHint } from '../src/lib/workflow.js';
|
|
8
9
|
|
|
9
10
|
const root = process.env.CLAUDE_PROJECT_DIR || process.cwd();
|
|
10
11
|
const k = path.join(root, '.keelson');
|
|
11
|
-
const changesDir = path.join(k, 'changes');
|
|
12
12
|
if (!fs.existsSync(k)) process.exit(0);
|
|
13
13
|
|
|
14
14
|
const read = (p) => (fs.existsSync(p) ? fs.readFileSync(p, 'utf8').replace(/\r\n?/g, '\n') : '');
|
|
@@ -35,32 +35,8 @@ if (sessionPath) {
|
|
|
35
35
|
session.source = 'claude-prompt';
|
|
36
36
|
writeJson(sessionPath, session);
|
|
37
37
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
const change = read(path.join(dir, 'change.md'));
|
|
43
|
-
if (!change) return null;
|
|
44
|
-
const tasks = read(path.join(dir, 'tasks.md'));
|
|
45
|
-
const total = (tasks.match(/^\s*[-*]\s+\[[ xX]\]/gm) || []).length;
|
|
46
|
-
const done = (tasks.match(/^\s*[-*]\s+\[[xX]\]/gm) || []).length;
|
|
47
|
-
const ledger = read(path.join(dir, 'ledger.md'));
|
|
48
|
-
const verifies = [...ledger.matchAll(/^###\s+Verify:[\s\S]*?exit\s*(?:code)?\s*[:=]?\s*(\d+)/gim)];
|
|
49
|
-
const lastExit = verifies.length ? Number(verifies.at(-1)[1]) : null;
|
|
50
|
-
const explicit = (change.match(/^status:\s*([\w-]+)/m) || [])[1];
|
|
51
|
-
const verify = verifies.length ? (lastExit === 0 ? 'passed' : 'failed') : 'not-run';
|
|
52
|
-
const open = (change.match(/^##\s+Open questions?\s*\n([\s\S]*?)(?=^##\s|(?![\s\S]))/im) || [])[1] || '';
|
|
53
|
-
const openCount = (open.match(/^\s*[-*]\s+(?!…|none)/gim) || []).length;
|
|
54
|
-
return `${name} · ${explicit || (total ? (done < total ? 'in-progress' : 'awaiting verification') : 'in-progress')} · verify ${verify}${total ? ` · ${done}/${total} tasks` : ''}${openCount ? ` · ${openCount} open` : ''}`;
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
if (session?.change) {
|
|
58
|
-
const line = summarize(session.change);
|
|
59
|
-
if (line) process.stdout.write(`[keelson] focus: ${line}\n`);
|
|
60
|
-
process.exit(0);
|
|
38
|
+
try {
|
|
39
|
+
process.stdout.write(workflowHint(root, { ...process.env, ...(envIdentity ? { KEELSON_SESSION_ID: envIdentity } : {}) }) + '\n');
|
|
40
|
+
} catch (error) {
|
|
41
|
+
process.stdout.write(`[keelson] Cannot restore workflow: ${error.message}. Run keelson doctor before implementation.\n`);
|
|
61
42
|
}
|
|
62
|
-
|
|
63
|
-
const names = fs.readdirSync(changesDir, { withFileTypes: true })
|
|
64
|
-
.filter((d) => d.isDirectory() && d.name !== 'archive' && fs.existsSync(path.join(changesDir, d.name, 'change.md')))
|
|
65
|
-
.map((d) => d.name);
|
|
66
|
-
if (names.length === 1) process.stdout.write(`[keelson] resume candidate: ${summarize(names[0])}; bind only if this prompt continues that work\n`);
|
package/hooks/session-start.mjs
CHANGED
|
@@ -5,6 +5,7 @@ import crypto from 'node:crypto';
|
|
|
5
5
|
import fs from 'node:fs';
|
|
6
6
|
import path from 'node:path';
|
|
7
7
|
import { runtimeDir } from '../src/lib/runtime-path.js';
|
|
8
|
+
import { activeWorkflow, phaseContext, renderPhaseContext, workflowHint } from '../src/lib/workflow.js';
|
|
8
9
|
|
|
9
10
|
const root = process.env.CLAUDE_PROJECT_DIR || process.cwd();
|
|
10
11
|
const k = path.join(root, '.keelson');
|
|
@@ -57,6 +58,7 @@ if (sessionPath) {
|
|
|
57
58
|
session = readJson(sessionPath) || { schema: 1, change: null, createdAt: new Date().toISOString() };
|
|
58
59
|
session.updatedAt = new Date().toISOString();
|
|
59
60
|
session.source = 'claude-session-start';
|
|
61
|
+
session.injectedContexts = []; // compact/resume must restore previously injected constraints.
|
|
60
62
|
writeJson(sessionPath, session);
|
|
61
63
|
}
|
|
62
64
|
|
|
@@ -91,4 +93,9 @@ if (ordered.length) {
|
|
|
91
93
|
lines.push('', '--- Active work ---');
|
|
92
94
|
for (const c of ordered.slice(0, 6)) lines.push(`${c.name}${c.name === focused ? ' [focus]' : ''}: ${c.tier}${c.status ? `, ${c.status}` : ''}${c.total ? `, ${c.done}/${c.total} tasks` : ''}${c.owner ? `, ${c.owner}` : ''}`);
|
|
93
95
|
}
|
|
96
|
+
try {
|
|
97
|
+
const env = { ...process.env, ...(envIdentity ? { KEELSON_SESSION_ID: envIdentity } : {}) };
|
|
98
|
+
lines.push('', workflowHint(root, env));
|
|
99
|
+
if (focused) lines.push(renderPhaseContext(phaseContext(root, activeWorkflow(root, focused, env))));
|
|
100
|
+
} catch (error) { lines.push(`[keelson] Context restoration needs attention: ${error.message}`); }
|
|
94
101
|
process.stdout.write(lines.join('\n') + '\n');
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Host-specific file-tool gates and phase context injection. Shell/MCP writers
|
|
3
|
+
// remain host-policy territory; this is a workflow guard, not a sandbox.
|
|
4
|
+
import crypto from 'node:crypto';
|
|
5
|
+
import fs from 'node:fs';
|
|
6
|
+
import path from 'node:path';
|
|
7
|
+
import { findProjectRoot } from '../src/lib/paths.js';
|
|
8
|
+
import { hookEnvironment } from '../src/lib/hook-context.js';
|
|
9
|
+
import { readSession, writeSession } from '../src/lib/session.js';
|
|
10
|
+
import { activeWorkflow, implementationBlockers, phaseContext, renderPhaseContext } from '../src/lib/workflow.js';
|
|
11
|
+
|
|
12
|
+
let input = {};
|
|
13
|
+
try { input = JSON.parse(fs.readFileSync(0, 'utf8')); } catch { process.exit(2); }
|
|
14
|
+
const host = process.argv[2] || 'claude';
|
|
15
|
+
const projectDir = host === 'claude' ? process.env.CLAUDE_PROJECT_DIR : host === 'codebuddy' ? process.env.CODEBUDDY_PROJECT_DIR : null;
|
|
16
|
+
const root = findProjectRoot(projectDir || input.cwd || process.cwd());
|
|
17
|
+
if (!root) process.exit(0);
|
|
18
|
+
const env = hookEnvironment(host, input);
|
|
19
|
+
const event = input.hook_event_name || 'PreToolUse';
|
|
20
|
+
const tool = input.tool_name;
|
|
21
|
+
const output = (fields) => process.stdout.write(JSON.stringify({ hookSpecificOutput: { hookEventName: event, ...fields } }) + '\n');
|
|
22
|
+
|
|
23
|
+
try {
|
|
24
|
+
const session = readSession(root, env);
|
|
25
|
+
const name = session.state?.change;
|
|
26
|
+
if (host === 'codex' && event === 'SubagentStart' && !name) {
|
|
27
|
+
// session_id is the root, not necessarily the spawning parent. Let the
|
|
28
|
+
// assigned task name its change rather than inheriting an unrelated focus.
|
|
29
|
+
output({ additionalContext: '[keelson] Preserve your assigned scope, including read-only work. If your task includes KEELSON_CHANGE=<name>, run `keelson focus <name>`, then `keelson context --phase check` for review or `--phase implement` for implementation before doing that work. Do not infer a task from the root session or sole repository candidate. Without a marker, keep discovery read-only; create or select a change only when the task explicitly requires implementation. These commands do not grant permission to edit.' });
|
|
30
|
+
process.exit(0);
|
|
31
|
+
}
|
|
32
|
+
const workflow = activeWorkflow(root, name, env);
|
|
33
|
+
// Never infer an unrelated session's change from the sole repository candidate.
|
|
34
|
+
if (!name) workflow.change = null;
|
|
35
|
+
const args = input.tool_input ?? {};
|
|
36
|
+
const file = args.file_path ?? args.notebook_path;
|
|
37
|
+
const patch = host === 'codex' && tool === 'apply_patch';
|
|
38
|
+
const editing = patch || ['Edit', 'Write', 'MultiEdit', 'NotebookEdit', 'NotebookWrite'].includes(tool);
|
|
39
|
+
const files = patch
|
|
40
|
+
? [...String(args.command ?? '').matchAll(/^\*\*\* (?:Add File|Update File|Delete File|Move to): (.+)\r?$/gm)].map((m) => m[1].trim())
|
|
41
|
+
: typeof file === 'string' ? [file] : [];
|
|
42
|
+
const relative = files.map((f) => path.relative(root, path.resolve(input.cwd || root, f)).replace(/\\/g, '/'));
|
|
43
|
+
const planningOnly = relative.length > 0 && relative.every((f) => f.startsWith('.keelson/') && !f.split('/').includes('..'));
|
|
44
|
+
if (editing && !planningOnly) {
|
|
45
|
+
const blockers = implementationBlockers(workflow.change, workflow.changes);
|
|
46
|
+
if (blockers.length) {
|
|
47
|
+
output({ permissionDecision: 'deny', permissionDecisionReason: blockers.join(' ') + ' The agent should resolve this within existing authorization; do not ask the user to run workflow commands.' });
|
|
48
|
+
process.exit(0);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (editing && planningOnly) process.exit(0);
|
|
52
|
+
if (!workflow.change) process.exit(0);
|
|
53
|
+
if (host === 'codex' && ['spawn_agent', 'Agent', 'Task'].includes(tool)) {
|
|
54
|
+
const markers = [...String(args.message ?? args.prompt ?? '').matchAll(/^\s*KEELSON_CHANGE=([^\s]+)[ \t]*$/gm)];
|
|
55
|
+
if (markers.length !== 1 || markers[0][1] !== name) {
|
|
56
|
+
output({ permissionDecision: 'deny', permissionDecisionReason: `Add the single line KEELSON_CHANGE=${name} to this child task so its own CLI session can bind the assigned change. Keep its phase, original instructions and any read-only scope. The agent should correct the task prompt; do not ask the user to run workflow commands.` });
|
|
57
|
+
process.exit(0);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
const descriptor = `${input.agent_type ?? ''} ${args.subagent_type ?? args.agent_type ?? ''} ${args.description ?? ''} ${args.prompt ?? args.message ?? ''}`;
|
|
61
|
+
const reviewing = /KEELSON_PHASE=check|keelson-check|\breview\b|\breviewer\b|复核|审查/i.test(descriptor);
|
|
62
|
+
if (event === 'SubagentStart' && !reviewing && !/KEELSON_PHASE=implement|keelson-implement/i.test(descriptor)) {
|
|
63
|
+
// Generic agent_type carries no parent's prompt or reliable phase. The
|
|
64
|
+
// Agent/Task hook already injected the appropriate pack into that prompt.
|
|
65
|
+
const hint = '[keelson] Follow the phase and contracts in your task prompt. If they are missing, load `keelson context --phase check` for review or `--phase implement` for implementation. Preserve your assigned scope; context is not permission to edit.';
|
|
66
|
+
// A bound Codex child can safely receive its own packs. An unbound child
|
|
67
|
+
// received explicit binding instructions above, never a guessed root task.
|
|
68
|
+
const packs = host === 'codex' ? ['implement', 'check'].map((phase) => renderPhaseContext(phaseContext(root, workflow, phase))) : [];
|
|
69
|
+
output({ additionalContext: [hint, ...packs].join('\n\n') });
|
|
70
|
+
process.exit(0);
|
|
71
|
+
}
|
|
72
|
+
const phase = reviewing ? 'check' : 'implement';
|
|
73
|
+
const pack = phaseContext(root, workflow, phase, relative);
|
|
74
|
+
const context = renderPhaseContext(pack);
|
|
75
|
+
if (['Agent', 'Task'].includes(tool) && typeof args.prompt === 'string') {
|
|
76
|
+
// Preserve every original argument and normal host permission checks.
|
|
77
|
+
if (host === 'codex') output({ additionalContext: context });
|
|
78
|
+
else output({ [host === 'codebuddy' ? 'modifiedInput' : 'updatedInput']: { ...args, prompt: `${args.prompt}\n\n${context}` } });
|
|
79
|
+
} else if (event === 'SubagentStart') {
|
|
80
|
+
output({ additionalContext: context });
|
|
81
|
+
} else if (host === 'codex' && input.agent_id) {
|
|
82
|
+
// Codex does not emit SessionStart when a child compacts or resumes. Do
|
|
83
|
+
// not suppress the next contract pack on the basis of a pre-compact cache.
|
|
84
|
+
output({ additionalContext: context });
|
|
85
|
+
} else if (host !== 'codebuddy') {
|
|
86
|
+
const digest = crypto.createHash('sha256').update(`${input.agent_id ?? 'main'}\n${context}`).digest('hex');
|
|
87
|
+
if (!(session.state?.injectedContexts ?? []).includes(digest)) {
|
|
88
|
+
output({ additionalContext: context });
|
|
89
|
+
writeSession(root, { injectedContexts: [...(session.state?.injectedContexts ?? []).slice(-15), digest] }, env);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
} catch (error) {
|
|
93
|
+
if (event === 'PreToolUse') output({ permissionDecision: 'deny', permissionDecisionReason: `Keelson context could not be loaded: ${error.message}. Repair the declared context before retrying.` });
|
|
94
|
+
else output({ additionalContext: `Keelson context could not be loaded: ${error.message}. Investigate before implementation.` });
|
|
95
|
+
}
|
package/package.json
CHANGED
package/registry/platforms.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 2,
|
|
3
|
-
"updated": "2026-09-
|
|
4
|
-
"note": "Adapters describe generated discovery paths, not a promise of live end-to-end host parity. Codex session identity has been exercised locally. Other hosts have adapter contract tests;
|
|
3
|
+
"updated": "2026-09-21",
|
|
4
|
+
"note": "Adapters describe generated discovery paths, not a promise of live end-to-end host parity. Codex session identity has been exercised locally. Other hosts have adapter contract tests; Claude Code, Codex and CodeBuddy have workflow hook adapters; hook execution depends on the host version, trust and settings. Native session identity sources include CODEX_THREAD_ID, Claude hooks, Pi environment and explicit KEELSON_SESSION_ID. No source means an honest degraded state. Default installation is lightweight; --vendor explicitly copies package guidance.",
|
|
5
5
|
"platforms": {
|
|
6
6
|
"claude": {
|
|
7
7
|
"label": "Claude Code",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"bin": "codex",
|
|
20
20
|
"instructions": "AGENTS.md",
|
|
21
21
|
"skillsDir": ".agents/skills",
|
|
22
|
-
"hooks":
|
|
22
|
+
"hooks": true,
|
|
23
23
|
"confidence": "verified",
|
|
24
24
|
"support": "first-class",
|
|
25
25
|
"sessionFocus": "native",
|
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
"bin": "codebuddy",
|
|
72
72
|
"instructions": "CODEBUDDY.md",
|
|
73
73
|
"skillsDir": ".codebuddy/skills",
|
|
74
|
-
"hooks":
|
|
74
|
+
"hooks": true,
|
|
75
75
|
"confidence": "documented",
|
|
76
76
|
"support": "first-class",
|
|
77
77
|
"sessionFocus": "native",
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"source": "Generated from published @zyaiting/keelson 0.4.0 and 0.4.1 (English/Chinese, lean/guided, guide on/off). Hashes include paths and normalized file bytes; only exact generated content may be replaced.",
|
|
3
|
+
"versions": {
|
|
4
|
+
"0.4.0": {
|
|
5
|
+
"shims": [
|
|
6
|
+
"cebe268136c46d9b190f31d5521770a8fe81dd0aa53dfccfd1dfbf39dafa26e7",
|
|
7
|
+
"5cef12b9c5aec6410040c1f5033fc60cc76fd9837bc73abfef147e36096b981a"
|
|
8
|
+
],
|
|
9
|
+
"skills": [
|
|
10
|
+
"490534b10c8f594cd8ca40dc4817f56f1d9e84bca1cff973c45d857f367269d1",
|
|
11
|
+
"a8cdf54fc5e68a03d74c4d8a8a1f714997c1340318b3c664fab1d3473c865dd7",
|
|
12
|
+
"7d56a7c7197f2363bbbace9149465ade63c8308eb2dfed15d76fbcf892dd5a58",
|
|
13
|
+
"4e2ca439e8e11683d8913ab72f05537cbbde4afa6d61ad0e0848a59f9cf7bae7"
|
|
14
|
+
],
|
|
15
|
+
"workflows": [
|
|
16
|
+
"455f5bb4060b984cd1839aed452fb82cbc09101d81d28630bdaa9547aca6d050",
|
|
17
|
+
"9099f590ae1b8192de759cc9b9d2187d37961b841e80bedd6175c23eac752af1",
|
|
18
|
+
"73f8562e785d8259d853257d02ac1e0688a5882d8c8e701b42a4e289b317be31",
|
|
19
|
+
"ca267bd38b5353684e3deb7d1774bb75d25005381541ba67597cd9fb530ad538"
|
|
20
|
+
]
|
|
21
|
+
},
|
|
22
|
+
"0.4.1": {
|
|
23
|
+
"shims": [
|
|
24
|
+
"4afd7eb69ca1ab1913c73737e56890ca6e363881b1cedc76e95f97b0e5d528e3",
|
|
25
|
+
"a2d88237dbaa7a9aa0fc5340e73690737a5c58f13013dff93604d2414f3fef38"
|
|
26
|
+
],
|
|
27
|
+
"skills": [
|
|
28
|
+
"bc676907188784049abf44f271643ea726b82ad34eb3af994bbf1b382f8e3d5f",
|
|
29
|
+
"9f2a472f526646a3f1e180bb1cf9f1aaec74a0da5f4e937c9ca1ed5d88f11602",
|
|
30
|
+
"adb328b4553e9d3d5e1826f91ffd10528b7f7b6b04565e0c1801606d04509686",
|
|
31
|
+
"d7ac8d6b0e8c849cca28f574fc6fb355aa863f90c93fbf2165a43a1d14cabe34"
|
|
32
|
+
],
|
|
33
|
+
"workflows": [
|
|
34
|
+
"455f5bb4060b984cd1839aed452fb82cbc09101d81d28630bdaa9547aca6d050",
|
|
35
|
+
"9099f590ae1b8192de759cc9b9d2187d37961b841e80bedd6175c23eac752af1",
|
|
36
|
+
"73f8562e785d8259d853257d02ac1e0688a5882d8c8e701b42a4e289b317be31",
|
|
37
|
+
"ca267bd38b5353684e3deb7d1774bb75d25005381541ba67597cd9fb530ad538"
|
|
38
|
+
]
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
package/skills/keelson/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: keelson
|
|
3
|
-
description: Engineering
|
|
3
|
+
description: Engineering workflow for repositories with a .keelson/ directory. Apply automatically to ordinary requests to explore an idea, build or change a feature, fix a bug, create or improve an interface, continue prior work, or improve recurring engineering failures. Routes discovery, design, implementation, verification and project memory without requiring skill names or workflow commands.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Keelson
|
|
@@ -21,6 +21,8 @@ Completion is **not** an intent and never depends on the user saying “done”.
|
|
|
21
21
|
|
|
22
22
|
- For interface design, review, interaction or responsive work, load `frontend.md`; use `keelson design` for focused action briefs. Keep browser observations distinct from code checks.
|
|
23
23
|
|
|
24
|
+
Route from the requested outcome and repository evidence, not special vocabulary. Users describe work; the agent loads guidance and runs workflow commands. Automatically include `model.md` for conflicting terms or shared boundaries, `engineer.md` for non-obvious design choices, and `frontend.md` when the affected path includes a user interface, even without an explicit design request. During implementation use `build.md`; complete with `verify.md` → `land.md` → `reconcile.md` within existing authorization. `guide: true` adds teaching, not activation; both profiles use this workflow by default.
|
|
25
|
+
|
|
24
26
|
## Operating rules
|
|
25
27
|
|
|
26
28
|
- A conversation/session is only a focus pointer. Ending a window, going idle, or continuing to ask questions MUST NOT mark a change complete.
|
|
@@ -28,9 +30,10 @@ Completion is **not** an intent and never depends on the user saying “done”.
|
|
|
28
30
|
- On Resume, use `keelson focus --auto`; branch match or a sole active change may be suggested. Never silently bind an ambiguous session.
|
|
29
31
|
- If `NOW.md` says “First contact”, infer and confirm `INTENT.md`; do not inventory the whole repository into specs/rules.
|
|
30
32
|
- Non-trivial modifying work starts from current context; shared modules get `keelson impact <files>`.
|
|
31
|
-
-
|
|
33
|
+
- Automatically assess discovery needs on new goals, material follow-ups and changed premises using `interview.md`; unresolved goals, connected product choices or high-impact commitments trigger deeper discovery without special wording. Clear tasks proceed directly. Ask one ready owner decision for a simple gap, or the whole ready frontier for connected uncertainty, with concrete options, a recommendation and reason; reuse settled answers and investigate facts yourself.
|
|
32
34
|
- Route non-obvious mechanisms/architecture through `engineer.md`: reduce to facts, outcome, constraints, and invariants; state a falsifiable hypothesis; use the cheapest experiment/ablation that can discriminate; complexity must earn its keep with evidence.
|
|
33
|
-
- Size only the work: trivial =
|
|
35
|
+
- Size only the work: trivial = minimal quick change; quick = lightweight change; spec = acceptance + behavior delta + plan within existing user authorization; clarify only unresolved owner choices.
|
|
36
|
+
- Before product edits, automatically run `keelson start` for the focused change, then load `keelson context --phase implement`; after new material decisions, restart only once they are settled. Users need not run these commands.
|
|
34
37
|
- Artifacts are information containers, not ceremony. Do not create empty roadmap/glossary/rule/task/ledger/handoff/spec files.
|
|
35
38
|
- `tasks.md` is an execution plan, not completion authority. Unchecked plan items never override satisfied acceptance + fresh evidence; reconcile or remove stale tasks when the implementation path changes.
|
|
36
39
|
- Knowledge maintenance is internal. During RECONCILE, automatically rewrite/split/dedupe pressured durable docs and let `land` auto-shard large specs; never ask the owner to maintain Keelson unless a product-semantic decision is required.
|
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
Execute `tasks.md` slice by slice. You choose how; these notes cover the parts that are easy to get wrong.
|
|
4
4
|
|
|
5
|
+
## Enter implementation with the current plan
|
|
6
|
+
<!-- keelson: id=build.start | without: an agent edits product files before resolving the plan or reads an unrelated change's rules | sunset: never -->
|
|
7
|
+
|
|
8
|
+
For modifying work, create the smallest useful change, record concrete acceptance, and run `keelson start` automatically within the owner's existing authorization. Trivial work uses a minimal quick change without a separate plan or interview. Start rejects open decisions, assumptions, missing acceptance and active prerequisites; it records the current plan and declares phase context in `context.json`. Reopened decisions or changed plan/delta require resolving the affected branches and starting again. Do not ask the owner to operate the workflow.
|
|
9
|
+
|
|
10
|
+
Read `keelson context --phase implement` before editing. The pack contains current and delta specs, relevant rules, decisions and checks; `context.json` can declare additional project-relative files per `implement`/`check` phase. Add newly affected paths to context routing. For spec work, retain the owner's original request and material follow-ups in `request.md` so the reviewer sees the actual requested outcome. Do not replace it with your implementation summary.
|
|
11
|
+
|
|
12
|
+
Claude Code, Codex and CodeBuddy have native gates for supported file-editing tools and hooks for session context. Codex requires trusted hooks. Shell/MCP writers and other hosts must follow this same protocol through the agent. This is not a sandbox or proof of user authorization.
|
|
13
|
+
|
|
14
|
+
|
|
5
15
|
## Rulings, not stalls
|
|
6
16
|
<!-- keelson: id=build.rulings | without: agent parks the session on questions the plan already answers; or decides silently and the reasoning is lost | sunset: never -->
|
|
7
17
|
|
|
@@ -21,6 +31,8 @@ When tasks are mostly independent and the host offers subagents, dispatch a fres
|
|
|
21
31
|
|
|
22
32
|
More agents are not a linear throughput multiplier. When tasks share mutable state or the same contract, or need constant synchronization, coordination and merge cost can exceed the parallelism benefit; keep them sequential. Parallelize only when boundaries are clear, outputs are independently verifiable, and the merge contract is explicit. Do not try to rescue tightly coupled work by simply adding agents.
|
|
23
33
|
|
|
34
|
+
For a tracked task, include a standalone `KEELSON_CHANGE=<change-name>` line and the phase in each child task. In Codex the child automatically runs `keelson focus <change-name>` and `keelson context --phase implement` (or `check` for review) before working. Each child has its own thread identity; never infer its task from the root session. Preserve assigned read-only scope. When resuming a child with an existing focus, retain it unless the new assignment explicitly changes it. Untracked read-only investigation needs no change or marker.
|
|
35
|
+
|
|
24
36
|
After each task, a reviewer subagent (tier ≥ `standard`, never below the implementer) checks the diff against the spec and the rules. Record both in the ledger:
|
|
25
37
|
|
|
26
38
|
```markdown
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# Discovering what is wanted
|
|
2
2
|
|
|
3
|
-
The user often cannot describe the whole requirement in the first sentence, and they should not need to know which engineering choice matters. Discovery finds the problem behind the request before anyone picks a database.
|
|
3
|
+
The user often cannot describe the whole requirement in the first sentence, and they should not need to know which engineering choice matters. Discovery finds the problem behind the request before anyone picks a database. Apply `interview.md` automatically to determine depth from the goal, unresolved choices and consequences, including when the user simply asks to build something. Load `design-lenses.md` only when the work triggers a real cross-domain risk.
|
|
4
|
+
|
|
5
|
+
During read-only requests, reuse existing artifacts but keep all new write-backs, decisions and notes in the conversation, even when a change is active. The persistence steps below apply only within existing write authorization.
|
|
4
6
|
|
|
5
7
|
## Scenario before technology
|
|
6
8
|
<!-- keelson: id=discover.scenario-first | without: the first question is a technology choice the owner cannot answer, and the product is shaped by whatever they guessed | sunset: never -->
|
|
@@ -42,11 +44,11 @@ Before asking, classify the gap by who can resolve it:
|
|
|
42
44
|
|---|---|
|
|
43
45
|
| Already established in repository/context | Use it; cite the source in the write-back |
|
|
44
46
|
| Reality-owned (code behaviour, API contract, measurement, dependency capability) | Investigate or run a small experiment |
|
|
45
|
-
| User-owned and load-bearing (goal, scope, acceptance, risk tolerance, public commitment) | Ask one question |
|
|
47
|
+
| User-owned and load-bearing (goal, scope, acceptance, risk tolerance, public commitment) | Ask one question for a simple gap or the whole ready frontier for connected uncertainty |
|
|
46
48
|
| Non-load-bearing or cheap to reverse | Decide under authorization, or leave unresolved for a later slice |
|
|
47
49
|
| Evidence exhausted | Mark it UNKNOWN; do not convert uncertainty into a user belief |
|
|
48
50
|
|
|
49
|
-
|
|
51
|
+
Use `interview.md` to choose a single question for a simple gap or the whole ready frontier for connected uncertainty. Prioritize by practical value of information: the answer most likely to change the next slice, weighted by the cost of being wrong. Before asking, apply the `interview.md` question protocol. After the answer, update the write-back and reassess the frontier. Question count follows decision complexity: when no user-owned load-bearing gap exists, ask nothing and proceed.
|
|
50
52
|
|
|
51
53
|
## Scope guard
|
|
52
54
|
<!-- keelson: id=discover.scope-guard | without: a first request asks for five independent domains at once, and integration risk, debugging cost, and requirement churn compound | sunset: never -->
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Frontend design
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Apply automatically when the requested work or affected code creates, changes, diagnoses or verifies an interface people see and operate. Users need not request a design action or name this reference. Keep the existing change lifecycle; add design judgment and observable interface acceptance, scoped to the affected user journey.
|
|
4
4
|
|
|
5
5
|
## Route by the problem
|
|
6
6
|
<!-- keelson: id=frontend.routing | without: Small UI fixes turn into broad redesigns and every request loads all guidance | sunset: never -->
|