Files changed: - CHANGES.md - VERSION - docs/how-to/README.md - docs/how-to/back-up-to-a-synced-folder.md - docs/how-to/collect-from-a-synced-folder.md - docs/how-to/export-guidelines.md - docs/how-to/export-to-a-synced-folder.md - docs/reference/commands/README.md - docs/reference/commands/exports.md - docs/reference/commands/git.md - docs/reference/commands/guideline-export.md - docs/reference/commands/instance-health.md - docs/reference/commands/raw-material-and-uploads.md - docs/reference/configuration.md - docs/reference/exit-codes.md - instructions/setup-instance.md - raw/CONTRACT.md - tools/CONTRACT.md - tools/README.md - tools/chemenu/backup.py - tools/chemenu/cli_contract.py - tools/chemenu/commands/doctor.py - tools/chemenu/commands/export_cmd.py - tools/chemenu/commands/git_publish.py - tools/chemenu/commands/raw/_common.py - tools/chemenu/commands/raw/accept.py - tools/chemenu/commands/raw/capture.py - tools/chemenu/config_shapes.py - tools/chemenu/guideline_export.py - tools/chemenu/page_export.py - tools/chemenu/reference_doc.py - tools/chemenu/repo_capture.py - tools/chemenu/tests/test_config_shapes.py - tools/chemenu/tests/test_export_run.py Co-Authored-By: Claude Code <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SnAJ7Z3CpVD3PRbN73QtU2
19 KiB
19 KiB
Git
Pulling in the remote and publishing a change - the only way a change leaves this checkout - and backing the checkout up into a synced folder.
Contents
sync
Fetch <remote>/<branch> and bring the local branch up to date with it.
Synopsis
wikitool sync [--remote origin] [--branch main] [--confirm-rebase TOKEN]
Options
--remote <str> Git remote to reconcile against [default: origin]
--branch <str> Branch to reconcile [default: main]
--confirm-rebase TOKEN Clear the Rebase-Review Gate for the exact upstream
state and file overlap this token was issued for. The
token comes from the gate's own refusal output.
-h, --help Show this message and exit.
Examples
tools/wikitool sync
tools/wikitool sync --confirm-rebase <token> # re-run after exit 42, once the user approved
Behaviour
- Fetches
<remote>/<branch>, then: fast-forwards when only the remote moved; rebases the local commits on top when both sides moved but touched disjoint files; exits 42 (Rebase-Review Gate) when both sides touched the same file. - Files
wikitoolgenerates (kb/index.md,kb/log.md,kb/provenance.md, everykb/**/INDEX.md) never count as an overlap and never reach the gate. Where they are what stops git - uncommitted ones in the way of a fast-forward or rebase, or a rebase conflict in them - they are merged mechanically:kb/log.mdbecomes the incoming log plus the entries only this side appended, and the catalog andkb/provenance.mdare regenerated from the merged pages and left as an uncommitted change. A reconcile git can do on its own is unchanged and regenerates nothing. - Uncommitted changes that no incoming commit touches do not stop a rebase: they are carried through it (
git rebase --autostash) and come back unchanged. - Before anything is set aside, the working tree is stored as a commit under
refs/wikitool/reconcile-backup. A successful reconcile drops it; a failed one restores the working tree and names the ref. - A refused call performs no rebase attempt and leaves the branch where it was.
- The
--confirm-rebasetoken covers the exact upstream state and the set of files touched on both sides, generated files excluded; either one moving makes it stale. - Makes no commit, no push, and no forced operation of any kind.
- Three messages for a fetch that fails: no remote of that name, a remote that answers but has no such branch yet (a new, empty repository), and a remote that cannot be reached. All three exit 0 here;
publishstops on the first and the last. - Run it once at the start of a writing session.
Properties
- Changes files: yes
- Idempotent: yes
- Atomic: No - fetch, then at most one merge/rebase attempt, aborted cleanly on failure with the working tree restored; a success that merged generated files then rewrites the catalog
- Counts toward the session call budget: yes
- Can reach the network: yes
- Gates: rebase-review - see exit codes and gates
Exit codes
0- success0- No remote configured - reported and skipped, not a failure0- The remote cannot be reached - reported and skipped, not a failure1- The automatic rebase hit a real conflict outside the generated files (git failed), orkb/log.mdwas edited rather than appended to; it is aborted cleanly and the working tree restored1- An uncommitted change - or an untracked file - sits on a path the incoming commits also change; nothing was changed42- Rebase-Review Gate:<remote>/<branch>moved and both sides changed the same file, generated files aside; the output lists the upstream commits, the overlapping files and their diff
See also
wikitool publish- runs the same reconcile before it commits and pushesinstructions/session-setup.md- where a session runssyncinstructions/gates.md- the gate procedure
publish
Reconcile with <remote>/<branch>, then stage all changes, commit, and push.
Synopsis
wikitool publish --message "<op>: <desc>" [--no-push] [--confirm TOKEN] [--confirm-rebase TOKEN] [--threshold N] [--remote origin] [--branch main] [--path P ...]
Options
--message <str> Commit message summary, e.g. 'ingest: docker-
cheatsheet' [required]
--push / --no-push [default: push]
--confirm TOKEN Clear the Mass-Update Gate for the exact changeset
this token was issued for. The token comes from the
gate's own refusal output - run without it first to
see the file list, show that output to the user, and
only pass this once they have approved it.
--confirm-rebase TOKEN Clear the Rebase-Review Gate raised by the pre-push
reconcile step. The token comes from that gate's own
refusal output - see `tools/wikitool sync`.
--threshold <int> Mass-Update Gate threshold: number of counted files
at/above which clearance is required. [default: 10]
--remote <str> Git remote to push to [default: origin]
--branch <str> Branch to push [default: main]
--path <str> Limit this publish to a path (repeatable). Lets a
large change be committed in reviewable batches
instead of one opaque commit - the Mass-Update Gate
then counts only the files in scope.
-h, --help Show this message and exit.
Examples
tools/wikitool publish --message "ingest: docker-cheatsheet"
tools/wikitool publish --confirm <token> --message "ingest: docker-cheatsheet" # re-run after a Mass-Update exit 42, once the user approved
tools/wikitool publish --confirm-rebase <token> --message "ingest: docker-cheatsheet" # re-run after a rebase-review exit 42, once the user approved
Behaviour
- Order: branch check and Publish-Remote Gate, then the reconcile with
<remote>/<branch>, then the Mass-Update Gate, thengit add -A, commit and push.--no-pushskips all but the Mass-Update Gate and the commit. - Without
--no-push, a remote that is not configured or cannot be reached ends the call with exit 1 at the reconcile - before the gate,git addand the commit, and also on a clean tree. Nothing is committed, the index and the working tree are unchanged, and the message names--no-pushas the way to a local commit. The nextpublishthat reaches the remote pushes that commit along with whatever is new. A remote that answers but has no<branch>yet (a new, empty repository) is not this case: the first publish of an instance commits and pushes as before. - Reconcile: fetches
<remote>/<branch>, fast-forwards when only the remote moved, rebases the local commits on top when both sides moved but touched disjoint files, and exits 42 (Rebase-Review Gate) when both sides touched the same file. A refused reconcile performs no rebase attempt. The--confirm-rebasetoken covers the exact upstream state and the set of files touched on both sides. - Generated files are never an overlap: where they are all that stops the reconcile, it merges them as
syncdoes (both sides' log entries kept, the catalog andkb/provenance.mdregenerated) and carries uncommitted changes no incoming commit touches through the rebase. The proactive reconcile runs before staging, so this publish commits the regenerated files - with--pathtoo, see there; on the retry after a rejected push they get a commit of their own before the second push. - The push target must be the checked-out branch; this is checked before anything is staged. The unborn branch of a fresh
git init -b maincounts as checked out, so the first publish of a new instance works; a real detached HEAD is refused. - With nothing new to stage, a local commit the remote lacks is still pushed: one left behind by an earlier publish whose push failed, or every commit when the remote answers but does not have the branch yet (a new, empty remote repository).
- A rejected push that finds the remote unreachable on its one retry reports the original push error.
- A rejected push gets exactly one more reconcile-and-push; never more than one.
- Mass-Update Gate: counts the files that would be committed, refuses with exit 42 at
--threshold(default 10) or more, and prints a review report - a scale line (file count, total lines added/removed, status breakdown), attention notes where they apply (deletions by name, control-plane and harness-config touches, published pages, the largest single change, binaries), and every counted path grouped by area with its status and churn. The list is what the commit will hold: it is computed from a scratch copy of the index aftergit add -A, so a path that is staged as deleted and back in the working tree is not counted twice, and a rename counts as its old path deleted plus its new path added. The real index and the working tree are not touched, so a refused publish leaves both byte-identical. - Never counted and never shown for approval, but committed like everything else: anything under
work/, and the fileswikitoolgenerates itself (kb/index.md,kb/log.md,kb/provenance.md, everyINDEX.mdunderkb/). The refusal line accounts for both, by reason. - The
--confirmtoken covers each counted path, the blob id of its contents and the publish target: a different file list or edited contents need a new clearance. - Publish-Remote Gate: when
.wikitool-local.jsoncarriesremotes.allowed_push_urlsand the push URL of--remoteis not listed in it, exits 42 before the reconcile fetches anything. The URL is read withgit remote get-url --push, so a repointed remote does not pass on its name. An absent section means unrestricted; a malformed one is an error, not permission. - The remotes settings file of an earlier version is not read: while it exists this exits 42 and names
tools/wikitool config migrate, so a restriction is never lost silently. --path(repeatable) scopes the whole operation - gate count, staging and commit - to that subtree, with one exception: uncommitted generated files outside--path(kb/index.md,kb/log.md,kb/provenance.md, everyINDEX.mdunderkb/) are staged and committed too, and a line names them - whether a reconcile or the change itself wrote them. They stay out of the gate count, and the--confirmtoken and the re-run line cover the--pathgiven. Every other file outside--pathis left as it is.- Commit message:
--message, then aFiles changed:paragraph listing every committed path. When--messageends in a paragraph git reads as a trailer block (Co-Authored-By:and the like), that block stays the last paragraph and the list goes in front of it, since git reads trailers from the last paragraph only.git interpret-trailersdecides whether there is such a block, and the list moves only when git reads the same trailers from the result; otherwise it is appended at the end.--messageis not part of any gate token. - Machine-data backup: with a
backupsection in.wikitool-local.jsonwhosemachine_datais true, a call that pushed then mirrors this machine's files that are not in git into<target>/<machine>/- the same step asbackup run. A failure there prints aWARNline with the reason and still exits 0, since the commit and the push stand. No backup with--no-push, after a failed push, or when there was nothing to push. A malformedbackupsection stops the call with exit 1 before anything is committed,--no-pushincluded. - Export after publish: every target of the
exportsection withafter_publish: trueis refreshed once a commit was made - the same step asexport run,--no-pushincluded, since the export reads the committedkb/. A failure there prints aWARNline with the reason and still exits 0, since the commit stands;export runrepeats it. A malformedexportsection stops the call with exit 1 before anything is committed, but only when some target setsafter_publish. - After a successful commit or push whose changed files include
tools/,types/,instructions/,AGENTS.mdor a path ending inCONTRACT.md, prints one reminder line: the phase past this point (an issue-body rewrite,docs/staleness, a changelog entry's accuracy) is not covered bydocs verify,instructions verifyorpytest. It is not a gate: no exit code change, nothing to clear, and silent for an ordinary content publish.
Properties
- Changes files: yes
- Idempotent: no
- Atomic: No - sequential git operations. Every gate runs before staging, except on the one retry of a rejected push, where the Rebase-Review Gate can exit 42 after the commit: nothing is pushed, and the re-run with
--confirm-rebasepushes that commit - Counts toward the session call budget: yes
- Can reach the network: yes
- Gates: mass-update, publish-remote, rebase-review - see exit codes and gates
Exit codes
0- success0- The machine-data backup after the push failed: aWARNline names the reason, and the commit and the push stand0- The export after the commit failed: aWARNline names the target and the reason, and the commit stands1- git failed -git add,git commit,git push, or the reconcile's automatic rebase (a conflict outside the generated files, an editedkb/log.md, or an uncommitted change on a path the incoming commits change)1- The push target (--branch) is not the checked-out branch, or HEAD is detached; the unborn branch of a freshgit initis not this case1- No--no-push, and the remote is not configured or cannot be reached; nothing was committed1---yes/-ywas passed - the flag does not exist and fails with an explicit error1- The settings files do not pass their check,remotes.allowed_push_urlsis not a list of strings, thebackupsection is malformed, or theexportsection is malformed while a target setsafter_publish; nothing was committed42- The remotes settings file of an earlier version is still there42- Mass-Update Gate:--threshold(default 10) or more counted files would be committed, or the--confirmtoken does not match this changeset42- Rebase-Review Gate:<remote>/<branch>moved and both sides changed the same file; the output lists the upstream commits, the overlapping files and their diff42- Publish-Remote Gate:remotes.allowed_push_urlsis set and the push URL of--remoteis not listed in it, or--remoteresolves to no push URL
See also
wikitool sync- the same reconcile on its own, without committing or pushinginstructions/gates.md- the gate procedureinstructions/setup-instance.md- the first publish of a new instancewikitool backup run- the machine-data backup on its ownwikitool export run- the page export on its own
backup init
Create the backup target's bare repository and make it origin when there is none.
Synopsis
wikitool backup init
Options
-h, --help Show this message and exit.
Examples
tools/wikitool backup init
Behaviour
- Reads the
backupsection of.wikitool-local.jsonand creates<target>/and<target>/git, the latter as a bare repository (git init --bare -b main). An existing bare repository there, or an empty directory, is used as it is. - Sets
originto<target>/gitwhen the checkout has noorigin. Anoriginthat already pushes there is left as it is; one that pushes anywhere else stops the command. - When
remotes.allowed_push_urlsexists and lacks the URLoriginpushes to, prints theremotessection with that URL added, for the user to copy into.wikitool-local.json. It never writes that file: the field is a gate. - Pushes nothing: the next
publishsends the history to the neworigin.
Properties
- Changes files: yes
- Idempotent: yes
- Atomic: Every precondition is checked first; a refusal changes nothing
- Counts toward the session call budget: yes
- Can reach the network: no
Exit codes
0- success1- Nobackupsection in.wikitool-local.json, or a malformed one - a target that is not absolute or lies inside the instance, amachine_namethat cleans to nothing or togit, anextrapath that resolves outside the instance or into.git/1-<target>/gitexists and is not a bare repository; nothing was changed1-originalready pushes to another URL; the message names both and nothing was changed
See also
wikitool backup run- the machine-data half of the backupwikitool publish- pushes to the bare repository and runs the machine-data backup after itdocs/how-to/back-up-to-a-synced-folder.md- the whole procedure, restoring included
backup run
Mirror this machine's files that are not in git into <target>/<machine>/.
Synopsis
wikitool backup run
Options
-h, --help Show this message and exit.
Examples
tools/wikitool backup run
Behaviour
- Mirrors
.wikitool-local.json,ENVIRONMENT.mdif present, every file inincoming/but.gitkeep, and theextrapaths of thebackupsection into<target>/<machine>/, then writes the manifest.chemenu-backup.jsonthere: time, stack version, machine name, and per file its relative path, size and sha256. - Never mirrors
quarantine/,reports/,.wikitool-tools.json,tools/.venv/, the published skills or.git/- unless anextrapath names one of the first ones. The secrets file lies outside the instance and is never read. - Writes and deletes only under
<target>/<machine>/. Deletes only a file the previous manifest lists and the instance no longer has; a file there the manifest does not list stays as it is. A file whose size and sha256 match the previous manifest is not rewritten. - A symbolic link or junction inside a mirrored directory is skipped and named in the output, never followed.
publishruns the same step after every push whenmachine_datais true.
Properties
- Changes files: yes
- Idempotent: yes
- Atomic: Per file - each is written to a temporary file and renamed, the manifest last; an interrupted run leaves whole files and the previous manifest
- Counts toward the session call budget: yes
- Can reach the network: no
Exit codes
0- success1- Nobackupsection in.wikitool-local.json, or a malformed one - a target that is not absolute or lies inside the instance, amachine_namethat cleans to nothing or togit, anextrapath that resolves outside the instance or into.git/1-machine_datais false1-<target>/<machine>/is not empty and has no manifest, or its manifest cannot be read; nothing was written1- The target is not a directory (the synced folder is missing or not mounted), or a write failed
See also
wikitool backup init- sets up the target's bare repositorywikitool doctor- thebackupline reports the age of the last rundocs/how-to/back-up-to-a-synced-folder.md- the whole procedure, restoring included