whynot-cli 0.0.0-stage → 0.1.1
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/AGENTS.snippet.md +69 -0
- package/AGENTS.snippet.zh-CN.md +60 -0
- package/CONTRIBUTING.md +75 -0
- package/LICENSE +21 -0
- package/README.md +274 -2
- package/README.zh-CN.md +257 -0
- package/assets/icon-dark.svg +11 -0
- package/assets/icon-light.svg +11 -0
- package/bin/whynot.js +4 -0
- package/docs/design.md +139 -0
- package/docs/design.zh-CN.md +102 -0
- package/docs/e1-code-context.md +169 -0
- package/docs/e2-false-obedience.md +167 -0
- package/docs/e3-power.md +156 -0
- package/docs/e4-dose-response.md +171 -0
- package/docs/e5-real-agent.md +151 -0
- package/docs/findings.md +108 -0
- package/docs/findings.zh-CN.md +90 -0
- package/docs/judge-calibration.md +170 -0
- package/docs/preregistration.md +257 -0
- package/docs/validation.md +30 -0
- package/docs/validation.zh-CN.md +24 -0
- package/package.json +65 -4
- package/src/audit.js +222 -0
- package/src/cli.js +293 -0
- package/src/frontmatter.js +128 -0
- package/src/index.js +34 -0
- package/src/mcp.js +310 -0
- package/src/store.js +415 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# whynot — paste this block into your AGENTS.md / CLAUDE.md
|
|
2
|
+
|
|
3
|
+
The block below is the *behavioral* half of whynot. The MCP server gives the
|
|
4
|
+
agent the ability to read and write decisions; this text is what makes it
|
|
5
|
+
actually do so. Copy it verbatim.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Recorded decisions (`.decisions/`)
|
|
10
|
+
|
|
11
|
+
This repository keeps a record of settled decisions — especially approaches
|
|
12
|
+
that were **tried and rejected** — in `.decisions/`.
|
|
13
|
+
|
|
14
|
+
**At the start of a session**, call `decisions_check` with no arguments. You get
|
|
15
|
+
a compact index (id, type, title, tags) of everything already settled. It is
|
|
16
|
+
short by design — read it once.
|
|
17
|
+
|
|
18
|
+
**Before proposing a technical approach**, call `decisions_check` with keywords
|
|
19
|
+
for what you are about to suggest, and read the full entries that come back. If
|
|
20
|
+
the topic is covered, do not re-propose the rejected option. You may propose it
|
|
21
|
+
again only if you can point to concrete evidence that the stated `revisit_when`
|
|
22
|
+
condition has now been met.
|
|
23
|
+
|
|
24
|
+
Matching is keyword-based, so **query with the nouns the entry would use**, and
|
|
25
|
+
try more than one phrasing before concluding nothing is recorded. An empty
|
|
26
|
+
result means "nothing found", not "nothing decided".
|
|
27
|
+
|
|
28
|
+
**When the user rejects one of your suggestions**, or when you discover that an
|
|
29
|
+
approach does not work, call `decisions_record` with:
|
|
30
|
+
- `title` — what was ruled out
|
|
31
|
+
- `why` — the specific reason it failed (not "it didn't work"; say what broke)
|
|
32
|
+
- `type: rejected`
|
|
33
|
+
- `evidence` — a commit sha, PR number, or URL a human can check later
|
|
34
|
+
- `revisit_when` — strongly preferred: the condition that would change the answer
|
|
35
|
+
|
|
36
|
+
Every entry expires (90 days for a rejection by default) and then stops being
|
|
37
|
+
shown to you. If a decision is genuinely permanent, say so to the user and let
|
|
38
|
+
them decide — do not set a long TTL yourself to work around this.
|
|
39
|
+
|
|
40
|
+
**When you are asked to plan or design**, call `decisions_stale` first and
|
|
41
|
+
surface anything that needs re-confirmation. Do not silently follow a stale
|
|
42
|
+
entry; ask. A stale entry is a question for the user, not an instruction.
|
|
43
|
+
|
|
44
|
+
Never invent an entry, and never record something the user did not actually
|
|
45
|
+
decide. A wrong entry is worse than a missing one, because it will be trusted
|
|
46
|
+
for months.
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## Registering the MCP server
|
|
51
|
+
|
|
52
|
+
`decisions_check` / `decisions_record` / `decisions_stale` come from the whynot
|
|
53
|
+
MCP server. Add it to your agent's MCP config:
|
|
54
|
+
|
|
55
|
+
```json
|
|
56
|
+
{
|
|
57
|
+
"mcpServers": {
|
|
58
|
+
"whynot": {
|
|
59
|
+
"command": "npx",
|
|
60
|
+
"args": ["-y", "whynot-cli", "mcp"]
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
If your agent reads `AGENTS.md` but not MCP, the fallback still works: the
|
|
67
|
+
entries are plain Markdown in `.decisions/`, so the agent can read and grep them
|
|
68
|
+
directly. That is intentional — the format is the product, and it keeps working
|
|
69
|
+
without the tool.
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# whynot —— 把这段粘进你的 AGENTS.md / CLAUDE.md
|
|
2
|
+
|
|
3
|
+
下面这段是 whynot 的**行为部分**。MCP server 只是让 agent 有能力读写;真正让它
|
|
4
|
+
主动去做的,是这段文字。请原样复制。
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## 已记录的决策(`.decisions/`)
|
|
9
|
+
|
|
10
|
+
这个仓库在 `.decisions/` 里记录已经定下来的决策——尤其是**试过并否决**的方案。
|
|
11
|
+
|
|
12
|
+
**每次会话开始时**,不带参数调用 `decisions_check`。你会得到一个紧凑的索引
|
|
13
|
+
(id、类型、标题、标签),里面是已经定下的所有事。它故意做得很短——读一遍就行。
|
|
14
|
+
|
|
15
|
+
**在提出技术方案之前**,用描述你即将建议的关键词调用 `decisions_check`,然后把
|
|
16
|
+
返回的完整条目读完。如果这个话题已经被覆盖,不要再提被否决的选项。除非你能
|
|
17
|
+
指出明确证据说明 `revisit_when` 条件已经满足,否则不要重新提议。
|
|
18
|
+
|
|
19
|
+
匹配是基于关键词的,所以**用条目里可能出现的名词去查**,并且在得出「没有记录」
|
|
20
|
+
之前,换几种说法再试一次。返回空表示「没找到」,不表示「没定过」。
|
|
21
|
+
|
|
22
|
+
**当用户否决了你的某个建议**,或者你发现某个方案行不通时,调用 `decisions_record`:
|
|
23
|
+
|
|
24
|
+
- `title` —— 被否决的是什么
|
|
25
|
+
- `why` —— 具体是什么失败了(不要写「它不工作」;说清楚哪里崩了)
|
|
26
|
+
- `type: rejected`
|
|
27
|
+
- `evidence` —— 一条 commit sha、PR 号,或者一个 URL,让人以后能核对
|
|
28
|
+
- `revisit_when` —— 强烈建议填写:什么条件会改变这个结论
|
|
29
|
+
|
|
30
|
+
每条记录都会过期(否决类默认 90 天),过期后就不再展示给你。如果某个决策确实
|
|
31
|
+
永久有效,告诉用户,让他们决定——不要自己设一个超长 TTL 来绕过这个机制。
|
|
32
|
+
|
|
33
|
+
**当你被要求做规划或设计时**,先调用 `decisions_stale`,把需要重新确认的东西
|
|
34
|
+
摆出来。不要默默遵循一条过期条目;先问。**过期条目是给用户的问题,不是给你的
|
|
35
|
+
指令。**
|
|
36
|
+
|
|
37
|
+
永远不要编造条目,也不要把用户没有真正决定过的事记进去。一条错误的记录比没有
|
|
38
|
+
记录更糟,因为它会被信任好几个月。
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## 注册 MCP server
|
|
43
|
+
|
|
44
|
+
`decisions_check` / `decisions_record` / `decisions_stale` 来自 whynot 的 MCP
|
|
45
|
+
server。在你的 agent 的 MCP 配置里加上:
|
|
46
|
+
|
|
47
|
+
```json
|
|
48
|
+
{
|
|
49
|
+
"mcpServers": {
|
|
50
|
+
"whynot": {
|
|
51
|
+
"command": "npx",
|
|
52
|
+
"args": ["-y", "whynot-cli", "mcp"]
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
如果你的 agent 读 `AGENTS.md` 但不用 MCP,降级方案依然成立:记录就是
|
|
59
|
+
`.decisions/` 里的普通 Markdown,agent 可以直接读、直接 grep。这是刻意的设计
|
|
60
|
+
——**格式本身就是产品**,所以没有工具它也能工作。
|
package/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Thanks for looking. This project is small on purpose, and a few design
|
|
4
|
+
decisions are not open for negotiation. Read this before opening a PR.
|
|
5
|
+
|
|
6
|
+
## The four constraints
|
|
7
|
+
|
|
8
|
+
These are the reason the tool exists. A PR that breaks one will be declined,
|
|
9
|
+
even if it is well written and useful in isolation.
|
|
10
|
+
|
|
11
|
+
1. **The data stays plain Markdown in git.** No database, no binary format, no
|
|
12
|
+
schema that requires the tool to read. If this project dies, users must be
|
|
13
|
+
able to `grep` their own files.
|
|
14
|
+
|
|
15
|
+
2. **No vector store, no embeddings, no model call on the write path.**
|
|
16
|
+
Retrieval quality is not the bottleneck; auditability is. Vector stores and
|
|
17
|
+
LLM-extracted memories are the failure modes this project is a response to.
|
|
18
|
+
|
|
19
|
+
3. **No daemon, no background process, no file watching.** The tool runs when
|
|
20
|
+
it is called. Background processes are how these tools become unreliable and
|
|
21
|
+
then abandoned.
|
|
22
|
+
|
|
23
|
+
4. **No hosted service, no telemetry, no account.** Decisions about someone's
|
|
24
|
+
codebase are the most sensitive thing in their repository. They stay on the
|
|
25
|
+
user's machine.
|
|
26
|
+
|
|
27
|
+
If you think one of these should change, open an issue and make the argument
|
|
28
|
+
with evidence. The constraints are load-bearing, not aesthetic.
|
|
29
|
+
|
|
30
|
+
## What is welcome
|
|
31
|
+
|
|
32
|
+
- Bug fixes, especially cross-platform ones.
|
|
33
|
+
- Better heuristics for `whynot audit`, with tests.
|
|
34
|
+
- Documentation that is shorter or clearer than what it replaces.
|
|
35
|
+
- Additional agent integrations that reuse the existing file format.
|
|
36
|
+
- Reproductions of the validation experiments on other models. If a model
|
|
37
|
+
behaves differently from what `docs/validation.md` reports, that is a useful
|
|
38
|
+
finding — please share it.
|
|
39
|
+
|
|
40
|
+
## What will be declined
|
|
41
|
+
|
|
42
|
+
- Anything that makes the tool heavier without removing a reported problem.
|
|
43
|
+
- New configuration surface. Every option is a thing someone has to understand.
|
|
44
|
+
- "Make it work for teams" features that require a server.
|
|
45
|
+
- PRs that rewrite the README into marketing copy.
|
|
46
|
+
|
|
47
|
+
## Before you send a PR
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
node --test "test/*.test.js"
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
There are no dependencies to install. If a test fails on your machine but not
|
|
54
|
+
in CI, that is a bug worth reporting — the project claims to work on Windows,
|
|
55
|
+
macOS, and Linux.
|
|
56
|
+
|
|
57
|
+
Keep commits focused. One change per PR. Explain *what problem it removes*, not
|
|
58
|
+
what feature it adds.
|
|
59
|
+
|
|
60
|
+
## Style
|
|
61
|
+
|
|
62
|
+
- Plain language in docs. Short sentences. No superlatives.
|
|
63
|
+
- Comments explain *why*, not *what*. If the code needs a comment to say what it
|
|
64
|
+
does, rename something instead.
|
|
65
|
+
- No emoji in source files.
|
|
66
|
+
- Chinese and English docs are kept in sync. If you change one, change both or
|
|
67
|
+
flag it in the PR.
|
|
68
|
+
|
|
69
|
+
## Security and privacy
|
|
70
|
+
|
|
71
|
+
Do not include personal paths, usernames, API keys, or the contents of anyone's
|
|
72
|
+
`~/.codex` or `~/.claude` directory in a PR or an issue. `experiments/out/` is
|
|
73
|
+
gitignored for this reason; keep it that way.
|
|
74
|
+
|
|
75
|
+
If you find a leak, open an issue without pasting the leaked value.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Stakenshake
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,275 @@
|
|
|
1
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<picture>
|
|
3
|
+
<source media="(prefers-color-scheme: dark)" srcset="assets/icon-dark.svg">
|
|
4
|
+
<img src="assets/icon-light.svg" alt="whynot" width="88">
|
|
5
|
+
</picture>
|
|
6
|
+
</p>
|
|
2
7
|
|
|
3
|
-
|
|
8
|
+
<h1 align="center">whynot</h1>
|
|
9
|
+
|
|
10
|
+
<p align="center">
|
|
11
|
+
<b>Your agent keeps re-suggesting what you already rejected.</b><br>
|
|
12
|
+
Record the rejection once. It expires. Your agent stops bringing it up.
|
|
13
|
+
</p>
|
|
14
|
+
|
|
15
|
+
<p align="center">
|
|
16
|
+
<a href="https://www.npmjs.com/package/whynot-cli"><img src="https://img.shields.io/npm/v/whynot-cli?style=flat-square&color=111111&label=npm" alt="npm"></a>
|
|
17
|
+
<img src="https://img.shields.io/badge/license-MIT-blue?style=flat-square" alt="MIT">
|
|
18
|
+
<img src="https://img.shields.io/badge/node-%E2%89%A520-brightgreen?style=flat-square" alt="node 20+">
|
|
19
|
+
<img src="https://img.shields.io/badge/tests-29%20passing-brightgreen?style=flat-square" alt="29 tests passing">
|
|
20
|
+
<img src="https://img.shields.io/badge/dependencies-0-brightgreen?style=flat-square" alt="zero dependencies">
|
|
21
|
+
</p>
|
|
22
|
+
|
|
23
|
+
<p align="center">
|
|
24
|
+
<img src="https://img.shields.io/badge/platform-Windows%20%7C%20macOS%20%7C%20Linux-lightgrey?style=flat-square" alt="platforms">
|
|
25
|
+
<img src="https://img.shields.io/badge/MCP-compatible-8A2BE2?style=flat-square" alt="MCP compatible">
|
|
26
|
+
<img src="https://img.shields.io/badge/Claude%20Code%20%C2%B7%20Codex%20%C2%B7%20Cursor%20%C2%B7%20Gemini%20CLI-supported-informational?style=flat-square" alt="agent support">
|
|
27
|
+
</p>
|
|
28
|
+
|
|
29
|
+
<p align="center">
|
|
30
|
+
<a href="README.md">English</a> · <a href="README.zh-CN.md">简体中文</a>
|
|
31
|
+
</p>
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
<p align="center">
|
|
36
|
+
<a href="#the-problem">The problem</a> ·
|
|
37
|
+
<a href="#install">Install</a> ·
|
|
38
|
+
<a href="#quick-start">Quick start</a> ·
|
|
39
|
+
<a href="#how-it-works">How it works</a> ·
|
|
40
|
+
<a href="#what-the-evidence-says">Evidence</a> ·
|
|
41
|
+
<a href="#docs">Docs</a> ·
|
|
42
|
+
<a href="#license">License</a>
|
|
43
|
+
</p>
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## The problem
|
|
48
|
+
|
|
49
|
+
You tried Redis for session storage. It failed at 8 seconds during a regional
|
|
50
|
+
outage, so you moved to Postgres.
|
|
51
|
+
|
|
52
|
+
Three weeks later, in a new session, your agent suggests Redis.
|
|
53
|
+
|
|
54
|
+
You explain again. A month after that you switch from Claude Code to Codex, and
|
|
55
|
+
explain a third time. Six months later you no longer remember why Redis was
|
|
56
|
+
rejected — and neither does anyone else on the team.
|
|
57
|
+
|
|
58
|
+
**Code remembers what you chose. Nothing remembers what you rejected.**
|
|
59
|
+
|
|
60
|
+
Memory tools record what happened. That is already in your commits, your pull
|
|
61
|
+
requests, and the code itself. `whynot` records the other half: the options you
|
|
62
|
+
ruled out, and the reason, in a file your agent reads before it proposes
|
|
63
|
+
anything.
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Install
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
npx whynot-cli init
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Nothing to install globally, no account, no telemetry. Node 20+ is the only
|
|
74
|
+
requirement.
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Quick start
|
|
79
|
+
|
|
80
|
+
### 1. See what will never expire
|
|
81
|
+
|
|
82
|
+
`audit` is read-only. It scans your existing `AGENTS.md`, `CLAUDE.md`, and
|
|
83
|
+
`.cursor/rules` for absolute rules that state no condition — the ones that will
|
|
84
|
+
be obeyed forever.
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
npx whynot-cli audit
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
Scanned 2 agent config files:
|
|
92
|
+
AGENTS.md (last changed 412d ago)
|
|
93
|
+
CLAUDE.md (last changed 8d ago)
|
|
94
|
+
|
|
95
|
+
3 rules look like permanent constraints:
|
|
96
|
+
|
|
97
|
+
AGENTS.md:3
|
|
98
|
+
"Never use TypeScript in this repo."
|
|
99
|
+
→ absolute rule with no stated condition; unchanged for 412 days
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### 2. Create the store
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
npx whynot-cli init
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
This creates `.decisions/` and adds `*.md text eol=lf` to `.gitattributes`.
|
|
109
|
+
|
|
110
|
+
### 3. Record a rejection
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
npx whynot-cli add \
|
|
114
|
+
--title "session 不存 Redis" \
|
|
115
|
+
--why "us-east 故障时读延迟 8s,SLO 要求 p99 < 500ms" \
|
|
116
|
+
--type rejected \
|
|
117
|
+
--revisit "Redis 支持跨区域强一致时" \
|
|
118
|
+
--evidence pr:412 \
|
|
119
|
+
--tags infra,session
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
```markdown
|
|
123
|
+
---
|
|
124
|
+
id: 0001
|
|
125
|
+
title: session 不存 Redis
|
|
126
|
+
type: rejected
|
|
127
|
+
status: live
|
|
128
|
+
created: 2026-09-21
|
|
129
|
+
expires_on: 2026-12-20
|
|
130
|
+
revisit_when: "Redis 支持跨区域强一致时"
|
|
131
|
+
evidence:
|
|
132
|
+
- "pr:412"
|
|
133
|
+
tags: [infra, session]
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## 结论
|
|
137
|
+
不能把 session 存 Redis。
|
|
138
|
+
|
|
139
|
+
## 为什么
|
|
140
|
+
试过 Redis + 单写区域。us-east 故障时读延迟飙到 8s,SLO 要求 p99 < 500ms。
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### 4. Give it to your agent
|
|
144
|
+
|
|
145
|
+
Add the MCP server:
|
|
146
|
+
|
|
147
|
+
```json
|
|
148
|
+
{
|
|
149
|
+
"mcpServers": {
|
|
150
|
+
"whynot": {
|
|
151
|
+
"command": "npx",
|
|
152
|
+
"args": ["-y", "whynot-cli", "mcp"]
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Then paste the block from [`AGENTS.snippet.md`](AGENTS.snippet.md) into your
|
|
159
|
+
`AGENTS.md` or `CLAUDE.md`. The MCP server gives the agent the tools; the
|
|
160
|
+
snippet is what makes it actually use them.
|
|
161
|
+
|
|
162
|
+
> **If MCP is unavailable, the format still works.** `.decisions/` is plain
|
|
163
|
+
> Markdown, so the agent can read and grep it directly. This was observed in the
|
|
164
|
+
> real-agent test, not assumed.
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## How it works
|
|
169
|
+
|
|
170
|
+
### Every entry expires
|
|
171
|
+
|
|
172
|
+
| Type | Default lifetime |
|
|
173
|
+
|---|---|
|
|
174
|
+
| `rejected` | 90 days |
|
|
175
|
+
| `decision` | 180 days |
|
|
176
|
+
| `constraint` | 365 days |
|
|
177
|
+
|
|
178
|
+
When an entry lapses it **stops reaching your agent**. Not annotated, not
|
|
179
|
+
warned about — absent. `whynot stale` lists it, and you either renew it or
|
|
180
|
+
retire it.
|
|
181
|
+
|
|
182
|
+
This is the core of the design. Telling an agent "this note is old, be
|
|
183
|
+
skeptical" was tested and does not work. Removing the note from view does.
|
|
184
|
+
|
|
185
|
+
### Three entry types
|
|
186
|
+
|
|
187
|
+
| Type | Use it for |
|
|
188
|
+
|---|---|
|
|
189
|
+
| **`rejected`** | An approach you tried and abandoned. The most valuable kind — nothing else in the repository remembers it. |
|
|
190
|
+
| `decision` | A choice between viable options, with the reason |
|
|
191
|
+
| `constraint` | A hard requirement the project must satisfy |
|
|
192
|
+
|
|
193
|
+
### Written for humans, by design
|
|
194
|
+
|
|
195
|
+
- **Markdown in git.** Read it, diff it, review it, revert it. If this tool
|
|
196
|
+
disappears, `grep` still works.
|
|
197
|
+
- **No vector store, no embeddings, no model call on write.** Each of those is
|
|
198
|
+
a failure mode: index staleness, write-path cost, and results nobody can
|
|
199
|
+
audit.
|
|
200
|
+
- **No daemon, no telemetry, no hosted service.** Your reasoning about your own
|
|
201
|
+
codebase stays on your machine.
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
## What the evidence says
|
|
206
|
+
|
|
207
|
+
Six experiments, three model families, mostly n=20 per cell.
|
|
208
|
+
|
|
209
|
+
| Question | Result |
|
|
210
|
+
|---|---|
|
|
211
|
+
| Does the age of a decision matter? | **No.** 30 days and 7 years were obeyed at the same rate (0/12 each). Expired → 12/12. |
|
|
212
|
+
| Does recording a rejection change the answer? | **Yes.** 78–87 percentage points, p < 0.0001. |
|
|
213
|
+
| Does an irrelevant record distort unrelated work? | **No.** 0/30. |
|
|
214
|
+
| Does a real agent use it across sessions? | **Yes.** Codex respected the decision in 9/9 sessions. |
|
|
215
|
+
|
|
216
|
+
Two qualifications worth knowing before you install:
|
|
217
|
+
|
|
218
|
+
- **About one in five responses resisted a stale record** — by attacking its
|
|
219
|
+
stated reason. A reason that names a *condition* ("the team did not know
|
|
220
|
+
TypeScript") invites re-checking; one that states a *property* ("this project
|
|
221
|
+
changes constantly") does not.
|
|
222
|
+
- **With real code in context, some agents infer the answer from the repository**
|
|
223
|
+
and ignore the record. Records matter most for what code cannot express: the
|
|
224
|
+
option you rejected.
|
|
225
|
+
|
|
226
|
+
Full results, methods, and reproduction scripts: [`docs/findings.md`](docs/findings.md).
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## Docs
|
|
231
|
+
|
|
232
|
+
| | |
|
|
233
|
+
|---|---|
|
|
234
|
+
| [Design](docs/design.md) | Why the tool looks like this |
|
|
235
|
+
| [Findings](docs/findings.md) | Every experiment, what it found, what it did not |
|
|
236
|
+
| [Validation](docs/validation.md) | Index of the detailed write-ups |
|
|
237
|
+
| [Pre-registration](docs/preregistration.md) | Decision rules fixed before the data |
|
|
238
|
+
| [Contributing](CONTRIBUTING.md) | The four design constraints that are not negotiable |
|
|
239
|
+
| [AGENTS snippet](AGENTS.snippet.md) | The block that makes your agent use this |
|
|
240
|
+
|
|
241
|
+
---
|
|
242
|
+
|
|
243
|
+
## CLI reference
|
|
244
|
+
|
|
245
|
+
```
|
|
246
|
+
whynot init Create .decisions/ and the .gitattributes rule
|
|
247
|
+
whynot add --title T --why W Record an entry
|
|
248
|
+
[--type rejected|decision|constraint]
|
|
249
|
+
[--revisit "condition"] When to reconsider
|
|
250
|
+
[--ttl N] Days until it expires
|
|
251
|
+
[--expires never] Explicitly permanent
|
|
252
|
+
[--evidence pr:412] Repeatable
|
|
253
|
+
[--tags infra,session]
|
|
254
|
+
whynot list [--all] List live entries
|
|
255
|
+
whynot check "<query>" Show live entries matching a query
|
|
256
|
+
whynot stale Entries needing a human decision
|
|
257
|
+
whynot renew <id> [--days N] Extend an entry's life
|
|
258
|
+
whynot retire <id> Archive an entry (never deletes)
|
|
259
|
+
whynot audit [--days N] Scan agent config files (read-only)
|
|
260
|
+
whynot doctor Validate the store
|
|
261
|
+
whynot mcp Run the MCP server on stdio
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
---
|
|
265
|
+
|
|
266
|
+
## License
|
|
267
|
+
|
|
268
|
+
MIT. No account, no telemetry, no paid tier, no closed binary.
|
|
269
|
+
There is nothing to upsell you.
|
|
270
|
+
|
|
271
|
+
---
|
|
272
|
+
|
|
273
|
+
<p align="center">
|
|
274
|
+
<sub><a href="README.zh-CN.md">简体中文</a> · <a href="https://github.com/Stakenshake/whynot">GitHub</a> · <a href="https://www.npmjs.com/package/whynot-cli">npm</a></sub>
|
|
275
|
+
</p>
|