Compare commits

...
5 Commits
Author SHA1 Message Date
fraujulian 4865bea481 docs(git): require git commands for commits and pushes
CI / Capabilities and shell quality (push) Successful in 14s
CI / Python tests and compilation (push) Successful in 13s
CI / PowerShell tests on Ubuntu (push) Failing after 41s
CI / CI configuration security checks (push) Successful in 4s
CI / Build and inspect generated packages (push) Successful in 9s
CI / Bash integration and installation guards (push) Canceled after 0s
CI / Installed client configuration smoke tests (push) Canceled after 0s
CI / Qwen retrieval integration (push) Canceled after 2m9s
2026-09-25 18:04:35 +02:00
fraujulian 1f3ff6576c chore: remove todo ledger 2026-09-25 17:54:15 +02:00
fraujulian e16eeefe3b docs(agents): separate review from verification 2026-09-25 17:53:58 +02:00
fraujulian def30779c8 docs(mcp): clarify native and mcporter routing 2026-09-25 17:53:35 +02:00
fraujulian 0d771c7ee3 chore(prompt-budget): separate soft target from hard limit 2026-09-25 17:52:35 +02:00
10 changed files with 17 additions and 55 deletions

No files matched your search

-39
View File
@@ -1,39 +0,0 @@
# TODO
## Data loss and security
- [x] Validate every path read from `.ai-config-manifest.tsv` and reject links before backup, overwrite, or removal. Both manifest writers join unchecked recorded paths to the destination; a `../` entry or linked target can reach files outside the managed directory. (`scripts/lib/manifest.ps1:20`, `scripts/lib/manifest.ps1:136`, `scripts/lib/manifest.sh:20`, `scripts/lib/manifest.sh:170`)
- [x] Keep an installed semantic retrieval runtime when an `auto` benchmark says no. `benchmark()` deletes the whole runtime and ownership state even when `state['clients']` still contains active clients. (`scripts/lib/semantic-retrieval.py:117`, `scripts/lib/semantic-retrieval.py:142`)
- [x] Check semantic retrieval ownership and links before copying or deleting its directory. An existing owned runtime's source files are overwritten without comparing recorded hashes; a replaced target symlink is followed on enable, and disabling the last client removes foreign files inside the runtime. (`scripts/lib/semantic-retrieval.py:82`, `scripts/lib/semantic-retrieval.py:100`)
- [x] Preserve pre-existing MCPorter server entries. `ensure_mcporter()` adds a server and claims ownership without checking existing configuration; if the add succeeds for an existing name, a later removal deletes that user's entry. (`scripts/lib/managed-extensions.py:395`, `scripts/lib/managed-extensions.py:263`)
- [x] Preserve pre-existing global CLI packages. `ensure_cli()` and `ensure_qmd()` install and claim npm packages without checking whether they were already installed; later removal can uninstall a user's package. (`scripts/lib/managed-extensions.py:342`, `scripts/lib/managed-extensions.py:378`)
- [x] Fetch skill archives by an immutable commit and record that same commit. The archive uses GitHub `HEAD`, while `resolvedRevision` comes from a separate later request, so the recorded revision may not identify the installed payload. (`scripts/lib/managed-extensions.py:94`, `scripts/lib/managed-extensions.py:140`, `scripts/lib/managed-extensions.py:409`)
- [x] Protect the semantic retrieval daemon's IPC protocol. It uses a hardcoded authentication key and `multiprocessing.connection.recv()`, which deserializes messages; a process that can reach its socket or pipe can submit arbitrary roots and potentially crafted objects. Use a private per-install credential and a non-pickle wire format, or restrict the endpoint to the current user. (`shared/retrieval/server.py:47`, `shared/retrieval/server.py:306`, `shared/retrieval/server.py:314`)
- [x] Write semantic retrieval ownership state atomically. `save_state()` replaces the JSON with a direct write, unlike the extension and selection ledgers; interruption can leave it unreadable and block later reconciliation. (`scripts/lib/semantic-retrieval.py:63`)
## Menus and reconciliation
- [x] Build update-menu checks per client when `Both` is selected. Both menus inspect Claude's installed plugins for every entry, so a Codex resource can start unchecked and the combined sync can remove it. (`scripts/lib/plugins.ps1:98`, `scripts/lib/plugins.sh:108`)
- [x] Keep shared MCPorter servers until neither client needs them. Reconciliation processes `shared` records even when only one client is selected; uninstalling that client with an empty selection removes servers still used by the other. (`scripts/lib/managed-extensions.py:463`, `scripts/commands/uninstall.ps1:59`, `scripts/commands/uninstall.sh:77`)
- [x] Manage global packages once across clients. With `--client both`, MCPorter is installed and recorded twice; QMD's global package can be removed during a Codex-only deselection while Claude still uses its plugin. (`scripts/lib/managed-extensions.py:342`, `scripts/lib/managed-extensions.py:378`, `scripts/lib/managed-extensions.py:463`)
- [x] Fix Bash `auto` semantic retrieval selection. Both `test_semantic_retrieval_device()` and its caller read `$?` after a completed `if`, losing the benchmark's exit code; an unsuitable device produces an empty choice instead of `false`. (`scripts/lib/semantic-retrieval.sh:13`, `scripts/lib/install-options.sh:52`)
- [x] Make ordinary update dry-runs use the saved/current selection. Both menus bypass selection in dry-run and select every manifest entry, so the preview can diverge from the real update. (`scripts/lib/plugins.ps1:91`, `scripts/lib/plugins.sh:97`)
- [x] Reconcile resources whose ownership record remains but whose installation was removed manually. `ensure_cli()` and `ensure_mcporter()` return early from a ledger record without checking the actual CLI or server; normal sync cannot restore the missing resource. (`scripts/lib/managed-extensions.py:342`, `scripts/lib/managed-extensions.py:395`)
- [x] Update owned MCPorter itself on `--update`. `ensure_cli()` returns whenever its ledger record exists, so a selected MCPorter package never receives the requested update. (`scripts/lib/managed-extensions.py:342`)
- [x] Keep terminal newlines in Bash-managed files that need substitution. Command substitution strips trailing newlines before Bash hashes and writes the content, while PowerShell retains them; switching installers causes needless file changes and backups. (`scripts/lib/manifest.sh:70`, `scripts/lib/manifest.ps1:75`)
- [x] Parse the Bash plugin inventory as JSON and stop when listing fails. `plugin_installed()` searches for one exact spacing pattern and suppresses CLI errors; a minified response or listing failure marks installed plugins unchecked, allowing an update to remove owned plugins. PowerShell parses JSON and fails on a CLI error. (`scripts/lib/plugins.sh:4`, `scripts/lib/plugins.ps1:36`)
- [x] Serialize Bash manifest entries without shell word splitting. `write_managed_manifest()` loops over command substitution; a managed filename containing spaces becomes multiple invalid entries and can no longer be reconciled correctly. (`scripts/lib/manifest.sh:47`)
- [x] Allow uninstall to reconcile owned extensions when file manifests are missing. Both uninstall commands stop with “Not installed” based only on destination manifests, even if `extensions.json` still owns plugins, skills, or MCP servers. (`scripts/commands/uninstall.ps1:21`, `scripts/commands/uninstall.sh:34`)
## Rules, checks, and documentation
- [x] Make `jq` conditional in capability checks. Both checks fail when it is absent, although the runtime doctor only warns and the requirement is limited to Claude's Bash status line. (`scripts/commands/check-capabilities.ps1:12`, `scripts/commands/check-capabilities.sh:19`, `README.md:110`)
- [x] Review the global MCPorter-only rule's failure behavior. It prohibits all direct MCP use and requires stopping when MCPorter is unavailable, even for a user-authorized native connection; decide whether this restriction should be scoped to managed servers. (`shared/global-instructions.md:7`)
- [x] Align Context7 selection with the MCPorter-only rule. If Context7 is selected without MCPorter, reconciliation installs its native client plugin even though the generated instructions forbid using native MCP connections. Either require MCPorter for this entry or change the rule and menu together. (`scripts/lib/managed-extensions.py:465`, `adapters/plugins.tsv:5`, `shared/global-instructions.md:7`)
- [x] Clarify the decision rule for minor reversible UI choices. Its broad instruction to ask when UI/UX behavior is open to interpretation can block routine choices that `general.md` says to make independently unless materially ambiguous. (`shared/rules/decision-rule.md:6`, `shared/rules/general.md:5`)
- [x] Review the permanent-prompt budget thresholds. Both baselines and absolute limits are 6000 bytes, so the advertised 15% relative allowance can never be used; even a small increase past 6000 fails. Decide whether the hard cap or the relative allowance is intended. (`adapters/prompt-budget-baseline.json:1`, `adapters/prompt-budget-baseline.tsv:2`, `scripts/commands/prompt-budget.ps1:26`, `scripts/commands/prompt-budget.sh:20`)
- [x] Correct QMD documentation. It says Codex registers `qmd mcp` and deselection leaves the global executable, while the manager does not register that MCP server and removes owned QMD npm packages. (`docs/plugins.md:17`, `scripts/lib/managed-extensions.py:378`)
- [x] Include source/script changes in Bash repository-context invalidation. Its cache key hashes only `AI-Instructions.md` and `adapters/`, while the PowerShell variant also hashes source scripts; Bash can keep stale context after an uncommitted script or rule edit. (`scripts/commands/repository-context.sh:7`, `scripts/commands/repository-context.ps1:9`)
- [x] Correct the optional command-safety utility description or add the missing Bash check. Documentation says both variants check outside-workspace paths, but only the PowerShell variant attempts that check. The utility is currently unregistered. (`docs/hooks.md:17`, `shared/hooks/scripts/validate-command-safety.sh:4`, `shared/hooks/scripts/Validate-CommandSafety.ps1:4`)
- [x] Align doctor checks across shells. PowerShell checks whether Codex and Claude Stop hooks are registered; Bash omits this check, so the same installation can produce different diagnostics. (`scripts/commands/doctor.ps1:87`, `scripts/commands/doctor.sh:98`)
- [x] Update the documented Claude status-line example to include the `Review` field printed by both implementations. (`docs/configuration.md:24`, `shared/statusline/statusline.ps1:40`, `shared/statusline/statusline.sh:70`)
+1 -1
View File
@@ -1 +1 @@
{"Claude permanent context":6000,"Codex permanent context":6000,"Claude permanent context absolute limit":6900,"Codex permanent context absolute limit":6900}
{"Claude permanent context":4000,"Codex permanent context":4000,"Claude permanent context absolute limit":6000,"Codex permanent context absolute limit":6000}
+2 -2
View File
@@ -1,2 +1,2 @@
Claude 6000 6900
Codex 6000 6900
Claude 4000 6000
Codex 4000 6000
1 Claude 4000 6900 6000
2 Codex 4000 6900 6000
+2 -2
View File
@@ -5,8 +5,8 @@ The five shared agents are logical roles, not mandatory steps.
- `implementer` executes the smallest complete engineering change and performs self-review.
- `researcher` investigates code, patterns, evidence, alternatives, and unknowns without modifying implementation code by default.
- `architect` evaluates technical boundaries, dependencies, interfaces, constraints, and design options.
- `verifier` supplies execution evidence from relevant tests, builds, checks, generated output, and behavior reproduction. It does not repeat a general architecture review.
- `reviewer` starts with the actual diff and changed symbols, then examines necessary callers, dependencies, tests, and contracts for analytical correctness. It does not automatically rerun the test suite.
- `verifier` supplies execution evidence from relevant tests, builds, checks, generated output, and behavior reproduction. It inspects implementation only to choose checks and does not review the diff for general correctness.
- `reviewer` starts with the actual diff and changed symbols, then examines necessary callers, dependencies, tests, and contracts for analytical correctness. It does not run tests, builds, or runtime checks; it reports missing execution evidence.
Use only the roles that are likely to improve the outcome. Choose `researcher`, `reviewer`, and `verifier` based on the task's uncertainty, complexity, risk, blast radius, and verification value; none runs automatically. The agent may make evidence-based, reversible technical decisions. Ask the user when technical choices remain materially uncertain or when business behavior, user-visible behavior, UI, UX, APIs, database models, configuration formats, compatibility behavior, or other high-impact decisions are ambiguous or open to interpretation.
+3 -3
View File
@@ -24,11 +24,11 @@ if ($old) {
$previous = [double]$old.($row.Name)
$absolute = [double]$old.(($row.Name + ' absolute limit'))
$baselineValues[$row.Name] = @($previous, $absolute)
if ($previous -gt 0 -and $row.Bytes -gt $previous * 1.15) { $fail = $true; Write-Error "Prompt budget relative limit failed: $($row.Name) $($row.Bytes) bytes (baseline $previous, limit 15%)." }
if ($absolute -gt 0 -and $row.Bytes -gt $absolute) { $fail = $true; Write-Error "Prompt budget absolute limit failed: $($row.Name) $($row.Bytes) bytes (absolute limit $absolute)." }
if ($previous -gt 0 -and $row.Bytes -gt $previous * 1.15) { Write-Warning "Prompt budget soft target exceeded: $($row.Name) $($row.Bytes) bytes (target $previous, 15% tolerance)." }
if ($absolute -gt 0 -and $row.Bytes -gt $absolute) { $fail = $true; Write-Error "Prompt budget hard limit failed: $($row.Name) $($row.Bytes) bytes (hard limit $absolute)." }
}
}
if ($Summary) { Write-Output 'Prompt Budget'; foreach ($row in $rows | Select-Object -First 2) { $limits = $baselineValues[$row.Name]; $base = if($limits){$limits[0]}else{'-'}; $absolute = if($limits){$limits[1]}else{'-'}; Write-Output ('{0,-28} {1,8} bytes baseline {2} relative 115% absolute {3}' -f $row.Name,$row.Bytes,$base,$absolute) }; $rows | Select-Object -Skip 2 | ForEach-Object { Write-Output ('{0,-28} {1,8} bytes {2,6} tokens' -f $_.Name,$_.Bytes,$_.Tokens) } } else { $rows | ForEach-Object { Write-Output ('{0}: {1} bytes / {2} tokens' -f $_.Name,$_.Bytes,$_.Tokens) } }
if ($Summary) { Write-Output 'Prompt Budget'; foreach ($row in $rows | Select-Object -First 2) { $limits = $baselineValues[$row.Name]; $base = if($limits){$limits[0]}else{'-'}; $absolute = if($limits){$limits[1]}else{'-'}; Write-Output ('{0,-28} {1,8} bytes soft target {2} hard limit {3}' -f $row.Name,$row.Bytes,$base,$absolute) }; $rows | Select-Object -Skip 2 | ForEach-Object { Write-Output ('{0,-28} {1,8} bytes {2,6} tokens' -f $_.Name,$_.Bytes,$_.Tokens) } } else { $rows | ForEach-Object { Write-Output ('{0}: {1} bytes / {2} tokens' -f $_.Name,$_.Bytes,$_.Tokens) } }
& python (Join-Path $root 'scripts/lib/prompt-inventory.py') --home ([Environment]::GetFolderPath('UserProfile'))
if ($LASTEXITCODE -ne 0) { throw 'Prompt inventory failed.' }
if ($fail) { exit 1 }
+4 -4
View File
@@ -16,11 +16,11 @@ if [ -f "$root/adapters/prompt-budget-baseline.tsv" ]; then
current=$([ "$name" = Claude ] && printf '%s' "$claude" || printf '%s' "$codex")
[ "$name" = Claude ] && claude_baseline=$old && claude_absolute=$absolute
[ "$name" = Codex ] && codex_baseline=$old && codex_absolute=$absolute
if awk -v n="$current" -v o="$old" 'BEGIN { exit !(o > 0 && n > o * 1.15) }'; then printf 'Prompt budget relative limit failed: %s %s bytes (baseline %s, limit 15%%).\n' "$name" "$current" "$old" >&2; fail=true; fi
if awk -v n="$current" -v a="$absolute" 'BEGIN { exit !(a > 0 && n > a) }'; then printf 'Prompt budget absolute limit failed: %s %s bytes (absolute limit %s).\n' "$name" "$current" "$absolute" >&2; fail=true; fi
if awk -v n="$current" -v o="$old" 'BEGIN { exit !(o > 0 && n > o * 1.15) }'; then printf 'Prompt budget soft target exceeded: %s %s bytes (target %s, 15%% tolerance).\n' "$name" "$current" "$old" >&2; fi
if awk -v n="$current" -v a="$absolute" 'BEGIN { exit !(a > 0 && n > a) }'; then printf 'Prompt budget hard limit failed: %s %s bytes (hard limit %s).\n' "$name" "$current" "$absolute" >&2; fail=true; fi
done < "$root/adapters/prompt-budget-baseline.tsv"
fi
if [ "$summary" = true ]; then printf 'Prompt Budget\nClaude permanent context %8s bytes baseline %s relative 115%% absolute %s\nCodex permanent context %8s bytes baseline %s relative 115%% absolute %s\nClaude skill files (lazy) %8s bytes %6s tokens\nLargest lazy rule %8s bytes %6s tokens\n' "$claude" "$claude_baseline" "$claude_absolute" "$codex" "$codex_baseline" "$codex_absolute" "$skills" "$(tokens "$skills")" "$lazy" "$(tokens "$lazy")"; else printf 'Prompt budget: Claude %s bytes, Codex %s bytes, skills %s bytes, largest lazy rule %s bytes\n' "$claude" "$codex" "$skills" "$lazy"; fi
if [ "$summary" = true ]; then printf 'Prompt Budget\nClaude permanent context %8s bytes soft target %s hard limit %s\nCodex permanent context %8s bytes soft target %s hard limit %s\nClaude skill files (lazy) %8s bytes %6s tokens\nLargest lazy rule %8s bytes %6s tokens\n' "$claude" "$claude_baseline" "$claude_absolute" "$codex" "$codex_baseline" "$codex_absolute" "$skills" "$(tokens "$skills")" "$lazy" "$(tokens "$lazy")"; else printf 'Prompt budget: Claude %s bytes, Codex %s bytes, skills %s bytes, largest lazy rule %s bytes\n' "$claude" "$codex" "$skills" "$lazy"; fi
python3 "$root/scripts/lib/prompt-inventory.py" --home "${HOME:?HOME is required}"
$fail && { printf 'Prompt budget: permanent context increased by more than 15 percent.\n' >&2; exit 1; }
$fail && { printf 'Prompt budget: permanent context exceeded hard limit.\n' >&2; exit 1; }
exit 0
+2 -2
View File
@@ -1,7 +1,7 @@
# Reviewer
Provide analytical correctness review using the acceptance criteria and actual git diff. Inspect changed symbols first, then direct callers, dependencies, tests, and contracts needed to judge correctness. Expand for shared state, configuration, persistence, security, generated code, or public API effects; avoid broad repository exploration by default.
Provide static and semantic correctness review using the acceptance criteria and actual git diff. Inspect changed symbols first, then direct callers, dependencies, tests, and contracts needed to judge correctness. Expand for shared state, configuration, persistence, security, generated code, or public API effects; avoid broad repository exploration by default. Do not run tests, builds, or runtime checks; identify missing execution evidence for the parent or verifier instead.
For each finding, report SEVERITY (blocking, important, or minor), LOCATION, IMPACT, EVIDENCE, and SCOPE (introduced, pre-existing, or uncertain). Do not report stylistic preferences or pre-existing issues unless they materially affect the requested change. Prioritize actionable correctness defects, keep unrelated cleanup out of scope, and use blocking only for security, data-loss, broken contracts, or deterministic failures.
Check logic, regressions, architecture, maintainability, security, and contract consistency. Do not automatically rerun the full test suite or duplicate a verifier's evidence. Follow the shared orchestration handoff protocol; report actionable findings with severity and evidence. Do not modify implementation code unless assigned.
Check logic, regressions, architecture, maintainability, security, and contract consistency. Do not execute checks or duplicate a verifier's evidence. Follow the shared orchestration handoff protocol; report actionable findings with severity and evidence. Do not modify implementation code unless assigned.
+1 -1
View File
@@ -1,5 +1,5 @@
# Verifier
Provide execution evidence against acceptance criteria. Start with changed paths and relevant test/build commands; choose the smallest sufficient tests, builds, checks, generated-output validation, or behavior reproduction. Reuse valid earlier results instead of repeating checks.
Provide execution evidence against acceptance criteria. Start with the requested behavior and relevant test/build commands; inspect only enough implementation to choose the smallest sufficient checks. Run tests, builds, checks, generated-output validation, or behavior reproduction as needed. Reuse valid earlier results instead of repeating checks. Do not perform a static review of the diff; report implementation concerns only when they block or explain execution results.
Report commands, outcomes, failures, and unverified areas using the shared orchestration handoff protocol. Do not perform a second general architecture review unless execution exposes a design issue. Do not change implementation code unless assigned.
+1 -1
View File
@@ -20,6 +20,6 @@ Cross-cutting: unclear requirements or significant choices => `rules/decision-ru
## Tools and delegation
Use the `mcporter` CLI for MCP services by default. Use a native MCP connection when MCPorter is not active, or when the user explicitly requests it or selects a native MCP plugin in this configuration. If the requested route is unavailable, report the limitation instead of silently switching routes.
Use the `mcporter` CLI for MCP servers this configuration registers there, especially when the same server must work across Claude and Codex. Use a selected native plugin's MCP tools directly even when MCPorter is active; do not route them through an extra CLI hop or register the same server through both paths. Prefer native Codex plugin packaging when it provides the needed MCP server and skills together. Keep MCPorter where it provides a concrete shared benefit such as credential handling, discovery, or cross-client portability. If the selected route is unavailable, report the limitation instead of silently switching routes.
The main agent owns state and decisions. Delegate only independent work when it saves effort; use one implementer for contained work. Subagents do not spawn agents; pass minimal context and verify handoffs.
+1
View File
@@ -15,6 +15,7 @@
* Permission to push does not imply permission to create or merge a pull request.
* Only perform Git write operations that the user explicitly requested.
* Read-only Git commands may be used when needed to inspect repository state.
* Create commits only with `git commit` and push commits only with `git push`. Never create commits or publish repository code through REST APIs, hosting-provider APIs, or other non-Git interfaces.
## Repository Safety