settings: three tiers - wikitool.json (instance), .wikitool-local.json (checkout), secrets by reference incl. 1Password CLI; new command config set (#207)
Every settings field declares its tier; a value in the wrong file is an error naming
file, key and tier. A field naming a program or affecting a gate cannot be declared
instance. Secrets are references only: {"ref": "<name>"} via WIKITOOL_SECRET_<NAME> or
a user-only secrets file, {"ref": "op://..."} via op read (locked 1Password: exit 42).
The preflight records op as an optional tool. doctor gains one line per tier, docs
verify checks a committed wikitool.json for plaintext secrets, CI resolves a real
op:// value through 1password/load-secrets-action. No feature reads its settings
this way yet; without the two files every other command is unchanged.
Files changed:
- .gitea/workflows/ci.yml
- .gitignore
- AGENTS.md
- CHANGES.md
- INSTALL.md
- VERSION
- docs/explanation/README.md
- docs/explanation/configuration-tiers.md
- docs/how-to/README.md
- docs/how-to/use-1password-for-settings.md
- docs/reference/commands/README.md
- docs/reference/commands/configuration.md
- docs/reference/commands/instance-health.md
- docs/reference/commands/types-instructions-and-docs.md
- docs/reference/configuration.md
- docs/reference/exit-codes.md
- instructions/dev/doc-pull-through.md
- instructions/dev/testing-conventions.md
- instructions/preflight.md
- tools/CONTRACT.md
- tools/README.md
- tools/chemenu/cli.py
- tools/chemenu/cli_contract.py
- tools/chemenu/commands/_util.py
- tools/chemenu/commands/config_cmd.py
- tools/chemenu/commands/docs_verify.py
- tools/chemenu/commands/doctor.py
- tools/chemenu/config.py
- tools/chemenu/config_shapes.py
- tools/chemenu/prerequisites.py
- tools/chemenu/settings.py
- tools/chemenu/tests/conftest.py
- tools/chemenu/tests/test_dist_cmd.py
- tools/chemenu/tests/test_preflight.py
- tools/chemenu/tests/test_preflight_pwsh.py
- tools/chemenu/tests/test_settings.py
- tools/chemenu/toolpaths.py
- tools/preflight.ps1
- tools/preflight.sh
- tools/prerequisites.txt
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SnAJ7Z3CpVD3PRbN73QtU2
This commit is contained in:
1 parent
059a0a1840
commit
f6aaadc413
40 files changed
+2246
-31
No files matched your search
+70
-2
@@ -48,6 +48,7 @@ ON FAILURE and NEVER, which address an agent.
|
||||
- [Telemetry](#telemetry)
|
||||
- [Distribution and versioning](#distribution-and-versioning)
|
||||
- [Content migrations](#content-migrations)
|
||||
- [Configuration](#configuration)
|
||||
- [Instance health](#instance-health)
|
||||
- [Design notes](#design-notes)
|
||||
- [Tests](#tests)
|
||||
@@ -165,6 +166,7 @@ migrate status read idempotent budget:exempt exit:0,1
|
||||
migrate verify read idempotent budget:exempt exit:0,1 Compare `kb/` against a git revision on the invariants a content migration must not change.
|
||||
migrate done write non-idempotent budget:counted exit:0,1 Record one migration as applied, advancing `kb_version` in `.wikitool-kb.json`.
|
||||
migrate baseline write idempotent budget:counted exit:0,1 Declare `kb_version` once, for an instance predating `.wikitool-kb.json`.
|
||||
config set write idempotent budget:counted exit:0,1,42 Set one value of the tiered settings, in the file its tier names.
|
||||
doctor read idempotent budget:exempt exit:0,1 Check that this instance is correctly configured.
|
||||
```
|
||||
|
||||
@@ -2579,6 +2581,7 @@ Check the docs that mirror the code.
|
||||
- 1 The `<!-- wikitool:commands -->` region of `tools/CONTRACT.md` is stale
|
||||
- 1 A type-spec's own frontmatter fails its schema
|
||||
- 1 A subtype template `types/<type>.<value>.md` has no type-spec with a `subtype_field:` beside it, names a value outside that field's enum, or carries frontmatter
|
||||
- 1 `wikitool.json` holds a secret or private value as plain text, or a value its tier puts elsewhere
|
||||
- 1 A shipped `.md`/`.template` cites an issue number
|
||||
- 1 A region of the human reference under `docs/reference/` is stale
|
||||
- 1 A page of the human reference is missing or lacks its marker pair, or a page under `docs/reference/commands/` belongs to no group
|
||||
@@ -2598,6 +2601,7 @@ Check the docs that mirror the code.
|
||||
- The `<!-- wikitool:commands -->` region of `tools/CONTRACT.md` is stale -> Run `docs contract --apply`, then re-run
|
||||
- A type-spec's own frontmatter fails its schema -> Fix the field, or add a matching line to `types/type-spec.schema.yaml` if the field is legitimately new
|
||||
- A subtype template `types/<type>.<value>.md` has no type-spec with a `subtype_field:` beside it, names a value outside that field's enum, or carries frontmatter -> Rename the file to the type and value it was meant for, delete it, or remove its frontmatter block
|
||||
- `wikitool.json` holds a secret or private value as plain text, or a value its tier puts elsewhere -> Show the user the message: a plain value there may already be in the history. Move it as the message says - a secret into 1Password, the secrets file or a variable, set by the user, with only the reference left behind - then re-run
|
||||
- A shipped `.md`/`.template` cites an issue number -> Say what was decided instead of pointing at where, or move the pointer behind a `<!-- dist:strip-start/end -->` block
|
||||
- A region of the human reference under `docs/reference/` is stale -> Run `docs reference --apply`, then re-run
|
||||
- A page of the human reference is missing or lacks its marker pair, or a page under `docs/reference/commands/` belongs to no group -> Create the page with a title, a one-sentence head and the marker pair the message names (or add the pair), then run `docs reference --apply`; `git mv` or `git rm` a page left over from a renamed or removed group
|
||||
@@ -2620,7 +2624,8 @@ Check the docs that mirror the code.
|
||||
- Collections: every directory under `kb/` has a `COLLECTION.md` and no directory outside it does; every collection declares `profile:` and a `required_by_stack:` that agrees with the stack's own list.
|
||||
- Types: every type the stack lists (currently `source` and `project`) has a type-spec of that name whose schema requires the field the stack list names (`raw_files:`/`state:`); every file under `types/` declaring `type: types/type-spec.md` validates against `types/type-spec.schema.yaml`; every subtype template `types/<type>.<value>.md` (any `<value>` but `guidance`) sits beside a type-spec declaring `subtype_field:`, names a value that field's schema enum allows, and carries no frontmatter; no pre-migration `type: entity` blocks are left in the contracts.
|
||||
- `kb/CONVENTIONS.md`, if it exists at all, names all three tool-owned section headings; every stage contract is present.
|
||||
- The `.gitignore` canaries clear in both directions: nothing ignored under `raw/`/`kb/`, `incoming/` ignored, everything ignored under `reports/` and the published skill directories.
|
||||
- The `.gitignore` canaries clear in both directions: nothing ignored under `raw/`/`kb/`, `incoming/` ignored, everything ignored under `reports/` and the published skill directories, `.wikitool-local.json` ignored and `wikitool.json` tracked.
|
||||
- A `wikitool.json` at the root holds every value in the place its tier allows - no secret and no private field as plain text, no `checkout` field at all except as a reference - and a well-formed `schema` and `instance_id`. The local file is not read.
|
||||
- No `.md`/`.template` file `dist export` would ship cites an issue number. A `<!-- dist:strip-start/end -->` region is exempt: the check reads the export plan's text, from which it is already gone.
|
||||
- Every reference file `docs toc` covers carries the current table-of-contents region for its own headings - missing and stale are one check.
|
||||
- Every relative markdown link in one of those reference files resolves to an existing file. A target's `#anchor` suffix is stripped first, and code fences and inline code spans are masked before scanning, so link syntax shown as an example is not mistaken for a real reference.
|
||||
@@ -3658,6 +3663,68 @@ Declare `kb_version` once, for an instance predating `.wikitool-kb.json`.
|
||||
- `wikitool migrate done` - advances the version after a migration
|
||||
- `wikitool migrate status` - what is owed from the declared version
|
||||
|
||||
### Configuration
|
||||
|
||||
#### `config set`
|
||||
|
||||
Set one value of the tiered settings, in the file its tier names.
|
||||
|
||||
**SYNOPSIS**
|
||||
|
||||
- `wikitool config set <section>.<field> <value>`
|
||||
- `wikitool config set <section>.<field> --ref <name|op://vault/item/field>`
|
||||
|
||||
**PROPERTIES**
|
||||
|
||||
- effect: write
|
||||
- idempotent: yes
|
||||
- atomic: Each file is replaced in one rename; both are checked before either is written
|
||||
- budget: counted
|
||||
- network: no
|
||||
|
||||
**EXAMPLES**
|
||||
|
||||
- `tools/wikitool config set tracker.stale_days 14`
|
||||
- `tools/wikitool config set tracker.token --ref tracker_token`
|
||||
- `tools/wikitool config set tracker.url --ref op://Chemenu/tracker/url`
|
||||
|
||||
**EXIT STATUS**
|
||||
|
||||
- 0 success
|
||||
- 1 The key names no registered section or field, or is not `<section>.<field>`
|
||||
- 1 A plain value given for a field of tier `secret`
|
||||
- 1 `--ref` given for a field that takes a plain value, or a malformed reference
|
||||
- 1 The value is not of the field's type, or the files would not pass their check afterwards
|
||||
- 42 The field names a program to run or affects a gate
|
||||
|
||||
**ON FAILURE**
|
||||
|
||||
- The key names no registered section or field, or is not `<section>.<field>` -> Use a key from the list the message prints; `docs/reference/configuration.md` describes the sections
|
||||
- A plain value given for a field of tier `secret` -> Do not retry with the value. Ask the user to put it into `WIKITOOL_SECRET_<NAME>`, the secrets file or 1Password, then set the field with `--ref`
|
||||
- `--ref` given for a field that takes a plain value, or a malformed reference -> Give the value itself, or fix the reference to `<name>` (lower case, digits, `_`) or `op://<vault>/<item>/<field>`
|
||||
- The value is not of the field's type, or the files would not pass their check afterwards -> Fix the value or the problem the message names in the file it names, then re-run once
|
||||
- The field names a program to run or affects a gate -> Show the user the output verbatim and stop. Only the user sets this field, by editing `.wikitool-local.json` themselves
|
||||
|
||||
**NEVER**
|
||||
|
||||
- Never pass a secret's value on the command line - not to this command and not to any other.
|
||||
- Never read the secrets file or run `op read` yourself to see a value.
|
||||
|
||||
**NOTES**
|
||||
|
||||
- Writes a plain value of a field of tier `instance` into `wikitool.json`, and one of tier `checkout` - a private field's included - into `.wikitool-local.json`.
|
||||
- With `--ref`, writes a reference instead of a value into `wikitool.json`: `<name>` resolves through `WIKITOOL_SECRET_<NAME>`, then the secrets file in the user's configuration directory; `op://<vault>/<item>/<field>` resolves through the 1Password CLI. Only a secret or private field takes one.
|
||||
- Removes the same key from the other file, so a value never has two places, and says so.
|
||||
- Creates `wikitool.json` with a fresh `instance_id` the first time it writes anything; the secrets file is found by that id.
|
||||
- Checks both files as they would stand after the write against every registered section, and writes nothing when that fails.
|
||||
- Prints the key and the file it wrote, never the value. Resolves no reference.
|
||||
|
||||
**SEE ALSO**
|
||||
|
||||
- `wikitool doctor` - whether both files pass and every reference resolves
|
||||
- `docs/reference/configuration.md` - the files, the tiers and the references
|
||||
- `docs/how-to/use-1password-for-settings.md` - setting 1Password up as the source
|
||||
|
||||
### Instance health
|
||||
|
||||
#### `doctor`
|
||||
@@ -3704,6 +3771,7 @@ Check that this instance is correctly configured.
|
||||
- Task tracker: `.wikitool-tasks.json` present, absent or malformed - absent is `OK` (no tracker configured), malformed is a `FAIL`. When `WIKITOOL_TASKS_CONFIG` is set, that file is read instead and the finding names it; a set variable that names no file is a `FAIL`, never `OK`.
|
||||
- For a configured `superproductivity` provider, the configured `access` path's own state: `access: "api"` reports whether its local REST API answers `GET /health` with a ready renderer right now, `access: "snapshot"` whether a backup file is ready. The other access path is never attempted, and neither state is ever a `FAIL`.
|
||||
- For a configured `caldav` provider, whether the server is reachable and Basic auth succeeds - never a `FAIL`; only a broken config block is.
|
||||
- Settings (`settings-instance`, `settings-checkout`, `settings-secrets`): one line per tier. `wikitool.json` and `.wikitool-local.json` each present or absent - absent is `OK` - and a `FAIL` naming file, key and the right tier when a value sits in the wrong file, a secret or a committed private field holds a plain value, or a value fails its field; a section this version does not read is a `WARN`. For the references: how many resolve, never a value - an unresolvable one is a `FAIL`, one 1Password will not hand out until a human unlocks it a `WARN`.
|
||||
- Session id source: `OK` for `WIKITOOL_SESSION_ID` or a registered harness variable, `WARN` only for the bare parent-pid fallback.
|
||||
- Telemetry: on or off and why - installation-form default, `.wikitool-telemetry.json`, or `WIKI_TRACE` - and the current session's count and byte total against both caps; never a `FAIL`. A `WARN` when `.wikitool-telemetry.json` is not read as written - unreadable JSON, not an object, `enabled` not a JSON boolean, a cap not a positive integer, or an unknown key - naming the field; telemetry itself drops or reinterprets such a value without a word, so this is where it shows.
|
||||
- Exits 1 only on a `FAIL`; a missing remote, session id or `VERSION` is a `WARN`, not a fault.
|
||||
@@ -3713,7 +3781,7 @@ Check that this instance is correctly configured.
|
||||
|
||||
- `instructions/setup-instance.md` - the setup steps most findings point back to
|
||||
- `instructions/preflight.md` - what `tool-paths` and `install-dir` point back to
|
||||
- `docs/reference/configuration.md` - the per-checkout configuration files
|
||||
- `docs/reference/configuration.md` - the per-checkout configuration files and the tiered settings
|
||||
- `docs/explanation/telemetry-and-evaluation.md` - telemetry state and caps
|
||||
- `instructions/session-setup.md` - setting `WIKITOOL_SESSION_ID`
|
||||
<!-- /wikitool:commands -->
|
||||
|
||||
Reference in new issue
Block a user