@r1z4x/tezgah 1.6.0 → 1.7.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.
Files changed (64) hide show
  1. package/CHANGELOG.md +80 -1
  2. package/MANIFEST +5 -0
  3. package/README.md +6 -3
  4. package/bin/tezgah-docs +18 -16
  5. package/bin/tezgah-doctor +152 -0
  6. package/bin/tezgah-research +234 -10
  7. package/bin/tezgah-route +48 -1
  8. package/bin/tezgah-setup +26 -13
  9. package/bin/tezgah-task +589 -17
  10. package/bin/tezgah-taste +48 -10
  11. package/docs/architecture.md +7 -4
  12. package/docs/clarity-baseline.json +2 -2
  13. package/docs/contract.md +108 -24
  14. package/docs/evidence.md +201 -28
  15. package/docs/feature-audit.md +1 -1
  16. package/docs/gate.md +60 -22
  17. package/docs/glossary.md +4 -4
  18. package/docs/hosts.md +8 -8
  19. package/docs/index.json +11 -5
  20. package/docs/judge.md +9 -3
  21. package/docs/models.md +35 -2
  22. package/docs/operations.md +103 -3
  23. package/docs/research.md +346 -13
  24. package/docs/skills.md +1 -1
  25. package/docs/status-line.md +5 -5
  26. package/docs/testing.md +2 -2
  27. package/docs/vision.md +12 -4
  28. package/hooks/hooks.json +2 -2
  29. package/hooks/lang/en.json +323 -0
  30. package/hooks/lang/tr.json +344 -0
  31. package/hooks/projects-posttooluse.py +24 -5
  32. package/hooks/projects-pretooluse.py +9 -4
  33. package/hooks/projects-stop.py +28 -16
  34. package/hooks/tezgah_agents.py +29 -10
  35. package/hooks/tezgah_clarity.py +7 -3
  36. package/hooks/tezgah_context.py +425 -406
  37. package/hooks/tezgah_gate.py +583 -33
  38. package/hooks/tezgah_integrity.py +1480 -197
  39. package/hooks/tezgah_models.py +337 -15
  40. package/hooks/tezgah_paths.py +103 -10
  41. package/hooks/tezgah_policy.py +258 -126
  42. package/hooks/tezgah_rank.py +29 -27
  43. package/hooks/tezgah_replay.py +200 -30
  44. package/hooks/tezgah_research.py +1294 -9
  45. package/hooks/tezgah_stopspec.py +7 -0
  46. package/hooks/tezgah_store.py +74 -27
  47. package/hooks/tezgah_task.py +915 -6
  48. package/hosts/codex/hook.py +9 -10
  49. package/hosts/cursor/hook.py +21 -14
  50. package/hosts/dsh/hooks.json +2 -2
  51. package/hosts/omp/hook.py +44 -23
  52. package/hosts/omp/tezgah-hook.ts.in +93 -7
  53. package/hosts/opencode/plugins/tezgah.js +102 -2
  54. package/output-styles/tezgah.md +76 -42
  55. package/package.json +1 -1
  56. package/skills/i-have-adhd/EVALS.md +22 -2
  57. package/skills/i-have-adhd/SKILL.md +12 -5
  58. package/skills/plan-add/SKILL.md +5 -3
  59. package/skills/plan-sync/SKILL.md +5 -3
  60. package/skills/ponytail/EVALS.md +21 -2
  61. package/skills/ponytail/SKILL.md +4 -4
  62. package/skills/research/SKILL.md +89 -1
  63. package/skills/tezgah-contract/EVALS.md +52 -7
  64. package/skills/tezgah-contract/SKILL.md +151 -56
@@ -96,7 +96,7 @@ measure the surface cannot see, then armed-and-used or armed-not-used.
96
96
  | `graph` | a code-graph tool call (an `mcp__…codegraph…` tool) | `.no-graph` — a missing binary is `idx`'s report, not this mark's |
97
97
  | `orch` | a delegate call (`Task`/`Agent`/`spawn_agent`) or a subagent start | `orchestrate-off` |
98
98
  | `judge` | a shell command really ran `tezgah-triage` or `tezgah-docs` | `judge-off`, or no credential: no `TYPESAFE_API_KEY` and no non-empty `~/.config/typesafe/key`, and neither the fallback's `OPENROUTER_API_KEY` nor its `~/.config/openrouter/key` |
