@arbiterforge/ca-pi 0.15.12 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/package.json +1 -1
- package/plugins/ca-pi/CHANGELOG.md +26 -0
- package/plugins/ca-pi/SKILLS.md +1 -1
- package/plugins/ca-pi/agents/infra-author.md +7 -1
- package/plugins/ca-pi/agents/scout.md +40 -8
- package/plugins/ca-pi/generated/command-catalog.json +1 -1
- package/plugins/ca-pi/helpers/artifacts/ca-artifact-darwin-amd64 +0 -0
- package/plugins/ca-pi/helpers/artifacts/ca-artifact-darwin-arm64 +0 -0
- package/plugins/ca-pi/helpers/artifacts/ca-artifact-linux-amd64 +0 -0
- package/plugins/ca-pi/helpers/artifacts/ca-artifact-linux-arm64 +0 -0
- package/plugins/ca-pi/helpers/artifacts/ca-artifact-windows-amd64.exe +0 -0
- package/plugins/ca-pi/helpers/artifacts/ca-artifact-windows-arm64.exe +0 -0
- package/plugins/ca-pi/helpers/artifacts/release.json +104 -6
- package/plugins/ca-pi/hooks/_activationlib.py +97 -13
- package/plugins/ca-pi/hooks/_arbiterstatelib.py +7 -2
- package/plugins/ca-pi/hooks/_artifactauthoritylib.py +206 -2
- package/plugins/ca-pi/hooks/_artifactlib.py +166 -2
- package/plugins/ca-pi/hooks/_artifactpromptlib.py +106 -2
- package/plugins/ca-pi/hooks/_bashguardlib.py +14 -0
- package/plugins/ca-pi/hooks/_contextreportlib.py +564 -6
- package/plugins/ca-pi/hooks/_contextselectlib.py +464 -0
- package/plugins/ca-pi/hooks/_contextsnapshotlib.py +999 -0
- package/plugins/ca-pi/hooks/_debughandofflib.py +767 -0
- package/plugins/ca-pi/hooks/_hooklib.py +1 -0
- package/plugins/ca-pi/hooks/_host.py +1 -1
- package/plugins/ca-pi/hooks/_intentlib.py +5 -5
- package/plugins/ca-pi/hooks/_protectedlib.py +3 -3
- package/plugins/ca-pi/hooks/_protectedstatelib.py +152 -2
- package/plugins/ca-pi/hooks/_provenancelib.py +604 -34
- package/plugins/ca-pi/hooks/_readinjectlib.py +131 -1
- package/plugins/ca-pi/hooks/artifact-authority.py +20 -1
- package/plugins/ca-pi/hooks/debug-handoff.py +85 -0
- package/plugins/ca-pi/hooks/doctor.py +4 -2
- package/plugins/ca-pi/hooks/hostapi.py +1 -1
- package/plugins/ca-pi/hooks/init-codearbiter.py +143 -15
- package/plugins/ca-pi/hooks/prompt-submit.py +14 -0
- package/plugins/ca-pi/hooks/session-start.py +26 -7
- package/plugins/ca-pi/includes/author-tdd-workflow.md +16 -4
- package/plugins/ca-pi/includes/helper-invocation.md +128 -0
- package/plugins/ca-pi/includes/pi-host-notes.md +13 -0
- package/plugins/ca-pi/includes/routing-table.md +1 -1
- package/plugins/ca-pi/package.json +1 -1
- package/plugins/ca-pi/routines/INDEX.md +1 -1
- package/plugins/ca-pi/routines/commit-gate/SKILL.md +5 -3
- package/plugins/ca-pi/routines/context-check/SKILL.md +103 -17
- package/plugins/ca-pi/routines/context-creation/SKILL.md +290 -54
- package/plugins/ca-pi/routines/debug/SKILL.md +303 -55
- package/plugins/ca-pi/routines/debug/references/debug-handoff.schema.json +879 -0
- package/plugins/ca-pi/routines/debug/references/handoff.md +155 -0
- package/plugins/ca-pi/routines/decompose/SKILL.md +13 -0
- package/plugins/ca-pi/routines/subagent-driven-development/SKILL.md +34 -0
- package/plugins/ca-pi/routines/tdd/SKILL.md +91 -17
- package/plugins/ca-pi/skills/ca-commit/SKILL.md +5 -3
- package/plugins/ca-pi/skills/ca-context-check/SKILL.md +103 -17
- package/plugins/ca-pi/skills/ca-create-context/SKILL.md +290 -54
- package/plugins/ca-pi/skills/ca-debug/SKILL.md +303 -55
- package/plugins/ca-pi/skills/ca-decompose/SKILL.md +13 -0
- package/plugins/ca-pi/skills/ca-feature/SKILL.md +1 -1
- package/plugins/ca-pi/skills/ca-fix/SKILL.md +36 -3
- package/plugins/ca-pi/skills/ca-init/SKILL.md +19 -0
- package/plugins/ca-pi/skills/ca-review/SKILL.md +33 -4
- package/plugins/ca-pi/skills/ca-status/SKILL.md +5 -0
- package/plugins/ca-pi/skills/ca-task/SKILL.md +55 -8
|
@@ -34,7 +34,7 @@ sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
|
|
34
34
|
import hostapi # noqa: E402 — host seam (ADR-0011): plugin root + capability flags
|
|
35
35
|
from _durabilitylib import is_ephemeral_path # noqa: E402
|
|
36
36
|
from _hooklib import ( # noqa: E402
|
|
37
|
-
frontmatter_enabled, get_host, marker_root, project_root, set_host,
|
|
37
|
+
frontmatter_enabled, get_host, initialized_body_text, marker_root, project_root, set_host,
|
|
38
38
|
utf8_stdio, write_text_atomic,
|
|
39
39
|
)
|
|
40
40
|
from _standuplib import ( # noqa: E402
|
|
@@ -59,7 +59,6 @@ import _updatelib # noqa: E402 — update-available notifier (cache read + noti
|
|
|
59
59
|
from _modelib import _DEV_PENDING_CLOSE_MAX, _settle_dev_close # noqa: E402,F401
|
|
60
60
|
import _modelib # noqa: E402
|
|
61
61
|
|
|
62
|
-
INITIALIZED_RE = re.compile(r"<!--\s*INITIALIZED\s*-->")
|
|
63
62
|
STAGE_RE = re.compile(r"^stage:\s*([0-9]+)", re.I | re.M)
|
|
64
63
|
CONFIRM_RE = re.compile(r"CONFIRM-[0-9]+")
|
|
65
64
|
|
|
@@ -853,7 +852,7 @@ def clear_mode_marker(root, host_name=None, session_id=None, now=None):
|
|
|
853
852
|
_settle_dev_close(root, marker=marker, new_line=line, host_name=host_name)
|
|
854
853
|
|
|
855
854
|
|
|
856
|
-
def provenance_drift_line(root, runner=None):
|
|
855
|
+
def provenance_drift_line(root, runner=None, report_unknown=False):
|
|
857
856
|
"""One-line SessionStart drift notice, or "" when clean/degraded.
|
|
858
857
|
|
|
859
858
|
Wraps _provenancelib.startup_drift_line; any failure degrades to "" so the
|
|
@@ -861,12 +860,26 @@ def provenance_drift_line(root, runner=None):
|
|
|
861
860
|
injectable so tests are deterministic/offline; production passes None which
|
|
862
861
|
lets the lib bind its default `git -C root hash-object` runner. (T-16)"""
|
|
863
862
|
try:
|
|
864
|
-
|
|
865
|
-
|
|
863
|
+
unknown = [] if report_unknown else None
|
|
864
|
+
line = _provenancelib.startup_drift_line(
|
|
865
|
+
root, runner=runner, cmd_ref=get_host().cmd_ref, unknown=unknown)
|
|
866
|
+
if report_unknown and unknown:
|
|
867
|
+
return "context coverage: unknown ({}) -- run {}".format(
|
|
868
|
+
unknown[0], get_host().cmd_ref("context-check"))
|
|
869
|
+
return line
|
|
866
870
|
except Exception: # noqa: BLE001 — never crash session startup
|
|
867
871
|
return ""
|
|
868
872
|
|
|
869
873
|
|
|
874
|
+
def context_coverage_line(root):
|
|
875
|
+
"""Bounded provenance coverage notice; no source hash or authority claim."""
|
|
876
|
+
try:
|
|
877
|
+
return _provenancelib.startup_context_coverage_line(
|
|
878
|
+
root, cmd_ref=get_host().cmd_ref)
|
|
879
|
+
except Exception: # noqa: BLE001 — never crash session startup
|
|
880
|
+
return "context coverage: unknown -- run /ca:context-check"
|
|
881
|
+
|
|
882
|
+
|
|
870
883
|
# --- Update-available notifier (spec: update-available-notifier.md) ---------
|
|
871
884
|
# codeArbiter ships via a third-party marketplace, which Claude Code does NOT
|
|
872
885
|
# auto-update by default. This surfaces a single line when the cached "latest"
|
|
@@ -1110,6 +1123,11 @@ def emit_daily_briefing(root, summary, date_iso, marker_present, ctx_text=None,
|
|
|
1110
1123
|
|
|
1111
1124
|
|
|
1112
1125
|
def main():
|
|
1126
|
+
# This is the ACTIVE host startup path. It may settle mode state, heal a
|
|
1127
|
+
# host-owned statusline pin, install Git enforcement, and spawn fetch/update
|
|
1128
|
+
# children. An unfamiliar repository must be inspected by the explicit-root
|
|
1129
|
+
# init --check --passive route BEFORE entering a host session; a later skill
|
|
1130
|
+
# cannot retroactively prevent SessionStart effects.
|
|
1113
1131
|
utf8_stdio()
|
|
1114
1132
|
# get_host() (#257): resolves the SAME Host run(host) already primed via
|
|
1115
1133
|
# set_host(), instead of a second hostapi.load_host() disk/probe.
|
|
@@ -1231,7 +1249,7 @@ def main():
|
|
|
1231
1249
|
emit_banner(getattr(host, "name", "unknown"), mode)
|
|
1232
1250
|
|
|
1233
1251
|
ctx_text = read_text(ctx) or ""
|
|
1234
|
-
if not
|
|
1252
|
+
if not initialized_body_text(ctx_text):
|
|
1235
1253
|
emit_not_initialized(root, host, mode)
|
|
1236
1254
|
sys.exit(0)
|
|
1237
1255
|
|
|
@@ -1246,8 +1264,9 @@ def main():
|
|
|
1246
1264
|
emit_task_summary(ot_text)
|
|
1247
1265
|
|
|
1248
1266
|
# --- Passive provenance drift notice (T-16, spec pillar 4) ---
|
|
1249
|
-
_drift = provenance_drift_line(root)
|
|
1267
|
+
_drift = provenance_drift_line(root, report_unknown=True)
|
|
1250
1268
|
emit_provenance_drift(_drift)
|
|
1269
|
+
emit_provenance_drift(context_coverage_line(root))
|
|
1251
1270
|
|
|
1252
1271
|
# --- Update-available notice (AC-1/AC-2/AC-3) --------------------------
|
|
1253
1272
|
_update = update_notice_line(plugin)
|
|
@@ -1,15 +1,27 @@
|
|
|
1
1
|
# Author TDD workflow — non-negotiable, fixed order
|
|
2
2
|
|
|
3
|
-
Canonical for the author agents (`backend-author`, `frontend-author`). Loaded via each agent's
|
|
3
|
+
Canonical for the author agents (`backend-author`, `frontend-author`, `infra-author`). Loaded via each agent's
|
|
4
4
|
Required Reading; the agent bodies do not restate it. This is the worker's execution order for
|
|
5
5
|
one task — the tdd skill's phase gates govern the lane above it.
|
|
6
6
|
Apply `<plugin-root>/includes/verification-boundary.md` throughout.
|
|
7
7
|
|
|
8
|
+
Use the Phase 1 checklist for the owning route. For a bug-origin `/fix`, carry the
|
|
9
|
+
current expectation, cited evidence, supported cause, and regression oracle into
|
|
10
|
+
the existing obligation ledger; confirm the original caller's repair authority and
|
|
11
|
+
source freshness through the fix owner. Do not fabricate a feature artifact. For
|
|
12
|
+
`/feature`, keep the approved spec and its criteria; for `/refactor`, keep its
|
|
13
|
+
approved surface and parity contract. An ADR remains a user-attributed decision
|
|
14
|
+
through `/adr`, never an author shortcut.
|
|
15
|
+
|
|
8
16
|
Fixed order. Do not skip or reorder.
|
|
9
17
|
|
|
10
|
-
1. **
|
|
11
|
-
2. **Confirm tests
|
|
18
|
+
1. **Map failing tests** — bind each Phase 1 obligation to a test ID. For `/fix`, assess an existing failing test against target red using the current regression oracle and evidence. Name the existing test ID in the ledger and reuse that named existing target-red test when its oracle is adequate and the assertion matches the defect. Do not duplicate a test because of its age or because it predates repair. Add tests only for uncovered obligations.
|
|
19
|
+
2. **Confirm tests are red for the right reason** — run the test command from `tech-stack.md`; the target failure must match the obligation. Record unrelated existing failures in the baseline; an unrelated failure is not target red. An import or setup error is not target red. Preserve and report their identities and outputs. Required commit gates remain blocked while required checks fail. Do not skip tests, suppress failures, or waive gates to proceed.
|
|
12
20
|
3. **Write minimum implementation** — only enough code to make the failing tests pass; no extra scope
|
|
13
|
-
4. **Run impact-bounded local suite** —
|
|
21
|
+
4. **Run impact-bounded local suite** — rerun the same named target test for fresh green on the repaired source, with its assertions unchanged between red and green. Rerun fresh affected-contract tests on that source and record their results; exhaustive and cross-platform proof runs in exact-head hosted CI before merge
|
|
14
22
|
5. **Run lint and type-check** — both clean
|
|
15
23
|
6. **Stage for commit** — only after steps 1–5 complete
|
|
24
|
+
|
|
25
|
+
For a repair, observe target red on the broken source before minimum implementation. If a material fixture or setup change occurs after that observation, the earlier red no longer qualifies: repeat target red on the broken implementation with the changed fixture or setup before continuing the repair. Keep the test's assertions unchanged between red and green.
|
|
26
|
+
|
|
27
|
+
For an intermittent or timing defect, use a faithful deterministic seam when one exists. Otherwise define a finite repeated-trial oracle with its trial bound and pass/fail rule before running it. Record the stochastic sample limit; do not claim deterministic proof from a passing sample or retry until green. A failing trial must still match the target mechanism, and fresh green remains bounded by the stated oracle.
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# Installed private helper location
|
|
2
|
+
|
|
3
|
+
Use this card only for the debug packet validator and an authorized task-board
|
|
4
|
+
follow-up. The exact installed helper leaves are `hooks/debug-handoff.py` (the
|
|
5
|
+
private `validate` operation) and `hooks/taskwrite.py` (the existing board
|
|
6
|
+
writer). The caller chooses one of those literal leaves before resolution;
|
|
7
|
+
packet text, a project file, and a user argument never choose executable code.
|
|
8
|
+
Select and validate one Python 3 interpreter before invoking the helper. Try
|
|
9
|
+
`python3` first, then `python` only if the first candidate is absent, a launcher
|
|
10
|
+
stub, or incompatible. The probe executes the candidate to obtain its actual
|
|
11
|
+
`sys.executable`, then validates that absolute executable directly as Python
|
|
12
|
+
3.8 or newer. The installed debug validator's `_debughandofflib.py` uses an
|
|
13
|
+
assignment expression, which Python 3.7 cannot parse; the shared selection
|
|
14
|
+
must satisfy that helper even when the current call targets `taskwrite.py`.
|
|
15
|
+
Invoke the helper through that executable, not a batch or shell launcher that
|
|
16
|
+
could alter quoted arguments. A name on `PATH` or a successful `--version`
|
|
17
|
+
alone does not establish compatibility. This source-derived minimum is not a
|
|
18
|
+
claim that every newer minor has been qualified. Once selected, invoke the one resolved absolute helper with `-B` and
|
|
19
|
+
literal arguments. Preserve its exit, stdout, and stderr; do not replay a
|
|
20
|
+
failure under another interpreter or helper.
|
|
21
|
+
|
|
22
|
+
Use the selection block for the current shell before the first helper call.
|
|
23
|
+
These blocks set `$caPython` in PowerShell or `ca_python` in POSIX sh. A missing
|
|
24
|
+
compatible interpreter stops before the helper; fix the host installation
|
|
25
|
+
before retrying the whole operation.
|
|
26
|
+
|
|
27
|
+
### Pi PowerShell interpreter selection
|
|
28
|
+
```powershell
|
|
29
|
+
$caPython = $null
|
|
30
|
+
foreach ($caName in @('python3', 'python')) {
|
|
31
|
+
$caCommand = Get-Command -Name $caName -CommandType Application -ErrorAction SilentlyContinue | Select-Object -First 1
|
|
32
|
+
if ($null -eq $caCommand) { continue }
|
|
33
|
+
try {
|
|
34
|
+
$caExecutable = & $caCommand.Source -B -c "import sys; sys.exit(1) if not (sys.version_info[0] == 3 and sys.version_info >= (3, 8)) else None; print(sys.executable)" 2>$null
|
|
35
|
+
if ($LASTEXITCODE -ne 0 -or $caExecutable -isnot [string] -or
|
|
36
|
+
-not [System.IO.Path]::IsPathFullyQualified($caExecutable) -or
|
|
37
|
+
-not (Test-Path -LiteralPath $caExecutable -PathType Leaf)) { continue }
|
|
38
|
+
$caIdentity = & $caExecutable -B -c "import sys; print('codearbiter-python3' if sys.version_info[0] == 3 and sys.version_info >= (3, 8) else 'incompatible')" 2>$null
|
|
39
|
+
if ($LASTEXITCODE -eq 0 -and $caIdentity -ceq 'codearbiter-python3') {
|
|
40
|
+
$caPython = $caExecutable
|
|
41
|
+
break
|
|
42
|
+
}
|
|
43
|
+
} catch { continue }
|
|
44
|
+
}
|
|
45
|
+
if (-not $caPython) { throw 'compatible Python 3 interpreter unavailable' }
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Pi POSIX interpreter selection
|
|
49
|
+
```sh
|
|
50
|
+
ca_python=
|
|
51
|
+
for ca_candidate in python3 python; do
|
|
52
|
+
ca_path=$(command -v "$ca_candidate" 2>/dev/null) || continue
|
|
53
|
+
case "$ca_path" in /*) ;; *) continue;; esac
|
|
54
|
+
[ -f "$ca_path" ] || continue
|
|
55
|
+
ca_executable=$("$ca_path" -B -c 'import sys; sys.exit(1) if not (sys.version_info[0] == 3 and sys.version_info >= (3, 8)) else None; print(sys.executable)' 2>/dev/null) || continue
|
|
56
|
+
case "$ca_executable" in
|
|
57
|
+
/*) ;;
|
|
58
|
+
[A-Za-z]:'\'*)
|
|
59
|
+
command -v cygpath >/dev/null 2>&1 || continue
|
|
60
|
+
ca_executable=$(cygpath -u "$ca_executable") || continue ;;
|
|
61
|
+
*) continue ;;
|
|
62
|
+
esac
|
|
63
|
+
[ -f "$ca_executable" ] && [ -x "$ca_executable" ] || continue
|
|
64
|
+
ca_identity=$("$ca_executable" -B -c 'import sys; print("codearbiter-python3" if sys.version_info[0] == 3 and sys.version_info >= (3, 8) else "incompatible")' 2>/dev/null) || continue
|
|
65
|
+
if [ "$ca_identity" = codearbiter-python3 ]; then ca_python=$ca_executable; break; fi
|
|
66
|
+
done
|
|
67
|
+
if [ -z "$ca_python" ]; then printf '%s\n' 'compatible Python 3 interpreter unavailable' >&2; exit 2; fi
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Start from the absolute path of the **loaded installed entry resource** that
|
|
71
|
+
the host actually supplied: `commands/task.md` or `commands/debug.md` on
|
|
72
|
+
Claude, `skills/ca-task/SKILL.md` or `skills/ca-debug/SKILL.md` on Codex and
|
|
73
|
+
Pi. The Codex and Pi skill directories are two levels below the package root;
|
|
74
|
+
Claude's command directory is one level below it. Do not use the current directory, a project checkout,
|
|
75
|
+
an unset `PLUGIN_ROOT`/`CLAUDE_PLUGIN_ROOT` token from a hook runner, `/hooks`,
|
|
76
|
+
a source clone, or a recursive cache search. If the loaded resource, package
|
|
77
|
+
identity, or exact helper is absent, report that failure and stop. Keep the
|
|
78
|
+
current working directory at the intended project when invoking `taskwrite.py`.
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
Pi's loaded `skills/ca-task/SKILL.md` or `skills/ca-debug/SKILL.md` is the
|
|
82
|
+
anchor. `package.json` is the installed package identity marker; a written
|
|
83
|
+
`<plugin-root>` string is not an executable path. Bind the selected resource
|
|
84
|
+
and one literal helper leaf as above.
|
|
85
|
+
|
|
86
|
+
### Pi PowerShell resolution
|
|
87
|
+
```powershell
|
|
88
|
+
$caResolvedResource = (Resolve-Path -LiteralPath $caLoadedResource -ErrorAction Stop).ProviderPath
|
|
89
|
+
$caResourceDirectory = Split-Path -Parent $caResolvedResource
|
|
90
|
+
$caInstalledRoot = (Resolve-Path -LiteralPath (Join-Path $caResourceDirectory '..\..') -ErrorAction Stop).ProviderPath
|
|
91
|
+
$caManifest = Join-Path $caInstalledRoot 'package.json'
|
|
92
|
+
if (-not (Test-Path -LiteralPath $caManifest -PathType Leaf)) { throw "installed ca-pi package identity missing" }
|
|
93
|
+
$caHelper = Join-Path $caInstalledRoot $caHelperRelative
|
|
94
|
+
if (-not (Test-Path -LiteralPath $caHelper -PathType Leaf)) { throw "installed helper missing: $caHelper" }
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Pi POSIX resolution
|
|
98
|
+
```sh
|
|
99
|
+
case "$ca_loaded_resource" in /*) ;; *) printf '%s\n' 'loaded installed resource must be absolute' >&2; exit 2;; esac
|
|
100
|
+
if [ ! -f "$ca_loaded_resource" ]; then printf '%s\n' 'loaded installed resource missing' >&2; exit 2; fi
|
|
101
|
+
ca_installed_root=$(CDPATH= cd -P "$(dirname "$ca_loaded_resource")/../.." && pwd -P) || exit 2
|
|
102
|
+
if [ ! -f "$ca_installed_root/package.json" ]; then printf '%s\n' 'installed ca-pi package identity missing' >&2; exit 2; fi
|
|
103
|
+
ca_helper=$ca_installed_root/$ca_helper_relative
|
|
104
|
+
if [ ! -f "$ca_helper" ]; then printf '%s\n' 'installed helper missing' >&2; exit 2; fi
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
Never repair a missing installed helper by selecting a similarly named file
|
|
109
|
+
from a checkout or cache. A missing or partial package blocks the operation.
|
|
110
|
+
|
|
111
|
+
For private debug validation, select the literal leaf
|
|
112
|
+
`hooks/debug-handoff.py` with the resolution block above. Supply one finite
|
|
113
|
+
packet of at most 65,536 bytes through the host execution tool's stdin and
|
|
114
|
+
retain that tool's timeout and output controls. The helper owns rejection of
|
|
115
|
+
oversize input; never build a shell pipeline, command string, path argument,
|
|
116
|
+
or unbounded read to transport the packet. Invoke only once with the literal
|
|
117
|
+
`validate` operation and retain its original exit, stdout, and stderr.
|
|
118
|
+
|
|
119
|
+
### Pi PowerShell validate invocation
|
|
120
|
+
```powershell
|
|
121
|
+
& $caPython -B $caHelper validate
|
|
122
|
+
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Pi POSIX validate invocation
|
|
126
|
+
```sh
|
|
127
|
+
"$ca_python" -B "$ca_helper" validate
|
|
128
|
+
```
|
|
@@ -22,6 +22,19 @@ file maps those actions to Pi's extension API.
|
|
|
22
22
|
silently allows classified reads. Plan mode is read-only except for the
|
|
23
23
|
current canonical spec, plan, and plan-ledger files; source, configuration,
|
|
24
24
|
unrelated project-state, and external mutations deny.
|
|
25
|
+
- For an authorized debug validator or task-board writer call, load
|
|
26
|
+
[helper-invocation.md](helper-invocation.md) relative to this installed host
|
|
27
|
+
note. Derive the installed package
|
|
28
|
+
from the absolute path of the currently loaded `ca-debug` or `ca-task`
|
|
29
|
+
`SKILL.md`, then check the exact helper and run the card's PowerShell or POSIX
|
|
30
|
+
Python 3 selection block before invoking it. Select once by an executed
|
|
31
|
+
identity probe; preserve a failed helper's original output and exit status
|
|
32
|
+
without a second-interpreter attempt. Put task options before `--` and pass
|
|
33
|
+
user text as one literal argument. Feed validation one finite packet of at
|
|
34
|
+
most 65,536 bytes through the host tool's stdin using the card's direct
|
|
35
|
+
`validate` call. The literal `<plugin-root>` spelling
|
|
36
|
+
is not a shell path. A missing helper blocks the call; preserve the current
|
|
37
|
+
project working directory for board writes.
|
|
25
38
|
- `codearbiter_background_bash` and `/ca-jobs list|tail|cancel` are bounded,
|
|
26
39
|
session-only parent capabilities. Jobs and their metadata terminate at
|
|
27
40
|
shutdown and are never restored from Pi session entries.
|
|
@@ -27,7 +27,7 @@ reached the same way.
|
|
|
27
27
|
| Docs edit / dep bump / revert | `/chore` (type-scaled gates) | `dependency-reviewer` for deps | No behavioral code; suite green for deps/revert; exits via `commit-gate` |
|
|
28
28
|
| Exploratory throwaway spike | `/spike` (self-contained command) → `spike/<slug>` branch | — | Never merges or PRs; `commit-gate`-exempt (nothing on the branch can land); exits to a findings note or `/feature` |
|
|
29
29
|
| Behavior-preserving restructure | `refactor` skill at `<plugin-root>/routines/refactor/SKILL.md` (explicit `/refactor` uses the same owner) | `tdd` Phase 1 (coverage backfill or new seams) | No refactor without parity-coverage proof |
|
|
30
|
-
| Unknown defect / investigation | `debug` skill at `<plugin-root>/routines/debug/SKILL.md` (explicit `/debug` uses the same owner) | — | No code change in the skill; one
|
|
30
|
+
| Unknown defect / investigation | `debug` skill at `<plugin-root>/routines/debug/SKILL.md` (explicit `/debug` uses the same owner) | — | No code change in the skill; one of confirmed_code_defect, confirmed_noncode_cause, design_question, no_action, or unresolved with evidence; continuation retains caller authority |
|
|
31
31
|
| Commit | `commit-gate` skill at `<plugin-root>/routines/commit-gate/SKILL.md` (explicit `/commit` uses the same owner) | — | No commit without all nine gates green |
|
|
32
32
|
| Open a PR / finish a branch | `finishing-a-development-branch` at `<plugin-root>/routines/finishing-a-development-branch/SKILL.md`; select direct-open or caller mode first | reviewer fleet per path; PR-body prose applies `anti-slop-design` (`core` + `medium-documents` §7.A.1) | PR only; no direct-to-default, no force-push |
|
|
33
33
|
| Watch a PR's CI / babysit checks | `/watch` → detached `gh pr checks --watch` | on-red diagnose (propose\|branch) | Never auto-merges; green → notify + offer; merge-to-default routes through the hard gate; no poll loop |
|
|
@@ -15,7 +15,7 @@ not both merely to repeat the same procedure. This index lists what each skill O
|
|
|
15
15
|
| [tdd](tdd/SKILL.md) | `/feature` (after spec approval), `/fix`, `/refactor` | The test-first gate: six phases — obligation scan → red → green → obligation verify → coverage → lint. No implementation before Phase 1; no path to `commit-gate` until all six gates are green. |
|
|
16
16
|
| [commit-gate](commit-gate/SKILL.md) | `/commit` | The commit gate: nine phases — permission, branch, classification, impact-bounded local verification under the shared [verification boundary](../includes/verification-boundary.md), behavioral proof, diff review, selective stage, message, commit. No commit while an applicable check is red, the behavior unproven, or secrets/cruft present; exhaustive exact-head proof remains a hosted-CI merge gate. |
|
|
17
17
|
| [decision-variance](decision-variance/SKILL.md) | Architectural reconciliation or variance report; explicit `/reconcile` retained | One SMARTS arbitration owner; report-only is non-mutating. Analysis card loads on demand; only explicit user choices enter the append-only log. |
|
|
18
|
-
| [debug](debug/SKILL.md) | Diagnosis intent or `/debug` | Investigate-then-decide root-cause analysis: five phases. Investigation only, no code change here;
|
|
18
|
+
| [debug](debug/SKILL.md) | Diagnosis intent or `/debug` | Investigate-then-decide root-cause analysis: five phases. Investigation only, no code change here; returns one evidence-backed result: confirmed_code_defect, confirmed_noncode_cause, design_question, no_action, or unresolved. Follow-up action retains caller authority; no default task or ADR write. |
|
|
19
19
|
| [refactor](refactor/SKILL.md) | Behavior-preserving restructure intent or `/refactor` | Behavior-preserving change behind a parity-coverage proof gate; routes to `tdd` Phase 1 for coverage backfill or new test seams. |
|
|
20
20
|
| [context-creation](context-creation/SKILL.md) | `/create-context` (brownfield) | Back-fills `.codearbiter/` from existing source via parallel scouts; writes `CONTEXT.md` (`arbiter: enabled` + `stage:`) and locks it `<!--INITIALIZED-->`. |
|
|
21
21
|
| [decompose](decompose/SKILL.md) | greenfield startup, `/decompose` | Six-layer senior-architect interview, compaction-resilient via per-layer disk drafts + DRAFT ADRs; populates `.codearbiter/` and locks it initialized. |
|
|
@@ -107,10 +107,12 @@ Gate: the change is proven to do what it claimed by fresh evidence — command o
|
|
|
107
107
|
|
|
108
108
|
Compute the heal worklist from the staged set via `_provenancelib.heal_worklist(staged_paths, provenance, current_hashes)` — the subset of staged paths that are `drift_trigger:true` provenance entries whose recorded hash has diverged or is absent. **Empty worklist → skip this phase entirely; most commits pay nothing** (cost guarantee: ordinary commits touching no provenance source do zero re-scout work).
|
|
109
109
|
|
|
110
|
-
Non-empty worklist →
|
|
110
|
+
Non-empty worklist → call `_provenancelib.compute_drift(provenance, current_hashes)` to retain the document/source mapping. For each stale document in that drift report, get its record as `doc_provenance` and call `_provenancelib.changed_scope(doc_provenance, drift)`. Intersect that document's drifted paths with the worklist; skip a document when the intersection is empty. The hash map can omit unstaged paths, so a missing entry outside the worklist must not broaden this commit's re-scout. Confirm that every selected worklist path maps to at least one stale document after this filtering; if a record is malformed or the mapping is incomplete, STOP and report the gap rather than treating the path as fresh.
|
|
111
111
|
|
|
112
|
-
|
|
113
|
-
|
|
112
|
+
Run an **incremental re-scout for each affected document**, scoped to its selected staged paths only (not the full repo). A fresh first document does not discharge a stale second document's claims for the same source. Resolve each selected document/path dependency independently:
|
|
113
|
+
|
|
114
|
+
- **Claim still holds → silently re-baseline only that document's provenance record.** Call `_provenancelib.rebaseline(doc_provenance, selected_current_hashes)` where `selected_current_hashes` contains current hashes only for the selected staged paths whose claims in that document were inspected and still hold. Do not re-baseline a path whose claim changed or was not inspected. Stage only `.codearbiter/.provenance/<doc>.json` by explicit path so the re-baselined record rides THIS commit (ADR-0008 ride-along pattern — nothing is surfaced to the user). After staging, re-run the secrets scan from `tech-stack.md` over the newly-staged path(s) — any file staged after Phase 4 must still pass the automated secrets scan before the commit proceeds. A missing current hash (deletion or rename) cannot be silently re-baselined; surface it in Phase 6 for review.
|
|
115
|
+
- **Claim changed → route to the existing Phase 6 diff-review.** Propose only the affected doc or code-map edit required to reflect its changed claim. The user reviews that edit in the normal diff, and Phase 7 stages approved paths explicitly; do not silently rewrite or add unrelated documentation.
|
|
114
116
|
|
|
115
117
|
## Phase 6 — Diff review · gate: BLOCK
|
|
116
118
|
|
|
@@ -31,6 +31,13 @@ Report first. Write only after the user selects re-scout or re-baseline for that
|
|
|
31
31
|
document; never change an unselected derived document. This owner neither stages
|
|
32
32
|
nor commits. Routine commit-gate auto-heal is unchanged.
|
|
33
33
|
|
|
34
|
+
An **initialized refresh** belongs to this existing owner after an explicit
|
|
35
|
+
selection. It is separate from initial population: do not call the initialized
|
|
36
|
+
`/ca-create-context`/`/ca-init --brownfield` path, rerun the scaffolder,
|
|
37
|
+
clear `<!--INITIALIZED-->`, or repeat context finalization. An ordinary status
|
|
38
|
+
snapshot and the initial `/ca-status drift` report are read-only. A declined
|
|
39
|
+
refresh leaves every file unchanged.
|
|
40
|
+
|
|
34
41
|
## Pre-flight
|
|
35
42
|
|
|
36
43
|
Read these before computing drift:
|
|
@@ -57,8 +64,23 @@ Use `_provenancelib` helpers in this order:
|
|
|
57
64
|
Alternatively reuse the same logic as `startup_drift_line` by calling it for
|
|
58
65
|
a human-readable summary, then inspecting `compute_drift` directly for detail.
|
|
59
66
|
|
|
60
|
-
|
|
61
|
-
|
|
67
|
+
The `entries`/Git-hash comparison above covers legacy v1 records only. For
|
|
68
|
+
every enrolled v2 document, call `assess_context_provenance` with the bounded
|
|
69
|
+
current source/target snapshot and an action-boundary snapshot probe. Inspect
|
|
70
|
+
its per-document states as well as aggregate coverage. A missing, corrupt or
|
|
71
|
+
unsupported record, incomplete acquisition, partial hash or unchecked identity
|
|
72
|
+
is unknown coverage, even when a neighboring v1 or v2 record is usable. Report
|
|
73
|
+
the usable records and the unknowns separately; never turn an empty legacy
|
|
74
|
+
drift report into a fresh verdict for v2. `v2_current` acknowledges matching
|
|
75
|
+
identities only. `semantic: unverified` and `verified_fresh: false` remain in
|
|
76
|
+
force until the owning semantic review and writer receipt establish otherwise;
|
|
77
|
+
changing hashes or choosing re-baseline does not perform that review.
|
|
78
|
+
|
|
79
|
+
Only if the relevant legacy drift report is empty and v2 coverage/identities
|
|
80
|
+
have been checked without unknowns may this audit report no stale identities.
|
|
81
|
+
That is not a claim that instruction-bearing facts are semantically verified.
|
|
82
|
+
Only a separately explicit full initialized refresh selection may proceed
|
|
83
|
+
without a stale-document list.
|
|
62
84
|
|
|
63
85
|
### Step 2 — Report stale docs
|
|
64
86
|
|
|
@@ -71,28 +93,92 @@ Stale docs (N):
|
|
|
71
93
|
...
|
|
72
94
|
```
|
|
73
95
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
96
|
+
Also present every enrolled v2 document's `v2_current`, `v2_stale` or unknown
|
|
97
|
+
state from Step 1. For `v2_stale`, derive a proposed affected scope from that
|
|
98
|
+
document's bounded evidence references and recheck the exact paths before
|
|
99
|
+
selection; the legacy `changed_scope` list cannot discover v2 drift. An
|
|
100
|
+
unknown state needs a bounded recovery/inspection, not an inferred fresh or
|
|
101
|
+
stale path. Do not offer an automatic write for an unbounded scope.
|
|
102
|
+
|
|
103
|
+
### Unsupported human content and owner reconciliation
|
|
104
|
+
|
|
105
|
+
An unsupported human Markdown layout, ambiguous duplicate anchor, unparseable
|
|
106
|
+
custom section, oversized document or absent managed ownership record is a
|
|
107
|
+
write refusal for that document, not a reason to erase it or abandon safe
|
|
108
|
+
task-time reading. An unrelated unknown section in an otherwise supported
|
|
109
|
+
document remains unowned and byte-identical during a supported field update.
|
|
110
|
+
Preserve exact bytes and report the specific unsupported or unowned span.
|
|
111
|
+
Use the existing applicable instructions under their actual precedence for the
|
|
112
|
+
current task; referencing those instructions unchanged does not create a new
|
|
113
|
+
normative rule or require a new approval. Keep observed upstream conventions
|
|
114
|
+
and accepted ADR references source-scoped when they do not already govern this
|
|
115
|
+
project. Surface a real conflict without silently displacing either source.
|
|
116
|
+
|
|
117
|
+
If the requested change would adopt or replace normative instructions, route
|
|
118
|
+
the proposal to its actual owner and obtain that owner's actual approval before
|
|
119
|
+
any supported bounded update. An unsupported template needs explicit
|
|
120
|
+
reconciliation or a qualified per-kind transition through the existing context
|
|
121
|
+
writer. Its refusal never authorizes raw Write/Edit fallback or a regex rewrite.
|
|
122
|
+
Task, question, audit, release and ADR files remain with their existing writers;
|
|
123
|
+
do not normalize, recreate or edit their history during context refresh.
|
|
124
|
+
|
|
125
|
+
### Step 3 — Selected initialized refresh
|
|
126
|
+
|
|
127
|
+
For each stale or bounded affected document, present supported re-scout,
|
|
128
|
+
re-baseline and defer choices; wait for the user's selection. A user may instead
|
|
129
|
+
explicitly select full refresh. Do not interpret
|
|
130
|
+
`status drift`, the drift report itself or an ordinary status request as that
|
|
131
|
+
selection. Record the selected documents and declared affected source paths
|
|
132
|
+
before any scout or write. An incremental refresh re-scouts only the selected
|
|
133
|
+
drifted paths and affected logical assignments. A full refresh declares all six
|
|
134
|
+
logical assignments and all five content documents. Retain prior coverage as
|
|
135
|
+
prior evidence; a scoped `join_scout_reports` result has `full_coverage: false`
|
|
136
|
+
and must never be described as a newly completed full scan.
|
|
77
137
|
|
|
78
138
|
**re-scout** — dispatch an incremental re-scout of the drifted paths for this
|
|
79
|
-
doc, scoped to those paths only
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
139
|
+
doc, scoped to those paths only. Use the context-creation containment profile,
|
|
140
|
+
run budget, `admit_scout_attempt` and `join_scout_reports` contract for exactly
|
|
141
|
+
the declared affected assignments. A missing/failed report, changed snapshot,
|
|
142
|
+
contradiction or unresolved task-dependent decision blocks the selected write.
|
|
143
|
+
If the claims still hold, a valid selected owned-field metadata refresh may
|
|
144
|
+
keep document bytes identical only when proposed v2 provenance actually
|
|
145
|
+
changes. Missing selection and unchanged proposed provenance refuse; retain
|
|
146
|
+
the stale pair and do not claim freshness in those cases. Any update still
|
|
147
|
+
requires current source evidence, exact preview approval and receipt-only
|
|
148
|
+
apply. Surface the proposed content and provenance pair for exact review.
|
|
149
|
+
|
|
150
|
+
**re-baseline** — the legacy v1 provenance choice may acknowledge a verified
|
|
151
|
+
cosmetic change through its existing owner, where applicable. For an enrolled
|
|
152
|
+
v2 content document, use only a selected owned field and the native bounded
|
|
153
|
+
update with new, validated source evidence and changed proposed provenance.
|
|
154
|
+
If no field is selected or the proposed pair is a true no-op, retain the stale
|
|
155
|
+
pair and defer that selection. Never directly write the v2 provenance or use
|
|
156
|
+
the legacy `rebaseline` helper as a fallback for it.
|
|
157
|
+
|
|
158
|
+
**full refresh** — only after explicit selection, use the same qualified
|
|
159
|
+
containment and bounded join with `mode: full` and six complete logical reports.
|
|
160
|
+
Synthesize all five content documents from the new evidence and reconcile gaps
|
|
161
|
+
under the context-creation Phase 3–4 rules. Do not enter its Phase 6 lock.
|
|
162
|
+
|
|
163
|
+
For each selected document, submit its finite typed `update` preview through
|
|
164
|
+
`python "<plugin-root>/hooks/init-codearbiter.py" --root <exact-root> --context-request <request-file>`.
|
|
165
|
+
The installed qualified context writer checks the existing document/provenance
|
|
166
|
+
pair, current source evidence, field ownership and protected target set. Review
|
|
167
|
+
the exact proposed pair and obtain its own native `approve-context` reply; apply
|
|
168
|
+
only its receipt through the same `--context-request` bridge. Read back the
|
|
169
|
+
committed pair and confirm the standalone `<!--INITIALIZED-->` marker remains
|
|
170
|
+
for `CONTEXT.md`. The writer's five content targets exclude task, question and
|
|
171
|
+
audit history. Never edit those owners as a side effect, hand-write a provenance
|
|
172
|
+
record, bypass a refusal, stage or commit here. If the installed writer or
|
|
173
|
+
qualified scout profile is unavailable, report that boundary and retain state.
|
|
89
174
|
|
|
90
175
|
**defer** — do nothing for this doc now. The drift line will reappear at the
|
|
91
176
|
next SessionStart. Use when the change is in-progress and the doc update should
|
|
92
177
|
wait for a later commit.
|
|
93
178
|
|
|
94
|
-
After processing
|
|
95
|
-
|
|
179
|
+
After processing selections, summarize changed documents, deferred selections,
|
|
180
|
+
the declared coverage, and whether the run was full or incremental. Keep
|
|
181
|
+
unselected content, initialized state and prior history intact.
|
|
96
182
|
|
|
97
183
|
## Hard rule
|
|
98
184
|
|