@arbiterforge/ca-pi 0.10.13 → 0.14.7
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 +2 -1
- package/plugins/ca-pi/CHANGELOG.md +167 -0
- package/plugins/ca-pi/SKILLS.md +1 -1
- package/plugins/ca-pi/SPRINT.md +40 -10
- package/plugins/ca-pi/agents/backend-author.md +1 -1
- package/plugins/ca-pi/agents/frontend-author.md +1 -1
- 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 +38 -0
- package/plugins/ca-pi/hooks/_approvallib.py +355 -0
- package/plugins/ca-pi/hooks/_artifactlib.py +855 -0
- package/plugins/ca-pi/hooks/_cleanuplib.py +1553 -0
- package/plugins/ca-pi/hooks/_hooklib.py +37 -13
- package/plugins/ca-pi/hooks/_host.py +1 -1
- package/plugins/ca-pi/hooks/_intentlib.py +31 -0
- package/plugins/ca-pi/hooks/_planfilelib.py +34 -1
- package/plugins/ca-pi/hooks/_prerequisitelib.py +971 -0
- package/plugins/ca-pi/hooks/_protectedstatelib.py +11 -1
- package/plugins/ca-pi/hooks/_readinjectlib.py +120 -0
- package/plugins/ca-pi/hooks/_releaselib.py +933 -85
- package/plugins/ca-pi/hooks/_standuplib.py +38 -10
- package/plugins/ca-pi/hooks/doctor.py +103 -0
- package/plugins/ca-pi/hooks/hostapi.py +1 -1
- package/plugins/ca-pi/hooks/pi-bridge.py +5 -1
- package/plugins/ca-pi/hooks/prompt-submit.py +47 -10
- package/plugins/ca-pi/hooks/releasehash.py +46 -32
- package/plugins/ca-pi/includes/artifacts.md +210 -0
- package/plugins/ca-pi/includes/author-tdd-workflow.md +2 -1
- package/plugins/ca-pi/includes/farm.md +27 -4
- package/plugins/ca-pi/includes/routing-table.md +2 -2
- package/plugins/ca-pi/includes/verification-boundary.md +27 -0
- package/plugins/ca-pi/package.json +18 -0
- package/plugins/ca-pi/routines/INDEX.md +4 -4
- package/plugins/ca-pi/routines/brainstorming/SKILL.md +23 -4
- package/plugins/ca-pi/routines/commit-gate/SKILL.md +30 -5
- package/plugins/ca-pi/routines/executing-plans/SKILL.md +52 -7
- package/plugins/ca-pi/routines/finishing-a-development-branch/SKILL.md +25 -3
- package/plugins/ca-pi/routines/refactor/SKILL.md +3 -2
- package/plugins/ca-pi/routines/release/SKILL.md +150 -44
- package/plugins/ca-pi/routines/subagent-driven-development/SKILL.md +53 -9
- package/plugins/ca-pi/routines/subagent-driven-development/references/farm-dispatch.md +20 -3
- package/plugins/ca-pi/routines/tdd/SKILL.md +27 -5
- package/plugins/ca-pi/routines/using-git-worktrees/SKILL.md +11 -2
- package/plugins/ca-pi/routines/writing-plans/SKILL.md +39 -10
- package/plugins/ca-pi/routines/writing-plans/references/farm-plan.md +34 -13
- package/plugins/ca-pi/skills/ca-chore/SKILL.md +7 -3
- package/plugins/ca-pi/skills/ca-commit/SKILL.md +3 -2
- package/plugins/ca-pi/skills/ca-doctor/SKILL.md +14 -0
- package/plugins/ca-pi/skills/ca-feature/SKILL.md +42 -8
- package/plugins/ca-pi/skills/ca-refactor/SKILL.md +4 -2
- package/plugins/ca-pi/skills/ca-release/SKILL.md +7 -6
- package/plugins/ca-pi/skills/ca-standup/SKILL.md +36 -8
|
@@ -381,6 +381,16 @@ def marker_name_for(rel_path):
|
|
|
381
381
|
(non-empty) rel_path can ever produce, since a real segment always
|
|
382
382
|
contributes a non-empty stem.
|
|
383
383
|
|
|
384
|
+
Every segment is case-folded (`.lower()`) before encoding (#624), matching
|
|
385
|
+
`_canon`/`lookup_policy`'s own case-insensitive registry comparison: a
|
|
386
|
+
marker name computed for a differently-cased Write/Edit target must equal
|
|
387
|
+
the one minted under the registry's canonical casing, or a legitimate
|
|
388
|
+
authoring write is wrongly blocked despite a fresh, correctly-minted
|
|
389
|
+
marker. This widens what two paths can collide into one marker (a
|
|
390
|
+
same-name directory differing only by case now shares a marker with its
|
|
391
|
+
canonical sibling) - the same accepted "widens admission, never narrows
|
|
392
|
+
protection" tradeoff `lookup_policy`'s own case fold already makes.
|
|
393
|
+
|
|
384
394
|
Residual (accepted): the escaping above closes hyphen/segment-boundary
|
|
385
395
|
ambiguity but is not a fully bijective encoding against adversarially
|
|
386
396
|
crafted underscore runs (e.g. a directory literally named "a_" holding
|
|
@@ -388,7 +398,7 @@ def marker_name_for(rel_path):
|
|
|
388
398
|
small, curated, human-authored set (spec B1/B2), not attacker-chosen
|
|
389
399
|
directory names, so this is judged out of proportion to close fully
|
|
390
400
|
here."""
|
|
391
|
-
parts = [p for p in norm_path(rel_path).split("/") if p not in ("", ".", "..")]
|
|
401
|
+
parts = [p for p in norm_path(rel_path).lower().split("/") if p not in ("", ".", "..")]
|
|
392
402
|
if not parts:
|
|
393
403
|
return "-authoring"
|
|
394
404
|
if parts[0] == ".codearbiter" and len(parts) > 1:
|
|
@@ -1084,3 +1084,123 @@ def compute_injection(root, session_id, rel, runner=None):
|
|
|
1084
1084
|
return ""
|
|
1085
1085
|
except Exception: # noqa: BLE001
|
|
1086
1086
|
return ""
|
|
1087
|
+
|
|
1088
|
+
# Typed artifact pilot bridge. Keep legacy matching unchanged; never cache HTML
|
|
1089
|
+
# authority by mtime. Importing this module performs no subprocess or file I/O.
|
|
1090
|
+
_artifact_legacy_build_index = build_index
|
|
1091
|
+
_artifact_legacy_spec_pointers = spec_pointers
|
|
1092
|
+
|
|
1093
|
+
|
|
1094
|
+
def build_index(root):
|
|
1095
|
+
result = _artifact_legacy_build_index(root)
|
|
1096
|
+
if not isinstance(result, dict):
|
|
1097
|
+
return result
|
|
1098
|
+
result = dict(result)
|
|
1099
|
+
try:
|
|
1100
|
+
from _artifactlib import ArtifactClient, helper_installation, has_html
|
|
1101
|
+
if not has_html(root):
|
|
1102
|
+
return result
|
|
1103
|
+
# Preserve full engine identities in the advisory snapshot. Pointer
|
|
1104
|
+
# matching uses only spec/path/globs, while dedup below hashes the same
|
|
1105
|
+
# entries including revision/model/normative identity. Do not reread the
|
|
1106
|
+
# artifact after this validated index stream.
|
|
1107
|
+
extra = []
|
|
1108
|
+
client = ArtifactClient(root, helper_installation(__file__))
|
|
1109
|
+
for entry in client.index("spec"):
|
|
1110
|
+
authority = entry["authority"]
|
|
1111
|
+
if authority["authority_verified"] and entry.get("governs"):
|
|
1112
|
+
extra.append({
|
|
1113
|
+
"spec": entry["artifact_id"],
|
|
1114
|
+
"path": entry["path"],
|
|
1115
|
+
"globs": entry["governs"],
|
|
1116
|
+
"artifact_html": True,
|
|
1117
|
+
"revision": entry.get("revision"),
|
|
1118
|
+
"model_sha256": entry.get("model_sha256"),
|
|
1119
|
+
"normative_sha256": entry.get("normative_sha256"),
|
|
1120
|
+
})
|
|
1121
|
+
except Exception as error:
|
|
1122
|
+
# Advisory read injection remains fail-open. This warning is NOT an
|
|
1123
|
+
# approved-spec pointer and MUST NOT authorize a planning/execution gate.
|
|
1124
|
+
code = getattr(error, "code", "CAPABILITY_MISSING")
|
|
1125
|
+
code = str(code)[:80]
|
|
1126
|
+
capability_codes = {
|
|
1127
|
+
"CAPABILITY_MISSING", "INVALID_INSTALLATION", "PACKAGE_INTEGRITY",
|
|
1128
|
+
"UNSUPPORTED_PLATFORM", "UNSUPPORTED_VERSION", "UNVERIFIED_PLATFORM",
|
|
1129
|
+
"INVALID_RESPONSE", "RESPONSE_TOO_LARGE", "SUBPROCESS_FAILED", "TIMEOUT",
|
|
1130
|
+
}
|
|
1131
|
+
extra = [{
|
|
1132
|
+
"artifact_diagnostic": code,
|
|
1133
|
+
"artifact_diagnostic_kind": (
|
|
1134
|
+
"capability" if code in capability_codes else "invalid-artifact"
|
|
1135
|
+
),
|
|
1136
|
+
"artifact_html": True,
|
|
1137
|
+
}]
|
|
1138
|
+
result["spec"] = [item for item in result.get("spec", [])
|
|
1139
|
+
if not isinstance(item, dict) or not item.get("artifact_html")] + extra
|
|
1140
|
+
return result
|
|
1141
|
+
|
|
1142
|
+
|
|
1143
|
+
def spec_pointers(rel, index):
|
|
1144
|
+
if not isinstance(index, list):
|
|
1145
|
+
return _artifact_legacy_spec_pointers(rel, index)
|
|
1146
|
+
warnings = [item for item in index if isinstance(item, dict) and item.get("artifact_diagnostic")]
|
|
1147
|
+
normal = [item for item in index if not isinstance(item, dict) or not item.get("artifact_diagnostic")]
|
|
1148
|
+
result = _artifact_legacy_spec_pointers(rel, normal)
|
|
1149
|
+
if warnings:
|
|
1150
|
+
warning = warnings[0]
|
|
1151
|
+
code = warning["artifact_diagnostic"]
|
|
1152
|
+
if warning.get("artifact_diagnostic_kind") == "capability":
|
|
1153
|
+
text = (
|
|
1154
|
+
"HTML artifact capability unavailable (" + code + "). Repair or reinstall "
|
|
1155
|
+
"the pinned artifact payload. Source inspection and unrelated legacy Markdown "
|
|
1156
|
+
"may continue; HTML planning/execution must stop until resolved."
|
|
1157
|
+
)
|
|
1158
|
+
else:
|
|
1159
|
+
text = (
|
|
1160
|
+
"HTML specification is invalid or unreadable (" + code + "). Inspect the "
|
|
1161
|
+
"engine diagnostic and repair-preview before any repair. Source inspection may "
|
|
1162
|
+
"continue; HTML planning/execution must stop until resolved."
|
|
1163
|
+
)
|
|
1164
|
+
result.append({"tier": "artifact-diagnostic", "text": text})
|
|
1165
|
+
return result
|
|
1166
|
+
|
|
1167
|
+
_artifact_legacy_compute_injection = compute_injection
|
|
1168
|
+
|
|
1169
|
+
|
|
1170
|
+
def compute_injection(root, session_id, rel, runner=None):
|
|
1171
|
+
# Bind the injected pointers and dedup epoch to ONE validated HTML snapshot.
|
|
1172
|
+
# A second artifact read here permits B(epoch) -> A(content) and records A
|
|
1173
|
+
# under B's marker, suppressing a later stable B read. HTML therefore builds
|
|
1174
|
+
# once before dedup; the same entries drive both context and epoch. This is
|
|
1175
|
+
# advisory identity only, never approval or execution authority.
|
|
1176
|
+
if not isinstance(rel, str) or rel.replace("\\", "/").split("/", 1)[0] == ".codearbiter":
|
|
1177
|
+
return _artifact_legacy_compute_injection(root, session_id, rel, runner)
|
|
1178
|
+
try:
|
|
1179
|
+
from _artifactlib import has_html
|
|
1180
|
+
if not has_html(root):
|
|
1181
|
+
return _artifact_legacy_compute_injection(root, session_id, rel, runner)
|
|
1182
|
+
index = build_index(root)
|
|
1183
|
+
if not isinstance(index, dict):
|
|
1184
|
+
return ""
|
|
1185
|
+
artifact_entries = [
|
|
1186
|
+
item for item in index.get("spec", [])
|
|
1187
|
+
if isinstance(item, dict) and item.get("artifact_html") is True
|
|
1188
|
+
]
|
|
1189
|
+
epoch = hashlib.sha256(
|
|
1190
|
+
json.dumps(
|
|
1191
|
+
artifact_entries, sort_keys=True, separators=(",", ":")
|
|
1192
|
+
).encode()
|
|
1193
|
+
).hexdigest()
|
|
1194
|
+
epoch_session = str(session_id) + "|html:" + epoch
|
|
1195
|
+
if already_injected(root, epoch_session, rel):
|
|
1196
|
+
return ""
|
|
1197
|
+
pointers = governing_docs(rel, index, runner)
|
|
1198
|
+
if not pointers:
|
|
1199
|
+
return ""
|
|
1200
|
+
context = assemble_context(pointers, budget=150)
|
|
1201
|
+
if context:
|
|
1202
|
+
record_injection(root, epoch_session, rel)
|
|
1203
|
+
return context
|
|
1204
|
+
return ""
|
|
1205
|
+
except Exception: # noqa: BLE001 - advisory injection always fails open
|
|
1206
|
+
return ""
|