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
@@ -298,11 +298,16 @@ introduced to protect.
298
298
 
299
299
  ### Out of scope (explicitly not decided here)
300
300
 
301
- 1. **Token-saving measurement POC.** Whether Graphify saves Nx tokens on a
302
- representative agent workload is a separate, instrumented experiment with
303
- its own success criteria. The 71.5× figure circulating in third-party write-ups
304
- is **not** verified by this ADR and must not be cited as a MISHKAN claim
305
- until measured.
301
+ 1. ~~**Token-saving measurement POC.**~~ **CLOSED 2026-06-07**
302
+ POC executed on the MISHKAN harness with Graphify v0.8.33: **88.1×
303
+ average reduction** across the 5 canonical structural questions
304
+ (range 69.4× to 141.8×). The third-party 71.5× claim is **verified**
305
+ in spirit — MISHKAN's actual measurement is +23 % higher (likely
306
+ driven by Python-heavy AST shape vs the mixed TS corpora of the
307
+ third-party benchmark). Full method, query-by-query results, and
308
+ honest gaps in `docs/research/graphify-token-saving-poc.md`. The 88.1×
309
+ figure may be cited as a MISHKAN claim. The 71.5× figure may be cited
310
+ as a third-party point reference within the observed range.
306
311
  2. **Refactor of the Explore agent / Hiram's exploration playbook.** Whether
307
312
  Hiram should consult Graphify before grep is a downstream agent change,
308
313
  not decided here.
@@ -353,7 +358,7 @@ discipline.
353
358
 
354
359
  ## D-009 — Graph-first PreToolUse gate for the five code-writing specialists (added 2026-06-05)
355
360
 
356
- **Decision:** introduce a MISHKAN PreToolUse hook — `pre-tool-graphify-nudge.py` —
361
+ **Decision:** introduce a MISHKAN PreToolUse hook — `pre-tool-knowledge-route.py` —
357
362
  that, for **exactly the five code-writing specialist agents** (Hizkiah, Salma,
358
363
  Oholiab, Nathan, Zadok), runs alongside the existing security (D-004) and
359
364
  model-routing hooks and **advises** — does not block — when a `Read` or `Grep`
@@ -481,10 +486,10 @@ enforcement. If it does not, a future ADR can revisit hardening.
481
486
 
482
487
  ### Integration
483
488
 
484
- - **Hook file.** `payload/mishkan/hooks/pre-tool-graphify-nudge.py`,
489
+ - **Hook file.** `payload/mishkan/hooks/pre-tool-knowledge-route.py`,
485
490
  registered alongside `pre-tool-security.sh` and `model-route.py` in the
486
491
  PreToolUse chain. Order: security (deny on violation) → model-route
487
- (inject model) → graphify-nudge (advise). Each is independent and
492
+ (inject model) → knowledge-route (advise). Each is independent and
488
493
  fail-open; chain order is for clarity, not correctness.
489
494
  - **Subagent detection.** Reuses the same `subagent_type` field
490
495
  `model-route.py` already reads from `tool_input`. When the field is