99
- | `gate` | never `on`: shown only as `gate✗`, right after the version, in two cases. One: the prompt hook found at least 3 gated calls in this session's transcript since its first turn: write and shell calls, every one of which the gate answers with a `began` or a `deny` row (Bash/PowerShell/Edit/Write/MultiEdit/NotebookEdit on Claude, `exec_command`/`shell`/`apply_patch` on Codex). Over the same span the ledger holds no row from the gate. A PostToolUse row is no proof: that hook keeps writing while a broken PreToolUse lets every call through. The same prompt carries the line "tezgah gate inactive on this host: ...". Two: a kill switch appeared after the session's first prompt; the prompt hook writes one `disarm` row naming it (`disarmed`, baseline a `switches` row of `<cache>/tezgah.db`). The mark is a `gate_inactive` row of the same database (`gate_inactive`, audit Phase 1.3) | a row from the gate appears and no switch armed mid-session is still armed |
99
+ | `gate` | never `on`: shown only as `gate✗`, right after the version, in two cases. One: the prompt hook found at least 3 gated calls in this session's transcript since its first turn: write and shell calls, every one of which the gate answers with a `began` or a `deny` row (Bash/PowerShell/Edit/Write/MultiEdit/NotebookEdit on Claude, `bash`/`edit`/`write` `toolCall` blocks on omp, `exec_command`/`shell`/`apply_patch` on Codex). Over the same span the ledger holds no row from the gate. A PostToolUse row is no proof: that hook keeps writing while a broken PreToolUse lets every call through. The same prompt carries the line "tezgah gate inactive on this host: ...". Two: a kill switch appeared after the session's first prompt; the prompt hook writes one `disarm` row naming it (`disarmed`, baseline a `switches` row of `<cache>/tezgah.db`). The mark is a `gate_inactive` row of the same database (`gate_inactive`, audit Phase 1.3) | a row from the gate appears and no switch armed mid-session is still armed |
100
100
  | `drift` | never `on`: shown as `drift✗` when a session start found tezgah's own hook entries changed since install (`hooks/tezgah_attest.py::run`). One mark per session and host, a `harness_drift` row of `<cache>/tezgah.db` keyed `<session hash>.<host>`; the session's `attest` row names what drifted | the next clean start of that host in that session |
101
101
  | `crash` | never `on`: shown as `crash✗` when a hook of this session could not import its core and ran without tezgah (`hooks/tezgah_guard.py::import_failed`, mark an `import_crash` row of `~/.cache/tezgah/tezgah.db` keyed `<session hash>`). When `tezgah_context` itself is the module that failed, `statusline.py` prints `tezgah ✗ core import failed` instead of the line | never by itself: the mark stays for the session |
102
102
 
@@ -160,11 +160,11 @@ the command really ran it (34-38,84) and is the one writer that can earn `judge`
160
160
  (a run of `bin/tezgah-triage` or `bin/tezgah-docs`, `shell_kind`, `hooks/tezgah_context.py::shell_kind`)
161
161
  — plus `hooks/projects-auto-init.py::main`
162
162
  (`orch` on subagent start), `hosts/codex/hook.py::main`,
163
- `hosts/cursor/hook.py::dispatch`, hosts/opencode/plugins/tezgah.js:2144-2151,
164
- hosts/opencode/plugins/tezgah.js:2702, `hosts/omp/hook.py::handle`. Both Claude (hooks/hooks.json) and dsh
163
+ `hosts/cursor/hook.py::dispatch`, hosts/opencode/plugins/tezgah.js:2167-2174,
164
+ hosts/opencode/plugins/tezgah.js:2725, `hosts/omp/hook.py::handle`. Both Claude (hooks/hooks.json) and dsh
165
165
  (hosts/dsh/hooks.json) wire PostToolUse to that one shared hook, which is how dsh
166
166
  gets any used mark at all: with no local transcript, the store is the only channel
167
- its line has (hooks/projects-posttooluse.py:33-37).
167
+ its line has (hooks/projects-posttooluse.py:45-49).
168
168
 
169
169
  Claude's line never reads the store: it parses `tool_use` blocks out of
170
170
  `payload["transcript_path"]` plus the subagent transcripts under it, which is how
@@ -185,7 +185,7 @@ Every other surface reads the store.
185
185
  `setWidget`, and it is plain because omp strips ANSI (12-29). `status_line()`
186
186
  builds the line and carries `idx_override`, so a per-tool redraw forks no git
187
187
  (`hosts/omp/hook.py::status_line`); it redraws on session start, session switch, turn end
188
- and each watched tool result (hosts/omp/tezgah-hook.ts.in:541-569,607-612,653-678).
188
+ and each watched tool result (hosts/omp/tezgah-hook.ts.in:596-636,674-679,720-745).
189
189
  **Motion:** while the agent runs (`agent_start` until an `agent_end` whose
190
190
  `isTerminal` is not `false`) the widget leads with a braille spinner, the tool
191
191
  in flight (`tool_execution_start`/`_end`, "thinking" between tools) and the
package/docs/testing.md CHANGED
@@ -69,11 +69,11 @@ No matrix cancels its other legs when one fails (`fail-fast: false`).
69
69
  pull request's base. A change only under `docs/`, `assets/`, a root `*.md`
70
70
  page or the GitHub templates is prose: it runs `docs` and nothing else. An
71
71
  empty diff, a base it cannot read, a release or a manual run runs everything.
