mishkan-harness 0.2.0 → 0.2.4

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 (116) hide show
  1. package/README.md +108 -172
  2. package/bin/mishkan.js +677 -16
  3. package/docs/design/MISHKAN_decisions.md +450 -8
  4. package/docs/design/MISHKAN_harness_design.md +1 -33
  5. package/docs/design/MISHKAN_observability.md +13 -9
  6. package/docs/engineer/profile-readable.md +201 -0
  7. package/docs/engineer/profile.md +754 -0
  8. package/docs/research/graphify-token-saving-poc.md +108 -0
  9. package/docs/usage/09-workflows.md +74 -4
  10. package/docs/usage/10-observability.md +37 -13
  11. package/docs/usage/11-graphify.md +264 -0
  12. package/docs/usage/12-skill-discovery.md +294 -0
  13. package/docs/usage/README.md +5 -3
  14. package/package.json +1 -1
  15. package/payload/install/settings.hooks.json +24 -0
  16. package/payload/mishkan/AGENT_SPEC.md +25 -7
  17. package/payload/mishkan/agents/ahikam.md +4 -2
  18. package/payload/mishkan/agents/aholiab.md +4 -2
  19. package/payload/mishkan/agents/asaph.md +5 -2
  20. package/payload/mishkan/agents/baruch.md +19 -2
  21. package/payload/mishkan/agents/benaiah.md +4 -2
  22. package/payload/mishkan/agents/bezalel.md +4 -2
  23. package/payload/mishkan/agents/caleb.md +4 -2
  24. package/payload/mishkan/agents/deborah.md +4 -2
  25. package/payload/mishkan/agents/elasah.md +4 -2
  26. package/payload/mishkan/agents/eliashib.md +4 -2
  27. package/payload/mishkan/agents/ezra.md +4 -2
  28. package/payload/mishkan/agents/hanun.md +5 -2
  29. package/payload/mishkan/agents/hiram.md +5 -2
  30. package/payload/mishkan/agents/hizkiah.md +5 -2
  31. package/payload/mishkan/agents/huldah.md +4 -2
  32. package/payload/mishkan/agents/huram.md +4 -2
  33. package/payload/mishkan/agents/hushai.md +5 -2
  34. package/payload/mishkan/agents/igal.md +4 -2
  35. package/payload/mishkan/agents/ira.md +5 -2
  36. package/payload/mishkan/agents/jahaziel.md +5 -2
  37. package/payload/mishkan/agents/jakin.md +4 -2
  38. package/payload/mishkan/agents/jehonathan.md +5 -2
  39. package/payload/mishkan/agents/jehoshaphat.md +4 -2
  40. package/payload/mishkan/agents/joab.md +5 -2
  41. package/payload/mishkan/agents/joah.md +5 -2
  42. package/payload/mishkan/agents/maaseiah.md +4 -2
  43. package/payload/mishkan/agents/meremoth.md +5 -2
  44. package/payload/mishkan/agents/meshullam.md +5 -2
  45. package/payload/mishkan/agents/nathan.md +5 -2
  46. package/payload/mishkan/agents/nehemiah.md +4 -2
  47. package/payload/mishkan/agents/obed.md +4 -2
  48. package/payload/mishkan/agents/oholiab.md +5 -2
  49. package/payload/mishkan/agents/palal.md +5 -2
  50. package/payload/mishkan/agents/phinehas.md +4 -2
  51. package/payload/mishkan/agents/rehum.md +4 -2
  52. package/payload/mishkan/agents/salma.md +5 -2
  53. package/payload/mishkan/agents/seraiah.md +4 -2
  54. package/payload/mishkan/agents/shallum.md +5 -2
  55. package/payload/mishkan/agents/shaphan.md +4 -2
  56. package/payload/mishkan/agents/shemaiah.md +4 -2
  57. package/payload/mishkan/agents/shevna.md +5 -2
  58. package/payload/mishkan/agents/uriah.md +5 -2
  59. package/payload/mishkan/agents/zaccur.md +4 -2
  60. package/payload/mishkan/agents/zadok.md +5 -2
  61. package/payload/mishkan/agents/zerubbabel.md +4 -2
  62. package/payload/mishkan/commands/code-graph.md +35 -0
  63. package/payload/mishkan/commands/eval-baruch.md +57 -0
  64. package/payload/mishkan/commands/mishkan-org-reference.md +58 -0
  65. package/payload/mishkan/commands/mishkan-resume.md +19 -5
  66. package/payload/mishkan/commands/mishkan-skills-misses.md +47 -0
  67. package/payload/mishkan/commands/mishkan-skills-reindex.md +33 -0
  68. package/payload/mishkan/commands/skills.md +35 -0
  69. package/payload/mishkan/commands/sprint-close.md +3 -1
  70. package/payload/mishkan/hooks/pre-tool-knowledge-route.sh +231 -0
  71. package/payload/mishkan/hooks/pre-tool-task-skill-route.sh +122 -0
  72. package/payload/mishkan/hooks/session-start-skill-index.sh +35 -0
  73. package/payload/mishkan/observability/schema.json +1 -1
  74. package/payload/mishkan/observability/watch/src/mishkan_watch/__main__.py +84 -2
  75. package/payload/mishkan/observability/watch/src/mishkan_watch/app.py +64 -3
  76. package/payload/mishkan/observability/watch/src/mishkan_watch/org_data.py +79 -0
  77. package/payload/mishkan/observability/watch/src/mishkan_watch/skills_data.py +267 -0
  78. package/payload/mishkan/observability/watch/src/mishkan_watch/tabs/agents.py +33 -1
  79. package/payload/mishkan/observability/watch/src/mishkan_watch/tabs/knowledge.py +118 -9
  80. package/payload/mishkan/observability/watch/src/mishkan_watch/tabs/live.py +102 -2
  81. package/payload/mishkan/observability/watch/src/mishkan_watch/tabs/org.py +139 -0
  82. package/payload/mishkan/observability/watch/src/mishkan_watch/tabs/skills.py +187 -0
  83. package/payload/mishkan/observability/watch/src/mishkan_watch/tabs/usage.py +377 -0
  84. package/payload/mishkan/observability/watch/src/mishkan_watch/tabs/workflows.py +199 -27
  85. package/payload/mishkan/observability/watch/src/mishkan_watch/theme.tcss +78 -4
  86. package/payload/mishkan/observability/watchd/src/mishkan_watchd/__main__.py +36 -6
  87. package/payload/mishkan/observability/watchd/src/mishkan_watchd/sources/bus_tail.py +16 -3
  88. package/payload/mishkan/observability/watchd/src/mishkan_watchd/sources/graphify_tail.py +220 -0
  89. package/payload/mishkan/observability/watchd/src/mishkan_watchd/sources/worktree_poll.py +13 -2
  90. package/payload/mishkan/observability/watchd/src/mishkan_watchd/state.py +157 -3
  91. package/payload/mishkan/observability/watchd/tests/test_state.py +6 -2
  92. package/payload/mishkan/org/org.json +141 -0
  93. package/payload/mishkan/scripts/pre-commit-eval-gate.sh +50 -0
  94. package/payload/mishkan/scripts/skill-discovery-indexer.py +462 -0
  95. package/payload/mishkan/scripts/skill-discovery-misses.py +173 -0
  96. package/payload/mishkan/scripts/skill-discovery-router.py +457 -0
  97. package/payload/mishkan/scripts/skill-discovery-smoke.sh +156 -0
  98. package/payload/mishkan/skills/graphify-query-craft/SKILL.md +162 -0
  99. package/payload/mishkan/skills/mishkan-init/SKILL.md +15 -0
  100. package/payload/mishkan/skills/skill-discovery/SKILL.md +120 -0
  101. package/payload/mishkan/templates/case-node.schema.json +1 -0
  102. package/payload/mishkan/templates/observability-log.schema.json +1 -0
  103. package/payload/mishkan/workflows/README.md +78 -13
  104. package/payload/mishkan/workflows/chosheb-feature-ship.js +75 -0
  105. package/payload/mishkan/workflows/migdal-dr-drill.js +94 -0
  106. package/payload/mishkan/workflows/migdal-infra-change.js +67 -0
  107. package/payload/mishkan/workflows/mishkan-blast-radius.js +144 -0
  108. package/payload/mishkan/workflows/mishkan-init.js +58 -0
  109. package/payload/mishkan/workflows/mishkan-knowledge-gap-discovery.js +121 -0
  110. package/payload/mishkan/workflows/mishkan-standards-rollout.js +153 -0
  111. package/payload/mishkan/workflows/mishmar-security-gate.js +83 -0
  112. package/payload/mishkan/workflows/panim-ds-rollout.js +83 -0
  113. package/payload/mishkan/workflows/sefer-release-notes.js +85 -0
  114. package/payload/mishkan/workflows/yasad-data-migration-wave.js +78 -0
  115. package/payload/mishkan/workflows/yasad-schema-evolution.js +76 -0
  116. package/payload/mishkan/templates/user-CLAUDE.md +0 -62
