sako 0.5.0__py3-none-any.whl

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.
sako/SAKO.md ADDED
@@ -0,0 +1,319 @@
1
+ # Working with SAKO
2
+
3
+ The SAKO method, a task ledger and finish gate for coding agents, installed in this
4
+ project. Project instructions and the owner's choices come first; they also name
5
+ the planner or source of work. This file holds no project state.
6
+
7
+ Use SAKO for project tasks here, code and documentation changes and bounded
8
+ investigations alike, without being asked each time. Questions and discussion need
9
+ no task record. Run `python3 .sako/sako.py <command>` (`python` on Windows) from
10
+ anywhere in the repository; from a linked worktree, use the command line the start
11
+ context prints.
12
+
13
+ ## Daily loop
14
+
15
+ 1. **Start.** The session-start hook prints the context and your session ID.
16
+ Without it, run `start --session <id>` with an ID unique to this conversation.
17
+ Pass the same ID to every command; in Claude Code and Codex, a command
18
+ without `--session` uses the client's session ID, the one the hook used.
19
+ 2. **Choose and claim.** Follow the owner's priority. `next` names the task to
20
+ start and why, what else is ready, and what waits. For new work, run
21
+ `add "task" --done-when "observable result" --scope src/`, then
22
+ `claim T-1 --session <id>` with the returned ID. Keep scopes narrow and widen
23
+ them in the ledger before the work grows. If nothing fits, return to the
24
+ selected planner; the table under **Read when needed** covers the rest.
25
+ 3. **Work and check.** Use the project's own tools and checks. Run `verify` when a
26
+ check is configured; it records a fingerprint of the checked content. For
27
+ discovery or a manual check, keep the actual findings or procedure and result.
28
+ A passing suite alone is not acceptance: inspect the requested behavior.
29
+ 4. **Close and commit.** `close T-1 --session <id> --evidence "result and proof"`
30
+ moves the row to the done record with a receipt: your evidence, then the
31
+ closing marker, the date, and what the check said. State the outcome and its
32
+ limits, not just "done". Commit the task's work within the owner's
33
+ authorization, staging explicit paths. SAKO never commits, pushes or deploys.
34
+ 5. **Finish.** Run `check --gate --session <id>` (the Stop hook runs it too) and
35
+ fix what it names, or report what remains. If you ran `start` yourself, run
36
+ `end --session <id>` last. With hooks, the client ends the session; do not run
37
+ `end`, since the Stop gate needs your start record. Report the result, the
38
+ evidence and the next decision.
39
+
40
+ You can stop incomplete: keep the claim and write its handoff. If commits are not
41
+ authorized, report the reviewed work as uncommitted. A satisfied goal needs no
42
+ new task.
43
+
44
+ ## Done means
45
+
46
+ The gate checks this session against three rules. Each finding names its rule and
47
+ ends with the command or edit that fixes it.
48
+
49
+ - **Recorded:** every file the session changed belongs to a task it claimed or closed.
50
+ - **Proven:** a task closed after checked content changed has a passing check.
51
+ - **Committed:** closed work is committed; in the repo and shared footprints, its records too.
52
+
53
+ Pausing is free: claimed, unfinished work passes. Two advisories never block: a
54
+ claimed, unfinished task without a `handoff.md`, and a closed task whose handoff
55
+ folder remains. A clear gate means these rules passed, not that the owner accepts
56
+ the result. A null `verify_command` means no automated evidence: close with the
57
+ manual check's procedure and result, and the receipt says "no automated check". It
58
+ never becomes a pass; do not call that work verified.
59
+
60
+ ## Records
61
+
62
+ | Information | Home |
63
+ |---|---|
64
+ | Direction, purpose, acceptance | The project's instructions, brief or README; a task's Source points to its planner item |
65
+ | Active work and ownership | `.sako/work/TASKS.md` |
66
+ | Completed work with receipts | `.sako/work/DONE.md`, created on first close |
67
+ | A paused task's handoff and notes | `.sako/work/T-<n>-<slug>/`, printed by `claim`; you delete it at close |
68
+ | Unresolved decisions | The affected task or the project's context: the question, any assumption, who decides |
69
+ | The owner holds agreed work ("wait until I try it") | That work's row, `parked` with the reason, so a fresh session waits too |
70
+
71
+ ```markdown
72
+ | ID | Pri | Task | Done when | Status | Scope | After | Source |
73
+ |---|---|---|---|---|---|---|---|
74
+ | T-1 | P1 | A named visitor receives a greeting | The sample prints Hello, Ada | open | `src/`, `tests/` | - | PLAN.md#N1 |
75
+ ```
76
+
77
+ This row is an example, not live work. `Pri` is P1, P2 (empty reads P2) or P3.
78
+ Status's first word is `open` (empty reads open), `parked` with its reason, or the
79
+ claiming session's marker. `After` lists prerequisite IDs. Scopes are
80
+ repository-relative path prefixes; `.` covers everything. The done record keeps
81
+ `ID | Task | Done when | Receipt | Scope | Source`. IDs are never reused. Columns are
82
+ read by name, in any order, and columns you add are kept. Keep a cell on one line,
83
+ without literal pipes. Commands change only their own rows; hand edits are fine but
84
+ not locked, so coordinate them with other sessions.
85
+
86
+ The records live where `status` says: local (`.sako/` is listed in
87
+ `.git/info/exclude`, so they are not in Git, and `git clean -x` deletes them), in
88
+ their own repository inside `.sako/` (repo), or committed with the code (shared,
89
+ one copy per branch).
90
+
91
+ Put each discovery where the next reader needs it: an invariant in the code or test
92
+ that enforces it, a product choice in the project's context, progress and traps in
93
+ the task's handoff. Reference that home from the receipt rather than copying it.
94
+
95
+ ## Read when needed
96
+
97
+ The following sections apply only in their situation:
98
+
99
+ | Situation | Section |
100
+ |---|---|
101
+ | Work comes from a plan, checklist, issue or planning skill | Task intake |
102
+ | No planner is selected, direction is unclear, or nothing is ready | No planner? Start here |
103
+ | Pausing, resuming, or a stale claim | Pause, handoff and takeover |
104
+ | Another session works in this repository | Working beside other sessions |
105
+ | A gate finding or check result needs explaining | The gate and checks in detail |
106
+ | Installing, updating, removing, or wiring a worktree | Install, update and remove |
107
+
108
+ ## Task intake
109
+
110
+ Read this when work comes from the project's plan, checklist, issue or planning
111
+ skill. Translate the selected work into local rows without replacing its planner or
112
+ copying its backlog. Keep a concrete outcome, a completion condition, a bounded
113
+ scope and known prerequisites; add only details that change execution.
114
+
115
+ 1. **Name the source.** Keep the item's authoritative location and a stable
116
+ reference such as `PLAN.md#N1` for `--source`. Give each local action from one
117
+ upstream item its own reference, and reuse it exactly on later intake.
118
+ 2. **Record or reuse it.** Put the outcome in the task text and the completion
119
+ condition in `--done-when`. Declare the files with `--scope`, including a source
120
+ document the task will update. Pass the planner's priority with `--pri` and
121
+ prerequisites with `--after`:
122
+
123
+ ```sh
124
+ python3 .sako/sako.py add "Discover note names" --done-when "Filtering and unchanged inputs are checked" --source PLAN.md#N1 --pri P1 --scope src/ --scope tests/
125
+ python3 .sako/sako.py add "Print sorted names" --done-when "The agreed sample matches" --source PLAN.md#N2 --after T-1 --scope preview.py
126
+ ```
127
+
128
+ Use the IDs the command returns. Prerequisites release when all are done;
129
+ `next` ranks what is ready by priority, then row order.
130
+ 3. **Handle repeat or changed input.** The same source, task, completion
131
+ condition, scope and prerequisites reuse the existing ID, completed work
132
+ included. A new `--pri` updates an unfinished task's priority and says so.
133
+ Any other difference refuses instead of replacing work: inspect the source and
134
+ the row, then reconcile deliberately. When an item changed after its task was
135
+ done, record the new work as a new task with its own source, such as
136
+ `PLAN.md#N1-v2`; the done row stays as history. Without `--source`, every `add`
137
+ is a new task.
138
+ 4. **Return the result.** Before starting, check that the source item still
139
+ applies. When returning the result edits a file the check covers, such as
140
+ ticking the item's box, make that edit before `verify` and `close`: an edit after
141
+ close needs a fresh check. After close, compare the result with the upstream
142
+ acceptance and return the evidence through the project's authorized procedure,
143
+ or report that update as pending. Local completion does not complete a larger
144
+ upstream item.
145
+
146
+ Source references are exact identifiers; the runtime does not fetch, interpret,
147
+ watch or synchronize them. When a source changes, you judge what it means.
148
+
149
+ ## No planner? Start here
150
+
151
+ Read this when no planner or work source is selected and the direction is unclear,
152
+ or nothing is ready. Begin with the owner's request and only as much evidence as
153
+ the next useful action needs: instructions, local changes, entry points, notes and
154
+ checks. Code shows what exists; it does not decide what the owner wants. An old
155
+ checklist is evidence, not an order.
156
+
157
+ | Starting point | Establish first | Preserve |
158
+ |---|---|---|
159
+ | An idea, little or no code | Who it helps, the first useful outcome, a constraint that changes the approach | The owner's uncertainty; direction can be provisional |
160
+ | Code with notes, TODOs or a backlog | Which source governs current intent; whether the work is still needed | Existing authority, IDs, conventions, unrelated changes |
161
+ | Code with little explanation | How the relevant behavior works today, what is unknown, what the owner wants next | Working behavior until a change is intended |
162
+
163
+ Ask a small, concrete question only when the answer changes the outcome, scope or
164
+ acceptance; find file locations and commands yourself. Record consequential
165
+ answers and label assumptions. Put just enough in an existing README or brief to
166
+ answer: the **direction** (who it serves, the current outcome), the **starting
167
+ point** (what works, what is unknown), the **boundaries**, the **next action**, and
168
+ what counts as **success**. A short paragraph and one task are often enough; a PRD,
169
+ phases or a full backlog are optional.
170
+
171
+ If intent or feasibility is too uncertain to build, add a bounded investigation:
172
+ the question, the evidence to collect, and when to stop. "Run the import with a
173
+ synthetic sample and record the accepted columns, the failure and the next
174
+ decision" is actionable; "try things until clear" is not. With no automated check,
175
+ leave `verify_command` null and say how the result will be judged; never add an
176
+ always-passing command.
177
+
178
+ When nothing is ready or evidence changes the plan:
179
+
180
+ | The evidence says | Next move |
181
+ |---|---|
182
+ | The outcome is unfinished and nothing is ready | Prepare the smallest justified action |
183
+ | Work is held by a session or a prerequisite | Inspect the owner or blocker; continue your own claim or leave a precise handoff |
184
+ | A decision is missing | Record the question and ask the owner instead of inventing direction |
185
+ | Feedback invalidates planned work | Revise the task or park it with a reason, keeping IDs and references |
186
+ | The outcome is satisfied | Report completion; an empty queue is a valid finish |
187
+
188
+ Do not create tasks to keep agents busy. Bring anything that would widen the agreed
189
+ outcome to the owner first.
190
+
191
+ ## Pause, handoff and takeover
192
+
193
+ Read this when you pause unfinished work, resume, or meet a stale claim. Before
194
+ pausing a claimed task, write `handoff.md` in the folder `claim` printed,
195
+ `.sako/work/T-<n>-<slug>/`: where the task stands, what landed, what is left, the
196
+ next step, and traps. Other working notes can sit beside it; plans stay in their
197
+ own home, linked. The folder is found by task ID and is never checked content or an
198
+ unrecorded change. On close, move its lasting facts to their real home and delete
199
+ it. `start` and `status` list open tasks' folders.
200
+
201
+ A new session reads the records, the handoff and the relevant Git diff before it
202
+ continues; `status --session <id>` shows the changes, ownership, evidence and
203
+ commits since that session began. A live owner cannot be replaced. For a stale
204
+ claim, inspect its work, then run `claim T-1 --session <new-id> --takeover "reason"`.
205
+
206
+ Each conversation needs its own session ID, even when several share one host
207
+ process; a resumed conversation reuses its ID. A subagent's shell carries its own
208
+ Claude Code session ID, so it passes the parent's `--session` explicitly.
209
+
210
+ Presence judges liveness by the host process where that process is visible. A
211
+ client's sandbox (Codex runs agent commands in one) hides the host's processes, so
212
+ there, and for a session started inside one, presence counts as live for 24 hours
213
+ after its last `start`, marked unverified. A claim held by an unverified session
214
+ can be taken over with a reason once you have checked that it stopped; the claim
215
+ says its holder was unverified. A session that ran `start` itself runs `end
216
+ --session <id>` when it finishes; otherwise its presence stays until its host
217
+ process exits or its 24 hours pass. Do not end a peer's presence without
218
+ confirming it stopped. `SAKO_AGENT_PID` can name a long-lived host process, never a
219
+ temporary shell.
220
+
221
+ An interrupted close can leave the same row in both records: repeat the exact
222
+ close command with the same evidence and session. Conflicting closed content is
223
+ refused; never delete completed evidence blindly.
224
+
225
+ ## Working beside other sessions
226
+
227
+ Read this when another session works in this repository. Every worktree uses the
228
+ main checkout's `.sako/`, so sessions share one ledger, one numbering and one lock.
229
+ A claim refuses a live owner and a scope that overlaps another session's claim.
230
+ The lock serializes `add`, `claim` and `close` only: not application edits, hand
231
+ edits of the records, Git's index or other clones. A push is a record, not a lock.
232
+ Keep scopes disjoint, coordinate direct record edits, and stage explicit paths.
233
+ SAKO does not schedule agents or merge their edits.
234
+
235
+ ## The gate and checks in detail
236
+
237
+ Read this when a gate finding or a check result needs explaining. `verify` runs the
238
+ configured argument array at the top of the checkout; use `["bash",
239
+ "scripts/check.sh"]` for shell features. It stamps a pass only when the checked
240
+ content and the command stay unchanged during the run; a failure deletes old
241
+ evidence. The stamp covers the content, paths, symlink text and executable bits of
242
+ unignored files under `verify_paths`; an empty list covers everything outside
243
+ `.sako/`, documentation included. Name product subtrees if documentation-only work
244
+ should not invalidate the check. Dependencies and services need another check by
245
+ judgment. Stamps are local, one per worktree: rerun `verify` after a fresh clone.
246
+
247
+ **Recorded** counts files edited since the session started or committed since then,
248
+ deletions and both sides of a rename; a file already dirty at start counts only when
249
+ it changes again. A live peer's claimed scope in the same checkout is not counted,
250
+ with a note. A linked worktree nested in the checkout, such as one a harness makes
251
+ for a subagent, is another checkout: its work counts once merged. Without a start
252
+ record, every uncommitted change counts and commits go unchecked; the gate says so.
253
+ **Proven:** while a claim you still hold covers changed checked files, a stale check
254
+ is that claim's work in progress, and a close whose receipt shows a pass stays
255
+ proven. **Committed** skips files inside a claim you still hold; its fix applies
256
+ only when the owner allows commits, otherwise say the work awaits approval.
257
+
258
+ `check --gate` prints advisories under a clear result, and a blocked stop lists
259
+ them after its problems; a clear stop stays silent. Hooks fail open on their own
260
+ errors and on a repeated stop, so the gate never traps a session. Exit codes: 0
261
+ success, 1 findings or a failed check, 2 a gate needing attention, 3 an actionable
262
+ refusal, 4 a bug.
263
+
264
+ ## Install, update and remove
265
+
266
+ Read this when installing, updating or removing the kit, or wiring a worktree. Run
267
+ `uvx sako init`, or `python3 <checkout>/sako.py init` from a reviewed checkout,
268
+ anywhere in the project's Git repository. It needs no flags. The runtime, this
269
+ method, `install.json`, `config.json` and an empty `work/TASKS.md` land in the main
270
+ checkout's `.sako/`, which is listed in `.git/info/exclude` with the client files
271
+ `init` writes, so nothing tracked changes. The project's instructions stay
272
+ untouched: the start context names the method, the records and the command line.
273
+
274
+ `init` wires SessionStart, Stop and SessionEnd hooks for each client it finds a
275
+ sign of: the Claude Code or Codex session running it, `.claude/` or `CLAUDE.md`
276
+ for Claude Code, `.codex/` for Codex, and `AGENTS.md` for both. It prints the choice and why
277
+ and records it; later runs and `--update` keep it. `--client claude`, `--client
278
+ codex` (repeat for both) or `--client none` replaces it; none means explicit
279
+ `start`, `check --gate` and `end`, also the route for clients without an adapter.
280
+ With no sign of a client, a later `init` detects one that appears, including a
281
+ Claude Code or Codex session running it.
282
+ The shared skill always installs in `.agents/skills/sako/`, and Claude Code gets a
283
+ copy in `.claude/skills/sako/`. Codex runs project hooks only after you trust them;
284
+ `status` says when each client's hook last ran. A tracked settings file is never
285
+ changed; `init` says what to add by hand. A client file whose folder leads
286
+ outside the repository is skipped with a note. A client that reads neither hooks
287
+ nor skills can be pointed to `.sako/SAKO.md` in its instructions.
288
+
289
+ Configure the check in `.sako/config.json`: `verify_command` as an argument array,
290
+ such as `["python3", "-B", "-m", "unittest"]`, and `verify_paths`. In a new linked
291
+ worktree, run `init` there: it wires that worktree for the clients the main
292
+ checkout chose and, for Codex, a writable root for the main `.sako/`, which Codex
293
+ reads once it trusts the project. The records stay in the main checkout.
294
+
295
+ Two footprints put the records in Git. `init --repo [url]` gives them their own
296
+ repository inside `.sako/`, still out of the code's: its `.gitignore` leaves out the
297
+ kit files and `state/`, so it tracks `config.json` and `work/`. With a URL, a
298
+ checkout without records clones them, and existing records get it as `origin`;
299
+ records on both sides refuse. `init --shared` commits the records with the code: it
300
+ takes `.sako/` out of `.git/info/exclude`, prints the commit command, and prints a
301
+ line to add to your instructions so an agent on a fresh clone finds SAKO. Each
302
+ branch then keeps its own copy, so a linked worktree uses its own `.sako/`, and one
303
+ on a branch without a copy refuses. It refuses while `.sako/.git` exists and names
304
+ the move. SAKO commits nothing; the gate's Committed rule asks for the records'
305
+ commit with its exact command. `install.json` records the footprint, and a
306
+ disagreement with Git is a finding. To go back to local, run `remove`, then `init`,
307
+ which names any Git command to run first; the records stay byte for byte. In the
308
+ repo footprint `remove` keeps `.sako/.git` and warns about commits that exist only
309
+ there; the command `init` then names moves that history out of `.sako/`, beside the
310
+ project, where it stays until you delete it.
311
+
312
+ To update, review the new release and run its `init --update` with no active work,
313
+ such as `uvx sako@latest init --update` (plain `uvx sako` can reuse a cached copy).
314
+ Modified kit files refuse; an unmodified one the new choice or release no longer
315
+ needs is deleted. `python3 .sako/sako.py remove` in the main checkout
316
+ removes unmodified kit files, SAKO's hook entries in every worktree and the
317
+ disposable state; `config.json` and `work/` stay, and deleting `.sako/` leaves no
318
+ trace. The client choice goes with `install.json`, so a later `init` detects the
319
+ clients again. The copy in a project cannot seed another project.