72
- - `docs`, prose only: the citations audit and
72
+ - `docs`, prose only: the citations audit, the clarity audit and
73
73
  `tests/impacted.py --ref <base>`, which maps a docs page to the docs modules.
74
74
  - `test` (`ci.yml:100`) on Python 3.10 and 3.14, the floor and the ceiling.
75
75
  It byte-compiles, lints with ruff from `requirements-dev.txt` (pip cached),
76
- audits the docs citations and runs `TEZGAH_E2E_STRICT=1 python3
76
+ audits the docs citations and clarity and runs `TEZGAH_E2E_STRICT=1 python3
77
77
  tests/e2e_plan_flow.py`. On `main` it also runs the serial suite with `-v`.
78
78
  A pull request skips that step, and so does a release, which passes the
79
79
  `release` input and runs one 3.10 leg.
package/docs/vision.md CHANGED
@@ -25,8 +25,10 @@ the workspace's own records; every number below names where it came from.
25
25
  3. **One review per plan, two rounds, fanned out.** Reviewers read the plan's
26
26
  whole diff once, in its verification phase. Round one spawns them together,
27
27
  one per dimension. Only a confirmed critical or major finding opens round two,
28
- and round two reads the fix's delta. After round two the user gets what is
29
- left, or the plan lists it as fix-later. `tezgah-task review` refuses a third
28
+ and round two reads the fix's delta. The session fixes a minor or suggestion
29
+ finding without a new round. The plan lists one fix-later only when it waits
30
+ on a user decision (KARAR). After round two the session fixes what is left,
31
+ or the plan lists it fix-later only with KARAR. `tezgah-task review` refuses a third
30
32
  round (`hooks/tezgah_agents.py::_reviewer_body`, `bin/tezgah-task::cmd_review`).
31
33
  (Measured: the old loop opened a round on any finding and ended only on a
32
34
  clean round. It reviewed one finished plan round after round. In another plan,
@@ -46,10 +48,16 @@ the workspace's own records; every number below names where it came from.
46
48
  | Tier | Command | Wall time |
47
49
  |---|---|---|
48
50
  | edit loop | `tests/impacted.py --run <changed paths>` | 0.1-95 s (integrity+gate: 18 modules, 93.8 s) |
49
- | pre-commit | that set + compileall + ruff (+ `--citations` when hooks/ or bin/ moved) | +~5 s |
50
- | pre-merge, once | `tests/impacted.py --all` + the two e2e scripts | 103.5 s (8 shards; 566.9 s serial) |
51
+ | pre-commit | that set + compileall + ruff | +~5 s |
52
+ | merge step, once | `tests/impacted.py --all` + neuter + `tezgah-docs --citations` and `--clarity` + `render_table.py --acceptance --strict` + the two e2e scripts | 103.5 s for the suite (8 shards; 566.9 s serial), the rest not timed here |
51
53
  | CI | the same, on the matrix in `.github/workflows/ci.yml` | unchanged |
52
54
 
55
+ Nothing in the merge-step row runs inside a turn (`AGENTS.md`, "Checks, by
56
+ tier", and `hooks/tezgah_policy.py::CORE`). The cut came from a replay of 522 turns
57
+ (the check-loop-cost research line, variant D). It kept 0.5958 of the in-turn
58
+ checks and lost no failure the status quo caught. A third of those failures
59
+ surface at the merge step or in CI instead of in the turn.
60
+
53
61
  A path the map does not know runs everything (`tests/impacted.py::modules_for`): `tests/support.py`,
54
62
  `hooks/tezgah_paths.py` and anything new. `tests/test_impacted.py` refuses a
55
63
  change that would silently run nothing.
package/hooks/hooks.json CHANGED
@@ -13,12 +13,12 @@
13
13
  { "hooks": [ { "type": "command", "command": "\"${TEZGAH_PYTHON:-python3}\" \"${CLAUDE_PLUGIN_ROOT}/hooks/projects-auto-init.py\"", "timeout": 10 } ] }
14
14
  ],
15
15
  "PreToolUse": [
16
- { "matcher": "Agent|agent|Task|task|Grep|grep|Bash|bash|PowerShell|pwsh|Shell|shell|subagent|Edit|Write|MultiEdit|NotebookEdit", "hooks": [ { "type": "command", "command": "\"${TEZGAH_PYTHON:-python3}\" \"${CLAUDE_PLUGIN_ROOT}/hooks/projects-pretooluse.py\"", "timeout": 5 } ] },
16
+ { "matcher": "Agent|agent|Task|task|Grep|grep|Bash|bash|PowerShell|pwsh|Shell|shell|subagent|Edit|Write|MultiEdit|NotebookEdit|AskUserQuestion", "hooks": [ { "type": "command", "command": "\"${TEZGAH_PYTHON:-python3}\" \"${CLAUDE_PLUGIN_ROOT}/hooks/projects-pretooluse.py\"", "timeout": 5 } ] },
17
17
  { "matcher": "^mcp__(?:.*[^A-Za-z0-9])?(?:append|cancel|clear|click|close|comment|commit|copy|create|delete|deploy|drag|edit|email|evaluate|exec|execute|fill|insert|install|kill|launch|merge|message|mkdir|move|navigate|notify|patch|pause|post|press|print|publish|push|put|release|remove|rename|replace|reply|resume|review|run|save|send|set|share|skip|start|stop|submit|swipe|tag|tap|terminate|type|uninstall|update|upload|write)(?:[^A-Za-z0-9].*)?$", "hooks": [ { "type": "command", "command": "\"${TEZGAH_PYTHON:-python3}\" \"${CLAUDE_PLUGIN_ROOT}/hooks/projects-pretooluse.py\"", "timeout": 5 } ] }
18
18
  ],
19
19
  "PostToolUse": [
20
20
  { "matcher": "Edit|edit|Write|write|MultiEdit|NotebookEdit|Bash|bash|PowerShell|pwsh|str_replace_editor|WebFetch|WebSearch|web_fetch|web_search|fetch|mcp__.*", "hooks": [ { "type": "command", "command": "\"${TEZGAH_PYTHON:-python3}\" \"${CLAUDE_PLUGIN_ROOT}/hooks/projects-posttooluse.py\"", "timeout": 5 } ] },
21
- { "matcher": "Agent|Task|Skill", "hooks": [ { "type": "command", "command": "\"${TEZGAH_PYTHON:-python3}\" \"${CLAUDE_PLUGIN_ROOT}/hooks/projects-posttooluse.py\"", "timeout": 5 } ] }
21
+ { "matcher": "Agent|Task|Skill|TodoWrite", "hooks": [ { "type": "command", "command": "\"${TEZGAH_PYTHON:-python3}\" \"${CLAUDE_PLUGIN_ROOT}/hooks/projects-posttooluse.py\"", "timeout": 5 } ] }
22
22
  ],
23
23
  "PostToolUseFailure": [
24
24
  { "matcher": "Edit|edit|Write|write|MultiEdit|NotebookEdit|Bash|bash|PowerShell|pwsh|str_replace_editor|WebFetch|WebSearch|web_fetch|web_search|fetch|mcp__.*", "hooks": [ { "type": "command", "command": "\"${TEZGAH_PYTHON:-python3}\" \"${CLAUDE_PLUGIN_ROOT}/hooks/projects-posttooluse.py\"", "timeout": 5 } ] }
@@ -0,0 +1,323 @@
1
+ {
2
+ "name": "English",
3
+ "done": [
4
+ "done|complete[d]?|finished|implemented|fixed|shipped|landed|merged|wired up|wired into|all tests? pass|all checks? pass|(?:tests?|checks?|suite) (?:is |are )?(?:green|passing)|build (?:passes|is green)"
5
+ ],
6
+ "verified": [
7
+ "tested|verified|i ran|ran the (?:tests?|suite|build|lint|checks?)"
8
+ ],
9
+ "negated": [
10
+ "unverified|not verified|could ?n[o']t verify|verification (?:was )?skipped"
11
+ ],
12
+ "admitted": [
13
+ "contradict|unsatisfiable|(?:can ?not|can't|can ?never|never) pass|impossible"
14
+ ],
15
+ "sycophant": {
16
+ "interjection": [
17
+ "yes|ah|oh|hmm"
18
+ ],
19
+ "opener": [
20
+ "you'?re (?:absolutely )?right|you are right|absolutely right|good catch|great catch|i didn'?t look closely|i should have checked|my mistake|my bad|sorry, i|great question|let me\\b|i['’]ll\\b|sure[!,.]|looking at your\\b"
21
+ ]
22
+ },
23
+ "closer": [
24
+ "let me know if you need anything else|hope (?:this|that) helps|happy to clarify"
25
+ ],
26
+ "next_action": [
27
+ "next (?:step|action|up)|next:"
28
+ ],
29
+ "preamble": [
30
+ "here(?:'s| is| are)\\b|below\\b|the following\\b"
31
+ ],
32
+ "markers": {
33
+ "letters": [],
34
+ "words": []
35
+ },
36
+ "negation_before": [
37
+ "\\bnot|n't|\\bnever"
38
+ ],
39
+ "question_particle": [],
40
+ "question_end": [],
41
+ "clause_join": [
42
+ "so|and|but"
43
+ ],
44
+ "external_state": [
45
+ "missing|absent|unpublished|exists?|not (?:published|released|found|there|listed|present)|published|released|deprecated|outdated|stale"
46
+ ],
47
+ "external_ci_state": [
48
+ "green|red|passing|passes|passed|failing|fails|failed|behind|flaky"
49
+ ],
50
+ "publish_state": [
51
+ "missing|absent|unpublished|exists?|published|released"
52
+ ],
53
+ "residual_label": [
54
+ "open (?:items?|issues?|questions?|points?|work)|remaining\\b|what(?:'s| is) left|left to do|pending\\b|outstanding\\b|not (?:done|verified|tested|run|checked|covered|looked at)|unverified|untested|unresolved|still open|could(?:n't| not) (?:verify|check|run)|unable to|unchecked|to[ -]?do(?=\\s*(?:\\(|$))|next\\s+(?:steps?|up|actions?)\\b|next(?=\\s*(?:\\(|$))|out of scope|follow[- ]?ups?\\b|deferred|skipped|known (?:issues?|limitations?|bugs?|gaps?)|future (?:work|improvements?)|tech(?:nical)? debt|suggested improvements?|manual (?:verification|checks?|testing)|blockers?\\b|partially"
55
+ ],
56
+ "residual_first": [],
57
+ "label_done": [
58
+ "resolved|addressed|closed"
59
+ ],
60
+ "partial": [
61
+ "partially"
62
+ ],
63
+ "nothing_left": [
64
+ "\\bnone|\\bnothing"
65
+ ],
66
+ "nothing_lead": [
67
+ "no|none|nothing"
68
+ ],
69
+ "empty_item": [
70
+ "none|nothing|n/a"
71
+ ],
72
+ "blockers": {
73
+ "decision": {
74
+ "pattern": "DECISION"
75
+ },
76
+ "irreversible": {
77
+ "pattern": "IRREVERSIBLE"
78
+ },
79
+ "access": {
80
+ "pattern": "ACCESS"
81
+ },
82
+ "env": {
83
+ "pattern": "ENV(?:IRONMENTS?)?"
84
+ },
85
+ "said_not": [
86
+ "not\\b|none\\b|isn"
87
+ ],
88
+ "tried_not": [],
89
+ "absent": []
90
+ },
91
+ "blocker_labels": [
92
+ "blocker"
93
+ ],
94
+ "blockers_only": [
95
+ "blockers?"
96
+ ],
97
+ "env_error": [
98
+ "not found|no such|cannot find|can'?t find|could not find|does(?:n'?t| not) exist|no module named|ModuleNotFound|not installed|not available|unavailable|missing|not set|ENOENT|\\b12[67]\\b|quota|limit exceeded|rate.?limit|\\b429\\b"
99
+ ],
100
+ "access_error": [
101
+ "permission denied|access denied|not permitted|EACCES|\\b40[13]\\b|quota|limit exceeded|rate.?limit|\\b429\\b"
102
+ ],
103
+ "spawn_words": [
104
+ "sub-?agent|\\bagent|provider|\\bmodel|spawn"
105
+ ],
106
+ "was_exclude": [],
107
+ "was": [],
108
+ "now": [],
109
+ "future": [],
110
+ "word_order": "verb_first",
111
+ "ui_objects": [
112
+ "components?|ui|ux|css|layout|styles?|tokens?|themes?|buttons?|cards?|icons?|labels?|elements?|widgets?|containers?|headers?|footers?|sidebars?|toolbars?|navbars?|nav|menu|modals?|dialogs?|dropdowns?|popovers?|tooltips?|badges?|avatars?|spinners?|skeletons?|inputs?|fields?|forms?|headings?|images?|logos?|grids?|panels?|columns?|screens?|pages?|views?|dashboards?|viewport|tables?|app"
113
+ ],
114
+ "ui_quality": [
115
+ "look\\w*|feels?\\w*|seems?\\w*|renders?\\w*"
116
+ ],
117
+ "hints": {
118
+ "spec": [
119
+ "normal (user )?behaviou?r|clean ui|nicer|more intuitive|un?professional|polish(ed)?|improve the (ui|ux)|make it (better|usable|look)|look(s)? better",
120
+ "refactor\\w* (the |this |our )?(\\w+ ){0,2}(components?|ui|ux|css|layout|screens?|pages?|styles?|theme|forms?|fields?|inputs?|views?|widgets?|buttons?|modals?|dialogs?)|ui|ux|css|tailwind|layout|responsive|hover|focus[- ](?:state|ring|outline|visible|indicator|style)|spacing|typography|component\\w*|dark mode|dark theme|light theme",
121
+ {
122
+ "ui_ask": "theme\\w*"
123
+ },
124
+ "animations?|accessib\\w*|wireframe|mockup|align[- ]?(?:items|self|content)|text-align|alignment\\w*|misalign\\w*|padding",
125
+ {
126
+ "ui_ask": "cent(er|re)\\w*"
127
+ },
128
+ {
129
+ "ui_ask": "margins?"
130
+ },
131
+ "gutter\\w*|line-?height|letter-?spacing|drop-?shadow|box-?shadow|border-?radius|corner radius|fonts?[- ](?:size|family|weight|face|stack|scale)\\w*|type ?scale|colou?r[- ](?:role|scheme|palette|token|contrast)|palette|cards?[- ](?:component\\w*|layout|grid|list|view|title|body|footer|header)|sidebars?|toolbars?|modals?|dialogs?|dropdowns?|popovers?|accordions?|tooltips?|toasts?|avatars?",
132
+ {
133
+ "ui_ask": "badges?"
134
+ },
135
+ "breadcrumbs?",
136
+ {
137
+ "ui_ask": "pagination"
138
+ },
139
+ "tab ?bar|steppers?|spinners?",
140
+ {
141
+ "ui_ask": "skeletons?"
142
+ },
143
+ "disabled\\w*|pressed|active state|selected state|empty state|breakpoints?\\w*|viewport|media quer\\w*|design (system|token|guide|library|language)\\w*|style guides?|wcag\\w*|a11y|aria-?\\w*|screen readers?|tab order|keyboard naviga\\w*|contrast (ratio|level|check|issue)|screenshots?|visual (review|regression|diff|check)|redesign\\w*|revamp\\w*|restyle\\w*|makeover",
144
+ {
145
+ "ui_ask": "cluttered"
146
+ },
147
+ "outdated|cohesive"
148
+ ],
149
+ "consult": [
150
+ "architect(ure|ural)|root cause|migrat(e|ion)|deploy|security|trade-?off|which approach|design decision|irreversible|rollback|schema change|re-?architect\\w*|restructur\\w*|rewrite\\w*|(refactor\\w*|rewrite\\w*) (the |this |our )?(\\w+ ){0,2}(module|subsystem|service|system|layer|engine|architecture|data ?model|code ?base|ingest\\w*)|breaking change\\w*|backwards?[- ]incompatib\\w*|api version\\w*|version(ing)? the api|backfill\\w*|revert\\w*|rollback|performance budget|perf budget|latency budget|hot ?path|threat model\\w*|security review\\w*|cve\\b|concurren\\w*|race condition\\w*|deadlock\\w*|capacit\\w* (plan|budget|test|limit)\\w*|scal(e|ing) (plan|strategy|limit|test)\\w*|load test\\w*|adrs?\\b|architecture decision record\\w*|design doc\\w*|rollout"
151
+ ],
152
+ "research": [
153
+ "research|literature|hypothes(is|es)|experiment(al)?|ablation|hyperparameter|benchmark|survey|paper|dataset|compar\\w*|(a/?b|ab) tests?|user interview\\w*|root[ -]?cause (analys|investigat)\\w*|reference review|lit(erature)?[ -]review|evaluat(e|ing) (whether|the (librar|technique|approach|tool|option|alternative))|measure(?! how (?:long|fast|much time)| the (?:time|duration|latency|speed|runtime))\\w*|post[ -]?mortem|error budget|incident (review|report)|is (this|that|it) (actually )?(true|right)|does (this|that) (claim )?hold"
154
+ ],
155
+ "product": [
156
+ "product(?!ion|ivity|ive)\\w*|feature(?!s?[ -](?:flags?|toggles?|gates?|branch\\w*))\\w*|roadmap|backlog|prd|north star|jtbd|retention|churn|onboarding|cohort|funnel|conversion rate|pricing|prioriti[sz]\\w*|user research|user interview\\w*|ab test|a/b test|activations?\\b|churn(ed|ing|s)?|funnels?|cohorts?|drop-?off|roadmaps?|priorit(y|ies)|adoption|conversion (rate|funnel|drop\\w*)|packaging|monetiz\\w*|price\\w*|tier(?!s?[ -]lists?)\\w*|positioning|value proposition|\\bicp\\b|ideal customer profile|persona\\w*|segment(?!(?:ation)?[ -]faults?)\\w*|(customer|user|product|problem) discovery|opportunity (tree|solution|space|score)|\\bnps\\b|net promoter|\\bcsat\\b|satisfaction|(customer|user)[ -]?feedback\\w*|support ticket\\w*|competitor\\w*|competitive (analysis|landscape|teardown|benchmark)\\w*|wizard|crud|form (validation|field|error|label)|data table|step flow|search (dropdown|box)|form validation|user management|(admin|users?) (panel|screen|page|list)",
157
+ {
158
+ "ui_ask": "(?:admin|users?) table"
159
+ }
160
+ ],
161
+ "graph": [
162
+ "who calls|callers?|call sites?|who uses|what breaks|blast radius|where is|where's|definition of|who invokes|impact (analysis|assessment|of (changing|renaming|removing|deleting|editing))|change impact|ripple effect|(who|what|anything)( else)? (depends on|uses)|dependents? of|dependenc(y|ies) (graph|direction|inversion|cycle)|layer (violation|boundar\\w*|direction)|layering|who imports|which (files|modules) import|call (graph|chain|path|tree|hierarchy)|transitive callers?|callers? of|usages? of|find usages|references? to|is \\w+ (still )?(used|referenced|called)|never called|dead code|unused (code|function|method|module|export|class|variable|import|param\\w*)|unreachable code|orphan(ed)? (module|file|code)|circular (import|dependenc\\w*)|(import|dependenc\\w*) cycle|cycle (between|detection)|(code|app|program|service|main|server|cli|boot) entry ?points?|boot (path|sequence|order)|startup (path|sequence|order)|how is (this|it|\\w+) wired|wired up|rename\\w*"
163
+ ]
164
+ },
165
+ "fan_verbs": [
166
+ "fix|add|update|write|remove|delete|rename|move|refactor|document|bump|create|implement|migrate|replace"
167
+ ],
168
+ "fan_join": [
169
+ "and"
170
+ ],
171
+ "fan_ordinals": [
172
+ "first(?:ly)?",
173
+ "second(?:ly)?"
174
+ ],
175
+ "fan_directives": [
176
+ "in parallel|sub-?agent\\w*|worktrees?|fan[- ]?out|orchestrat\\w*"
177
+ ],
178
+ "data_ask": [
179
+ "(?:design|create|make|build|sketch|propose|need|want)\\w* (?:\\w+ ){0,4}(?:dashboard|charts?|visuali[sz]ation)|(?:metri[ck]s?|kpis?|data|sales|revenue) (?:\\w+ ){0,2}dashboard|(?:what|which) (?:\\w+ ){0,3}(?:metri[ck]s|kpis|charts?) (?:\\w+ ){0,3}(?:should|to|do|matter|would)|what should (?:\\w+ ){0,3}dashboard show|(?:choose|pick|define|track|design)(?:s|ing)? (?:\\w+ ){0,3}(?:metri[ck]s|kpis)|(?:metri[ck]s|kpis) (?:should|to|do|would) (?:\\w+ ){0,2}(?:track|measure|use|watch)|success metrics?|(?:suggest|recommend)\\w* (?:\\w+ ){0,3}charts?|visuali[sz]\\w* (?:\\w+ ){0,3}(?:data|numbers)|data visuali[sz]ation"
180
+ ],
181
+ "code_sense": [
182
+ "\\w\\.(?:py|tsx?|jsx?|json|go|rs|ya?ml|sql|java|rb|css|html)\\b|\\b\\w+_\\w+\\b|/metrics\\b|\\bselect\\b.{0,200}?\\bfrom\\b",
183
+ "\\b(?:tables?|columns?|schema|sql|queries|query|bundle|webpack|vite|tests?|ci|counters?|registry|pipeline|backend|handlers?|structs?|endpoints?|exporters?|export\\w*|servers?|librar\\w*|packages?|modules?|database|index\\w*|middleware|debugger|data (?:structure|flow)s?|clipboard|spinner|threads?|commit|git|functions?|class|component|prop|hooks?|prometheus|grafana|kibana|statsd|opentelemetry|config\\w*|provision\\w*|api|routes?|snake_case)\\b"
184
+ ],
185
+ "constraint": {
186
+ "dont": [
187
+ "(?:do not|don'?t|never)\\s+(?:touch|modify|edit|change|delete|remove|rename|push|commit|merge|deploy|publish|release)\\s+(?:(?:the|any|my|this|that|to|a|an)\\s+)?[`\\\"“]?(?P<obj>[\\w~@/-](?:[\\w./@~-]*[\\w@~/-])?)"
188
+ ],
189
+ "ask": [
190
+ "ask\\s+(?:me\\s+)?(?:first\\s+)?before\\s+(?P<ask>\\w+)"
191
+ ],
192
+ "grant": [
193
+ "without asking(?: me)?|no need to ask|(?:you have|you've got) my (?:approval|permission|go-ahead)|\\bi approve\\b|(?:you are|you're) (?:approved|cleared|authori[sz]ed) to|go ahead and (?:push|release|publish|tag|open)\\w*|don'?t ask (?:me )?(?:again|for (?:approval|permission))"
194
+ ],
195
+ "lift": [
196
+ "ask (?:me )?(?:again|first from now on)|from now on,? ask (?:me )?(?:first|before)|(?:revoke|withdraw)\\w* (?:my |the )?(?:approval|permission|grant)"
197
+ ],
198
+ "lift_outward": [
199
+ "(?:don'?t|do not|stop|hold off(?: on)?|never)\\s+(?:\\w+\\s+){0,2}?(?:push|release|publish|tag|deploy|open (?:a |the )?pr)\\w*"
200
+ ],
201
+ "grant_not": [
202
+ "\\b(?:don'?t|do not|never|stop|didn'?t|did not|why did you)\\b"
203
+ ],
204
+ "grant_not_verb": [],
205
+ "grant_not_soft": []
206
+ },
207
+ "ask": {
208
+ "process": [
209
+ "\\b(?:shall|should|can|may) i (?:now |just |also )?(?:proceed|continue|go on|go ahead|start|begin|keep going|move on|carry on|open (?:a|the) plan|commit|merge|run (?:the )?(?:tests?|checks?|suite))\\b|\\b(?:do you want|would you like|want) me to (?:now |also |just )?(?:proceed|continue|go on|go ahead|start|begin|keep going|move on|carry on|commit|merge|open (?:a|the) plan|run (?:the )?(?:tests?|checks?|suite))\\b|\\bwhich (?:one |step |item |part |task )?(?:first|next)\\b|\\bwhere (?:should i|do i|to) start\\b|\\b(?:ok|okay|ready) to (?:proceed|continue|go ahead|start)\\b"
210
+ ],
211
+ "never_default": [
212
+ "force[- ]?push\\w*|--force\\b|rewrit\\w* (?:the )?history|reset --hard|\\bdelet\\w*|\\bdrop (?:the )?(?:table|database|volume)s?|unpublish\\w*|deprecat\\w*|production|\\bprod\\b|migrat\\w*|credential\\w*|password\\w*|secret\\w*|api key|\\baccount\\w*|e-?mail|send (?:it |this |them )?to\\b"
213
+ ],
214
+ "spend": [
215
+ "spend\\w*|\\bpaid\\b|billing|\\bcost\\w*|\\bbudget\\w*|\\busd\\b|\\$\\s?\\d"
216
+ ],
217
+ "default_mark": [
218
+ "recommend\\w*|\\bdefault\\b|i(?:'d| would) (?:pick|go with|choose)|\\bmy pick\\b"
219
+ ],
220
+ "options": [
221
+ "\\bor\\b|\\boptions?\\b|\\balternatives?\\b|\\bvs\\.?(?=\\s)|\\s/\\s|\\b(?:a|1)\\)?\\s.+?,\\s*(?:b|2)\\)?\\s"
222
+ ],
223
+ "cheap_answer": [
224
+ "yes|yep|yeah|ok(?:ay)?|sure|go(?: on| ahead)?|continue|proceed|do it|carry on|keep going|approved"
225
+ ],
226
+ "outward": {
227
+ "push": "\\bpush\\w*",
228
+ "release": "\\brelease\\w*|\\btag(?:s|ged|ging)?\\b|version bump|bump the version",
229
+ "publish": "\\bpublish\\w*|\\bnpm\\b|homebrew|pypi",
230
+ "pr": "pull request|\\bprs?\\b"
231
+ }
232
+ },
233
+ "needle_stop": [
234
+ "while",
235
+ "in",
236
+ "on",
237
+ "at",
238
+ "without",
239
+ "until",
240
+ "unless",
241
+ "and",
242
+ "or",
243
+ "for",
244
+ "to",
245
+ "with",
246
+ "before",
247
+ "after",
248
+ "from",
249
+ "into",
250
+ "of",
251
+ "but"
252
+ ],
253
+ "rank_stopwords": [
254
+ "the",
255
+ "and",
256
+ "that",
257
+ "this",
258
+ "with",
259
+ "for",
260
+ "from",
261
+ "are",
262
+ "was",
263
+ "were",
264
+ "not",
265
+ "but",
266
+ "its",
267
+ "into",
268
+ "than",
269
+ "then",
270
+ "they",
271
+ "them",
272
+ "their",
273
+ "have",
274
+ "has",
275
+ "had",
276
+ "will",
277
+ "would",
278
+ "can",
279
+ "could",
280
+ "should",
281
+ "you",
282
+ "your",
283
+ "what",
284
+ "when",
285
+ "which",
286
+ "who",
287
+ "how",
288
+ "all",
289
+ "any",
290
+ "out"
291
+ ],
292
+ "fold": [],
293
+ "say": {
294
+ "unverified": "unverified",
295
+ "reply_lang": "English",
296
+ "reply_in": "in English, even when the user\nwrites another language",
297
+ "reply_split": "in English, even when the user writes another language",
298
+ "reply_short": "reply English",
299
+ "gap_example": "\"I did not verify this before the deploy; this is how I weighed the risk: ...\"",
300
+ "blocker_tokens": "DECISION, ACCESS, IRREVERSIBLE, ENV",
301
+ "agree_word": "\"you're right\"",
302
+ "opener_short": "\"you're right\", \"good catch\", \"I didn't look closely\"",
303
+ "decision_gloss": "",
304
+ "access_gloss": "",
305
+ "irreversible_gloss": "",
306
+ "env_gloss": "",
307
+ "blockers_heading": "Blockers",
308
+ "decision": "DECISION",
309
+ "access": "ACCESS",
310
+ "irreversible": "IRREVERSIBLE",
311
+ "env": "ENV",
312
+ "done_claim": "done",
313
+ "opener_examples": "\"you're right\", \"absolutely right\", \"good catch\", \"I didn't look closely\", \"I should have checked\"",
314
+ "opener_ban": "never \"you're right\" / \"I didn't look closely\" / an apology",
315
+ "residual_lead": "",
316
+ "slice_lead": "",
317
+ "ready_lead": "",
318
+ "ask_lead": "",
319
+ "approval_heading": "Approval questions",
320
+ "recommended": "Recommended",
321
+ "grant_examples": "\"push without asking\", \"I approve\""
322
+ }
323
+ }