tools: command records, Workshop runs and session budget group - examples, prohibitions (#142)
Files changed: - CHANGES.md - VERSION - tools/CONTRACT.md - tools/chemenu/commands/run_budget.py - tools/chemenu/commands/work_cmd.py
This commit is contained in:
1 parent
964978a9c6
commit
b9c22f783f
5 files changed
+185
-36
No files matched your search
+76
-8
@@ -1734,18 +1734,42 @@ Scaffold `work/<runkey>/` for one workshop run.
|
||||
- budget: counted
|
||||
- network: no
|
||||
|
||||
**EXAMPLES**
|
||||
|
||||
- `tools/wikitool work new --input raw/2026/09/handbuch`
|
||||
- `tools/wikitool work new --key migrate-7.0.0`
|
||||
- `tools/wikitool work new --input raw/2026/09/handbuch --again`
|
||||
|
||||
**EXIT STATUS**
|
||||
|
||||
- 0 success
|
||||
- 1 Neither or both of `--input`/`--key` given, `--input` outside `raw/`, a `--key` that is empty or starts with `ingest-`, or the workshop already exists
|
||||
- 1 Neither or both of `--input`/`--key` given, or a `--key` that is empty or starts with `ingest-`
|
||||
- 1 `--input` is outside `raw/`, does not exist, or is `raw/` itself (an empty run key)
|
||||
- 1 The workshop already exists
|
||||
|
||||
**ON FAILURE**
|
||||
|
||||
- Neither or both of `--input`/`--key` given, `--input` outside `raw/`, a `--key` that is empty or starts with `ingest-`, or the workshop already exists -> A collision is not transient: resume the existing run instead, or pass `--again` if the tree itself changed. Never create a numbered variant by hand
|
||||
- Neither or both of `--input`/`--key` given, or a `--key` that is empty or starts with `ingest-` -> Fix the argument and retry once
|
||||
- `--input` is outside `raw/`, does not exist, or is `raw/` itself (an empty run key) -> Point `--input` at material under `raw/`, or use `--key` for a run with no raw input
|
||||
- The workshop already exists -> A collision is not transient: resume the existing run instead, or pass `--again` if the tree itself changed
|
||||
|
||||
**NEVER**
|
||||
|
||||
- Never create a numbered variant of a run key by hand.
|
||||
|
||||
**NOTES**
|
||||
|
||||
Refuses a collision instead of suffixing it, and writes the required `README.md` + `plan.md`. `--input` derives the run key from the path below `raw/` (an ingest); `--key` names it outright for a run with no raw input - a migration or a sweep across `kb/` - and may not start with `ingest-`, which stays reserved for derived keys. Exactly one of the two. `--again` opens a dated second pass over a tree that has itself changed. See `work/CONTRACT.md`
|
||||
- Creates `work/<runkey>/` with the required `README.md` and `plan.md`.
|
||||
- `--input` derives the run key from the path below `raw/` (an ingest); `--key` names it outright for a run with no raw input - a migration or a sweep across `kb/` - and may not start with `ingest-`, which stays reserved for derived keys. Exactly one of the two.
|
||||
- Refuses a collision instead of suffixing it.
|
||||
- `--again` opens a dated second pass (`<runkey>-<date>`) over a tree that has itself changed.
|
||||
- `--dry-run` reports the run key and files without writing.
|
||||
|
||||
**SEE ALSO**
|
||||
|
||||
- `work/CONTRACT.md` - run keys, required files, how a run closes
|
||||
- `wikitool work close` - deletes the run when it is done
|
||||
- `instructions/ingest-large-tree.md` - the ingest that opens a run
|
||||
|
||||
#### `work close`
|
||||
|
||||
@@ -1763,18 +1787,37 @@ Delete a finished workshop.
|
||||
- budget: counted
|
||||
- network: no
|
||||
|
||||
**EXAMPLES**
|
||||
|
||||
- `tools/wikitool work close --run-key ingest-2026-09-handbuch --dry-run`
|
||||
- `tools/wikitool work close --run-key ingest-2026-09-handbuch --yes`
|
||||
|
||||
**EXIT STATUS**
|
||||
|
||||
- 0 success
|
||||
- 1 Unknown run key, or `--yes` was not passed
|
||||
- 1 Unknown run key
|
||||
- 1 `--yes` was not passed - the output lists what would be lost
|
||||
|
||||
**ON FAILURE**
|
||||
|
||||
- Unknown run key, or `--yes` was not passed -> For "not confirmed": check the listed files are no longer needed, confirm the conclusions are in `kb/`, then re-run with `--yes`
|
||||
- Unknown run key -> Check `ls work/` for the open runs, then retry once
|
||||
- `--yes` was not passed - the output lists what would be lost -> Check the listed files are no longer needed, confirm the conclusions are in `kb/`, then re-run with `--yes`
|
||||
|
||||
**NEVER**
|
||||
|
||||
- Never pass `--yes` before the run's conclusions are in `kb/`.
|
||||
|
||||
**NOTES**
|
||||
|
||||
Lists what would be lost and requires `--yes`, because nothing in it is recoverable from the rest of the repo - the durable conclusions must already be in `kb/`
|
||||
- Deletes `work/<run-key>/` recursively.
|
||||
- Without `--yes` it lists what would be lost and refuses: nothing in a workshop is recoverable from the rest of the repo, so the durable conclusions must already be in `kb/`.
|
||||
- `--dry-run` lists the files without deleting.
|
||||
- Not idempotent: once deleted, the run key is unknown.
|
||||
|
||||
**SEE ALSO**
|
||||
|
||||
- `work/CONTRACT.md` - how a run closes
|
||||
- `wikitool work new` - opens a run
|
||||
|
||||
#### `budget status`
|
||||
|
||||
@@ -1792,13 +1835,23 @@ Show the current session's `wikitool` call count and recent command history.
|
||||
- budget: exempt
|
||||
- network: no
|
||||
|
||||
**EXAMPLES**
|
||||
|
||||
- `tools/wikitool budget status`
|
||||
|
||||
**EXIT STATUS**
|
||||
|
||||
- 0 success
|
||||
|
||||
**NOTES**
|
||||
|
||||
Recent command history is never counted against the budget. Never fails. Safe to retry freely.
|
||||
- Shows the current session's `wikitool` call count and its recent command history.
|
||||
- Never counted against the budget; never fails; safe to retry freely.
|
||||
|
||||
**SEE ALSO**
|
||||
|
||||
- `instructions/session-setup.md` - scoping the budget to a task
|
||||
- `instructions/gates.md` - what to do when the Iteration Budget Gate refuses
|
||||
|
||||
#### `budget reset`
|
||||
|
||||
@@ -1816,6 +1869,10 @@ Clear the current session's (or every session's) iteration budget state.
|
||||
- budget: counted
|
||||
- network: no
|
||||
|
||||
**EXAMPLES**
|
||||
|
||||
- `tools/wikitool budget reset --yes # only after the user approved it`
|
||||
|
||||
**EXIT STATUS**
|
||||
|
||||
- 0 success
|
||||
@@ -1825,9 +1882,20 @@ Clear the current session's (or every session's) iteration budget state.
|
||||
|
||||
- `--yes` not passed -> Get the user's approval, then re-run with `--yes`
|
||||
|
||||
**NEVER**
|
||||
|
||||
- Never run it on your own initiative to get past a budget or loop-breaker refusal.
|
||||
|
||||
**NOTES**
|
||||
|
||||
Requires `--yes`: clearing the counter is itself a way around the gate, so it needs the same explicit human approval
|
||||
- Clears the current session's iteration budget state; `--all` deletes every session's.
|
||||
- Requires `--yes`: clearing the counter is itself a way around the Iteration Budget Gate, so it needs the same explicit human approval.
|
||||
- Counted against the budget like any other call.
|
||||
|
||||
**SEE ALSO**
|
||||
|
||||
- `wikitool budget status` - the current count
|
||||
- `instructions/gates.md` - why `budget reset` is not the escape hatch
|
||||
|
||||
### Types, instructions and docs
|
||||
|
||||
|
||||
@@ -333,9 +333,18 @@ def refund() -> None:
|
||||
atomic="Read-only",
|
||||
budget=cli_contract.Budget.EXEMPT,
|
||||
),
|
||||
notes="Recent command history is never counted against the budget. Never fails. Safe to "
|
||||
"retry freely.",
|
||||
notes=(
|
||||
"Shows the current session's `wikitool` call count and its recent command history.",
|
||||
"Never counted against the budget; never fails; safe to retry freely.",
|
||||
),
|
||||
failures=(),
|
||||
examples=(
|
||||
"tools/wikitool budget status",
|
||||
),
|
||||
see_also=(
|
||||
"`instructions/session-setup.md` - scoping the budget to a task",
|
||||
"`instructions/gates.md` - what to do when the Iteration Budget Gate refuses",
|
||||
),
|
||||
))
|
||||
def status_command():
|
||||
"""Show the current session's call count and recent command history."""
|
||||
@@ -371,13 +380,26 @@ def reset_message() -> str:
|
||||
atomic="Read/rewrite of one JSON file (or its deletion, with `--all`)",
|
||||
budget=cli_contract.Budget.COUNTED,
|
||||
),
|
||||
notes="Requires `--yes`: clearing the counter is itself a way around the gate, so it needs "
|
||||
"the same explicit human approval",
|
||||
notes=(
|
||||
"Clears the current session's iteration budget state; `--all` deletes every session's.",
|
||||
"Requires `--yes`: clearing the counter is itself a way around the Iteration Budget "
|
||||
"Gate, so it needs the same explicit human approval.",
|
||||
"Counted against the budget like any other call.",
|
||||
),
|
||||
failures=(cli_contract.Failure(
|
||||
label="",
|
||||
cause="`--yes` not passed",
|
||||
reaction="Get the user's approval, then re-run with `--yes`",
|
||||
),),
|
||||
examples=(
|
||||
"tools/wikitool budget reset --yes # only after the user approved it",
|
||||
),
|
||||
never=(
|
||||
"Never run it on your own initiative to get past a budget or loop-breaker refusal.",
|
||||
),
|
||||
see_also=(
|
||||
"`wikitool budget status` - the current count",
|
||||
"`instructions/gates.md` - why `budget reset` is not the escape hatch",
|
||||
),
|
||||
))
|
||||
def reset_command(
|
||||
all_sessions: bool = typer.Option(
|
||||
|
||||
@@ -142,19 +142,48 @@ Cut the tree into units. One unit does one job and becomes one source page. A un
|
||||
atomic="Yes - one directory with two files",
|
||||
budget=cli_contract.Budget.COUNTED,
|
||||
),
|
||||
notes="Refuses a collision instead of suffixing it, and writes the required `README.md` + "
|
||||
"`plan.md`. `--input` derives the run key from the path below `raw/` (an ingest); `--key` "
|
||||
"names it outright for a run with no raw input - a migration or a sweep across `kb/` - and "
|
||||
"may not start with `ingest-`, which stays reserved for derived keys. Exactly one of the "
|
||||
"two. `--again` opens a dated second pass over a tree that has itself changed. See "
|
||||
"`work/CONTRACT.md`",
|
||||
failures=(cli_contract.Failure(
|
||||
label="",
|
||||
cause="Neither or both of `--input`/`--key` given, `--input` outside `raw/`, a "
|
||||
"`--key` that is empty or starts with `ingest-`, or the workshop already exists",
|
||||
reaction="A collision is not transient: resume the existing run instead, or pass "
|
||||
"`--again` if the tree itself changed. Never create a numbered variant by hand",
|
||||
),),
|
||||
notes=(
|
||||
"Creates `work/<runkey>/` with the required `README.md` and `plan.md`.",
|
||||
"`--input` derives the run key from the path below `raw/` (an ingest); `--key` names it "
|
||||
"outright for a run with no raw input - a migration or a sweep across `kb/` - and may "
|
||||
"not start with `ingest-`, which stays reserved for derived keys. Exactly one of the "
|
||||
"two.",
|
||||
"Refuses a collision instead of suffixing it.",
|
||||
"`--again` opens a dated second pass (`<runkey>-<date>`) over a tree that has itself "
|
||||
"changed.",
|
||||
"`--dry-run` reports the run key and files without writing.",
|
||||
),
|
||||
failures=(
|
||||
cli_contract.Failure(
|
||||
cause="Neither or both of `--input`/`--key` given, or a `--key` that is empty or "
|
||||
"starts with `ingest-`",
|
||||
reaction="Fix the argument and retry once",
|
||||
),
|
||||
cli_contract.Failure(
|
||||
cause="`--input` is outside `raw/`, does not exist, or is `raw/` itself (an empty "
|
||||
"run key)",
|
||||
reaction="Point `--input` at material under `raw/`, or use `--key` for a run with no "
|
||||
"raw input",
|
||||
),
|
||||
cli_contract.Failure(
|
||||
cause="The workshop already exists",
|
||||
reaction="A collision is not transient: resume the existing run instead, or pass "
|
||||
"`--again` if the tree itself changed",
|
||||
),
|
||||
),
|
||||
examples=(
|
||||
"tools/wikitool work new --input raw/2026/09/handbuch",
|
||||
"tools/wikitool work new --key migrate-7.0.0",
|
||||
"tools/wikitool work new --input raw/2026/09/handbuch --again",
|
||||
),
|
||||
never=(
|
||||
"Never create a numbered variant of a run key by hand.",
|
||||
),
|
||||
see_also=(
|
||||
"`work/CONTRACT.md` - run keys, required files, how a run closes",
|
||||
"`wikitool work close` - deletes the run when it is done",
|
||||
"`instructions/ingest-large-tree.md` - the ingest that opens a run",
|
||||
),
|
||||
))
|
||||
def new_command(
|
||||
input_path: Optional[str] = typer.Option(
|
||||
@@ -247,14 +276,36 @@ def new_command(
|
||||
atomic="No - a recursive delete",
|
||||
budget=cli_contract.Budget.COUNTED,
|
||||
),
|
||||
notes="Lists what would be lost and requires `--yes`, because nothing in it is recoverable "
|
||||
"from the rest of the repo - the durable conclusions must already be in `kb/`",
|
||||
failures=(cli_contract.Failure(
|
||||
label="",
|
||||
cause="Unknown run key, or `--yes` was not passed",
|
||||
reaction="For \"not confirmed\": check the listed files are no longer needed, confirm the "
|
||||
"conclusions are in `kb/`, then re-run with `--yes`",
|
||||
),),
|
||||
notes=(
|
||||
"Deletes `work/<run-key>/` recursively.",
|
||||
"Without `--yes` it lists what would be lost and refuses: nothing in a workshop is "
|
||||
"recoverable from the rest of the repo, so the durable conclusions must already be in "
|
||||
"`kb/`.",
|
||||
"`--dry-run` lists the files without deleting.",
|
||||
"Not idempotent: once deleted, the run key is unknown.",
|
||||
),
|
||||
failures=(
|
||||
cli_contract.Failure(
|
||||
cause="Unknown run key",
|
||||
reaction="Check `ls work/` for the open runs, then retry once",
|
||||
),
|
||||
cli_contract.Failure(
|
||||
cause="`--yes` was not passed - the output lists what would be lost",
|
||||
reaction="Check the listed files are no longer needed, confirm the conclusions are in "
|
||||
"`kb/`, then re-run with `--yes`",
|
||||
),
|
||||
),
|
||||
examples=(
|
||||
"tools/wikitool work close --run-key ingest-2026-09-handbuch --dry-run",
|
||||
"tools/wikitool work close --run-key ingest-2026-09-handbuch --yes",
|
||||
),
|
||||
never=(
|
||||
"Never pass `--yes` before the run's conclusions are in `kb/`.",
|
||||
),
|
||||
see_also=(
|
||||
"`work/CONTRACT.md` - how a run closes",
|
||||
"`wikitool work new` - opens a run",
|
||||
),
|
||||
))
|
||||
def close_command(
|
||||
run_key: str = typer.Option(..., "--run-key", help="The workshop directory name"),
|
||||
|
||||
Reference in new issue
Block a user