@r1z4x/tezgah 1.5.1 → 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.
- package/CHANGELOG.md +126 -1
- package/MANIFEST +11 -0
- package/README.md +6 -3
- package/bin/consult +13 -10
- package/bin/tezgah-docs +18 -16
- package/bin/tezgah-doctor +152 -0
- package/bin/tezgah-research +286 -12
- package/bin/tezgah-route +48 -1
- package/bin/tezgah-setup +27 -14
- package/bin/tezgah-task +771 -46
- package/bin/tezgah-taste +48 -10
- package/docs/architecture.md +7 -4
- package/docs/citations-baseline.json +1 -1
- package/docs/clarity-baseline.json +5 -5
- package/docs/contract.md +112 -25
- package/docs/evidence.md +201 -28
- package/docs/feature-audit.md +25 -4
- package/docs/gate.md +70 -33
- package/docs/glossary.md +4 -4
- package/docs/hosts.md +8 -8
- package/docs/index.json +30 -10
- package/docs/judge.md +9 -3
- package/docs/models.md +35 -2
- package/docs/operations.md +103 -3
- package/docs/research.md +392 -13
- package/docs/skills.md +24 -6
- package/docs/status-line.md +5 -5
- package/docs/testing.md +2 -2
- package/docs/vision.md +12 -4
- package/hooks/hooks.json +2 -2
- package/hooks/lang/en.json +323 -0
- package/hooks/lang/tr.json +344 -0
- package/hooks/projects-posttooluse.py +24 -5
- package/hooks/projects-pretooluse.py +9 -4
- package/hooks/projects-stop.py +28 -16
- package/hooks/tezgah_agents.py +29 -9
- package/hooks/tezgah_clarity.py +7 -3
- package/hooks/tezgah_components.py +2 -1
- package/hooks/tezgah_context.py +460 -390
- package/hooks/tezgah_gate.py +640 -104
- package/hooks/tezgah_integrity.py +1480 -197
- package/hooks/tezgah_models.py +337 -15
- package/hooks/tezgah_paths.py +103 -10
- package/hooks/tezgah_policy.py +286 -130
- package/hooks/tezgah_product.py +107 -0
- package/hooks/tezgah_rank.py +29 -27
- package/hooks/tezgah_replay.py +200 -30
- package/hooks/tezgah_research.py +1297 -12
- package/hooks/tezgah_skill_pick.py +58 -17
- package/hooks/tezgah_stopspec.py +7 -0
- package/hooks/tezgah_store.py +74 -27
- package/hooks/tezgah_task.py +917 -8
- package/hosts/codex/hook.py +9 -10
- package/hosts/cursor/hook.py +21 -14
- package/hosts/dsh/hooks.json +2 -2
- package/hosts/omp/hook.py +44 -23
- package/hosts/omp/tezgah-hook.ts.in +93 -7
- package/hosts/opencode/plugins/tezgah.js +119 -39
- package/output-styles/tezgah.md +76 -42
- package/package.json +1 -1
- package/skills/analyze-app/SKILL.md +57 -0
- package/skills/design-contract/EVALS.md +24 -1
- package/skills/design-contract/SKILL.md +17 -1
- package/skills/design-contract/data-views.md +86 -0
- package/skills/feature-audit/SKILL.md +32 -3
- package/skills/i-have-adhd/EVALS.md +22 -2
- package/skills/i-have-adhd/SKILL.md +12 -5
- package/skills/plan-add/EVALS.md +8 -8
- package/skills/plan-add/SKILL.md +22 -21
- package/skills/plan-sync/EVALS.md +2 -2
- package/skills/plan-sync/SKILL.md +14 -8
- package/skills/pm-frameworks/SKILL.md +6 -0
- package/skills/ponytail/EVALS.md +21 -2
- package/skills/ponytail/SKILL.md +4 -4
- package/skills/product-analysis/EVALS.md +23 -1
- package/skills/product-analysis/SKILL.md +50 -11
- package/skills/product-flow/EVALS.md +81 -0
- package/skills/product-flow/SKILL.md +91 -0
- package/skills/research/SKILL.md +99 -2
- package/skills/tezgah-contract/EVALS.md +52 -7
- package/skills/tezgah-contract/SKILL.md +204 -85
package/docs/operations.md
CHANGED
|
@@ -224,7 +224,7 @@ After a change to the contract text (`hooks/tezgah_policy.py`,
|
|
|
224
224
|
- `--refresh` does that without a reinstall, for every armed host's static
|
|
225
225
|
block and not only opencode's (`refresh_contract`). opencode has no
|
|
226
226
|
session-start hook, so its plugin runs it once per session
|
|
227
|
-
(`hosts/opencode/plugins/tezgah.js:
|
|
227
|
+
(`hosts/opencode/plugins/tezgah.js:2689-2693`). Until 2026-10-02 it
|
|
228
228
|
re-rendered opencode's files alone and reset the one shared hash, so a rule
|
|
229
229
|
edit left the other static files stale while `--report` went green (audit
|
|
230
230
|
M-5).
|
|
@@ -371,6 +371,7 @@ does not hold.
|
|
|
371
371
|
| `tezgah-doctor` | nothing: sizes, session and event counts, whether opencode is running, the two context-hygiene settings, the `.codegraph` bytes and index presence per repository, and the three host state dirs (`bin/tezgah-doctor::collect`, `bin/tezgah-doctor::report`) |
|
|
372
372
|
| `tezgah-doctor --clean` | vacuums opencode's database, and only when opencode is not running (`bin/tezgah-doctor::vacuum_db`, `bin/tezgah-doctor::main`); deletes every evidence ledger whose newest row is older than `--retention-days` (default 30), rows, import offsets and old JSONL file together (`hooks/tezgah_store.py::sweep_evidence`), and the turn stamps and used-tool marks last written before then (`hooks/tezgah_store.py::sweep_cache`); and deletes the files not modified for that long - `classify.log`, `context-drops.log`, `debug.log` and the `turns/` and `sessions/` files a running older release still writes - in the cache and its sandbox fallback, keeping the current session's (`$TEZGAH_SESSION`) ledger, stamp and marks whatever their age (`sweep_state`) |
|
|
373
373
|
| `tezgah-doctor --import-evidence` | imports every old `evidence/*.jsonl` file into the cache's `tezgah.db` now, in the cache and its sandbox fallback (`bin/tezgah-doctor::import_evidence`); session start runs the same import detached at most once a day (`hooks/tezgah_store.py::import_later`) |
|
|
374
|
+
| `tezgah-doctor --repair-evidence [--apply]` | counts, per session, the evidence rows an old `evidence/*.jsonl` file put in again when a volume remount gave it another device id, in the cache and its sandbox fallback. Every `imported` row of one file is one import stream, which put the file's first `bytes` in. For a row text, the longest stream's count stays and every other stream's count is a copy: that many of the newest rows go, so a row written to the database directly beside them stays. A session holding a file line fewer times than its streams put it in is left whole and printed for manual review. A file gone from its name, holding another inode or shorter than its longest stream is printed and skipped, not guessed (`bin/tezgah-doctor::evidence_plan`). It writes nothing without `--apply`, which backs `tezgah.db` up to `tezgah.db.bak-<YYYYmmdd-HHMMSS>` through SQLite's backup API, deletes those rows and leaves one import offset per file in one transaction. Before that transaction commits it counts the rows against the plan, and it rolls back and exits 1 when a row it kept is gone or a copy it deleted is still there (`bin/tezgah-doctor::repair_evidence`) |
|
|
374
375
|
| `tezgah-doctor --coverage` | every tracked file the codegraph index does not hold, in two classes — a supported extension the index is missing, and a shebang-only script with no `.py` twin — with the file counts it read, so an empty result cannot read as "everything is covered" |
|
|
375
376
|
| `tezgah-doctor --stack` | per host: the context files in load order, the skill dirs and which copy wins, the hook rows per event with their owner, the MCP servers, and every conflict; exits 1 on one ([hosts](hosts.md#precedence-what-each-host-loads-and-in-which-order), `hooks/tezgah_stack.py::report`) |
|
|
376
377
|
| `tezgah-doctor --prune-sessions DAYS` | deletes sessions idle longer than DAYS through `opencode session delete`, then vacuums; skipped when opencode is running or its CLI is missing (`bin/tezgah-doctor::prune_sessions`, `bin/tezgah-doctor::main`) |
|
|
@@ -412,7 +413,7 @@ ledger row. A rollback therefore never reads it as a pre-state (`capture_after`,
|
|
|
412
413
|
`hooks/tezgah_snapshot.py::capture_after`). A file outside the repository gets no
|
|
413
414
|
after blob.
|
|
414
415
|
opencode reaches the same call through a process (`noteTaste`,
|
|
415
|
-
`hosts/opencode/plugins/tezgah.js:
|
|
416
|
+
`hosts/opencode/plugins/tezgah.js:2436-2446`).
|
|
416
417
|
|
|
417
418
|
```sh
|
|
418
419
|
touch ~/.config/tezgah/taste-on # arm; rm it to disarm
|
|
@@ -425,7 +426,8 @@ bin/tezgah-taste export # accepted learnings into AGENTS.m
|
|
|
425
426
|
bin/tezgah-taste label; bin/tezgah-taste label ID preference # the calibration sample
|
|
426
427
|
bin/tezgah-taste calibrate # the bound a rule needs
|
|
427
428
|
bin/tezgah-taste gate # the pooled before/after test
|
|
428
|
-
bin/tezgah-taste mine --host omp --stats # sessions, writes, prompts after a writing turn
|
|
429
|
+
bin/tezgah-taste mine --host omp --stats # this repository's sessions, writes, prompts after a writing turn
|
|
430
|
+
bin/tezgah-taste mine --all-projects # every session under ~/Projects, each repo pseudonymised
|
|
429
431
|
bin/tezgah-taste measure --samples S --labels L [--typed] # judge precision/recall
|
|
430
432
|
```
|
|
431
433
|
|
|
@@ -614,6 +616,102 @@ it costs nothing there. On held-out Turkish phrasings of the docs index,
|
|
|
614
616
|
meaning alone found the page in the top three for 0.91 with `embed-mrl` and 0.78
|
|
615
617
|
with `embed-m2v`. The fusion found it for 0.75 and 0.74, BM25 for 0.68.
|
|
616
618
|
|
|
619
|
+
## Slice journal: `tezgah-task slice`
|
|
620
|
+
|
|
621
|
+
A delegated slice can die with its parent. A crash, an omp `/clear`, a quota or
|
|
622
|
+
429 answer, or a model or host switch ends the parent session. The child's
|
|
623
|
+
worktree and commits stay, but no one remembers them. The slice journal is that
|
|
624
|
+
memory, and it is host-neutral.
|
|
625
|
+
|
|
626
|
+
Each spawned slice gets one row in `<repo root>/.tezgah/slices/slices.db`, a SQLite
|
|
627
|
+
file opened like the taste store (`hooks/tezgah_task.py::SLICE_SCHEMA`).
|
|
628
|
+
An older release wrote one JSON file per record there. The first open imports each one and deletes it.
|
|
629
|
+
`.gitignore` excludes `.tezgah/`, a private directory, so the journal never reaches a commit.
|
|
630
|
+
The id is the host's own agent name: the omp task `name` or the Codex
|
|
631
|
+
`task_name`. A Claude `Agent`/`Task` input may carry a `name` too. Otherwise the
|
|
632
|
+
id is the first 12 hex digits of the brief's sha1. A record holds the host, the agent
|
|
633
|
+
type, the first 4000 characters of the brief, the parent session and the cwd.
|
|
634
|
+
It also holds the linked worktree the brief names, its branch, and the root's
|
|
635
|
+
HEAD at open. Its `status` is `open`, `done`, `stopped`, `resumed` or `stale`.
|
|
636
|
+
Its `failure` is one of `quota`, `rate_limit`, `aborted`, `timeout`, `cut_off`
|
|
637
|
+
or `error`. `attempts` counts each re-open of the same id
|
|
638
|
+
(`hooks/tezgah_task.py::open_slice`, `hooks/tezgah_task.py::close_slice`).
|
|
639
|
+
Another session's record of the same name is not re-opened under another brief.
|
|
640
|
+
The spawn gets this session's own record of that name, else `<name>-<sha1[:6]>` of its brief.
|
|
641
|
+
`name` keeps the spawned name, and the same brief from another session still re-opens the record
|
|
642
|
+
(`hooks/tezgah_task.py::_own_id`). The record stays in cwd's journal, the one its
|
|
643
|
+
owner's Stop rule, resume block and review guard read. When every absolute path its
|
|
644
|
+
brief names lies in one other repository, `repo` names that repository, and the
|
|
645
|
+
slice line says `(in <name>)` (`hooks/tezgah_task.py::_brief_repo`). A repository's
|
|
646
|
+
own `.tezgah` counts as that repository (`hooks/tezgah_task.py::main_repo`).
|
|
647
|
+
|
|
648
|
+
The slice's own task text (without a batch's shared `context`) decides its
|
|
649
|
+
worktree and its lease. The worktree is the one the task names last, else the
|
|
650
|
+
brief (`hooks/tezgah_task.py::_worktree_in`). `declared` holds the checkout a
|
|
651
|
+
`Worktree:`, `Checkout` or `Cwd:` line declares, which only the main-checkout
|
|
652
|
+
refusal reads (`hooks/tezgah_task.py::_declared_in`). Its `Owns:` lines name
|
|
653
|
+
repository-relative globs, and only that slice may write those paths while its
|
|
654
|
+
record runs (`hooks/tezgah_task.py::owned_globs`, `hooks/tezgah_task.py::owner_of`). A
|
|
655
|
+
Claude background child's record also keeps the launch's `agentId` as `child`,
|
|
656
|
+
which its own calls carry (`hooks/tezgah_task.py::slice_of`). The
|
|
657
|
+
gate holds siblings to the lease (`docs/gate.md`, the Lease rule), and the
|
|
658
|
+
spawn-time warning names two writing slices that share one worktree
|
|
659
|
+
(`hooks/tezgah_task.py::worktree_clash`).
|
|
660
|
+
|
|
661
|
+
The hooks write it. A spawn call - omp `task`, Claude, dsh and Cursor
|
|
662
|
+
`Agent`/`Task`, Codex `spawn_agent`, opencode `task` - opens one record per
|
|
663
|
+
slice (`hooks/tezgah_task.py::spawned`, `hooks/tezgah_task.py::note_spawn`).
|
|
664
|
+
Claude, dsh, Cursor and opencode answer the call once the child ended. So the
|
|
665
|
+
record closes at once (`hooks/tezgah_task.py::classify`). A failed call becomes
|
|
666
|
+
`stopped` with its failure class, and a good one `done`. The omp `task` and Codex
|
|
667
|
+
`spawn_agent` calls answer while the child runs, so the record stays `open`. So
|
|
668
|
+
does a Claude launch sent with `run_in_background` or one whose result names a
|
|
669
|
+
background child. That child's SubagentStop closes it as `done`
|
|
670
|
+
(`hooks/tezgah_task.py::close_child`). An omp
|
|
671
|
+
record settles from the newest child transcript in the parent's session dir.
|
|
672
|
+
omp names a same-name re-dispatch `<name>-2.jsonl`. The last 64 KB of that file
|
|
673
|
+
decide `stopped` or `done` (`hooks/tezgah_task.py::pending`). A record
|
|
674
|
+
nothing moved for six hours closes `stale`, and a background `job` after
|
|
675
|
+
omp's 3600 s deadline. Codex reports no child end tezgah can see, so its
|
|
676
|
+
records end `stale`. Every prompt lists up to three pending records, newest
|
|
677
|
+
first, each with the command that resumes it (`hooks/tezgah_task.py::slice_lines`).
|
|
678
|
+
They are the records this session spawned or nobody owns, such as one opened by hand. The resume block at
|
|
679
|
+
session start and after a compaction adds one line that counts the other
|
|
680
|
+
sessions' records. `tezgah-task slice reconcile` lists them all.
|
|
681
|
+
|
|
682
|
+
| Command | What it does |
|
|
683
|
+
|---|---|
|
|
684
|
+
| `tezgah-task slice open --id ID [--kind agent\|job] [--host H] [--agent A] [--brief TEXT\|--brief-file F] [--parent P] [--cwd PATH]` | records a slice by hand, for a host whose spawn the hooks do not see |
|
|
685
|
+
| `tezgah-task slice done ID` / `slice stop ID [--class C]` | closes a record as done, or as stopped with a failure class. An exact record id answers from any session. A spawned name answers too, and under `TEZGAH_SESSION` only for that session's records and unowned ones (`hooks/tezgah_task.py::find_slice`) |
|
|
686
|
+
| `tezgah-task slice reconcile [--prune]` | lists every pending record with a resume brief. `--prune` also removes landed worktrees and marks those records done. It deletes a landed local branch only when no worktree holds it, it tracks no upstream and its reflog shows a commit of its own; it never deletes main, master or the current branch |
|
|
687
|
+
| `tezgah-task slice resume ID` | prints the native path first: omp `write agent://<id>` while the parent lives, Claude `SendMessage` when the id is an agent name. Otherwise it prints a re-dispatch brief: the original brief plus the last commit, the uncommitted files and "do not redo committed steps". A quota or rate-limit stop is sent to another provider. It sets the status to `resumed` |
|
|
688
|
+
| `tezgah-task slice stats [--window DAYS] [--json]` | counts records per status, failure class and host. A `class+host` signature with 3 or more events is an RSI lever candidate, and so is one with 5% of a window that holds 20 or more slices. The line names the lever |
|
|
689
|
+
| `tezgah-task slice board [--parent P]` | lists the open slices one parent spawned - the session's own, or for a subagent its parent's - newest first: the `Owns:` globs, worktree, branch and last commit of each, bounded to 12 lines (`hooks/tezgah_task.py::board`) |
|
|
690
|
+
| `tezgah-task slice merge-plan [--base REF]` | forecasts every done slice branch that carries unmerged work against REF (HEAD) and against the others with `git merge-tree`, and leaves out a `merge=union` file such as CHANGELOG.md. A branch touching `MANIFEST` or the citation baseline comes last, the rest fewest conflicts first. A branch merge-tree cannot forecast is printed as `not judged` and the exit is 1 (`bin/tezgah-task::merge_plan`) |
|
|
691
|
+
|
|
692
|
+
`tezgah-task review NNN <reviewer> approve` refuses while an open, stopped or
|
|
693
|
+
stale record names that reviewer as its id, agent or spawned name. Under
|
|
694
|
+
`TEZGAH_SESSION` only that session's records and unowned ones count. The refusal
|
|
695
|
+
prints the exact id to resume or close. A record keeps the plan
|
|
696
|
+
that was active when it opened, and only that plan's records count. A record
|
|
697
|
+
with no plan counts when it changed after the plan's checkpoint commit. A
|
|
698
|
+
`resumed` record hands the guard to its re-dispatch's own record
|
|
699
|
+
(`bin/tezgah-task::unfinished_review`).
|
|
700
|
+
The lever map is a closed set. `rate_limit` and `quota` point at the
|
|
701
|
+
`hooks/tezgah_models.py` fallback chain. `cut_off` and `timeout` point at a
|
|
702
|
+
per-slice deadline, `aborted` at the `wip:` commit cadence, a duplicate job at
|
|
703
|
+
journalling background jobs. Plain `error` has no lever: read the transcript.
|
|
704
|
+
|
|
705
|
+
The orchestration text carries the session's rule
|
|
706
|
+
(`hooks/tezgah_policy.py::ORCHESTRATE`, `hooks/tezgah_agents.py::_orch_body`). A
|
|
707
|
+
slice commits `wip: <step>` after each step. The session resumes or re-dispatches
|
|
708
|
+
a stopped slice and never absorbs it inline. `slice board` shows the sibling
|
|
709
|
+
leases and `slice merge-plan` orders the landed branches. `slice reconcile
|
|
710
|
+
--prune` runs before the turn that merged slices ends.
|
|
711
|
+
The `~/.config/tezgah/slices-off` switch
|
|
712
|
+
stops the hooks from writing records (`hooks/tezgah_paths.py::UNCLASSIFIED_SWITCHES`).
|
|
713
|
+
A cwd outside a git repository writes nothing either.
|
|
714
|
+
|
|
617
715
|
## Troubleshooting
|
|
618
716
|
|
|
619
717
|
| Symptom | First check | Likely cause |
|
|
@@ -760,6 +858,8 @@ page exits 1 with the message it always printed (`available()`,
|
|
|
760
858
|
its pins, the fetch and conversion, the reader and `fuse`; the `embed-mrl` and
|
|
761
859
|
`embed-m2v` registry rows that `--enable`, `--disable` and `--features` read.
|
|
762
860
|
`tests/test_embed.py` builds tiny models in the test and pins the rest.
|
|
861
|
+
- `hooks/tezgah_task.py`, `bin/tezgah-task` — the slice journal: the record, the
|
|
862
|
+
spawn parser, reconcile, resume, prune and stats.
|
|
763
863
|
- `hooks/tezgah_paths.py`, `hooks/tezgah_context.py` — the paths and `off()`; the
|
|
764
864
|
marks and the kill-switch filtering.
|
|
765
865
|
- `RELEASING.md`, `README.md`, `AGENTS.md`, `.gitignore`, `tests/test_setup.py` —
|