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
+49
-3
@@ -537,6 +537,20 @@ foreach ($line in $ManifestLines) {
|
||||
}
|
||||
}
|
||||
|
||||
# Recorded when found, never asked for - see the manifest's own header.
|
||||
$Optional = @()
|
||||
foreach ($line in $ManifestLines) {
|
||||
$parts = $line.Split('|')
|
||||
if ($parts[0] -ne 'optional') {
|
||||
continue
|
||||
}
|
||||
if ($parts[1] -notmatch '^[a-z0-9]+$') {
|
||||
Write-ErrorLine "preflight: bad tool name '$($parts[1])' in $Manifest"
|
||||
exit 1
|
||||
}
|
||||
$Optional += $parts[1]
|
||||
}
|
||||
|
||||
function Get-InstallHint {
|
||||
param([string]$Tool)
|
||||
$choco = Get-ManifestField 'tool' $Tool 7
|
||||
@@ -696,8 +710,8 @@ function Get-SetValue {
|
||||
# --- --set: every named path has to work, or nothing is written -------------------
|
||||
|
||||
foreach ($name in $Sets.Keys) {
|
||||
if ($Tools -notcontains $name) {
|
||||
Write-ErrorLine "preflight: --set names '$name', which is not a tool this platform needs: $($Tools -join ' ')"
|
||||
if ($Tools -notcontains $name -and $Optional -notcontains $name) {
|
||||
Write-ErrorLine "preflight: --set names '$name', which is not a tool this platform needs: $($Tools -join ' ') (optional: $($Optional -join ' '))"
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
@@ -848,6 +862,38 @@ foreach ($tool in $Tools) {
|
||||
$Found[$tool] = $path
|
||||
}
|
||||
|
||||
# --- optional tools: recorded when found, never a problem when not ---------------
|
||||
|
||||
foreach ($tool in $Optional) {
|
||||
$label = Get-ManifestField 'optional' $tool 3
|
||||
$given = Get-SetValue $tool
|
||||
$path = ''
|
||||
if ($given) {
|
||||
if (Test-Usable $given) {
|
||||
$path = $given
|
||||
} else {
|
||||
Add-Problem "The path given for $label does not work: $given" (Get-ManifestField 'optional' $tool 4) `
|
||||
"Check the path - it has to be the $tool executable itself.`nThen run: $Self --set $tool=<full path to $tool>"
|
||||
$script:BadSet = $true
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
$previous = Get-RecordedPath $tool
|
||||
if ($previous -and (Test-Usable $previous)) {
|
||||
$path = $previous
|
||||
} else {
|
||||
$path = [string](Find-OnPath $tool | Select-Object -First 1)
|
||||
}
|
||||
}
|
||||
if (-not $path) {
|
||||
Add-Report 'ABSENT' $tool '-' 'optional, not installed'
|
||||
continue
|
||||
}
|
||||
$version = Get-VersionOf ([string](Invoke-Native -Path $path -Arguments @('--version')))
|
||||
Add-Report 'OK' $tool $(if ($version) { $version } else { '-' }) $path
|
||||
$Found[$tool] = $path
|
||||
}
|
||||
|
||||
# --- install folder length (Windows, long paths off) ------------------------------
|
||||
|
||||
if ($Platform -eq 'windows' -and -not (Test-LongPathsEnabled)) {
|
||||
@@ -945,7 +991,7 @@ function Write-ToolsFile {
|
||||
$flag = if ($Complete) { 'true' } else { 'false' }
|
||||
$text = "{`n `"schema`": 1,`n `"complete`": $flag,`n `"tools`": {"
|
||||
$separator = ''
|
||||
foreach ($tool in $Tools) {
|
||||
foreach ($tool in @($Tools) + @($Optional)) {
|
||||
if ($Found.ContainsKey($tool)) {
|
||||
$text += "$separator`n `"$tool`": `"$(ConvertTo-JsonString $Found[$tool])`""
|
||||
$separator = ','
|
||||
|
||||
Reference in new issue
Block a user