@@ -0,0 +1,162 @@
1
+ ---
2
+ name: graphify-query-craft
3
+ description: |
4
+ Use `graphify query "<question>"` to traverse the project's code-structure
5
+ graph for structural questions ("who calls X", "what depends on Y", "where
6
+ is the entry point") at ~1.8k tokens per query — 88.1× cheaper than
7
+ lifting the full source tree into context (verified on MISHKAN harness,
8
+ POC 2026-06-07). Use BEFORE grep / Read on source files whenever the
9
+ question is about code STRUCTURE rather than code SEMANTICS.
10
+ For every code-touching agent across the dev teams (per D-009 amended scope, 2026-06-07): Yasad backend (Hizkiah, Nathan, Zadok, Shallum, Uriah), Panim frontend (Salma, Oholiab, Asaph, Jahaziel), Chosheb UI (Hiram), Mishmar code-security (Ira, Joab, Hushai), Migdal infra-code (Palal, Meshullam, Meremoth, Hanun), Sefer documentation (Joah, Shevna, Jehonathan).
11
+ ---
12
+
13
+ # Graphify query craft
14
+
15
+ ## When to call
16
+
17
+ The crisp test from D-008's epistemological frontier:
18
+
19
+ > **Structure question → Graphify.**
20
+ > **Semantic question → Cognee work.**
21
+
22
+ Examples of **structure** questions you should answer with a `graphify
23
+ query` BEFORE reading any file:
24
+
25
+ - "Who calls `process_payment`?"
26
+ - "What depends on the `User` model?"
27
+ - "Where is the main entry point?"
28
+ - "What is the call graph for the auth flow?"
29
+ - "What are the god nodes in this codebase?"
30
+ - "What connects the data layer to the API?"
31
+ - "Show me everything that imports `pandas`."
32
+
33
+ Examples of **semantic** questions that go to Cognee work, not Graphify:
34
+
35
+ - "Why was X deprecated?" → ADR in Cognee work
36
+ - "What did we decide about Y last sprint?" → decision in Cognee work
37
+ - "How does the team handle Z?" → runbook in Cognee work
38
+
39
+ If you can't tell which side of the line you're on, prefer Graphify
40
+ first — its answer is cheaper and structurally precise. Cognee work is
41
+ the right second hop when the Graphify answer is structurally correct
42
+ but the engineer needs the WHY.
43
+
44
+ ## How to call
45
+
46
+ The graphify CLI lives outside Claude Code (installed via
47
+ `uv tool install "graphifyy>=0.8.33"` — pin matters: 0.8.33 fixed the
48
+ test-file-orphan bug; earlier 0.8.x silently dropped test edges).
49
+ It writes graphs into `<project>/graphify-out/` and the queries
50
+ traverse `graphify-out/graph.json`.
51
+
52
+ ```bash
53
+ # First, make sure the graph is current — fast on warm cache:
54
+ graphify update .
55
+
56
+ # Then ask the question:
57
+ graphify query "who calls process_payment"
58
+ ```
59
+
60
+ ### Pick the right traversal
61
+
62
+ - **`query`** (default BFS, ~2k tokens) — for "what surrounds this
63
+ concept" questions. Fans out from the seed.
64
+ - **`query --dfs`** — for **tracing a flow** when you already know the
65
+ entry node. Returns the call chain rather than the surrounding cluster.
66
+ Example: `graphify query "process_payment" --dfs` walks the call chain
67
+ from `process_payment` outward, single-thread.
68
+ - **`affected <node> --depth N --relations calls,imports`** — reverse
69
+ BFS. Pre-commit blast-radius check. Use BEFORE editing a function
70
+ whose downstream impact you don't fully know.
71
+ - **`path A B`** — directional shortest path. Add `--calls "[A]-->[B]"`
72
+ to constrain to a specific edge family. Answers "does X ever reach Y?"
73
+ without grep.
74
+ - **`explain <node>`** — node + neighbors + community context. Use when
75
+ you have a known symbol and want a quick map of its surroundings —
76
+ cheaper than `query`.
77
+
78
+ ### Always pass `--context` explicitly
79
+
80
+ Graphify's heuristic edge-type detection is brittle on mixed-language
81
+ repos (well-documented community gotcha). When you know the question is
82
+ structural-calls, say so:
83
+
84
+ ```bash
85
+ graphify query "who handles payment events" --context call --context import
86
+ graphify affected "User" --relations imports
87
+ ```
88
+
89
+ This consistently outperforms heuristic-detection on the MISHKAN harness
90
+ and avoids the "why didn't it find that obvious caller" trap.
91
+
92
+ ### Budget is rarely the dial you want
93
+
94
+ Default `--budget 2000` stays near 2k tokens even on 500k-word corpora.
95
+ Raising past ~8k almost always means **wrong seed** rather than budget
96
+ shortage. If the answer feels thin, re-seed (better question) before
97
+ re-budgeting.
98
+
99
+ The output is plain text that lists the graph path + the relevant
100
+ `file:line` citations. Cite them in your answer — per D-008
101
+ "citation discipline":
102
+
103
+ > When an agent answers from Graphify, it cites the graph node id and
104
+ > the source `file:line`. No "according to the graph" without an id.
105
+
106
+ ## Cite, then optionally Read
107
+
108
+ A Graphify answer typically narrows the relevant set from "the whole
109
+ repo" (158k tokens) to "5-10 file:line citations" (~1.8k tokens). When
110
+ the engineer needs prose context for ONE of those citations, THEN you
111
+ Read that single file. The savings come from not Read-ing the other 200
112
+ files just to find the relevant ones.
113
+
114
+ Worked example, full flow:
115
+
116
+ ```
117
+ 1. Engineer: "Refactor process_payment to use the new TransactionContext."
118
+
119
+ 2. You (Hizkiah / Salma / Nathan / Zadok / Oholiab):
120
+ $ graphify query "who calls process_payment"
121
+ → 7 file:line citations returned, ~1.8k tokens spent.
122
+
123
+ 3. You: Read the 7 cited files (selective, not bulk).
124
+
125
+ 4. You: Edit each call site to thread TransactionContext.
126
+ ```
127
+
128
+ Without Graphify, step 2 becomes "grep recursively + Read every match"
129
+ which on a 158k-token corpus is ~80k+ tokens minimum and frequently
130
+ misses indirect dispatch.
131
+
132
+ ## What graphify CAN'T do
133
+
134
+ - It does not understand call dispatch via dynamic strings (`getattr`,
135
+ `eval`, `dict-of-callables`). Those edges are invisible.
136
+ - It does not capture runtime configuration (env vars, feature flags).
137
+ Those are not in the AST.
138
+ - It does not understand cross-language boundaries (a Python call to a
139
+ Node script via subprocess). Each language's AST is its own island.
140
+
141
+ When the question requires those, fall back to grep + Read with a
142
+ narrowed file set, or escalate to Cognee work for the documented
143
+ intent.
144
+
145
+ ## Fail-open
146
+
147
+ If `graphify-out/graph.json` is missing or stale, run `graphify update
148
+ .` first (sub-second on warm cache). If the project doesn't use
149
+ Graphify at all (no `graphify-out/` dir), proceed with grep + Read as
150
+ normal — no graph means no Graphify query path, that's fine.
151
+
152
+ ## Reference
153
+
154
+ - D-008 — three-store knowledge surface (Graphify · Cognee work · Cognee
155
+ curated). The epistemological frontier between the three is the source
156
+ of "which question goes where". See `docs/design/MISHKAN_decisions.md`.
157
+ - D-009 — graph-first PreToolUse advisory hook for the five code-writing
158
+ specialists. The hook will, in Phase 2, surface a one-line reminder if
159
+ you do a structural Read without consulting Graphify first.
160
+ - POC report — `docs/research/graphify-token-saving-poc.md` (88.1×
161
+ average reduction, verified on MISHKAN harness 2026-06-07).
162
+ - Upstream Graphify — https://github.com/safishamsi/graphify.
@@ -46,6 +46,21 @@ to Y4NN before the first doc is written — the plan is the scope contract for i
46
46
  the team rules from `~/.claude/mishkan/rules/*` → `.claude/rules/*` for
47
47
  path-scoped loading, and `~/.claude/mishkan/templates/mcp.json` → `./.mcp.json`
48
48
  so agents can reach the Cognee knowledge-graph MCP.
49
+ 10. **Automated — Graphify code graph** (the third store of the knowledge stack,
50
+ per D-008): if `graphify` is on PATH (`uv tool install graphifyy` provides
51
+ it), run an initial scan so the project has a structure graph from Sprint
52
+ S0 onwards. Otherwise skip with a one-line note — the agent fleet still
53
+ works; the graph populates the first time Hizkiah / Salma / Nathan / Zadok /
54
+ Oholiab runs `graphify update .` mid-sprint.
55
+ ```bash
56
+ if command -v graphify >/dev/null 2>&1; then
57
+ graphify update . || echo "mishkan-init: graphify scan failed, skipping (project will scan on first structural query)"
58
+ fi
59
+ ```
60
+ The output `graphify-out/` is gitignored by convention — re-derivable, no
61
+ need to commit. The MISHKAN observability daemon's `graphify_tail` source
62
+ will start emitting `graphify_scan` / `graphify_query` events for the
63
+ Knowledge tab as soon as the graph exists.
49
64
 
50
65
  ## Outputs
51
66
 
@@ -0,0 +1,120 @@
1
+ ---
2
+ name: skill-discovery
3
+ description: Universal skill-discovery layer for the main session. Routes a task to the most relevant installed skills across MISHKAN, the user's ~/.claude/skills, plugin-bundled skills, and project-local skills. Returns three buckets — must_load, should_consider, adjacent — capped at 13 entries total. Advisory only; the model decides what to actually load. Use when a task arrives and you suspect a relevant skill exists but you cannot remember its name, when the surface of installed skills has grown past what fits in working memory, or when /skills is invoked explicitly.
4
+ ---
5
+
6
+ # skill-discovery — main-session router
7
+
8
+ > The harness has dozens of installed skills across four roots. This layer
9
+ > answers one question for the main session: *given this task, which skills
10
+ > should I be aware of right now?* It does **not** load skills; it surfaces
11
+ > them. The loading decision remains with the model.
12
+
13
+ ---
14
+
15
+ ## When to invoke
16
+
17
+ - A new task arrives and the relevant skill name is not immediately obvious.
18
+ - The user types `/skills` (the slash command runs this skill directly).
19
+ - A workflow declares `relevant_skill_categories` and asks for skill candidates
20
+ before its first stage runs.
21
+ - You catch yourself about to do work you suspect a skill already encodes —
22
+ ask the router before improvising.
23
+
24
+ **Do not invoke** when the right skill is already named in the request, or
25
+ when the work is trivial enough that no skill applies (a one-line edit, a
26
+ direct git command, a clear file read).
27
+
28
+ ---
29
+
30
+ ## How to invoke
31
+
32
+ Run the router script with the task description on `--task` (or piped on
33
+ stdin). The router reads the universal index at
34
+ `~/.claude/mishkan/skill-discovery/index.json` and emits a 3-bucket JSON.
35
+
36
+ ```
37
+ python3 ~/.claude/mishkan/scripts/skill-discovery-router.py \
38
+ --task "<one-paragraph task summary>" \
39
+ [--workflow <workflow-name>] \
40
+ [--relevant-categories cat1,cat2]
41
+ ```
42
+
43
+ If the index is missing or stale, run the indexer first (it is also wired to
44
+ session-boot via `--stat-only`):
45
+
46
+ ```
47
+ python3 ~/.claude/mishkan/scripts/skill-discovery-indexer.py --rebuild
48
+ ```
49
+
50
+ ---
51
+
52
+ ## Interpreting the three buckets
53
+
54
+ The router returns three buckets, hard-capped at **13 entries total**:
55
+
56
+ | Bucket | Cap | Semantics | What you do |
57
+ |---|---|---|---|
58
+ | `must_load` | ≤ 3 | Score ≥ threshold_high; strong trigger match | Load these into context; treat them as the directly-relevant skills for the task. |
59
+ | `should_consider` | ≤ 5 | Mid-band score; partial match | Skim the description; load if the work clearly intersects. Prefer keeping these *as references* over auto-loading them. |
60
+ | `adjacent` | ≤ 5 | Low score but same category | Awareness only; mention if relevant; do not load by default. |
61
+
62
+ **Bias rule.** When the count is tight (e.g. must_load is full but a
63
+ should_consider entry looks more relevant than a borderline must_load entry),
64
+ prefer enriching should_consider rather than padding must_load. The cost of
65
+ loading a wrong skill is higher than the cost of skipping a marginal one.
66
+
67
+ ---
68
+
69
+ ## Trust asymmetry — load only what you trust for the work
70
+
71
+ Each entry carries an `origin` field: `mishkan`, `user`, `plugin`, `project`.
72
+
73
+ - `mishkan` entries are harness-authored and trusted by default.
74
+ - `user` / `plugin` / `project` entries are third-party and carry a `trust`
75
+ warning in the router output.
76
+
77
+ **Rule.** Never auto-load a non-MISHKAN skill for a stateful operation
78
+ (anything in y4nn-standards §5: `git push`, SSH to production, `docker exec`
79
+ on prod, `sudo`, schema migration, log forensics). Surface them; ask Y4NN
80
+ before loading.
81
+
82
+ For generative work (boilerplate, doc draft, refactor sketch), non-MISHKAN
83
+ skills can be loaded once you've read the description and judged the fit.
84
+
85
+ ---
86
+
87
+ ## Name collisions
88
+
89
+ The indexer enforces precedence order at index time:
90
+ **mishkan → user → plugin → project**. Collisions are recorded in
91
+ `index.json.meta.collisions` (a shadowed skill is not silently dropped — it
92
+ is logged). If you suspect a collision is shadowing the skill you want, run
93
+ `/mishkan-skills-reindex` and inspect `meta.collisions`.
94
+
95
+ ---
96
+
97
+ ## Failure mode — fail-open
98
+
99
+ If the router returns empty buckets, the request is recorded in
100
+ `~/.claude/mishkan/skill-discovery/misses.jsonl` for later tuning. Continue
101
+ the task without the discovery layer — the absence of a router result is not
102
+ a blocker.
103
+
104
+ If the index is missing or unreadable, the router returns
105
+ `stale_rebuild_needed: true` and `warnings: ["index_missing_or_unreadable"]`.
106
+ Run `/mishkan-skills-reindex` and retry.
107
+
108
+ ---
109
+
110
+ ## Phase 1 scope (canary)
111
+
112
+ This skill is wired in two places only in Phase 1:
113
+
114
+ 1. The `/skills` slash command — invokes the router on the current task.
115
+ 2. The `mishkan-init` workflow — calls the router in an early phase as an
116
+ advisory hint to Bezalel before doc generation.
117
+
118
+ Other workflows route through their own craft skills as before. Phase 2 will
119
+ broaden integration once the canary has produced enough misses-log signal
120
+ to tune thresholds.
@@ -3,6 +3,7 @@
3
3
  "$id": "mishkan://templates/case-node.schema.json",
4
4
  "title": "MISHKAN Case Node",
5
5
  "description": "Written to Cognee when an agent solves a problem using a curated resource (design §8).",
6
+ "$comment": "SPEC-ONLY artifact. No runtime validator enforces this schema today — it is the canonical shape referenced from MISHKAN_harness_design.md and MISHKAN_ontology.md. To enforce at write time, plumb it through scripts/validate-research-log.sh or a Cognee write hook.",
6
7
  "type": "object",
7
8
  "additionalProperties": false,
8
9
  "required": ["type", "team", "agent", "problem_class", "resource_applied", "resolution", "outcome", "sprint", "task"],
@@ -3,6 +3,7 @@
3
3
  "$id": "mishkan://templates/observability-log.schema.json",
4
4
  "title": "MISHKAN Observability Log Entry",
5
5
  "description": "One entry per agent tool call, emitted by the PostToolUse hook (design §10).",
6
+ "$comment": "SPEC-ONLY artifact. The PostToolUse hook produces lines matching this shape but no runtime validator enforces it — the producer's discipline is the contract. To enforce, add a check in post-tool-observe.sh or a periodic conform pass.",
6
7
  "type": "object",
7
8
  "additionalProperties": false,
8
9
  "required": ["agent", "team", "sprint", "session", "tool_calls", "outcome", "timestamp"],
@@ -1,8 +1,9 @@
1
1
  # MISHKAN workflows
2
2
 
3
- Seven dynamic-workflow scripts that codify the orchestrations where
4
- parallel scale + repeatability justify a script. Each maps to one or
5
- more of the nine canonical workflow patterns from
3
+ Eighteen dynamic-workflow scripts ten org-level + eight team-level —
4
+ that codify the orchestrations where parallel scale + repeatability
5
+ justify a script. Each maps to one or more of the nine canonical workflow
6
+ patterns from
6
7
  [Anthropic's reference](https://code.claude.com/docs/en/workflows) and the
7
8
  [community patterns catalogue](https://github.com/ray-amjad/claude-code-workflow-creator/blob/main/references/patterns.md).
8
9
 
@@ -20,25 +21,85 @@ These run from the **main session only** (subagents cannot invoke
20
21
  | [`mishkan-architecture-panel.js`](mishkan-architecture-panel.js) | judge panel + impact-fanout + synthesis | Architecture decisions with a wide answer space; 3 Nathan runs from cost/scale/simplicity priors; Zadok+Phinehas+Shallum score; Bezalel synthesises | High-leverage architecture decisions |
21
22
  | [`mishkan-release-readiness.js`](mishkan-release-readiness.js) | barrier `parallel()` + structured pass/fail + nested workflow | Pre-deploy gate: tests + security + dependency + SLO + pipeline shape, all at once → single go/no-go | Before every staging-to-prod deploy |
22
23
  | [`mishkan-init.js`](mishkan-init.js) | pipeline with overlap (PRD → SRS → CONTRACT+ARCH in parallel → THREAT+C4 in parallel → settle) | Cut project init from hours to minutes without violating the sequence rule | Once per project at `/mishkan-init` |
24
+ | [`mishkan-blast-radius.js`](mishkan-blast-radius.js) | Graphify discovery + 3-lens orthogonal verify + synthesis | "What does this change actually touch?" Refactor blast-radius with three load-bearing lenses (caller-side / data-contract / runtime-behavior) so false positives drop before scheduling | Before editing a function whose downstream impact is uncertain; gated by `/plan` |
25
+ | [`mishkan-knowledge-gap-discovery.js`](mishkan-knowledge-gap-discovery.js) | parallel probe + **loop-until-dry** + research fan-out | Probe Cognee work for expected concepts; the only candidate that legitimately needs loop-until-X — confirm gaps via paraphrase retries before dispatching research | Sprint close (optional barrier step) or after `/sefer-pull` |
26
+ | [`mishkan-standards-rollout.js`](mishkan-standards-rollout.js) | pipeline (translate → verify) + barrier + judge panel (Bezalel + scope-conditional reviewers) | When a new rule lands in `y4nn-standards.md`, it propagates per-team with translation, drift verification, and CTO ratification — closes the silent failure mode of rules drift | When a new standard ships; BEFORE the rule is considered live across the fleet |
23
27
 
24
28
  ## The patterns each script uses
25
29
 
26
30
  | Pattern | Used by |
27
31
  |---|---|
28
- | Fan-out → synthesize | `codebase-audit`, `release-readiness`, `architecture-panel` |
29
- | Pipeline (overlapping) | `deep-research`, `migration-wave`, `init` |
30
- | Barrier `parallel()` | `sprint-close`, `release-readiness`, `architecture-panel` (Vote stage) |
32
+ | Fan-out → synthesize | `codebase-audit`, `release-readiness`, `architecture-panel`, `blast-radius` |
33
+ | Pipeline (overlapping) | `deep-research`, `migration-wave`, `init`, `standards-rollout` |
34
+ | Barrier `parallel()` | `sprint-close`, `release-readiness`, `architecture-panel` (Vote stage), `knowledge-gap-discovery`, `standards-rollout` |
31
35
  | Adversarial verification (3-vote refute) | `deep-research`, `codebase-audit` |
32
- | Judge panel | `architecture-panel`, `migration-wave` (2-reviewer accept) |
36
+ | Orthogonal 3-lens verify (caller / data / runtime) | `blast-radius` |
37
+ | Judge panel | `architecture-panel`, `migration-wave` (2-reviewer accept), `standards-rollout` (Bezalel + scope-conditional) |
33
38
  | Nested workflow | `release-readiness` → `codebase-audit` |
34
- | Loop-until-X | (mechanism inside scripts when needed; no top-level loop workflows yet) |
39
+ | Loop-until-X | `knowledge-gap-discovery` (paraphrase-retries to confirm gaps before research) |
40
+
41
+ ## Team-level catalogue
42
+
43
+ Eight team-level workflows codified per ADR D-010 (cap 4/team, PM+CTO
44
+ co-owned). Invoked through the Team Lead's craft skill.
45
+
46
+ | Script | Pattern combo | Real problem it solves | Team |
47
+ |---|---|---|---|
48
+ | [`chosheb-feature-ship.js`](chosheb-feature-ship.js) | barrier + synthesis | Design → handoff package complete (DS fit + a11y + assets + QA) | Chosheb |
49
+ | [`panim-ds-rollout.js`](panim-ds-rollout.js) | pipeline + worktree + judge panel | Design token change propagated to all consumers with a11y + regression review | Panim |
50
+ | [`yasad-data-migration-wave.js`](yasad-data-migration-wave.js) | pipeline + 4-lens judge panel | Wave of DB migrations, per-table reviewed (contracts/perf/security/tests) | Yasad |
51
+ | [`yasad-schema-evolution.js`](yasad-schema-evolution.js) | pipeline + per-phase judge panel | Phased schema change with zero-downtime invariants + per-phase rollback | Yasad |
52
+ | [`mishmar-security-gate.js`](mishmar-security-gate.js) | barrier + 3-vote adversarial refute | Security gate on sensitive surface (auth/payment/PII), 3 orthogonal lenses | Mishmar |
53
+ | [`migdal-infra-change.js`](migdal-infra-change.js) | barrier + 5-lens panel | Infra change validated by design/systems/devops/observability/health lenses | Migdal |
54
+ | [`migdal-dr-drill.js`](migdal-dr-drill.js) | pipeline + per-step judge panel | DR drill — enumerate, simulate, verify, RTO/RPO measurement, gap report | Migdal |
55
+ | [`sefer-release-notes.js`](sefer-release-notes.js) | pipeline + per-category fan-out + style synthesis | Release notes assembled from git log per category with style-guide application | Sefer |
56
+
57
+ Spare slots (Chosheb 3, Panim 3, Yasad 2, Mishmar 3, Migdal 2, Sefer 3)
58
+ are deliberately open; candidates compete for them at PM+CTO review.
59
+
60
+ ## Portfolio governance — D-010
61
+
62
+ The portfolio is **PM + CTO co-owned** with hard caps and an anti-pattern
63
+ canon (ADR D-010, 2026-06-07). Nehemiah owns scope, delivery, recurrence
64
+ justification; Bezalel owns orchestration shape, schema contracts, quality
65
+ bar. New workflows land through joint review — not ad hoc.
66
+
67
+ **Hard caps.** 10 org-level (full) + 4 per team (varies). To add, retire.
68
+ **Soft retirement.** Workflows that fire < 2× in 3 sprints surface at
69
+ `/sprint-close` for PM+CTO retirement vote; default is `workflows/proposed/`.
70
+
71
+ The June 2026 portfolio review produced the org-level additions
72
+ (`blast-radius`, `knowledge-gap-discovery`, `standards-rollout`), the
73
+ org-level removal (`multi-perspective-review` was theatre vs the existing
74
+ `architecture-panel`), the eight team-level workflows above, and the
75
+ anti-patterns below.
76
+
77
+ ### Anti-patterns to avoid (D-010)
78
+
79
+ 1. **Skill-in-workflow-clothing.** Linear sequence, no parallelism, no
80
+ termination predicate, no panel — that's a skill, not a workflow.
81
+ 2. **Workflow calling workflow without a contract.** Nested workflows
82
+ are valid (cf. `release-readiness` → `codebase-audit`) only when the
83
+ inner workflow's output schema is consumed structurally. Free-form
84
+ nesting hides token cost and breaks retry semantics.
85
+ 3. **Judge panels with non-orthogonal reviewers.** If two reviewers in
86
+ a panel share 70%+ of their evaluation criteria, the panel is
87
+ theatre. Each lens must be load-bearing and distinct (`blast-radius`
88
+ enforces this with caller-side / data-contract / runtime-behavior).
89
+ 4. **Workflow-as-status-page.** Orchestration that fans out to gather
90
+ state without synthesis is a dashboard query, not a workflow. If the
91
+ synthesis stage is missing or trivial, the work belongs in
92
+ observability, not in `Workflow()`.
35
93
 
36
94
  ## Cost discipline
37
95
 
38
96
  Workflows are expensive. The community baseline is **3–6 workflows per
39
- production team**. Seven is the working ceiling adding more
40
- typically means the new use case is better served by Task delegation
41
- or a skill.
97
+ production team**. The MISHKAN hard cap is **10 org-level + 4 per team**
98
+ (current count: 10 org + 8 team across 6 teams = 18 total). Adding more
99
+ typically means either (a) the new use case is better served by Task
100
+ delegation or a skill, or (b) an existing workflow should be retired —
101
+ soft-retirement happens after a workflow fires < 2× across 3 sprints,
102
+ under PM+CTO review.
42
103
 
43
104
  Cost expectations per run (subagent-tokens, rough orders of
44
105
  magnitude):
@@ -52,6 +113,9 @@ magnitude):
52
113
  | `mishkan-architecture-panel` | medium | 3 proposals × 3 reviewers + synthesis |
53
114
  | `mishkan-release-readiness` | low-medium | 7–8 parallel checks; nested audit if enabled |
54
115
  | `mishkan-init` | medium | 6 artefacts pipelined |
116
+ | `mishkan-blast-radius` | medium | `sites × 3 lenses` + discovery + synthesis; short-circuits on empty graph |
117
+ | `mishkan-knowledge-gap-discovery` | medium-high | probe × N concepts + loop-until-dry rephrasings + research fan-out per gap |
118
+ | `mishkan-standards-rollout` | low-medium | 6 translations + 6 verifications + 1-3 ratifiers (scope-conditional) |
55
119
 
56
120
  Run on a small slice first (one directory; one phase) before
57
121
  committing to a full wave.
@@ -76,8 +140,9 @@ Don't, unless:
76
140
  3. The repeatability is real (same orchestration each time, just different inputs).
77
141
 
78
142
  Otherwise: Task fan-out from the main session is the right answer.
79
- The seven workflows above were picked precisely because each clears
80
- all three bars.
143
+ The 10 org-level + 8 team-level workflows above were picked precisely
144
+ because each clears all three bars; the portfolio is capped at 10 + 4
145
+ per team per ADR D-010.
81
146
 
82
147
  ## Constraints (reminders)
83
148
 
@@ -0,0 +1,75 @@
1
+ // chosheb-feature-ship — design → handoff package complete to Panim.
2
+ //
3
+ // A Figma / design intent + feature context goes in; a complete handoff
4
+ // package comes out: design system fit, a11y/SEO audit, asset exports,
5
+ // QA visual matrix. Replaces the back-and-forth ping-pong that currently
6
+ // burns 2-3 days per feature.
7
+ //
8
+ // Pattern: barrier `parallel()` per dimension + synthesis.
9
+ // Per ADR D-010 anti-pattern check:
10
+ // - skill-in-workflow-clothing: no — 4 dimensions in parallel, panel.
11
+ // - workflow-calling-workflow-without-contract: no — no nesting.
12
+ // - non-orthogonal panel: no — DS-fit / a11y / assets / QA are distinct
13
+ // evaluation domains.
14
+ // - workflow-as-status-page: no — synthesis stage produces handoff doc.
15
+
16
+ export const meta = {
17
+ name: "chosheb-feature-ship",
18
+ description: "Design → complete handoff package for Panim (DS fit + a11y + assets + QA).",
19
+ whenToUse: "When Chosheb has a converged design and Huram needs to start implementation.",
20
+ phases: [{ title: "Audit" }, { title: "Package" }],
21
+ };
22
+
23
+ const design = args?.design_ref;
24
+ const feature = args?.feature_context;
25
+ if (!design) throw new Error("args.design_ref is required (Figma URL / asset path)");
26
+ if (!feature) throw new Error("args.feature_context is required (1-paragraph feature description)");
27
+
28
+ const AUDIT_SCHEMA = {
29
+ type: "object",
30
+ required: ["ready", "blockers"],
31
+ properties: {
32
+ ready: { type: "boolean" },
33
+ blockers: { type: "array", items: { type: "string" } },
34
+ deliverables: { type: "array", items: { type: "string" } },
35
+ notes: { type: "string" },
36
+ },
37
+ };
38
+
39
+ phase("Audit");
40
+ const LENSES = [
41
+ { key: "ds-fit", agent: "aholiab", prompt: "Design system fit: does this design reuse existing tokens / components / patterns? List net-new additions to the DS." },
42
+ { key: "a11y", agent: "asaph", prompt: "Accessibility + SEO audit: contrast ratios, keyboard flow, ARIA needs, semantic structure, meta requirements." },
43
+ { key: "assets", agent: "obed", prompt: "Asset preparation: list required exports (svg/png/webp per breakpoint), sizes, naming, optimisation notes." },
44
+ { key: "qa", agent: "jahaziel", prompt: "Visual QA matrix: states (default/hover/active/disabled/error), breakpoints, edge cases, browser/device coverage." },
45
+ ];
46
+
47
+ const audits = await parallel(LENSES.map(L => () =>
48
+ agent(
49
+ `Feature: ${feature}\nDesign: ${design}\nYour lens: ${L.prompt}\nReturn the schema.`,
50
+ { schema: AUDIT_SCHEMA, label: `audit:${L.key}`, agentType: L.agent, phase: "Audit" },
51
+ ).then(a => ({ ...L, ...a }))
52
+ ));
53
+
54
+ const valid = audits.filter(Boolean);
55
+ const allBlockers = valid.flatMap(a => a.blockers ?? []);
56
+ const allReady = valid.every(a => a.ready);
57
+
58
+ phase("Package");
59
+ const handoff = await agent(
60
+ `Chosheb → Panim handoff package. Feature: ${feature}. Audits: ${JSON.stringify(valid.map(a => ({lens: a.key, ready: a.ready, deliverables: a.deliverables, notes: a.notes})))}. ` +
61
+ `Produce a structured handoff document: design summary, DS additions list, a11y checklist, asset manifest, QA matrix, open questions. Markdown.`,
62
+ { label: "package-handoff", agentType: "aholiab", phase: "Package" },
63
+ );
64
+
65
+ return {
66
+ feature_context: feature,
67
+ design_ref: design,
68
+ audits: valid,
69
+ ready_to_ship: allReady,
70
+ blockers: allBlockers,
71
+ handoff_document: handoff,
72
+ summary: allReady
73
+ ? `Handoff package ready. ${valid.length}/4 lenses passed. Hand to Huram (Panim).`
74
+ : `Handoff BLOCKED. ${allBlockers.length} blockers across ${valid.length} lenses. Resolve before handoff.`,
75
+ };
@@ -0,0 +1,94 @@
1
+ // migdal-dr-drill — disaster recovery drill orchestration.
2
+ //
3
+ // A DR scenario (region loss, DB corruption, secret leak, control-plane
4
+ // outage) is specified; the workflow orchestrates the drill: enumerate
5
+ // recovery steps, simulate per step, verify each via independent observer,
6
+ // measure RTO/RPO against target. Synthesises a drill report with gaps.
7
+ //
8
+ // Pattern: pipeline (enumerate → simulate → verify) + barrier + judge panel.
9
+ // ADR D-010 check:
10
+ // - parallelism: simulation step × independent observer per step.
11
+ // - panel orthogonality: Palal (systems-level recovery) + Hanun (operational
12
+ // observability during drill) + Rehum (health/safety post-recovery).
13
+ // - synthesis: RTO/RPO measurement + gap list.
14
+
15
+ export const meta = {
16
+ name: "migdal-dr-drill",
17
+ description: "Disaster recovery drill — enumerate steps, simulate, verify, measure RTO/RPO, report gaps.",
18
+ whenToUse: "Quarterly DR exercise, or after any infra change that affects recovery topology.",
19
+ phases: [{ title: "Plan" }, { title: "Simulate" }, { title: "Report" }],
20
+ };
21
+
22
+ const scenario = args?.scenario;
23
+ const rtoTarget = args?.rto_target_minutes ?? 30;
24
+ const rpoTarget = args?.rpo_target_minutes ?? 5;
25
+ const project = args?.project ?? ".";
26
+ if (!scenario) throw new Error("args.scenario is required (e.g. 'primary-region-loss' | 'db-corruption' | 'secret-leak')");
27
+
28
+ const PLAN_SCHEMA = {
29
+ type: "object", required: ["steps"],
30
+ properties: { steps: { type: "array", items: { type: "object", required: ["order", "action", "expected_outcome"], properties: { order:{type:"integer"}, action:{type:"string"}, expected_outcome:{type:"string"}, depends_on:{type:"array", items:{type:"integer"}} } } } },
31
+ };
32
+ const VERIFY_SCHEMA = {
33
+ type: "object", required: ["verified", "rationale"],
34
+ properties: { verified:{type:"boolean"}, rationale:{type:"string"}, gap:{type:"string"}, time_estimate_minutes:{type:"number"} },
35
+ };
36
+
37
+ phase("Plan");
38
+ const plan = await agent(
39
+ `DR scenario: ${scenario}. Project: ${project}. RTO target: ${rtoTarget}min, RPO target: ${rpoTarget}min. Enumerate the recovery steps in order with dependencies. Return the schema.`,
40
+ { schema: PLAN_SCHEMA, label: "plan-recovery", agentType: "palal" },
41
+ );
42
+
43
+ const steps = plan?.steps ?? [];
44
+ log(`DR plan: ${steps.length} recovery steps.`);
45
+
46
+ phase("Simulate");
47
+ const OBSERVERS = [
48
+ { key: "systems", agent: "palal", prompt: "Systems lens: does this step actually recover the targeted system? Hidden dependencies?" },
49
+ { key: "ops", agent: "hanun", prompt: "Operations lens: are the runbooks ready, secrets accessible, on-call awake, monitoring live during this step?" },
50
+ { key: "health", agent: "rehum", prompt: "Health lens: post-step health checks, data-integrity probes, success criteria. Is the system actually healthy after?" },
51
+ ];
52
+
53
+ const simulated = await parallel(steps.map(S => () =>
54
+ parallel(OBSERVERS.map(O => () =>
55
+ agent(
56
+ `DR scenario: ${scenario}. Step ${S.order}: ${S.action} (expected: ${S.expected_outcome}). Your lens: ${O.prompt} Default verified=false if uncertain.`,
57
+ { schema: VERIFY_SCHEMA, label: `simulate:${O.key}:step${S.order}`, agentType: O.agent, phase: "Simulate" },
58
+ )
59
+ )).then(verdicts => {
60
+ const valid = verdicts.filter(Boolean);
61
+ const verifiedCount = valid.filter(v => v.verified).length;
62
+ const times = valid.map(v => v.time_estimate_minutes ?? 0).filter(t => t > 0);
63
+ const meanTime = times.length ? times.reduce((a,b)=>a+b, 0) / times.length : 0;
64
+ return { step: S, verdicts: valid, verified_count: verifiedCount, all_verified: verifiedCount === OBSERVERS.length, gaps: valid.map(v => v.gap).filter(Boolean), time_minutes: meanTime };
65
+ })
66
+ ));
67
+
68
+ phase("Report");
69
+ const totalTime = simulated.reduce((a, s) => a + (s.time_minutes ?? 0), 0);
70
+ const allGaps = simulated.flatMap(s => s.gaps);
71
+ const failedSteps = simulated.filter(s => !s.all_verified);
72
+
73
+ const rtoMet = totalTime <= rtoTarget;
74
+ const passes = failedSteps.length === 0;
75
+
76
+ const report = await agent(
77
+ `DR drill report. Scenario: ${scenario}. ${steps.length} steps, ${failedSteps.length} failed verification. Estimated RTO: ${totalTime.toFixed(1)}min vs target ${rtoTarget}min. Gaps: ${JSON.stringify(allGaps)}. Produce a markdown report: executive summary, per-step status, gap remediation list.`,
78
+ { label: "produce-report", agentType: "rehum", phase: "Report" },
79
+ );
80
+
81
+ return {
82
+ scenario,
83
+ rto_target_minutes: rtoTarget,
84
+ rto_estimate_minutes: totalTime,
85
+ rto_met: rtoMet,
86
+ steps_total: steps.length,
87
+ steps_passed: simulated.filter(s => s.all_verified).length,
88
+ gaps: allGaps,
89
+ report,
90
+ decision: passes && rtoMet ? "ready" : "not-ready",
91
+ summary: passes && rtoMet
92
+ ? `DR drill PASS. ${steps.length}/${steps.length} steps verified. RTO ${totalTime.toFixed(1)}min ≤ ${rtoTarget}min target.`
93
+ : `DR drill FAIL. ${failedSteps.length} unverified steps${rtoMet ? "" : `, RTO ${totalTime.toFixed(1)}min > ${rtoTarget}min target`}. ${allGaps.length} gaps to address.`,
94
+ };