@@ -567,6 +572,443 @@ providing the runtime mechanism D-008 explicitly deferred (D-008 Out of
567
572
  Scope #4). Composes with D-004 (existing PreToolUse Bash chain) without
568
573
  modifying it.
569
574
 
575
+ ## D-010 — Workflow portfolio discipline: four anti-patterns, two caps, PM+CTO co-ownership (added 2026-06-07)
576
+
577
+ **Decision:** the dynamic-workflow portfolio is governed by an explicit
578
+ discipline rather than ad-hoc accretion. Three rules together: (a) **hard
579
+ caps** — 10 top-level (org) workflows + 4 team workflows per team; (b) **four
580
+ named anti-patterns** that disqualify a candidate; (c) **PM + CTO joint
581
+ ownership** — every addition, retirement, or substitution goes through
582
+ Nehemiah and Bezalel together, never through a single agent's unilateral push.
583
+ A fire-count rule retires workflows that fire < 2× across 3 sprints, gated by
584
+ the same PM+CTO review.
585
+
586
+ ### Force-tension
587
+
588
+ **What pushes toward accretion.** Workflows are the most powerful primitive
589
+ the harness exposes — typed contracts, parallel fan-out, adversarial verify
590
+ panels. Every recurring task looks like a candidate. Each team has 5–7
591
+ specialists, so "one workflow per team's main shipping flow" feels natural.
592
+ Six team-ship workflows × six teams + the 10 org-level = a portfolio of 46.
593
+ Without a cap, that is the asymptote: most workflows fire once, contribute
594
+ nothing, and add maintenance debt.
595
+
596
+ **What pushes against.** Workflow runtime cost is real (Bun-shape migrations
597
+ hit hundreds of agents and thousands of subagent-tokens per run). Each
598
+ workflow carries a contract surface that must be kept correct as agents
599
+ evolve. Workflows that fire rarely cannot pay back their codification cost.
600
+ Worse, workflows that look load-bearing but encode skill-shape (linear
601
+ sequence, no panel, no termination predicate) blur the distinction between
602
+ workflow and skill, eroding the discipline that makes the workflow tool
603
+ worth reaching for.
604
+
605
+ ### Adopted shape
606
+
607
+ **(a) Hard caps.**
608
+
609
+ - **10 org-level workflows.** Current: `mishkan-sprint-close`,
610
+ `mishkan-deep-research`, `mishkan-codebase-audit`, `mishkan-migration-wave`,
611
+ `mishkan-architecture-panel`, `mishkan-release-readiness`, `mishkan-init`,
612
+ `mishkan-blast-radius`, `mishkan-knowledge-gap-discovery`,
613
+ `mishkan-standards-rollout`. Adding an 11th forces a retirement vote.
614
+ - **4 team-level workflows per team.** Current shipped count varies by team
615
+ (Chosheb 1, Panim 1, Yasad 2, Mishmar 1, Migdal 2, Sefer 1). Spare slots
616
+ per team are deliberately left open — candidates compete for them at
617
+ PM+CTO review, not on a team lead's word.
618
+
619
+ **(b) Four anti-patterns.** A candidate that exhibits any of these is rejected
620
+ or reworked, regardless of fit:
621
+
622
+ 1. **Skill-in-workflow-clothing.** Linear sequence, no parallelism, no
623
+ termination predicate, no panel. That shape is a skill, not a workflow.
624
+ If the cost-to-fan-out gain is < 2× wall-clock vs Task delegation, it
625
+ does not earn the workflow tool.
626
+ 2. **Workflow calling workflow without a contract.** Nested workflows are
627
+ valid (cf. `release-readiness` → `codebase-audit`) **only** when the
628
+ inner workflow's output schema is consumed structurally by the outer.
629
+ Free-form nesting hides token cost, breaks retry semantics, and produces
630
+ an opaque blob of subagent transcript that the orchestrator cannot
631
+ reason over.
632
+ 3. **Judge panels with non-orthogonal reviewers.** If two reviewers in a
633
+ panel share ≥ 70% of their evaluation criteria, the panel is theatre —
634
+ redundant votes from correlated judges. Each lens must be load-bearing
635
+ and distinct (the canonical example is `mishkan-blast-radius`'s
636
+ caller-side / data-contract / runtime-behavior triad).
637
+ 4. **Workflow-as-status-page.** Orchestration that fans out to gather state
638
+ without synthesis is a dashboard query, not a workflow. The synthesis
639
+ stage is the workflow's reason to exist; if it is missing or trivial,
640
+ the work belongs in observability, not in `Workflow()`.
641
+
642
+ **(c) PM + CTO joint ownership.** New workflow proposals are written as a
643
+ brief (problem, fan-out shape, termination predicate, expected fire-count,
644
+ anti-pattern self-check). Nehemiah owns delivery / recurrence justification;
645
+ Bezalel owns orchestration shape / schema contracts. Joint approval lands
646
+ the workflow under `payload/mishkan/workflows/`; unanimous rework lands it
647
+ under `payload/mishkan/workflows/proposed/` with the rework note; rejection
648
+ returns the brief to its proposer with the failing anti-pattern named.
649
+
650
+ **Soft-retirement rule.** A workflow that fires < 2 times across 3 consecutive
651
+ sprints surfaces in the next `/sprint-close` for PM+CTO review. The default
652
+ disposition is retirement to `proposed/`; the rebuttal is a concrete
653
+ upcoming-use justification.
654
+
655
+ ### Alternatives considered
656
+
657
+ 1. **No cap; allow accretion.** *Rejected.* This is the default state of every
658
+ ungoverned workflow portfolio in the wild. The reference cases (OneRedOak,
659
+ Bun-shape) show that production teams converge on 3–6 workflows after
660
+ accretion; the cap codifies that ceiling rather than letting the harness
661
+ relearn it under load.
662
+
663
+ 2. **Per-team unilateral additions, no PM+CTO review.** *Rejected.* Without
664
+ a joint gate the four anti-patterns reappear — every team adds the
665
+ workflow that feels load-bearing from their vantage point, and the
666
+ harness ends up with six near-identical feature-ship orchestrations.
667
+ The June 2026 portfolio review surfaced exactly this drift (Sefer
668
+ proposed two doc-generation workflows; both folded into skills under
669
+ the gate).
670
+
671
+ 3. **Workflow router that auto-selects per task.** *Deferred.* Selecting
672
+ among 18 workflows by task description is the same problem as skill
673
+ discovery (cf. `mishkan-skill-discovery`). Layering a router on top of
674
+ workflows duplicates that infrastructure. Wait for the skill-discovery
675
+ layer's telemetry before deciding whether workflows need their own
676
+ router or can be discovered through the same surface.
677
+
678
+ 4. **Cap of 6 org-level + 6 team workflows.** *Rejected after PM/CTO split
679
+ verdict.* Bezalel preferred 6 load-bearing org-level; Nehemiah preferred
680
+ 10 with retirement-based pruning. Adopted 10 because the existing
681
+ portfolio already contains 10 that pass the anti-pattern check; cutting
682
+ to 6 would retire workflows that clear the bar by lottery, not by
683
+ discipline. The retirement rule is the steady-state pressure.
684
+
685
+ ### Invariants of the discipline
686
+
687
+ - **Org-level cap = 10.** Always. To add, retire.
688
+ - **Team-level cap = 4 per team.** Always. To add, retire from that team.
689
+ - **Anti-pattern self-check** is part of the proposal brief — proposer
690
+ must name how the workflow avoids each of the four.
691
+ - **No solo additions.** Even Bezalel cannot land a workflow alone; the
692
+ rules-rollout workflow exists precisely to prevent that drift.
693
+ - **`proposed/` is not a parking lot.** Workflows there carry a written
694
+ promotion criterion (concrete fire-count, named use case).
695
+
696
+ ### Consequences
697
+
698
+ **Positive.**
699
+ - The portfolio stays legible. An engineer (or new agent) can read all 18
700
+ in an afternoon and know what each is for.
701
+ - The cost ceiling is bounded. Worst-case spend is the sum of 18 known
702
+ shapes, not an unbounded sprawl.
703
+ - The anti-pattern catalogue gives proposers concrete language for self-
704
+ review before bringing a brief, shortening the loop.
705
+ - The PM+CTO gate replays the same discipline used for architecture (D-002,
706
+ D-007) — consistency across the harness's governance surfaces.
707
+
708
+ **Negative.**
709
+ - Some legitimate one-off orchestrations will fail the cap and have to wait
710
+ for a retirement slot. The escape valve is `proposed/` — the work is not
711
+ lost, just not active.
712
+ - The fire-count rule is approximate; a workflow that fires 1× per sprint
713
+ but is genuinely load-bearing (e.g. quarterly audit) will trip the
714
+ retirement default and need to argue itself back each time. Tuned by
715
+ raising the window from 3 sprints to N if false-retirements appear.
716
+ - "Anti-pattern self-check" relies on the proposer's honesty about their
717
+ candidate; a determined push can word-paint around it. Mitigation: the
718
+ CTO half of the gate has explicit authority to reject on shape.
719
+
720
+ **Supersedes / amends:** none. Codifies the discipline implicit in D-002
721
+ (Claude Code models only — capability discipline) and D-007 (separate stores
722
+ — epistemic discipline) onto the orchestration layer.
723
+
724
+ ## D-011 — Universal skill-discovery layer (added 2026-06-07)
725
+
726
+ **Status:** adopted, Phase 1 canary.
727
+
728
+ **Context — the tension.** The harness now ships 40+ MISHKAN craft skills,
729
+ and the user surface adds dozens more (`~/.claude/skills/`, plugin-bundled,
730
+ project-local). When a task arrives, the main session cannot reliably
731
+ remember which skill applies — the list itself does not fit in working memory
732
+ without bloating context. Two failure modes compete:
733
+
734
+ 1. **Reinvention.** The model improvises work that a skill already encodes,
735
+ because the right skill was never surfaced. This is the silent failure —
736
+ no error, just degraded output.
737
+ 2. **Context bloat.** The model loads too many skills "just in case",
738
+ spending tokens on dormant guidance that crowds out the work itself.
739
+
740
+ The tension is not "should we make skills discoverable" — it is *who* decides
741
+ which skills surface and *how much context* that decision consumes. D-010
742
+ governed workflow portfolio discipline by cap + anti-pattern self-check; the
743
+ same discipline applies one layer down, but the right instrument is a router,
744
+ not a cap (we *want* the long tail of installed skills, we just don't want to
745
+ pay for all of them at once).
746
+
747
+ ### Alternatives considered
748
+
749
+ 1. **TUI-only browsing.** *Rejected.* A `mishkan-skills browse` TUI is
750
+ useful, but it puts the discovery cost on the engineer's reading time
751
+ for every task. The model still wouldn't know which skill to mention
752
+ in the first place, so the silent-reinvention failure mode persists.
753
+ Kept as a Phase 2 nice-to-have, not the primary surface.
754
+
755
+ 2. **Embedding-based matching.** *Rejected.* Local sentence-embedding
756
+ model + cosine similarity would give better recall than TF-IDF on
757
+ ambiguous queries. But: (a) it pulls in a model dependency (200MB+ at
758
+ minimum) for a layer that runs in every session, (b) the inference
759
+ latency is non-trivial at session boot, (c) the trigger-phrase match
760
+ on `Use when…` lines already covers the common case because skill
761
+ descriptions are written *for* matching. TF-IDF is the right fallback
762
+ for the long tail. Revisit if miss-log analysis shows recurring
763
+ semantic misses that token overlap cannot recover.
764
+
765
+ 3. **MCP server.** *Rejected for Phase 1.* An MCP server for skill
766
+ discovery would let other tools query the same index, but it adds a
767
+ process to manage and a network surface. The Python-script + flat-file
768
+ index has the same data shape with zero process overhead, and an MCP
769
+ wrapper around it remains a free Phase 2 option once the index format
770
+ stabilises.
771
+
772
+ 4. **No discovery layer; keep the implicit reach.** *Rejected.* The
773
+ forty-skill surface already exceeds what the model reaches reliably.
774
+ The reinvention rate observed in sessions (anecdotal but consistent)
775
+ was the trigger for this decision.
776
+
777
+ ### Adopted shape
778
+
779
+ - **Universal indexer** (`payload/mishkan/scripts/skill-discovery-indexer.py`).
780
+ Stdlib-only Python, scans four roots in precedence order:
781
+ `~/.claude/mishkan/skills/` → `~/.claude/skills/` →
782
+ `~/.claude/plugins/*/skills/` → `<repo>/.claude/skills/`.
783
+ Output: single flat JSON at
784
+ `~/.claude/mishkan/skill-discovery/index.json`.
785
+ Each entry: `{name, source_path, origin, description, triggers,
786
+ category, frontmatter_raw, sha256, indexed_at, mtime}`.
787
+ Refresh triggers: install/update (full rebuild), session boot
788
+ (`--stat-only` mtime sweep against `meta.last_scan`), manual
789
+ `/mishkan-skills-reindex`. Stale entries (source_path gone) are dropped
790
+ at routing time.
791
+
792
+ - **Router** (`payload/mishkan/scripts/skill-discovery-router.py`). Three
793
+ matching mechanisms layered: (a) trigger-phrase weighted match
794
+ (trigger = 3.0, description keyword = 1.0), (b) category prior
795
+ (×1.5 multiplier when invoked from a workflow declaring
796
+ `relevant_skill_categories`), (c) TF-IDF fallback when trigger pass
797
+ yields < 3 results. Output: 3 buckets capped at 13 total —
798
+ `must_load` ≤ 3, `should_consider` ≤ 5, `adjacent` ≤ 5.
799
+
800
+ - **Skill** (`payload/mishkan/skills/skill-discovery/SKILL.md`).
801
+ Main-session-side. Tells the model how to interpret the 3 buckets
802
+ and the trust asymmetry (mark, never auto-load, non-mishkan entries
803
+ for stateful operations).
804
+
805
+ - **Slash commands.** `/skills` (invoke router on current task);
806
+ `/mishkan-skills-reindex` (manual rebuild).
807
+
808
+ - **Phase 1 canary integration.** `mishkan-init` workflow declares
809
+ `relevant_skill_categories` and runs a `SkillRouter` phase before PRD.
810
+ Result is advisory and folded into Bezalel's signoff context. No
811
+ other workflow is wired in Phase 1.
812
+
813
+ ### Risks
814
+
815
+ 1. **Context bloat from over-trusting `must_load`.** Mitigation: cap of 3,
816
+ bias-rule in the skill (prefer should_consider over padding must_load),
817
+ miss-log surfaces over-firing.
818
+ 2. **Name collisions across roots.** Mitigation: precedence order at
819
+ index time (mishkan wins); collisions recorded in
820
+ `meta.collisions` rather than silently dropped.
821
+ 3. **Trust asymmetry violations.** Mitigation: every non-mishkan entry
822
+ carries an explicit `trust` warning; skill rule forbids auto-load
823
+ of non-mishkan skills for stateful operations (D-002 / y4nn-§5).
824
+ 4. **Stale index hiding real skills.** Mitigation: session-boot
825
+ `--stat-only` sweep + drop-at-routing-time for dead `source_path`.
826
+ 5. **Fail-closed makes the harness brittle.** Mitigation: the layer is
827
+ fail-open end-to-end — indexer errors are per-skill skips, router
828
+ exceptions return empty buckets, every miss is logged to
829
+ `~/.claude/mishkan/skill-discovery/misses.jsonl` for tuning.
830
+
831
+ ### Phase 1 → Phase 2 path
832
+
833
+ Phase 1 ships indexer + router + skill + slash commands + canary in
834
+ `mishkan-init`. Promotion to Phase 2 requires:
835
+
836
+ - **2 sprints of miss-log signal.** If the misses file shows recurring
837
+ patterns the trigger-match cannot catch, tune `description` text on
838
+ the implicated skills *before* reaching for embeddings.
839
+ - **Threshold validation.** Default thresholds (`high=4.0, mid=1.5`) are
840
+ guesses on Phase 1 data; revisit at sprint close with the actual
841
+ score distribution from the miss log and successful routings.
842
+ - **Broader workflow integration.** Once thresholds settle, add the
843
+ `relevant_skill_categories` field + SkillRouter phase to the other
844
+ org-level workflows that benefit (codebase-audit, release-readiness,
845
+ knowledge-gap-discovery).
846
+ - **TUI browse surface** (optional). A `mishkan-skills` CLI that wraps
847
+ the same index for cold-browsing without a task.
848
+ - **MCP wrapper** (optional). Exposes the router as an MCP tool so
849
+ agents in other contexts (project-local subagents) can query the
850
+ same surface.
851
+
852
+ **Supersedes / amends:** none. Layers under D-010 (workflow portfolio
853
+ discipline) one level down — the same discipline (cap + anti-pattern +
854
+ miss-log feedback) applied to the skill surface rather than the workflow
855
+ surface.
856
+
857
+ ### Amendment 2026-06-07: Phase 2 shipped
858
+
859
+ Phase 1 ended at "the router exists." Phase 2 turns that into "agents
860
+ auto-discover skills without being asked," through three injection
861
+ mechanisms — none of them blocking, all fail-open.
862
+
863
+ 1. **Install-time rebuild.** `bin/mishkan.js` install phase 1 spawns the
864
+ indexer in `--rebuild` mode after the payload copy so
865
+ `~/.claude/mishkan/skill-discovery/index.json` lands seeded before the
866
+ first session boots. Fail-open: a missing `python3` or an indexer
867
+ error logs a warning and the install continues; recovery path is
868
+ `/mishkan-skills-reindex`.
869
+
870
+ 2. **SessionStart drift check.** `hooks/session-start-skill-index.sh`
871
+ runs the indexer in `--stat-only` mode on session boot. The indexer
872
+ compares each SKILL.md mtime against `meta.last_scan` and rebuilds
873
+ only on drift (or if the index file is missing). p95 budget: 200 ms,
874
+ well within the SessionStart budget shared with the other boot hooks.
875
+ Fail-open: any error → exit 0 silently.
876
+
877
+ 3. **PreToolUse auto-injection on Task / Agent.**
878
+ `hooks/pre-tool-task-skill-route.sh` reads the Task payload from
879
+ stdin, extracts `tool_input.prompt`, runs the router in
880
+ `--format injection` mode, and returns the resulting compact markdown
881
+ block via `hookSpecificOutput.additionalContext` (the documented
882
+ Claude Code PreToolUse field for prepending advisory context). Hard
883
+ caps: ≤ 3 `must_load` + ≤ 3 `should_consider` entries, ≤ 600 tokens
884
+ of prepended markdown, `adjacent` dropped at injection time
885
+ (awareness-only doesn't justify its tokens here). Skip injection
886
+ entirely on empty buckets — never pollute with "no skills found".
887
+ p95 budget: 100 ms (worst-case timeout: 1.5 s as a hard floor). The
888
+ `mishkan-init` Phase 1 canary stays in place; this becomes the
889
+ dominant path for every other Task call.
890
+
891
+ **Trust marker.** The injection renderer suffixes every non-`mishkan`
892
+ entry with `(community)`. The skill-discovery skill's existing rule —
893
+ non-`mishkan` skills are never auto-loaded for stateful operations
894
+ (D-002 / y4nn-§5) — applies unchanged.
895
+
896
+ **Telemetry.** Every Task hook invocation emits a `hook_fire` event on
897
+ the observability bus (decision = `allow` with injection, `ok` without).
898
+ Every empty-bucket routing continues to land in
899
+ `~/.claude/mishkan/skill-discovery/misses.jsonl`. A new aggregator
900
+ script `scripts/skill-discovery-misses.py` (and `/mishkan-skills-misses`
901
+ slash command) clusters misses by sorted-keyword signature and surfaces
902
+ top-N patterns + by-reason breakdown.
903
+
904
+ **Threshold-tuning process.** The mid + high thresholds remain
905
+ `mid=1.5, high=4.0` from Phase 1. Tuning is now data-driven:
906
+
907
+ - After each sprint, run `/mishkan-skills-misses --top 10`.
908
+ - For any pattern with count ≥ 5 *and* a clearly-applicable skill that
909
+ should have matched, **edit the skill's description** to include the
910
+ pattern's keywords. Description tuning is free and bounded; it should
911
+ exhaust before threshold tuning.
912
+ - If a recurring pattern still misses after description tuning, *and*
913
+ the scores are clustering just under the `must_load` boundary, lower
914
+ `--threshold-high` to 3.5; if `must_load` is over-firing on
915
+ marginally-relevant skills, raise it to 4.5. Move in 0.5 steps and
916
+ one sprint at a time. Same recipe applies to `--threshold-mid`.
917
+ - `router_exception:*` reasons are bugs — escalate to Bezalel; never
918
+ tune around an exception.
919
+
920
+ The Phase 1 → Phase 2 promotion gate ("2 sprints of miss-log signal")
921
+ applied to broadening to Phase 2 hook mechanics; the same 2-sprint gate
922
+ now applies to threshold tuning before any default is moved in the
923
+ shipped router.
924
+
925
+ ## D-009 — Amendment 2026-06-07: Phase 2 advisory injection shipped
926
+
927
+ **Original D-009 §6.2** scoped Phase 1 to telemetry-only, with the
928
+ advisory injection deferred until "the baseline rate is measured." The
929
+ phase-2 promotion has happened.
930
+
931
+ **Why Phase 2 now.** The skill-discovery PreToolUse router (D-011
932
+ Phase 2) injects skill suggestions based on the Task prompt — it
933
+ matches "implement payment" to implementation skills, not to
934
+ `graphify-query-craft` whose triggers describe structural questions.
935
+ The router will not surface graphify for the vast majority of agent
936
+ dispatches; only a runtime hook on the specific tool calls Graphify
937
+ can answer (Read on source / Grep on bare identifier) closes that
938
+ gap. Without Phase 2, the carrier-set expansion in the §6 amendment
939
+ below has no enforcement path.
940
+
941
+ **Mechanism.** `pre-tool-knowledge-route.sh` now emits an
942
+ `hookSpecificOutput.additionalContext` advisory in addition to the
943
+ telemetry event:
944
+
945
+ - **Read** on a source extension → "about to Read `<file>`. For
946
+ structural questions, `graphify query` is cheaper."
947
+ - **Grep** on a bare identifier → "`graphify query \"who calls X\"`
948
+ or `graphify affected X --depth 2` is the dispatch-aware
949
+ alternative."
950
+
951
+ Suppressed when the project has no `graphify-out/` directory (no graph,
952
+ no recommendation). Never sets `permissionDecision` — purely advisory,
953
+ the tool call proceeds whether the agent acts on it or not.
954
+
955
+ **Invariants preserved.**
956
+ - Fail-open everywhere (missing jq, missing bus, malformed input → silent exit 0).
957
+ - ≤ 50 ms p95 — bash hot path, single jq subprocess, no Python.
958
+ - Telemetry event still fires (the Knowledge tab's Graphify activity counter is unchanged).
959
+ - Trigger surface unchanged from Phase 1 — same source extensions, same bare-identifier Grep pattern.
960
+
961
+ **What this changes.** A Hizkiah / Salma / Joah / Ira / etc. who Reads
962
+ source or Greps an identifier now gets, in the tool-call context, a
963
+ specific `graphify` command to consider. The advisory is structurally
964
+ precise (suggests the right Graphify subcommand for Read vs Grep) and
965
+ project-aware (suppressed where graphify-out/ doesn't exist), so it
966
+ doesn't add noise on projects that don't use Graphify.
967
+
968
+ ## D-009 — Amendment 2026-06-07: scope expanded to all code-touching dev agents
969
+
970
+ **Original D-009** scoped the Graphify advisory nudge to **exactly five
971
+ agents** (Hizkiah, Salma, Oholiab, Nathan, Zadok) — the highest token
972
+ consumers writing code. Empirical use since the POC made the original
973
+ "five only" boundary read narrower than the actual benefit space.
974
+
975
+ **Amended scope** — **20 code-touching dev agents** carry
976
+ `graphify-query-craft` and are reached by the PreToolUse nudge when
977
+ they hit `Read`/`Grep` on source:
978
+
979
+ - **Yasad backend (5):** Hizkiah, Nathan, Zadok, Shallum, Uriah
980
+ - **Panim frontend (4):** Salma, Oholiab, Asaph, Jahaziel
981
+ - **Chosheb UI (1):** Hiram
982
+ - **Mishmar code-security (3):** Ira, Joab, Hushai
983
+ - **Migdal infra-code (4):** Palal, Meshullam, Meremoth, Hanun
984
+ - **Sefer code-documentation (3):** Joah, Shevna, Jehonathan
985
+
986
+ **Why the broadening.** Graphify answers "who calls X" / "what depends
987
+ on Y" / "where is the entry point" — structural questions useful to any
988
+ agent reading code, not just writing it. A security reviewer auditing a
989
+ payment flow benefits from the call graph as much as Hizkiah
990
+ implementing it; a documentation specialist (Joah / Shevna) writing
991
+ module docs benefits from knowing its surroundings. Restricting to
992
+ writers left readers' queries — typically grep + Read — on the expensive
993
+ path.
994
+
995
+ **What did not change.**
996
+ - The hook stays **advisory**, never blocks (D-009 invariant preserved).
997
+ - Fail-open on missing/stale graph preserved.
998
+ - `--context` discipline in the craft skill body preserved.
999
+ - The hook's trigger predicate (Read on source ext / Grep on bare
1000
+ identifier) is agent-independent — adding agents to the carrier set is
1001
+ what changes coverage, the hook itself stays the same.
1002
+ - The two orchestrators, the research pipeline, the QA reporters who
1003
+ don't read source, and the team reporters remain out of scope —
1004
+ adding them would add noise without changing behaviour.
1005
+
1006
+ **Implication for D-010 (workflow portfolio).** The
1007
+ `mishmar-security-gate` and `sefer-release-notes` workflows now invoke
1008
+ agents carrying the skill — their structural-query phases will be
1009
+ served by Graphify where before they would have grep+Read. Token
1010
+ savings carry through to those workflows.
1011
+
570
1012
  ---
571
1013
 
572
1014
  *Decisions locked May 2026. Revisit only with a dated amendment below.*
@@ -159,7 +159,7 @@ milestones. Sefer pulls at milestones and on trigger events.
159
159
  │ Each team: Lead → Specialists → QA/Advisor → Reporter │
160
160
  │ │
161
161
  │ Collaboration model: │
162
- │ Chosheb ──→ Panim design handoff · unidirectional │
162
+ │ Chosheb Panim design handoff · unidirectional │
163
163
  │ Panim ↔ Yasad API contracts · bidirectional │
164
164
  │ Yasad ↔ Mishmar audit + remediation · bidirectional │
165
165
  │ Mishmar → Migdal security gates infrastructure │
@@ -780,38 +780,6 @@ already solved well.
780
780
 
781
781
  ---
782
782
 
783
- ## 20. Open Design Questions
784
-
785
- Not blockers — next design layer.
786
-
787
- | Question | Status |
788
- |----------|--------|
789
- | SessionStart hook — what it loads · Cognee query on wake | Pending Claude Code feature validation |
790
- | ACI per team — how each team interacts with its environment | Next layer |
791
- | Cross-sprint knowledge compression — sprint memory → project graph | Next layer |
792
- | Self-improvement loop — frequency · who acts on outputs | Next layer |
793
- | Curated library bootstrap — how each team's library gets seeded | Next layer |
794
- | Sefer trigger events — full list of what fires an immediate pull | Next layer |
795
-
796
- ---
797
-
798
- ## 21. What Is Not Yet Designed
799
-
800
- Explicitly out of scope — to be designed before building:
801
-
802
- - Agent specs (system prompts · input/output contracts · failure behavior)
803
- - Prompt engineering per agent
804
- - CLAUDE.md templates (user-level · project-level)
805
- - Rules files content per team
806
- - Hooks implementation (scripts)
807
- - Skills implementation (SKILL.md content)
808
- - Curated library initial content per team
809
- - Cognee graph schema (entity types · relationship types · ontology)
810
- - Observability pipeline (log aggregation · improvement layer queries)
811
- - Model routing configuration
812
-
813
- ---
814
-
815
783
  *MISHKAN Design Document — May 2026*
816
784
  *Living document. Claude Code-first. Cognee locked. Hebrew naming locked.*
817
785
  *Six teams including Sefer. Init flow locked. Sequential execution locked.*
@@ -22,9 +22,10 @@ foundation with:
22
22
  2. **A daemon (`mishkan-watchd`)** — tails every session's NDJSON, polls a few
23
23
  synchronous sources (git worktrees, Cognee stats), keeps a live snapshot of
24
24
  harness state, and exposes a UNIX-socket NDJSON protocol.
25
- 3. **A TUI client (`mishkan-watch`)** — Textual app. 5 tabs, key-driven, no
25
+ 3. **A TUI client (`mishkan-watch`)** — Textual app. 8 tabs, key-driven, no
26
26
  overload. Reads the daemon snapshot+delta stream, renders the view, never
27
- touches files directly.
27
+ touches files directly. Tabs 1-5 are live; tabs 6-8 (Org-Ref · Usage ·
28
+ Skills) are reference/analytical views added at v0.2.3.
28
29
 
29
30
  The TUI runs in any terminal (tmux pane, standalone window, attached over SSH).
30
31
  It is a passive observer — it never writes to harness state, never alters
@@ -62,8 +63,11 @@ directory paths. Nothing has to be registered in a config file.
62
63
  ### 3.4 No overload in the UI
63
64
 
64
65
  The TUI defaults to ONE view that answers "what is happening right now?". All
65
- historical depth lives behind explicit key presses. The 5-tab layout is a hard
66
- upper bound; if a sixth dimension matters we replace, not add.
66
+ historical depth lives behind explicit key presses. v0.2.0 shipped with a
67
+ 5-tab layout (Live · Agents · Workflows · Knowledge · Activity); v0.2.3
68
+ added three reference/analytical tabs (Org-Ref · Usage · Skills) for
69
+ recall and analysis without disturbing the live view. The 8-tab layout
70
+ is the new upper bound; if a ninth dimension matters we replace, not add.
67
71
 
68
72
  ## 4. Event schema
69
73
 
@@ -498,7 +502,7 @@ CSS classes + `set_timer` cover every effect below.
498
502
  ╠════════════════════════════════════════════════════════════════════════════════════════╣
499
503
  ║ ⏵ 02h14m · 142.4k in · 18.2k out · 89.1k cached · est. $2.40 · 2 active · 1 wf ║
500
504
  ╠════════════════════════════════════════════════════════════════════════════════════════╣
501
- ║ 1-5 tabs · / filter · enter detail · q quit · ? help · t time-order · r refresh ║
505
+ ║ 1-8 tabs · / filter · enter detail · q quit · ? help · t time-order · r refresh ║
502
506
  ╚════════════════════════════════════════════════════════════════════════════════════════╝
503
507
  ```
504
508
 
@@ -534,7 +538,7 @@ CSS classes + `set_timer` cover every effect below.
534
538
  ╠════════════════════════════════════════════════════════════════════════════════════════╣
535
539
  ║ ⏵ 02h14m · 142.4k in · 18.2k out · 89.1k cached · est. $2.40 · 2 active · 3 wf ║
536
540
  ╠════════════════════════════════════════════════════════════════════════════════════════╣
537
- ║ 1-5 tabs · enter detail · ←/→ select wf · ▸/▾ expand · / filter · q quit · ? help ║
541
+ ║ 1-8 tabs · enter detail · ←/→ select wf · ▸/▾ expand · / filter · q quit · ? help ║
538
542
  ╚════════════════════════════════════════════════════════════════════════════════════════╝
539
543
  ```
540
544
 
@@ -562,7 +566,7 @@ CSS classes + `set_timer` cover every effect below.
562
566
  ╠════════════════════════════════════════════════════════════════════════════════════════╣
563
567
  ║ ⏵ 02h14m · 142.4k in · 18.2k out · 89.1k cached · est. $2.40 · 2 active · 1 wf ║
564
568
  ╠════════════════════════════════════════════════════════════════════════════════════════╣
565
- ║ 1-5 tabs · enter detail · j/k row · tab pane · / filter · q quit · ? help ║
569
+ ║ 1-8 tabs · enter detail · j/k row · tab pane · / filter · q quit · ? help ║
566
570
  ╚════════════════════════════════════════════════════════════════════════════════════════╝
567
571
  ```
568
572
 
@@ -609,7 +613,7 @@ empty state dim-centered.
609
613
  ╠════════════════════════════════════════════════════════════════════════════════════════╣
610
614
  ║ ⏵ 02h14m · 142.4k in · 18.2k out · 89.1k cached · est. $2.40 · 2 active · 1 wf ║
611
615
  ╠════════════════════════════════════════════════════════════════════════════════════════╣
612
- ║ 1-5 tabs · enter detail · j/k row · tab pane · / filter · q quit · ? help ║
616
+ ║ 1-8 tabs · enter detail · j/k row · tab pane · / filter · q quit · ? help ║
613
617
  ╚════════════════════════════════════════════════════════════════════════════════════════╝
614
618
  ```
615
619
 
@@ -651,7 +655,7 @@ green / red / yellow / dim. `⟳` for STALE (poll deadline missed, not down).
651
655
  ╠════════════════════════════════════════════════════════════════════════════════════════╣
652
656
  ║ ⏵ 02h14m · 142.4k in · 18.2k out · 89.1k cached · est. $2.40 · 2 active · 1 wf ║
653
657
  ╠════════════════════════════════════════════════════════════════════════════════════════╣
654
- ║ 1-5 tabs · / filter focus · t order · End auto · j/k scroll · enter detail · q quit ║
658
+ ║ 1-8 tabs · / filter focus · t order · End auto · j/k scroll · enter detail · q quit ║
655
659
  ╚════════════════════════════════════════════════════════════════════════════════════════╝
656
660
  ```
657
661