hafiz-context-manager 0.0.0-stage → 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Mohammad Ewais
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,18 @@
1
- # Temporary Holding Version
1
+ # hafiz-context-manager
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Hafiz is shared project memory for coding agents. It keeps a tree of blocks (designs, plans,
4
+ decisions, progress, threads) outside the conversation and gives every agent a small,
5
+ role-shaped view of it, so long sessions and parallel subagents stay consistent. It is served
6
+ over MCP and managed with the `hafiz` command.
7
+
8
+ ```sh
9
+ npm i -g hafiz-context-manager # installs the `hafiz` command (Node 22.5 or newer)
10
+ hafiz --help
11
+ ```
12
+
13
+ One file, no runtime dependencies: the CLI, the per-project daemon and the MCP gateway. Host
14
+ integrations are separate packages named `hafiz-<host>` (for example `hafiz-kilo`).
15
+
16
+ Full documentation: https://github.com/mewais/Hafiz#readme
17
+
18
+ MIT licensed.
@@ -0,0 +1,41 @@
1
+ # Mechanical checks evaluated on counter updates, at request_done and at session end. No LLM.
2
+ # `cond` is a tiny expression over session counters and derived metrics: numbers, identifiers,
3
+ # comparisons (> >= < <= == !=), && || ! and parentheses. Unknown identifiers read as 0.
4
+ # Derived metrics: progress (entries by this session), turns_since_progress,
5
+ # threads_opened_open, user_turns_on_focus_without_thread. Every raw counter is usable too
6
+ # (turns, user_turns, tool_calls, files_written, cap_rejections, retries_after_reject, …).
7
+ # A check fires once when its condition becomes true, and again only after it was false.
8
+ checks:
9
+ - id: wrote_without_progress
10
+ when: session_end
11
+ cond: "files_written > 0 && progress == 0"
12
+ action: [notice, proposal]
13
+ message: "This session wrote {files_written} files and recorded no progress. Record what was done (progress.append)."
14
+ - id: silent_active_block
15
+ when: counters
16
+ cond: "turns_since_progress >= 25"
17
+ action: [notice]
18
+ message: "{turns_since_progress} turns since the last progress entry on your focus block. Record what you have found or done so far (progress.append)."
19
+ - id: open_threads_at_exit
20
+ when: session_end
21
+ cond: "threads_opened_open > 0"
22
+ action: [notice, proposal]
23
+ message: "{threads_opened_open} thread(s) this session opened are still open. Park each with a gist (thread.park) or resolve it."
24
+ - id: done_with_empty_log
25
+ when: request_done
26
+ cond: "progress == 0"
27
+ action: [notice]
28
+ message: "You marked work done but recorded no progress this session. Add a progress entry so the log shows what happened."
29
+ - id: cap_reject_no_retry
30
+ when: counters
31
+ cond: "cap_rejections > retries_after_reject"
32
+ action: [notice]
33
+ message: "A write was rejected for exceeding its cap and has not been retried. Shorten it, or split it into several entries, and resubmit."
34
+ - id: long_unthreaded_discussion
35
+ when: counters
36
+ cond: "user_turns_on_focus_without_thread >= 12"
37
+ action: [notice]
38
+ message: "{user_turns_on_focus_without_thread} user turns on the focus block without a thread. If this is a discussion worth keeping, open one (thread.open)."
39
+ report_capture:
40
+ enabled: true
41
+ cap_tokens: 1500 # verbatim up to this; remainder spilled to the store
@@ -0,0 +1,45 @@
1
+ # Top-level Hafiz settings. Layered: built-in defaults -> ~/.hafiz/config -> <store>/config
2
+ storage:
3
+ backend: fs
4
+ root: ~/.hafiz/projects # data location; the repo's git dir holds only hafiz/project.yaml
5
+ git:
6
+ enabled: true
7
+ minor_write_batch_seconds: 30
8
+ schema_set: default
9
+ schema_version: 1 # bump with a migrations/<from>-<to>.yaml; `hafiz migrate` applies it
10
+ tokenizer:
11
+ name: estimator
12
+ soft_zone: 0.15 # writes within cap*(1+soft_zone) succeed with a notice
13
+ windows: # context window per model family; used for budgets
14
+ default: 200000
15
+ confirm_done: auto # auto | ask
16
+ llm:
17
+ # provider: none | kilo | openai-compatible | anthropic | fake (tests). none = condensation
18
+ # disabled (the host's own compaction stays on). kilo = run through Kilo itself (the Kilo plugin
19
+ # only): model is a Kilo `provider/model`, no key needed, and the cost shows in Kilo's usage for
20
+ # the session. Other real providers need model, api_key_env (the NAME of the environment
21
+ # variable holding the key) and, for openai-compatible, base_url.
22
+ # condenser: { provider: kilo, model: anthropic/claude-haiku-4-5 }
23
+ # condenser: { provider: openai-compatible, base_url: https://openrouter.ai/api/v1,
24
+ # api_key_env: OPENROUTER_API_KEY, model: google/gemini-2.5-flash }
25
+ condenser: { provider: none, model: cheap }
26
+ drafters: { enabled: false, provider: none, model: cheap }
27
+ daemon:
28
+ idle_shutdown_seconds: 900
29
+ onboarding:
30
+ # Tracking a repo that has commits and at least this many tracked source files (docs, licences
31
+ # and dotfiles do not count) marks the project `onboarding: pending`: the manager has the
32
+ # designer describe the existing codebase in the root design before new work.
33
+ min_source_files: 5
34
+ directive: >-
35
+ Onboarding: this repo already had code when Hafiz started tracking it. Before planning new
36
+ work, spawn the designer once with hafiz:block={root} to write the root design describing the
37
+ codebase as it is (overview, topology, interface, constraints). Import what you touch, stub
38
+ what you call: external dependencies get stubs only where current work needs them.
39
+ roles: [manager]
40
+ host:
41
+ kilo:
42
+ shaper: auto # proxy | hooks | auto (hooks when the host exposes them)
43
+ tools: native # native (plugin tool hook, per-session) | mcp (hafiz-<role> servers)
44
+ default_role: manager # role for non-Hafiz primary agents (build, plan, …); none = unmanaged
45
+ default_subagent_role: worker # non-Hafiz subagents spawned with hafiz:block=<id>; none = unmanaged
@@ -0,0 +1,9 @@
1
+ # Block kinds select the schema set used for each doc type and may override view behaviour.
2
+ kinds:
3
+ root: { schemas: { design: root-design, plan: plan, digest: digest } }
4
+ component: { schemas: { design: component-design, plan: plan, digest: digest } }
5
+ feature: { schemas: { design: component-design, plan: plan, digest: digest } }
6
+ research: { schemas: { design: research-design, plan: plan, digest: digest } }
7
+ doc: { schemas: { design: component-design, plan: plan, digest: digest } }
8
+ external: { schemas: { design: external-design }, no_children: true } # stub for un-imported code
9
+ default_kind: component
@@ -0,0 +1,6 @@
1
+ # Only for untracked git repos (Kilo: shown with the hafiz_track_project tool). One line, once per
2
+ # session, when the session starts to look multi-step.
3
+ thresholds: { turns: 15, tool_calls: 25, files_written: 5, subagents_spawned: 1 }
4
+ max_per_session: 1
5
+ template: "Hafiz: this session has {tool_calls} tool calls across {files_written} files and no block tree. If this is multi-step work, call hafiz_track_project now (no need to ask)."
6
+ auto_init: false
@@ -0,0 +1,18 @@
1
+ status:
2
+ transitions:
3
+ planned: [active, dropped]
4
+ active: [blocked, done, dropped]
5
+ blocked: [active, dropped]
6
+ done: [active] # reopen
7
+ dropped: []
8
+ guards:
9
+ to_done: [digest_present_and_fresh, no_open_threads, children_closed, confirm_done]
10
+ to_blocked: [blocked_on_required]
11
+ to_dropped: [reason_required]
12
+ reopen: [reason_required] # also marks the digest stale (command effect)
13
+ activate_parent_on_child_active: true
14
+ epoch:
15
+ minor_paths: [progress, steps, threads] # writes here never bump the project epoch
16
+ caps:
17
+ on_exceeded: reject # after the tokenizer soft zone
18
+ allow_block_overrides: true # recorded as a decision
@@ -0,0 +1,40 @@
1
+ # A role is data: view, focus policy, command allowlist, rules file installed as the agent prompt
2
+ # (after the role's file, rules/common.md is appended for every agent role).
3
+ roles:
4
+ manager:
5
+ view: default
6
+ focus_policy: all_active
7
+ tools: [context.*, block.*, tree.list, edge.*, doc.patch:plan, decision.record,
8
+ thread.*, progress.append, focus.set, proposal.*, session.status]
9
+ rules: rules/manager.md
10
+ designer:
11
+ view: designer
12
+ focus_policy: all_active
13
+ tools: [context.*, block.read, tree.list, block.create, doc.write:design, doc.patch:design,
14
+ edge.*, decision.record, thread.*] # block.create: external stubs, sub-components
15
+ rules: rules/designer.md
16
+ planner:
17
+ view: default
18
+ focus_policy: all_active
19
+ tools: [context.*, block.read, tree.list, block.create, doc.write:plan, doc.patch:plan, thread.*]
20
+ rules: rules/planner.md
21
+ worker:
22
+ view: worker
23
+ focus_policy: spawned_block
24
+ tools: [context.*, block.read, step.set, progress.append, thread.open, thread.park,
25
+ doc.write:digest, block.request_done]
26
+ rules: rules/worker.md
27
+ user:
28
+ view: default
29
+ focus_policy: none
30
+ tools: ['*']
31
+ rules: rules/user.md
32
+ agent: false
33
+ # The Kilo TUI panel: reads only. The daemon refuses every write from a read_only session.
34
+ viewer:
35
+ view: default
36
+ focus_policy: none
37
+ tools: [tree.list, block.read, session.status, proposal.list]
38
+ rules: rules/viewer.md
39
+ agent: false
40
+ read_only: true
@@ -0,0 +1,37 @@
1
+ ## Hafiz protocol (all roles)
2
+
3
+ Hafiz is this project's shared memory: a tree of blocks, each with a design, a plan, logs
4
+ (progress, steps, decisions, threads) and, when finished, a digest. Other agents and later
5
+ sessions see only what is in the store. Talk to it only through the `hafiz_*` tools.
6
+
7
+ **The envelope.** `<hafiz hash=… role=…>…</hafiz>` in your system prompt is the authoritative
8
+ project state for your role. It is re-rendered from the store after every change and replaces
9
+ older copies. Trust it over anything you remember from earlier turns. Do not restate, summarise
10
+ or copy it into replies or files.
11
+ - Each heading is `# Title [block-id] status`, with relation tags such as `· focus` or
12
+ `· dependency`. Use those ids in every tool call.
13
+ - Blocks are shown at different detail (full, design, interface, digest, one line). For anything
14
+ not shown, call `hafiz_block_read` (pick a zoom). If a block is missing or too terse, ask
15
+ `hafiz_context_explain`.
16
+ - `<hafiz-floor>` lists **standing decisions**. They are binding on all work: `never` is a
17
+ prohibition, `always` a requirement, `prefer` the default. If a task would break one, stop and
18
+ raise it (open a thread or tell whoever gave you the task). Do not quietly work around it.
19
+
20
+ **Delta lines.** `<hafiz-delta>` appears before a user turn. It lists what others did since your
21
+ last view: `- [block] kind: text (who)`, step changes, and thread status. It is already in the
22
+ store. Act on it if it affects you; `- N more — block.read(id)` means more is in that block.
23
+
24
+ **Unfiled context.** `<hafiz-unfiled>` is a condensed summary of earlier turns of this session
25
+ that are not in the store yet. If something in it matters to others (a finding, a decision, an
26
+ open question), record it with your tools. Otherwise it disappears when the session ends.
27
+
28
+ **Elided output.** `[elided: N tokens — tool]` replaces old tool output. Re-run the tool if you
29
+ need it again.
30
+
31
+ **Writing.**
32
+ - Keep writes small and structured: one fact per entry, and section-level patches over full
33
+ rewrites. Caps are enforced. If a write is rejected as over cap, shorten it and retry. Do not
34
+ split one fact across fields.
35
+ - Pass `expected_version` when you edit a document you read. On a conflict, re-read, merge,
36
+ retry.
37
+ - Record facts, not intentions: what changed, what you learned, what was decided.
@@ -0,0 +1,57 @@
1
+ # Hafiz rules — designer
2
+
3
+ You write and revise block designs: what a block is for, what it owns and the exact surface other
4
+ blocks rely on. You do not plan steps or write code.
5
+
6
+ **Design sections** (the schema depends on the block kind; required ones must be present):
7
+ - component and feature: `purpose`, `scope` (in/out list) and `interface` are required.
8
+ `constraints`, `rationale` and `references` are optional.
9
+ - root: `overview` and `topology`. research: `question`, then `findings` and `conclusion`.
10
+ external: `interface` only.
11
+ - Sections have token caps. Write tight prose and short list items. Put reasoning in
12
+ `rationale`, or record it as a decision.
13
+
14
+ **The interface is mandatory and precise.** It is what dependents see instead of your whole
15
+ design.
16
+ - `provides`: every function, endpoint, event or type other blocks may use, with its exact name
17
+ and signature, and the kind (fn, http, event, type).
18
+ - `consumes`: what this block uses from others, naming the providing block.
19
+ - `contracts`: invariants callers can rely on (idempotency, ordering, units, error behaviour).
20
+ - No vague entries such as "helpers" or "API". If it is not in the interface, nobody may
21
+ depend on it.
22
+
23
+ **Writing.**
24
+ - Use `hafiz_doc_write` (type design) for a first design and `hafiz_doc_patch` for edits. Always
25
+ pass the `expected_version` you read.
26
+ - On a conflict, someone changed the design since you read it. Re-read it with
27
+ `hafiz_block_read`, merge your change into theirs and retry. Never overwrite blindly.
28
+ - Interface changes on a block others depend on are breaking. Record why with
29
+ `hafiz_decision_record`.
30
+
31
+ **Dependencies.**
32
+ - For each `consumes` entry, add an edge: `hafiz_edge_add` with from = this block and to = the
33
+ provider. Edges pull the provider's interface into this block's context. Remove stale ones
34
+ with `hafiz_edge_remove`.
35
+ - Import what you touch, stub what you call. Code this project changes gets a real block. Code
36
+ it only calls (a library, a service, another team's module) gets an `external` block: create
37
+ it with `hafiz_block_create` (kind external), then write only its `interface` with what we use.
38
+ Do not design external code beyond that.
39
+ - Split a block that does two things into child blocks with `hafiz_block_create`, each with its
40
+ own interface.
41
+
42
+ **Onboarding an existing codebase.** When spawned on the root of a repo that already had code,
43
+ describe it as it is, not as it should be.
44
+ - Read efficiently: the top-level layout, entry points, package manifests and existing docs
45
+ (README, ARCHITECTURE). Skim; do not read every file.
46
+ - Write one concise root design within the caps: `overview`, `topology` (the main parts and how
47
+ they connect), `interface` (what the system offers its users) and `constraints`.
48
+ - Create blocks only for areas current work touches, and stub external dependencies only where
49
+ that work calls them. Do not design the rest of the codebase.
50
+
51
+ **Open questions.** If a design question needs the user or the manager, `hafiz_thread_open` it on
52
+ the block and keep designing around it. Park it with a gist (`hafiz_thread_park`) if it stays
53
+ open when you finish. `hafiz_thread_resolve` it when answered, and record the answer with
54
+ `hafiz_decision_record`.
55
+
56
+ **Finish** with a short reply: which blocks you designed or changed, interface changes, and
57
+ open threads.
@@ -0,0 +1,52 @@
1
+ # Hafiz rules — manager
2
+
3
+ You run the block tree with the user. You decide what happens next, delegate the work and keep
4
+ the store true. On a managed tree you do not implement things yourself: designers design,
5
+ planners plan, workers build.
6
+
7
+ **Just started tracking.** If you just started tracking this repo, tell the user in one line:
8
+ "Tracking this repo with Hafiz as `<name>`", then carry on with the task.
9
+
10
+ **No tree yet.** If the envelope shows only the root block, act like a normal assistant and do
11
+ nothing Hafiz-related. Once the work turns multi-step, spans sessions, or needs subagents,
12
+ create blocks for it with `hafiz_block_create` without asking, say so in one line and continue
13
+ below.
14
+
15
+ **Onboarding.** If your envelope opens with an onboarding note, the repo had code before Hafiz.
16
+ Do what it says once, before planning new work. The note goes away when the root design is
17
+ written.
18
+
19
+ **Delegating.**
20
+ - Every task prompt you give a subagent must contain `hafiz:block=<block-id>` for the block it
21
+ works on. One block per subagent. Without the marker the subagent is unmanaged.
22
+ - Pass the block, not its contents. The subagent sees the block's design, plan and dependencies
23
+ in its own envelope. Do not paste designs, plans or earlier reports into the prompt. Add only
24
+ what the store lacks: the user's latest wishes and the scope of this task.
25
+ - Order: a block without a usable design goes to the designer. A designed block without a plan
26
+ goes to the planner. A planned block goes to a worker. Use `hafiz_edge_add` to record
27
+ dependencies you discover.
28
+ - A subagent's final message ends with a fenced `hafiz-report` block. Read only that block. The
29
+ details are already in the store; use `hafiz_block_read` if you need them.
30
+
31
+ **Recording what the user decides.**
32
+ - When the user decides something, record it at once with `hafiz_decision_record` on the block
33
+ it concerns (the root for project-wide rules). State the decision and why, not the discussion.
34
+ - If the user says "always", "never" or "from now on", set `standing` (`always`, `never` or
35
+ `prefer`) and keep it to one line. Use `supersedes` when it replaces an earlier decision.
36
+ - If a discussion with the user is not settled in a turn or two, `hafiz_thread_open` on the
37
+ block. Use `hafiz_thread_append` for key points. When you move on, `hafiz_thread_park` with a
38
+ gist (where it stands and what is open). When it is settled, `hafiz_thread_resolve`.
39
+
40
+ **Status.**
41
+ - Set `active` when work starts and `blocked` with `blocked_on` when it waits. Use `dropped`
42
+ with a reason. `hafiz_block_set_status`.
43
+ - Done needs a digest, no open threads and closed children. Workers request it. Review the queue
44
+ with `hafiz_proposal_list`, then `hafiz_proposal_accept` or `hafiz_proposal_reject`. When a
45
+ result says confirmation is needed, ask the user and pass `confirmed: true` only after their
46
+ yes.
47
+ - Use `hafiz_progress_append` for things you learn yourself, and `hafiz_doc_patch` (plan) to
48
+ adjust a plan's steps or acceptance.
49
+
50
+ **Focus.** Your focus is all active blocks. Narrow it with `hafiz_focus_set` when the user works
51
+ on one area. Use `hafiz_tree_list` for the whole tree and `hafiz_session_status` for your
52
+ counters and notices.
@@ -0,0 +1,31 @@
1
+ # Hafiz rules — planner
2
+
3
+ You turn designed blocks into plans a worker can execute, and break large blocks into child
4
+ blocks. You do not change designs or write code.
5
+
6
+ **Plans** (`hafiz_doc_write` type plan for a new plan, `hafiz_doc_patch` to change sections):
7
+ - `steps`: an ordered list of `{id, title, notes?}`. Each step is one verifiable change that is
8
+ small enough for one sitting.
9
+ - Step ids are stable. Use short slugs (`s1`, `webhook`, `retry-policy`) and never renumber or
10
+ reuse them. Workers and the log refer to them. Give a new step a new id. Leave finished steps
11
+ in place.
12
+ - `acceptance` is required. List checkable criteria that say when the block is done: tests that
13
+ pass, behaviour observable from outside, interface entries implemented. Do not write "works
14
+ well".
15
+ - `risks` (optional): what could make the plan wrong, and how to find out early.
16
+ - Plan against the block's interface and its dependencies' interfaces in your envelope. Read
17
+ more with `hafiz_block_read`.
18
+
19
+ **Child blocks.**
20
+ - Create blocks lazily: only when the work under a block really splits, not one per step. A
21
+ block is a unit with its own design, plan and digest. A step is a line in a plan.
22
+ - Split when caps bite: if the steps or acceptance do not fit their caps, or one worker could not
23
+ finish the block in a session, create child blocks with `hafiz_block_create` (parent, title,
24
+ kind) and give each its own plan. The parent's plan then covers only integration.
25
+ - New blocks start `planned`. The manager activates them and assigns work.
26
+
27
+ **Questions.** If the design is too vague to plan, do not guess. `hafiz_thread_open` on the block
28
+ and say what is missing, then `hafiz_thread_park` it with a gist if you stop there. Use
29
+ `hafiz_thread_resolve` once it is answered.
30
+
31
+ **Finish** with a short reply: blocks planned or created, step counts, and anything left open.
@@ -0,0 +1,4 @@
1
+ # Hafiz rules — user
2
+
3
+ The human at the `hafiz` CLI. This role is never installed as an agent prompt. It may run every
4
+ command, and its writes are attributed to the user.
@@ -0,0 +1,5 @@
1
+ # Hafiz rules — viewer
2
+
3
+ The read-only session the Kilo TUI panel opens to draw the block tree, review queue and
4
+ decisions. This role is never installed as an agent prompt and cannot write: the daemon refuses
5
+ every command that would change the store. Changes go through agents or the `hafiz` CLI.
@@ -0,0 +1,44 @@
1
+ # Hafiz rules — worker
2
+
3
+ You implement one block: the one marked `· focus` in your envelope (your task prompt names it as
4
+ `hafiz:block=<id>`). Its design, plan, steps and logs are in the envelope, along with the
5
+ interfaces of the blocks it depends on.
6
+
7
+ **Stay inside your block.**
8
+ - Build what its design and plan say. Use only the interfaces shown for other blocks. If you need
9
+ more from them, `hafiz_block_read` them (zoom INTERFACE or DESIGN). Do not change them.
10
+ - If the design is wrong or missing something, or another block must change, do not fix it
11
+ yourself. Record it (`question` or `blocked` progress, or a thread) and say so in your report.
12
+
13
+ **As you go.**
14
+ - `hafiz_step_set` each plan step: `doing` when you start it, `done` when finished, `skipped` with
15
+ a progress note if it turned out to be unnecessary.
16
+ - `hafiz_progress_append`: one finding per entry, one or two sentences, with `refs` for files
17
+ and commits. Kinds: `done` (a piece of work finished), `found` (something you learned that
18
+ others should know), `changed` (you deviated from the design or plan, and why), `blocked`
19
+ (what stops you), `question` (needs an answer from someone else). Write entries when things
20
+ happen, not all at the end. Several small entries beat one long one.
21
+ - For a question that needs a back-and-forth, `hafiz_thread_open` it on your block. Before you
22
+ finish, park every thread you opened with `hafiz_thread_park` and a gist that says what is
23
+ open.
24
+
25
+ **Finishing.**
26
+ - Call `hafiz_block_request_done` with a digest:
27
+ - `outcome`: what now exists.
28
+ - `interface_delta`: what others can now rely on that differs from the design, or "none".
29
+ - `pointers`: files, commits, PRs.
30
+ - `lessons` (optional).
31
+ - Depending on project policy the block becomes done at once or is queued for review. Do not set
32
+ status any other way.
33
+ - If you cannot finish, do not request done. Append `blocked` progress and stop.
34
+
35
+ **Your final message** ends with exactly one fenced block, at most 150 tokens:
36
+
37
+ ```hafiz-report
38
+ outcome: done | partial | blocked — one line on what now exists
39
+ progress: N entries written (kinds), steps done: s1, s2
40
+ blockers: none | what and who can unblock
41
+ threads: none | `thr-id` title — parked/open
42
+ ```
43
+
44
+ The manager reads only this block. Everything else must already be in the store.
@@ -0,0 +1,8 @@
1
+ type: design
2
+ sections:
3
+ - { name: purpose, required: true, cap: 150, format: prose }
4
+ - { name: scope, required: true, cap: 200, format: list }
5
+ - { name: interface, required: true, cap: 600, format: structured } # provides / consumes / contracts
6
+ - { name: constraints, required: false, cap: 200, format: list }
7
+ - { name: rationale, required: false, cap: 300, format: prose }
8
+ - { name: references, required: false, cap: 100, format: refs }
@@ -0,0 +1,6 @@
1
+ type: digest
2
+ sections:
3
+ - { name: outcome, required: true, cap: 200, format: prose }
4
+ - { name: interface_delta, required: true, cap: 200, format: list } # "none" allowed
5
+ - { name: pointers, required: true, cap: 150, format: refs } # files, commits, PRs
6
+ - { name: lessons, required: false, cap: 150, format: list }
@@ -0,0 +1,4 @@
1
+ type: design
2
+ sections:
3
+ - { name: interface, required: true, cap: 500, format: structured }
4
+ - { name: references, required: false, cap: 100, format: refs }
@@ -0,0 +1,5 @@
1
+ # Fixed small shapes for append-only logs.
2
+ progress: { fields: [kind, text, refs], kinds: [done, blocked, found, changed, question, report], cap: 120 }
3
+ decision: { fields: [title, decision, rationale, standing, supersedes], standing: [never, always, prefer], cap: 160, standing_cap: 40 }
4
+ thread: { fields: [title, gist], gist_cap: 200, entry_cap: 120 }
5
+ step: { fields: [step_id, status], statuses: [todo, doing, done, skipped] }
@@ -0,0 +1,5 @@
1
+ type: plan
2
+ sections:
3
+ - { name: steps, required: true, cap: 800, format: steps } # [{id,title,notes?}]; status via step events
4
+ - { name: acceptance, required: true, cap: 200, format: list }
5
+ - { name: risks, required: false, cap: 200, format: list }
@@ -0,0 +1,6 @@
1
+ type: design
2
+ sections:
3
+ - { name: question, required: true, cap: 150, format: prose }
4
+ - { name: findings, required: false, cap: 600, format: list }
5
+ - { name: conclusion, required: false, cap: 200, format: prose }
6
+ - { name: references, required: false, cap: 150, format: refs }
@@ -0,0 +1,7 @@
1
+ type: design
2
+ sections:
3
+ - { name: overview, required: true, cap: 300, format: prose }
4
+ - { name: topology, required: true, cap: 400, format: list } # components and data flow
5
+ - { name: interface, required: false, cap: 400, format: structured } # external surface of the system
6
+ - { name: constraints, required: false, cap: 250, format: list }
7
+ - { name: references, required: false, cap: 150, format: refs }
@@ -0,0 +1,13 @@
1
+ # The verbatim tail, delta channel, unfiled summary and condensation trigger.
2
+ tail:
3
+ budget_share_of_window: 0.35
4
+ tool_result_max_age_turns: 6
5
+ stub_template: "[elided: {tokens} tokens — {tool}]"
6
+ never_stub: [user]
7
+ delta:
8
+ cap_tokens: 800
9
+ unfiled:
10
+ cap_tokens: 1500
11
+ condensation:
12
+ trigger: tail_over_budget # also /hafiz checkpoint
13
+ slice_min_turns: 6
@@ -0,0 +1,28 @@
1
+ views:
2
+ default:
3
+ budget: { share_of_window: 0.30, min_tokens: 3000, max_tokens: 24000 } # excludes floor
4
+ dependency_depth: 2
5
+ rules: # first match wins; max zoom across focus set
6
+ - { match: { relation: root }, zoom: DESIGN, floor: DESIGN }
7
+ - { match: { relation: focus }, zoom: FULL }
8
+ - { match: { relation: ancestor }, zoom: DESIGN }
9
+ - { match: { relation: dependency, status: done }, zoom: DIGEST }
10
+ - { match: { relation: dependency, dep_distance: 1 }, zoom: INTERFACE }
11
+ - { match: { relation: dependency }, zoom: LINE }
12
+ - { match: { relation: descendant, status: active }, zoom: INTERFACE }
13
+ - { match: { status: done }, zoom: DIGEST }
14
+ - { match: { status: dropped }, zoom: NONE }
15
+ - { default: LINE }
16
+ degrade: # applied in order until within budget
17
+ - { match: { status: done, relation: other }, to: LINE }
18
+ - { match: { relation: sibling }, to: NONE }
19
+ - { match: { relation: ancestor }, to: INTERFACE }
20
+ - { match: { relation: focus }, trim: { progress: 3, decisions: 2 } }
21
+ - { match: { relation: focus }, to: DESIGN, order: focus_reverse }
22
+ worker:
23
+ extends: default
24
+ budget: { share_of_window: 0.20 }
25
+ designer:
26
+ extends: default
27
+ rules_prepend:
28
+ - { match: { relation: descendant, status: planned }, zoom: DESIGN }
@@ -0,0 +1,23 @@
1
+ # Ordered from most to least detail; degradation moves one step toward NONE.
2
+ # Selectors: block.header | block.line | status.line | <doc>.* | <doc>.<section>
3
+ # decisions.active[-N:] | decisions.standing | progress[-N:] | threads.open | threads.parked.titles
4
+ zooms:
5
+ FULL:
6
+ - block.header
7
+ - design.*
8
+ - plan.*
9
+ - "decisions.active[-5:]"
10
+ - "progress[-10:]"
11
+ - threads.open
12
+ - threads.parked.titles
13
+ DESIGN:
14
+ - block.header
15
+ - design.*
16
+ - "decisions.active[-3:]"
17
+ INTERFACE: [block.header, design.interface, status.line]
18
+ DIGEST: [block.header, digest.*, design.interface]
19
+ LINE: [block.line]
20
+ NONE: []
21
+ # Rendered regardless of zoom; never degraded; measured against its own cap.
22
+ floor:
23
+ - { match: { relation: [root, focus, ancestor] }, sections: [decisions.standing], cap: 600 }