tools: command records, Private instances group - one line per cause, examples, prohibitions (#142)
Files changed: - CHANGES.md - VERSION - tools/CONTRACT.md - tools/chemenu/commands/upstream_cmd.py
This commit is contained in:
1 parent
243db66134
commit
b83a3982c5
4 files changed
+167
-54
No files matched your search
+9
-1
@@ -59,7 +59,7 @@ concern - readable here, never shipped as something to parse.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 7.1.0-beta.18 - 2026-09-26 - Command records, Content migrations group: one line per cause, examples, prohibitions
|
## 7.1.0-beta.19 - 2026-09-26 - Command records, Private instances group: one line per cause, examples, prohibitions
|
||||||
|
|
||||||
**Author:** Torben Nehmer
|
**Author:** Torben Nehmer
|
||||||
|
|
||||||
@@ -87,6 +87,7 @@ concern - readable here, never shipped as something to parse.
|
|||||||
- Command records, Types, instructions and docs group: one line per cause, examples, prohibitions
|
- Command records, Types, instructions and docs group: one line per cause, examples, prohibitions
|
||||||
- Command records, Telemetry group: examples, the missing --fail-on-error exit line
|
- Command records, Telemetry group: examples, the missing --fail-on-error exit line
|
||||||
- Command records, Content migrations group: one line per cause, examples, prohibitions
|
- Command records, Content migrations group: one line per cause, examples, prohibitions
|
||||||
|
- Command records, Private instances group: one line per cause, examples, prohibitions
|
||||||
<!-- /wikitool:bumps -->
|
<!-- /wikitool:bumps -->
|
||||||
|
|
||||||
### CalDAV task-tracker provider (Nextcloud Tasks, iOS Reminders); review reports unknown-value findings instead of skipping them
|
### CalDAV task-tracker provider (Nextcloud Tasks, iOS Reminders); review reports unknown-value findings instead of skipping them
|
||||||
@@ -316,6 +317,13 @@ never advance the version with `baseline --force` or by editing `.wikitool-kb.js
|
|||||||
behind counting marker pairs rather than comparing their names, and behind an offered migration
|
behind counting marker pairs rather than comparing their names, and behind an offered migration
|
||||||
ignoring the chain, moved into the `verify` and `done` docstrings.
|
ignoring the chain, moved into the `verify` and `done` docstrings.
|
||||||
|
|
||||||
|
### Command records, Private instances group: one line per cause, examples, prohibitions
|
||||||
|
|
||||||
|
`upstream merge` and `upstream verify` rewritten the same way; text only. `upstream merge`'s
|
||||||
|
single paragraph is now one bullet per step of the merge, and its exit-1 causes - including the
|
||||||
|
fetch failure, a failing git step inside the open merge, and the post-commit leak, which its old
|
||||||
|
record mentioned only in passing - each carry their own reaction.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 7.0.0 - 2026-09-22 - Task-Tracker-Anbindung: Vorhaben als Seitenart, Verpflichtungsschicht, Weekly Review als Read-Time-Join
|
## 7.0.0 - 2026-09-22 - Task-Tracker-Anbindung: Vorhaben als Seitenart, Verpflichtungsschicht, Weekly Review als Read-Time-Join
|
||||||
|
|||||||
+58
-6
@@ -3039,18 +3039,51 @@ Take a stack update into a private instance's branch, machinery only.
|
|||||||
- budget: counted
|
- budget: counted
|
||||||
- network: no
|
- network: no
|
||||||
|
|
||||||
|
**EXAMPLES**
|
||||||
|
|
||||||
|
- `tools/wikitool upstream merge`
|
||||||
|
- `tools/wikitool upstream merge --remote upstream --branch main --no-fetch`
|
||||||
|
|
||||||
**EXIT STATUS**
|
**EXIT STATUS**
|
||||||
|
|
||||||
- 0 success
|
- 0 success
|
||||||
- 1 Dirty working tree, a merge already in progress, the remote does not resolve, git refused to open the merge at all (unrelated histories), or a real conflict remains in `tools/`/`types/`/`instructions/` after the content stages and stack-owned paths were restored
|
- 1 Dirty working tree, or a merge already in progress
|
||||||
|
- 1 The remote does not resolve, the fetch failed, or `HEAD` does not resolve
|
||||||
|
- 1 git refused to open the merge at all (unrelated histories); nothing was touched
|
||||||
|
- 1 A real conflict remains in `tools/`/`types/`/`instructions/` after the content stages and stack-owned paths were restored; the merge is left open
|
||||||
|
- 1 A git step failed inside the open merge (`git checkout MERGE_HEAD -- <path>` or `git commit --no-edit`)
|
||||||
|
- 1 The postcheck after the commit found a leak; the merge commit already exists
|
||||||
|
|
||||||
**ON FAILURE**
|
**ON FAILURE**
|
||||||
|
|
||||||
- Dirty working tree, a merge already in progress, the remote does not resolve, git refused to open the merge at all (unrelated histories), or a real conflict remains in `tools/`/`types/`/`instructions/` after the content stages and stack-owned paths were restored -> **Not idempotent, and not safe to retry unchanged.** For a dirty tree or an in-progress merge: fix the named precondition and retry once. For a real conflict: **do not retry, do not force** - resolve the named paths by hand (take the upstream side, or re-file the local change as an issue against the public repo per `instructions/private-instance.md`) and either `git commit --no-edit` yourself or `git merge --abort`. If the postcheck after commit finds a leak, the merge commit already exists and is **not** rolled back automatically - inspect it by hand; this is a bug report, not a retry
|
- Dirty working tree, or a merge already in progress -> Fix the named precondition and retry once
|
||||||
|
- The remote does not resolve, the fetch failed, or `HEAD` does not resolve -> Fix `--remote`/`--branch` or the repository state, then retry once
|
||||||
|
- git refused to open the merge at all (unrelated histories); nothing was touched -> Do not retry unchanged - report it to the user
|
||||||
|
- A real conflict remains in `tools/`/`types/`/`instructions/` after the content stages and stack-owned paths were restored; the merge is left open -> **Do not retry, do not force** - resolve the named paths by hand (take the upstream side, or re-file the local change as an issue against the public repo per `instructions/private-instance.md`) and either `git commit --no-edit` yourself or `git merge --abort`
|
||||||
|
- A git step failed inside the open merge (`git checkout MERGE_HEAD -- <path>` or `git commit --no-edit`) -> Do not retry unchanged - inspect the open merge by hand
|
||||||
|
- The postcheck after the commit found a leak; the merge commit already exists -> It is **not** rolled back automatically - inspect it by hand; this is a bug report, not a retry
|
||||||
|
|
||||||
|
**NEVER**
|
||||||
|
|
||||||
|
- Never retry a failed merge unchanged, and never force.
|
||||||
|
|
||||||
**NOTES**
|
**NOTES**
|
||||||
|
|
||||||
The code procedure behind `instructions/private-instance.md` § "Taking a stack update". Refuses on a dirty working tree, a merge already in progress, or a remote that does not resolve; WARNs (does not block) when `.wikitool-remotes.json` is absent, pointing at the setup step that arms it. Fetches `<remote>/<branch>` (unless `--no-fetch`) and reports "already up to date" if nothing new exists. Otherwise opens `git merge --no-commit --no-ff <remote>/<branch>` - and stops, untouched, if git refused to open a merge at all (unrelated histories), since without a `MERGE_HEAD` every stack path would read as "the upstream deleted it". Then forces every content stage (`kb/`, `raw/`, `work/`, `reports/`) back to the local side by removing **only the paths tracked in either tree** and checking `HEAD`'s back out - never the stage directory wholesale, because `reports/` is gitignored apart from its contract and holds local, non-recomputable data (telemetry traces `eval score` reads, saved eval and lint reports) that no merge has business deleting. Then restores from the upstream side exactly the paths `chemenu.ownership.is_stack_owned` recognises as machinery (`<stage>/CONTRACT.md`, and anything ending `.template` under a content stage) - including a deletion, if the upstream removed one. A real conflict left in `tools/`, `types/` or `instructions/` after that leaves the merge open, uncommitted, and exits 1 rather than guessing. Commits with `git commit --no-edit`, then re-checks the resulting range with the same logic as `upstream verify`; a finding there is a loud, uncommitted-nothing-rolled-back error, because the merge commit already exists and needs a human's eyes, not an automatic repair. Never pushes. Not idempotent - see the tool error contract below
|
- Refuses on a dirty working tree, a merge already in progress, or a remote that does not resolve. WARNs (does not block) when `.wikitool-remotes.json` is absent, pointing at the setup step that arms it.
|
||||||
|
- Fetches `<remote>/<branch>` (unless `--no-fetch`) and reports "already up to date" if nothing new exists.
|
||||||
|
- Otherwise opens `git merge --no-commit --no-ff <remote>/<branch>`, and stops, untouched, if git refused to open a merge at all (unrelated histories).
|
||||||
|
- Forces every content stage (`kb/`, `raw/`, `work/`, `reports/`) back to the local side by removing **only the paths tracked in either tree** and checking `HEAD`'s back out - never the stage directory wholesale, so untracked and ignored local data under a stage (telemetry traces, saved eval and lint reports) is never deleted.
|
||||||
|
- Then restores from the upstream side exactly the machinery paths - `<stage>/CONTRACT.md` and anything ending `.template` under a content stage - including a deletion, if the upstream removed one.
|
||||||
|
- A real conflict left in `tools/`, `types/` or `instructions/` after that leaves the merge open, uncommitted, and exits 1 rather than guessing.
|
||||||
|
- Commits with `git commit --no-edit`, then re-checks the resulting range with the `upstream verify` check; a finding there is a loud error, and the merge commit is not rolled back.
|
||||||
|
- Never pushes.
|
||||||
|
- Not idempotent, and not safe to retry unchanged.
|
||||||
|
|
||||||
|
**SEE ALSO**
|
||||||
|
|
||||||
|
- `instructions/private-instance.md` § "Taking a stack update" - the procedure this implements
|
||||||
|
- `wikitool upstream verify` - the same check on any revision range
|
||||||
|
- `wikitool publish` - pushes the merge afterwards
|
||||||
|
|
||||||
#### `upstream verify`
|
#### `upstream verify`
|
||||||
|
|
||||||
@@ -3068,18 +3101,37 @@ Compare two revisions: did anything under a content stage change except through
|
|||||||
- budget: exempt
|
- budget: exempt
|
||||||
- network: no
|
- network: no
|
||||||
|
|
||||||
|
**EXAMPLES**
|
||||||
|
|
||||||
|
- `tools/wikitool upstream verify --since HEAD~1`
|
||||||
|
- `tools/wikitool upstream verify --since v7.0.0 --until HEAD`
|
||||||
|
|
||||||
**EXIT STATUS**
|
**EXIT STATUS**
|
||||||
|
|
||||||
- 0 success
|
- 0 success
|
||||||
- 1 A leak was found (content changed under a content stage through a path that is not stack-owned), or `--since`/`--until` is not a revision in this repository
|
- 1 A leak: content changed under a content stage through a path that is not stack-owned
|
||||||
|
- 1 `--since`/`--until` is not a revision in this repository
|
||||||
|
|
||||||
**ON FAILURE**
|
**ON FAILURE**
|
||||||
|
|
||||||
- A leak was found (content changed under a content stage through a path that is not stack-owned), or `--since`/`--until` is not a revision in this repository -> A finding is not fixed by re-running - it names the paths that leaked. Fix the revision argument and retry for the second case
|
- A leak: content changed under a content stage through a path that is not stack-owned -> A finding is not fixed by re-running - it names the paths that leaked
|
||||||
|
- `--since`/`--until` is not a revision in this repository -> Fix the revision argument and retry
|
||||||
|
|
||||||
|
**NEVER**
|
||||||
|
|
||||||
|
- Never re-run to make a leak finding go away.
|
||||||
|
|
||||||
**NOTES**
|
**NOTES**
|
||||||
|
|
||||||
Shares its check with `upstream merge`'s own postcheck, so a hand-resolved merge conflict, or a `dist upgrade`, can be verified the same way. Exit 1 with the offending paths if anything leaked; otherwise reports which stack-owned paths legitimately moved. Read-only and exempt from the Iteration Budget Gate, like `migrate verify`
|
- Compares `--since` with `--until` (default `HEAD`): did anything under a content stage change except through a stack-owned path?
|
||||||
|
- The same check `upstream merge` runs after its commit, so a hand-resolved merge conflict, or a `dist upgrade`, can be verified the same way.
|
||||||
|
- Exits 1 with the offending paths if anything leaked; otherwise reports which stack-owned paths legitimately moved.
|
||||||
|
- Read-only and exempt from the Iteration Budget Gate.
|
||||||
|
|
||||||
|
**SEE ALSO**
|
||||||
|
|
||||||
|
- `wikitool upstream merge` - runs this check after its commit
|
||||||
|
- `instructions/private-instance.md` - the private-instance workflow
|
||||||
|
|
||||||
### Instance health
|
### Instance health
|
||||||
|
|
||||||
|
|||||||
@@ -250,42 +250,75 @@ def _merge_success_message(
|
|||||||
atomic="**No** - can leave an open, uncommitted merge behind on refusal after fetching",
|
atomic="**No** - can leave an open, uncommitted merge behind on refusal after fetching",
|
||||||
budget=cli_contract.Budget.COUNTED,
|
budget=cli_contract.Budget.COUNTED,
|
||||||
),
|
),
|
||||||
notes="The code procedure behind `instructions/private-instance.md` § \"Taking a stack "
|
notes=(
|
||||||
"update\". Refuses on a dirty working tree, a merge already in progress, or a remote that "
|
"Refuses on a dirty working tree, a merge already in progress, or a remote that does "
|
||||||
"does not resolve; WARNs (does not block) when `.wikitool-remotes.json` is absent, pointing "
|
"not resolve. WARNs (does not block) when `.wikitool-remotes.json` is absent, pointing "
|
||||||
"at the setup step that arms it. Fetches `<remote>/<branch>` (unless `--no-fetch`) and "
|
"at the setup step that arms it.",
|
||||||
"reports \"already up to date\" if nothing new exists. Otherwise opens "
|
"Fetches `<remote>/<branch>` (unless `--no-fetch`) and reports \"already up to date\" "
|
||||||
"`git merge --no-commit --no-ff <remote>/<branch>` - and stops, untouched, if git refused "
|
"if nothing new exists.",
|
||||||
"to open a merge at all (unrelated histories), since without a `MERGE_HEAD` every stack "
|
"Otherwise opens `git merge --no-commit --no-ff <remote>/<branch>`, and stops, "
|
||||||
"path would read as \"the upstream deleted it\". Then forces every content stage (`kb/`, "
|
"untouched, if git refused to open a merge at all (unrelated histories).",
|
||||||
"`raw/`, `work/`, `reports/`) back to the local side by removing **only the paths tracked "
|
"Forces every content stage (`kb/`, `raw/`, `work/`, `reports/`) back to the local "
|
||||||
"in either tree** and checking `HEAD`'s back out - never the stage directory wholesale, "
|
"side by removing **only the paths tracked in either tree** and checking `HEAD`'s back "
|
||||||
"because `reports/` is gitignored apart from its contract and holds local, non-recomputable "
|
"out - never the stage directory wholesale, so untracked and ignored local data under "
|
||||||
"data (telemetry traces `eval score` reads, saved eval and lint reports) that no merge has "
|
"a stage (telemetry traces, saved eval and lint reports) is never deleted.",
|
||||||
"business deleting. Then restores from the upstream side exactly the paths "
|
"Then restores from the upstream side exactly the machinery paths - `<stage>/CONTRACT.md` "
|
||||||
"`chemenu.ownership.is_stack_owned` recognises as machinery (`<stage>/CONTRACT.md`, and "
|
"and anything ending `.template` under a content stage - including a deletion, if the "
|
||||||
"anything ending `.template` under a content stage) - including a deletion, if the upstream "
|
"upstream removed one.",
|
||||||
"removed one. A real conflict left in `tools/`, `types/` or `instructions/` after that "
|
"A real conflict left in `tools/`, `types/` or `instructions/` after that leaves the "
|
||||||
"leaves the merge open, uncommitted, and exits 1 rather than guessing. Commits with "
|
"merge open, uncommitted, and exits 1 rather than guessing.",
|
||||||
"`git commit --no-edit`, then re-checks the resulting range with the same logic as "
|
"Commits with `git commit --no-edit`, then re-checks the resulting range with the "
|
||||||
"`upstream verify`; a finding there is a loud, uncommitted-nothing-rolled-back error, "
|
"`upstream verify` check; a finding there is a loud error, and the merge commit is not "
|
||||||
"because the merge commit already exists and needs a human's eyes, not an automatic repair. "
|
"rolled back.",
|
||||||
"Never pushes. Not idempotent - see the tool error contract below",
|
"Never pushes.",
|
||||||
failures=(cli_contract.Failure(
|
"Not idempotent, and not safe to retry unchanged.",
|
||||||
label="",
|
),
|
||||||
cause="Dirty working tree, a merge already in progress, the remote does not resolve, "
|
failures=(
|
||||||
"git refused to open the merge at all (unrelated histories), or a real conflict remains "
|
cli_contract.Failure(
|
||||||
"in `tools/`/`types/`/`instructions/` after the content stages and stack-owned paths "
|
cause="Dirty working tree, or a merge already in progress",
|
||||||
"were restored",
|
reaction="Fix the named precondition and retry once",
|
||||||
reaction="**Not idempotent, and not safe to retry unchanged.** For a dirty tree or an "
|
),
|
||||||
"in-progress merge: fix the named precondition and retry once. For a real conflict: "
|
cli_contract.Failure(
|
||||||
"**do not retry, do not force** - resolve the named paths by hand (take the upstream "
|
cause="The remote does not resolve, the fetch failed, or `HEAD` does not resolve",
|
||||||
"side, or re-file the local change as an issue against the public repo per "
|
reaction="Fix `--remote`/`--branch` or the repository state, then retry once",
|
||||||
|
),
|
||||||
|
cli_contract.Failure(
|
||||||
|
cause="git refused to open the merge at all (unrelated histories); nothing was "
|
||||||
|
"touched",
|
||||||
|
reaction="Do not retry unchanged - report it to the user",
|
||||||
|
),
|
||||||
|
cli_contract.Failure(
|
||||||
|
cause="A real conflict remains in `tools/`/`types/`/`instructions/` after the "
|
||||||
|
"content stages and stack-owned paths were restored; the merge is left open",
|
||||||
|
reaction="**Do not retry, do not force** - resolve the named paths by hand (take the "
|
||||||
|
"upstream side, or re-file the local change as an issue against the public repo per "
|
||||||
"`instructions/private-instance.md`) and either `git commit --no-edit` yourself or "
|
"`instructions/private-instance.md`) and either `git commit --no-edit` yourself or "
|
||||||
"`git merge --abort`. If the postcheck after commit finds a leak, the merge commit "
|
"`git merge --abort`",
|
||||||
"already exists and is **not** rolled back automatically - inspect it by hand; this is "
|
),
|
||||||
"a bug report, not a retry",
|
cli_contract.Failure(
|
||||||
),),
|
cause="A git step failed inside the open merge (`git checkout MERGE_HEAD -- <path>` "
|
||||||
|
"or `git commit --no-edit`)",
|
||||||
|
reaction="Do not retry unchanged - inspect the open merge by hand",
|
||||||
|
),
|
||||||
|
cli_contract.Failure(
|
||||||
|
cause="The postcheck after the commit found a leak; the merge commit already exists",
|
||||||
|
reaction="It is **not** rolled back automatically - inspect it by hand; this is a bug "
|
||||||
|
"report, not a retry",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
examples=(
|
||||||
|
"tools/wikitool upstream merge",
|
||||||
|
"tools/wikitool upstream merge --remote upstream --branch main --no-fetch",
|
||||||
|
),
|
||||||
|
never=(
|
||||||
|
"Never retry a failed merge unchanged, and never force.",
|
||||||
|
),
|
||||||
|
see_also=(
|
||||||
|
"`instructions/private-instance.md` § \"Taking a stack update\" - the procedure this "
|
||||||
|
"implements",
|
||||||
|
"`wikitool upstream verify` - the same check on any revision range",
|
||||||
|
"`wikitool publish` - pushes the merge afterwards",
|
||||||
|
),
|
||||||
))
|
))
|
||||||
@app.command("merge")
|
@app.command("merge")
|
||||||
def merge_command(
|
def merge_command(
|
||||||
@@ -431,17 +464,37 @@ def _verify_success_message(stack_moved: list[str], since: str, until: str) -> s
|
|||||||
atomic="Read-only",
|
atomic="Read-only",
|
||||||
budget=cli_contract.Budget.EXEMPT,
|
budget=cli_contract.Budget.EXEMPT,
|
||||||
),
|
),
|
||||||
notes="Shares its check with `upstream merge`'s own postcheck, so a hand-resolved merge "
|
notes=(
|
||||||
"conflict, or a `dist upgrade`, can be verified the same way. Exit 1 with the offending "
|
"Compares `--since` with `--until` (default `HEAD`): did anything under a content stage "
|
||||||
"paths if anything leaked; otherwise reports which stack-owned paths legitimately moved. "
|
"change except through a stack-owned path?",
|
||||||
"Read-only and exempt from the Iteration Budget Gate, like `migrate verify`",
|
"The same check `upstream merge` runs after its commit, so a hand-resolved merge "
|
||||||
failures=(cli_contract.Failure(
|
"conflict, or a `dist upgrade`, can be verified the same way.",
|
||||||
label="",
|
"Exits 1 with the offending paths if anything leaked; otherwise reports which "
|
||||||
cause="A leak was found (content changed under a content stage through a path that is "
|
"stack-owned paths legitimately moved.",
|
||||||
"not stack-owned), or `--since`/`--until` is not a revision in this repository",
|
"Read-only and exempt from the Iteration Budget Gate.",
|
||||||
reaction="A finding is not fixed by re-running - it names the paths that leaked. Fix the "
|
),
|
||||||
"revision argument and retry for the second case",
|
failures=(
|
||||||
),),
|
cli_contract.Failure(
|
||||||
|
cause="A leak: content changed under a content stage through a path that is not "
|
||||||
|
"stack-owned",
|
||||||
|
reaction="A finding is not fixed by re-running - it names the paths that leaked",
|
||||||
|
),
|
||||||
|
cli_contract.Failure(
|
||||||
|
cause="`--since`/`--until` is not a revision in this repository",
|
||||||
|
reaction="Fix the revision argument and retry",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
examples=(
|
||||||
|
"tools/wikitool upstream verify --since HEAD~1",
|
||||||
|
"tools/wikitool upstream verify --since v7.0.0 --until HEAD",
|
||||||
|
),
|
||||||
|
never=(
|
||||||
|
"Never re-run to make a leak finding go away.",
|
||||||
|
),
|
||||||
|
see_also=(
|
||||||
|
"`wikitool upstream merge` - runs this check after its commit",
|
||||||
|
"`instructions/private-instance.md` - the private-instance workflow",
|
||||||
|
),
|
||||||
))
|
))
|
||||||
@app.command("verify")
|
@app.command("verify")
|
||||||
def verify_command(
|
def verify_command(
|
||||||
|
|||||||
Reference in new issue
Block a user