@ccoalm/ccl-skills 0.15.0 → 0.15.2
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 +3 -1
- package/dist/assets/marketplace/plugins/ccl-skills/agent-context/session-start.md +1 -1
- package/dist/assets/marketplace/plugins/ccl-skills/packages/opencode-plugin/ccl-skills.ts +80 -4
- package/dist/assets/marketplace/plugins/ccl-skills/packages/opencode-plugin/commands/ccl-install-skills.md +16 -4
- package/dist/assets/marketplace/plugins/ccl-skills/scripts/owner-dispatch/owner-dispatch.sh +13 -2
- package/dist/assets/marketplace/plugins/ccl-skills/scripts/owner-dispatch/test.sh +53 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/app-cross-platform-dev/SKILL.md +2 -2
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/SKILL.md +6 -5
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/references/development-completion.md +26 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/references/staged-review-contract.md +37 -13
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/AGENTS.md +5 -2
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/codex_review.sh +77 -5
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/kimi_packet_mcp.py +98 -4
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/parse_cli_review.py +48 -1
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/review_gate.py +237 -17
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/test_cli_review_wrappers.sh +165 -11
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/test_kimi_packet_mcp.py +143 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/test_review_client_compat.py +572 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/test_review_gate.sh +65 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/defect-diagnosis/SKILL.md +3 -1
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-dev/SKILL.md +1 -1
- package/dist/assets/marketplace/plugins/ccl-skills/skills/llm-inference-integration/SKILL.md +2 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/miniapp-product-dev/SKILL.md +1 -1
- package/dist/assets/marketplace/plugins/ccl-skills/skills/multi-agent-delegation/SKILL.md +1 -1
- package/dist/assets/marketplace/plugins/ccl-skills/skills/nodejs-service-dev/SKILL.md +2 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-observability/SKILL.md +7 -5
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-observability/references/alerting-and-on-call.md +8 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-release-engineering/SKILL.md +3 -1
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-service-connectivity/SKILL.md +16 -14
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-service-connectivity/references/dual-sidecar-and-traffic-config-center.md +1 -1
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-service-connectivity/references/grpc-authority-workaround.md +40 -83
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-service-connectivity/references/mesh-architecture.md +2 -2
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-service-connectivity/references/retry-timeout-circuit-breaker.md +44 -37
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-service-connectivity/references/service-discovery-recipe.md +1 -1
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/SKILL.md +7 -7
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/references/delivery-lifecycle.md +1 -1
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/references/design-review-gate-mechanics.md +1 -1
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/references/pre-final-continuation-gate.md +20 -11
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/references/refactoring-discipline.md +7 -1
- package/dist/assets/marketplace/plugins/ccl-skills/skills/python-service-dev/SKILL.md +1 -1
- package/dist/assets/marketplace/plugins/ccl-skills/skills/requirement-scope/SKILL.md +8 -5
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/SKILL.md +2 -2
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/dual-track-review-gate.md +17 -17
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/external-practice-controls.md +3 -3
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/harness-patterns-and-eval.md +4 -4
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/resume-paused-delivery.md +3 -3
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/source-register.md +24 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/eval-golden-trace.rb +31 -7
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/impact-chain-gate.rb +74 -3
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/skill-behavior-eval.py +103 -21
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_ai_coding_implementation_gates.sh +83 -48
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_body_compliance_grading.sh +80 -2
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_check_ccl_impact_chain_refscripts.sh +74 -1
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_controlled_escalation_pins.sh +3 -2
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_eval_runtime.py +428 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_validate_extraction_review_state.sh +190 -2
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/validate_extraction_review_state.py +106 -4
- package/dist/assets/marketplace/plugins/ccl-skills/skills/terminal-cli-dev/SKILL.md +1 -1
- package/dist/assets/marketplace/plugins/ccl-skills/skills/testing-strategy/SKILL.md +3 -1
- package/dist/assets/marketplace/plugins/ccl-skills/skills/web-react-dev/SKILL.md +1 -1
- package/dist/assets/release.json +87 -67
- package/dist/claude-adapter.js +14 -7
- package/dist/codex-host.d.ts +2 -4
- package/dist/codex-host.js +40 -19
- package/dist/host-probe.d.ts +27 -0
- package/dist/host-probe.js +51 -0
- package/dist/opencode-adapter.js +24 -19
- package/dist/operations.js +34 -8
- package/dist/unified.d.ts +1 -1
- package/dist/unified.js +18 -9
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -23,7 +23,7 @@ Restart your CLI so it reloads the skills.
|
|
|
23
23
|
|
|
24
24
|
`install` configures every host it detects. The package carries an immutable snapshot of the skills, agent context, plugin manifests, and runtime hooks, so installation needs no Git checkout.
|
|
25
25
|
|
|
26
|
-
Requirements: Node.js 20 or later, macOS or Linux, and at least one host CLI — Claude Code, Codex
|
|
26
|
+
Requirements: Node.js 20 or later, macOS or Linux, and at least one host CLI — Claude Code, Codex with working `plugin marketplace list` and `plugin list` commands, or OpenCode. Codex availability is checked through these commands rather than its version number.
|
|
27
27
|
|
|
28
28
|
Run it without a global install:
|
|
29
29
|
|
|
@@ -62,6 +62,8 @@ ccl-skills uninstall --yes # remove host assets
|
|
|
62
62
|
|
|
63
63
|
Limit any operation to one host with `--host claude`, `--host codex`, or `--host opencode`. Add `--json` for machine-readable output.
|
|
64
64
|
|
|
65
|
+
For `--host codex`, unreadable public plugin state returns exit `3` with `host-state-unknown`; a missing CLI or failed capability probe returns `4`. If that host failure occurs with a pending journal, recovery is deferred: exit `5` with `partial-journal` retains the journal and records `details.hostFailure`. Restore the CLI or readable public plugin state, then rerun the command. Other outcomes can share these exit codes, so inspect the JSON status as well.
|
|
66
|
+
|
|
65
67
|
`update` and `uninstall` are previews unless `--yes` is supplied. `update --yes` first upgrades the global npm package to `@latest`, then asks the freshly installed CLI to refresh host assets. Set `CCL_SKILLS_SKIP_SELF_UPDATE=1` for an assets-only refresh; `--allow-downgrade` always uses the currently invoked package without installing `@latest` first.
|
|
66
68
|
|
|
67
69
|
After `ccl-skills uninstall --yes`, remove the CLI package itself with `npm uninstall --global @ccoalm/ccl-skills` if it is no longer needed.
|
|
@@ -41,5 +41,5 @@
|
|
|
41
41
|
- **完整优先**:能多花几分钟做完就别交半成品;但"完整"是把该做的做完,不是镀金或扩范围(详见 product-rd / feature-risk-router 的 gate)。
|
|
42
42
|
- **持久件锚定(长/多阶段/委托/跨会话工作)**:锚到持久件、别只靠对话或临时任务卡——交付级 spec/plan → product-rd-workflow、委托进度 → multi-agent-delegation、技能/流程教训 → skill-extraction-workflow 的 source-register;更新/取代既有件,别复制(只提醒,不是第二个 plan 门,深度归 product-rd)。
|
|
43
43
|
- **大文件/大技能分块读(读取易丢中段)**:单次读取**输出**超过 ~256 行 / 10KB 时,codex 等工具会头尾截断、丢中段([openai/codex#6426](https://github.com/openai/codex/issues/6426)),常有截断标记但极易忽略、某些场景无标记(无标记 ≠ 读全)。需要看全时(完整评审 / 下"没有 X"结论 / 加载技能照做)分块读(每块 < ~200 行**且** < 8KB)并确认**中段**已读到,别一次整文件读就当看全(定点 `sed -n 'Np'` 不受限)。写码/测试/评审同样适用,详见 skill-extraction blocked-source-read。(`project_doc_max_bytes` 只管 project-doc 预算、不影响工具输出截断,不是绕过手段。)
|
|
44
|
-
-
|
|
44
|
+
- **开发完成自动评审(含窄修复和测试代码)**:实现者先自检分支/失败路径及 security/privacy/authority/数据丢失风险,按 `testing-strategy` 完成适用测试,再自动调用 `code-review`,无需用户提醒;执行与收尾见 `skills/code-review/references/development-completion.md`。自审、读技能或说“下一步评审”都不算独立评审。按风险定深度;窄任务不额外套 product-rd self-review row,既有高风险/shared-skill gate 不降级。评审覆盖实际 diff,采用对抗问题,不要求确认实现者结论;findings 先核实再修复或有证据处置,避免循环追逐建议。用户明确跳过时记录 skipped;当前候选已有有效独立评审则复用。详见 product-rd 验证门 + skill-extraction `dual-track-review-gate.md`。
|
|
45
45
|
</ccl-skills-routing>
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
mkdirSync,
|
|
7
7
|
mkdtempSync,
|
|
8
8
|
readFileSync,
|
|
9
|
+
readdirSync,
|
|
9
10
|
realpathSync,
|
|
10
11
|
rmSync,
|
|
11
12
|
statSync,
|
|
@@ -337,6 +338,7 @@ export const CclSkills = async (context: {
|
|
|
337
338
|
const hooksRoot = runtimeRoot()
|
|
338
339
|
const parentSessions = new Map<string, string>()
|
|
339
340
|
const idleInFlight = new Set<string>()
|
|
341
|
+
const pendingSkills = new Map<string, string>()
|
|
340
342
|
let stateRoot: string | null = null
|
|
341
343
|
|
|
342
344
|
function ensureStateRoot() {
|
|
@@ -390,9 +392,67 @@ export const CclSkills = async (context: {
|
|
|
390
392
|
return typeof command === "string" && /\b(?:git\s+(?:push|merge)|gh\b[^\n;&|]*\bpr\s+merge|glab\b[^\n;&|]*\bmr\s+(?:merge|accept)|curl|wget)\b/i.test(command)
|
|
391
393
|
}
|
|
392
394
|
|
|
393
|
-
function
|
|
394
|
-
if (
|
|
395
|
-
|
|
395
|
+
function sameSkillDirectory(loaded: string, active: string) {
|
|
396
|
+
if (loaded === realpathSync(active)) return true
|
|
397
|
+
const pending = [[loaded, active]]
|
|
398
|
+
while (pending.length) {
|
|
399
|
+
const [copy, owner] = pending.pop()!
|
|
400
|
+
const copyStat = lstatSync(copy), ownerStat = lstatSync(owner)
|
|
401
|
+
if (copyStat.isSymbolicLink() || ownerStat.isSymbolicLink()) return false
|
|
402
|
+
if (copyStat.isDirectory() && ownerStat.isDirectory()) {
|
|
403
|
+
const copyNames = readdirSync(copy).sort(), ownerNames = readdirSync(owner).sort()
|
|
404
|
+
if (copyNames.length !== ownerNames.length || copyNames.some((name, index) => name !== ownerNames[index])) return false
|
|
405
|
+
for (const name of ownerNames) pending.push([join(copy, name), join(owner, name)])
|
|
406
|
+
} else if (!copyStat.isFile() || !ownerStat.isFile() || copyStat.size !== ownerStat.size || !readFileSync(copy).equals(readFileSync(owner))) return false
|
|
407
|
+
}
|
|
408
|
+
return true
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
function completedSkill(name: string | undefined, metadata: unknown) {
|
|
412
|
+
if (!name || !hooksRoot || !metadata || typeof metadata !== "object") return null
|
|
413
|
+
const result = metadata as { name?: unknown; dir?: unknown }
|
|
414
|
+
if (result.name !== name || typeof result.dir !== "string") return null
|
|
415
|
+
// The native tool reports the loaded source directory. A same-named skill
|
|
416
|
+
// elsewhere must never be promoted to a CCL owner by its caller's argument.
|
|
417
|
+
try {
|
|
418
|
+
const loaded = realpathSync(result.dir)
|
|
419
|
+
const entry = join(loaded, "SKILL.md")
|
|
420
|
+
if (!lstatSync(entry).isFile() || lstatSync(entry).isSymbolicLink()) return null
|
|
421
|
+
const content = readFileSync(entry, "utf8")
|
|
422
|
+
if (!content.startsWith(`---\nname: ${name}\n`)) return null
|
|
423
|
+
const activeRoot = existsSync(join(hooksRoot, "skills")) ? hooksRoot : resolve(hooksRoot, "../..")
|
|
424
|
+
// Bind the full skill to the running runtime: progressive disclosure loads
|
|
425
|
+
// references/scripts relative to this directory. Active source/project edits
|
|
426
|
+
// remain valid; inactive copies must match current files, without a stale cache.
|
|
427
|
+
const activeSkill = join(activeRoot, "skills", name)
|
|
428
|
+
const activeEntry = join(activeSkill, "SKILL.md")
|
|
429
|
+
if (!existsSync(activeEntry) || !lstatSync(activeEntry).isFile() || lstatSync(activeEntry).isSymbolicLink() || !sameSkillDirectory(loaded, activeSkill)) return null
|
|
430
|
+
const nativeRoots = [activeRoot, join(HOST_HOME, ".config/opencode"), join(directory, ".opencode"), join(context.worktree ?? directory, ".opencode")]
|
|
431
|
+
for (const root of nativeRoots) {
|
|
432
|
+
const expected = join(root, "skills", name)
|
|
433
|
+
if (existsSync(expected) && realpathSync(expected) === loaded && (root === activeRoot || existsSync(join(root, "ccl-skills/runtime/hooks/hooks.json")))) return `ccl-skills:${name}`
|
|
434
|
+
}
|
|
435
|
+
// Explicit skills.paths can select a CCL source checkout while a global
|
|
436
|
+
// adapter supplies the runtime. Require both its layout and the active bytes.
|
|
437
|
+
const sourceRoot = resolve(loaded, "../..")
|
|
438
|
+
const manifestPath = join(sourceRoot, ".claude-plugin/plugin.json")
|
|
439
|
+
if (loaded === join(sourceRoot, "skills", name) && existsSync(manifestPath)) {
|
|
440
|
+
const manifest = JSON.parse(readFileSync(manifestPath, "utf8"))
|
|
441
|
+
if (manifest?.name === "ccl-skills" && manifest?.skills === "./skills/") return `ccl-skills:${name}`
|
|
442
|
+
}
|
|
443
|
+
// The source installer also supports ~/.agents/skills. Require its existing
|
|
444
|
+
// receipt and the current native skill's bytes, not just a same-named file.
|
|
445
|
+
const compatibility = join(HOST_HOME, ".agents/skills", name)
|
|
446
|
+
const native = join(HOST_HOME, ".config/opencode/skills", name, "SKILL.md")
|
|
447
|
+
const receipt = join(HOST_HOME, ".config/opencode/ccl-skills/install-manifest.json")
|
|
448
|
+
if (existsSync(compatibility) && realpathSync(compatibility) === loaded && existsSync(receipt) && existsSync(native)) {
|
|
449
|
+
const manifest = JSON.parse(readFileSync(receipt, "utf8"))
|
|
450
|
+
if (manifest?.installer === "scripts/install-opencode.sh" && manifest?.install_mode === "global" && readFileSync(native, "utf8") === content) return `ccl-skills:${name}`
|
|
451
|
+
}
|
|
452
|
+
return null
|
|
453
|
+
} catch {
|
|
454
|
+
return null
|
|
455
|
+
}
|
|
396
456
|
}
|
|
397
457
|
|
|
398
458
|
async function resumeForStop(sessionID: string, reasons: string[]) {
|
|
@@ -446,6 +506,9 @@ export const CclSkills = async (context: {
|
|
|
446
506
|
output.args = args
|
|
447
507
|
const targets = editPaths(tool, args, directory)
|
|
448
508
|
const toolName = claudeToolName(tool)
|
|
509
|
+
if (tool === "skill" && typeof args.name === "string" && /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(args.name) && args.name.length <= 64) {
|
|
510
|
+
pendingSkills.set(`${sessionID}\0${callID}`, args.name)
|
|
511
|
+
}
|
|
449
512
|
if (targets.length) {
|
|
450
513
|
targets.forEach((filePath, index) => appendTranscript(sessionID, {
|
|
451
514
|
type: "assistant",
|
|
@@ -454,7 +517,7 @@ export const CclSkills = async (context: {
|
|
|
454
517
|
} else {
|
|
455
518
|
appendTranscript(sessionID, {
|
|
456
519
|
type: "assistant",
|
|
457
|
-
message: { content: [{ type: "tool_use", id: callID, name: toolName, input:
|
|
520
|
+
message: { content: [{ type: "tool_use", id: callID, name: toolName, input: {} }] },
|
|
458
521
|
})
|
|
459
522
|
}
|
|
460
523
|
|
|
@@ -507,6 +570,15 @@ export const CclSkills = async (context: {
|
|
|
507
570
|
const tool = input.tool.toLowerCase()
|
|
508
571
|
const sessionID = input.sessionID ?? `pid-${process.ppid}`
|
|
509
572
|
const callID = input.callID ?? "unknown-call"
|
|
573
|
+
if (tool === "skill") {
|
|
574
|
+
const key = `${sessionID}\0${callID}`
|
|
575
|
+
const owner = completedSkill(pendingSkills.get(key), output.metadata)
|
|
576
|
+
pendingSkills.delete(key)
|
|
577
|
+
if (owner) appendTranscript(sessionID, {
|
|
578
|
+
type: "assistant",
|
|
579
|
+
message: { content: [{ type: "tool_use", id: callID, name: "Skill", input: { skill: owner } }] },
|
|
580
|
+
})
|
|
581
|
+
}
|
|
510
582
|
appendTranscript(sessionID, {
|
|
511
583
|
type: "user",
|
|
512
584
|
message: { content: [{ type: "tool_result", tool_use_id: callID, content: "" }] },
|
|
@@ -536,6 +608,9 @@ export const CclSkills = async (context: {
|
|
|
536
608
|
? (properties.info as { id: string }).id
|
|
537
609
|
: ""
|
|
538
610
|
if (!sessionID) return
|
|
611
|
+
if (event.type === "session.deleted" || event.type === "session.idle" || (properties.status as { type?: string } | undefined)?.type === "idle") {
|
|
612
|
+
for (const key of pendingSkills.keys()) if (key.startsWith(`${sessionID}\0`)) pendingSkills.delete(key)
|
|
613
|
+
}
|
|
539
614
|
if (event.type === "session.deleted") {
|
|
540
615
|
const path = transcriptPath(sessionID)
|
|
541
616
|
if (path) rmSync(path, { force: true })
|
|
@@ -562,6 +637,7 @@ export const CclSkills = async (context: {
|
|
|
562
637
|
},
|
|
563
638
|
|
|
564
639
|
dispose: async () => {
|
|
640
|
+
pendingSkills.clear()
|
|
565
641
|
if (stateRoot) rmSync(stateRoot, { recursive: true, force: true })
|
|
566
642
|
stateRoot = null
|
|
567
643
|
},
|
|
@@ -3,12 +3,24 @@ description: Install or refresh CCL skills for OpenCode
|
|
|
3
3
|
argument-hint: "[--project]"
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
Install or reapply the CCL assets using the current installation mode. Check the existing CCL installation record and available entrypoint before running a command.
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
For an npm installation, reapply the invoked package's OpenCode assets:
|
|
9
9
|
|
|
10
10
|
```bash
|
|
11
|
-
|
|
11
|
+
ccl-skills install --host opencode
|
|
12
12
|
```
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
For a newer package version, follow `/ccl-update-skills`. The npm package does not include the source installer or support `--project`; do not forward that flag to the npm CLI.
|
|
15
|
+
|
|
16
|
+
For a source checkout, locate the actual CCL repository and verify its installer exists. By default, from that checkout run:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
bash scripts/install-opencode.sh --no-agent $ARGUMENTS
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Use `--project` only for source mode when the user wants `.opencode/skills`, `.opencode/commands`, and `.opencode/plugins` copied into that checkout. Do not run a relative source-installer path in an unrelated project.
|
|
23
|
+
|
|
24
|
+
For a global source installation, omit `--no-agent` when the user also needs `~/.agents/skills` for another tool. To sync only that compatibility path, run `bash scripts/install-opencode.sh --only-agent`; this mode does not install OpenCode assets and cannot be combined with `--project` or `--no-agent`.
|
|
25
|
+
|
|
26
|
+
After OpenCode assets change, restart OpenCode or open a new session. After a compatibility-only sync, restart the tool that reads `~/.agents/skills`.
|
|
@@ -1059,7 +1059,15 @@ def main(argv):
|
|
|
1059
1059
|
head_enabled = enabled(head_cfg)
|
|
1060
1060
|
base_enabled = enabled(base_cfg)
|
|
1061
1061
|
|
|
1062
|
-
|
|
1062
|
+
# --no-renames so a file moved OUT of a gated directory is still seen at its old
|
|
1063
|
+
# (gated) path; rename detection would only report the exempt destination.
|
|
1064
|
+
# --ignore-submodules=none so repository config (diff.ignoreSubmodules=all) cannot
|
|
1065
|
+
# suppress a gitlink move out of the gated tree, which would leave only .gitmodules.
|
|
1066
|
+
diff = run_git(
|
|
1067
|
+
["diff", "-z", "--name-only", "--no-renames", "--ignore-submodules=none", base, "HEAD"],
|
|
1068
|
+
cwd=repo,
|
|
1069
|
+
text=False,
|
|
1070
|
+
)
|
|
1063
1071
|
if diff.returncode != 0:
|
|
1064
1072
|
return fail("owner-dispatch ci: diff failed — FAIL-CLOSED (2)")
|
|
1065
1073
|
changed = [p.decode("utf-8", "surrogateescape") for p in diff.stdout.split(b"\0") if p]
|
|
@@ -1183,7 +1191,10 @@ cmd_ci() {
|
|
|
1183
1191
|
# file (NUL can't survive a shell var) so paths with spaces/newlines classify exactly.
|
|
1184
1192
|
local CHANGED=() difftmp rel
|
|
1185
1193
|
difftmp=$(mktemp 2>/dev/null) || { echo "owner-dispatch ci: mktemp failed — FAIL-CLOSED (2)" >&2; return 2; }
|
|
1186
|
-
|
|
1194
|
+
# -C "$repo" so diff.relative cannot truncate the set when ci runs from a subdirectory;
|
|
1195
|
+
# --no-renames and --ignore-submodules=none: see the Python path above. Both paths must
|
|
1196
|
+
# classify the same file set regardless of repository diff configuration or cwd.
|
|
1197
|
+
git -C "$repo" diff -z --name-only --no-renames --ignore-submodules=none "$base" HEAD > "$difftmp" 2>/dev/null || { rm -f "$difftmp"; echo "owner-dispatch ci: diff failed — FAIL-CLOSED (2)" >&2; return 2; }
|
|
1187
1198
|
while IFS= read -r -d '' rel; do CHANGED+=("$rel"); done < "$difftmp"
|
|
1188
1199
|
rm -f "$difftmp"
|
|
1189
1200
|
|
|
@@ -523,6 +523,59 @@ echo "// z" >> "$REPO/src/foo.go"; gc more
|
|
|
523
523
|
# 10i. CI fails CLOSED when it cannot determine a base (no --base, no upstream).
|
|
524
524
|
if ( cd "$REPO" && bash "$ENGINE" ci >/dev/null 2>&1 ); then bad "ci no-base should fail-closed"; else ok "ci: no base => fail-closed (non-zero)"; fi
|
|
525
525
|
|
|
526
|
+
# 10j. a gated file moved OUT of the gated tree is still a gated change. Two ways the diff
|
|
527
|
+
# can hide it: rename detection resolves a pure move to the exempt destination only,
|
|
528
|
+
# and diff.ignoreSubmodules=all drops a moved gitlink entirely. Both ci paths (jq and
|
|
529
|
+
# the python fallback) must classify the same set, so each case runs on both.
|
|
530
|
+
command -v jq >/dev/null 2>&1 || bad "ci rename-out: jq absent" "the jq lane would silently be a second python run"
|
|
531
|
+
[ -z "$(PATH="$NOJQBIN" command -v jq || true)" ] || bad "ci rename-out: NOJQBIN still resolves jq" "the python lane would silently be a second jq run"
|
|
532
|
+
printf '%s\n' "$EN" | rawcfg
|
|
533
|
+
mkdir -p "$REPO/design" "$REPO/exempt"; echo "owners: x" > "$REPO/design/map.md"
|
|
534
|
+
echo "package x" > "$REPO/src/moved.go"; gc renamebase
|
|
535
|
+
rnbase=$(git -C "$REPO" rev-parse HEAD)
|
|
536
|
+
git -C "$REPO" config diff.renames true # else the base engine reports the source anyway
|
|
537
|
+
git -C "$REPO" mv src/moved.go exempt/moved.go; gc renameout
|
|
538
|
+
jq_rc=0; jq_out=$( cd "$REPO" && bash "$ENGINE" ci --base "$rnbase" 2>&1 ) || jq_rc=$?
|
|
539
|
+
py_rc=0; py_out=$( cd "$REPO" && PATH="$NOJQBIN" bash "$ENGINE" ci --base "$rnbase" 2>&1 ) || py_rc=$?
|
|
540
|
+
[ "$jq_rc" = 1 ] && [ "$py_rc" = 1 ] && ok "ci: gated file renamed out of scope, stale map => fail on both lanes" || bad "ci rename-out rc" "jq=$jq_rc py=$py_rc"
|
|
541
|
+
case "$jq_out$py_out" in *src/moved.go*src/moved.go*) ok "ci rename-out: both lanes name the gated source path" ;; *) bad "ci rename-out diagnostic" "$jq_out | $py_out" ;; esac
|
|
542
|
+
# cwd must not change the verdict: with diff.relative=true a diff run from a subdirectory
|
|
543
|
+
# would drop paths outside it, and the two lanes would disagree.
|
|
544
|
+
git -C "$REPO" config diff.relative true
|
|
545
|
+
rel_jq=0; ( cd "$REPO/exempt" && bash "$ENGINE" ci --base "$rnbase" >/dev/null 2>&1 ) || rel_jq=$?
|
|
546
|
+
rel_py=0; ( cd "$REPO/exempt" && PATH="$NOJQBIN" bash "$ENGINE" ci --base "$rnbase" >/dev/null 2>&1 ) || rel_py=$?
|
|
547
|
+
[ "$rel_jq" = 1 ] && [ "$rel_py" = 1 ] && ok "ci: run from a subdirectory under diff.relative=true => still fail on both lanes" || bad "ci rename-out relative rc" "jq=$rel_jq py=$rel_py"
|
|
548
|
+
git -C "$REPO" config --unset diff.relative
|
|
549
|
+
echo "owners: y" >> "$REPO/design/map.md"; gc renameoutmap
|
|
550
|
+
ok_jq=0; ( cd "$REPO" && bash "$ENGINE" ci --base "$rnbase" >/dev/null 2>&1 ) || ok_jq=$?
|
|
551
|
+
ok_py=0; ( cd "$REPO" && PATH="$NOJQBIN" bash "$ENGINE" ci --base "$rnbase" >/dev/null 2>&1 ) || ok_py=$?
|
|
552
|
+
[ "$ok_jq" = 0 ] && [ "$ok_py" = 0 ] && ok "ci: renamed-out gated file with updated map => ok on both lanes" || bad "ci rename-out with map" "jq=$ok_jq py=$ok_py"
|
|
553
|
+
# an option-like base must be rejected before any diff runs, on both lanes
|
|
554
|
+
for badbase in "--output=$WORK/pwned" "-z"; do
|
|
555
|
+
b_jq=0; ( cd "$REPO" && bash "$ENGINE" ci --base "$badbase" >/dev/null 2>&1 ) || b_jq=$?
|
|
556
|
+
b_py=0; ( cd "$REPO" && PATH="$NOJQBIN" bash "$ENGINE" ci --base "$badbase" >/dev/null 2>&1 ) || b_py=$?
|
|
557
|
+
[ "$b_jq" = 2 ] && [ "$b_py" = 2 ] && ok "ci: option-like base '$badbase' => fail-closed(2) on both lanes" || bad "ci option-base rc" "jq=$b_jq py=$b_py"
|
|
558
|
+
done
|
|
559
|
+
[ ! -e "$WORK/pwned" ] && ok "ci: option-like base created no file" || bad "ci option-base wrote a file"
|
|
560
|
+
|
|
561
|
+
# 10j2. the same bypass through a submodule, which repository config can hide outright.
|
|
562
|
+
SUBSRC="$WORK/subsrc"; mkdir -p "$SUBSRC"
|
|
563
|
+
git -C "$SUBSRC" init -q; git -C "$SUBSRC" config user.email t@t; git -C "$SUBSRC" config user.name t
|
|
564
|
+
echo hi > "$SUBSRC/f.txt"; git -C "$SUBSRC" add -A; git -C "$SUBSRC" commit -qm sub
|
|
565
|
+
sub_err=$(git -C "$REPO" -c protocol.file.allow=always submodule add -q "$SUBSRC" src/vendor 2>&1) || true
|
|
566
|
+
if [ -e "$REPO/src/vendor/f.txt" ]; then
|
|
567
|
+
gc subbase
|
|
568
|
+
sub_base=$(git -C "$REPO" rev-parse HEAD)
|
|
569
|
+
git -C "$REPO" config diff.ignoreSubmodules all
|
|
570
|
+
git -C "$REPO" mv src/vendor exempt/vendor; gc submove
|
|
571
|
+
sm_jq=0; sm_jq_out=$( cd "$REPO" && bash "$ENGINE" ci --base "$sub_base" 2>&1 ) || sm_jq=$?
|
|
572
|
+
sm_py=0; sm_py_out=$( cd "$REPO" && PATH="$NOJQBIN" bash "$ENGINE" ci --base "$sub_base" 2>&1 ) || sm_py=$?
|
|
573
|
+
[ "$sm_jq" = 1 ] && [ "$sm_py" = 1 ] && ok "ci: submodule moved out of scope under diff.ignoreSubmodules=all => fail on both lanes" || bad "ci submodule-move rc" "jq=$sm_jq py=$sm_py"
|
|
574
|
+
git -C "$REPO" config --unset diff.ignoreSubmodules
|
|
575
|
+
else
|
|
576
|
+
bad "ci submodule-move: could not create the submodule fixture" "$sub_err"
|
|
577
|
+
fi
|
|
578
|
+
|
|
526
579
|
# ---- 11. SubagentStop: agent_id-scoped enforcement (the same engine handles Stop +
|
|
527
580
|
# SubagentStop; agent_id is present only for the latter and scopes markers/cap). ----
|
|
528
581
|
rm -rf "$BDIR"
|
|
@@ -5,7 +5,7 @@ description: Use when designing, implementing, reviewing, debugging, testing, or
|
|
|
5
5
|
|
|
6
6
|
# App Cross-Platform Dev
|
|
7
7
|
|
|
8
|
-
Use this skill for mobile app and cross-platform client engineering. It covers Flutter, React Native, native Android, and native iOS. It does not own mini-programs, React web, backend service design, product requirements, or visual design rules.
|
|
8
|
+
Use this skill for mobile app and cross-platform client engineering. It covers Flutter, React Native, native Android, and native iOS. It does not own mini-programs, React web, backend service design, product requirements, or visual design rules. After code/test edits, self-check and invoke `code-review` automatically before completion.
|
|
9
9
|
|
|
10
10
|
## Routing
|
|
11
11
|
|
|
@@ -15,7 +15,7 @@ Use this skill for mobile app and cross-platform client engineering. It covers F
|
|
|
15
15
|
- Use `web-react-dev` for React web and browser-specific client work.
|
|
16
16
|
- Use Go or Python backend skills for server contracts, persistence, queues, auth services, and API ownership.
|
|
17
17
|
- Use `testing-strategy` to choose the test layer; return here for Flutter, React Native, Android, or iOS implementation details.
|
|
18
|
-
- Use `test-artifact-management`
|
|
18
|
+
- Use `test-artifact-management` for structured Feishu Bitable cases derived from Feishu requirements or code before implementation.
|
|
19
19
|
- Use `defect-diagnosis` first for bugs, failed tests, flaky behavior, crashes, rendering regressions, build failures, or store/release symptoms.
|
|
20
20
|
- For money, quota, permission, tenant/user data, high-impact AI, repeated submit, async finality, or support-traceable incidents, apply `product-rd-workflow` high-risk resilience gates before treating the app flow as complete.
|
|
21
21
|
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: code-review
|
|
3
|
-
description: Use
|
|
3
|
+
description: Use automatically after changing code or executable tests, before completion or landing handoff, even without a user review request. Obtain independent CLI review/challenge across Claude Code, Kimi, OpenCode, or Codex by capability, model-family independence, and the user's client order; also covers Claude-only consultation, code review, Claude review, Kimi review, OpenCode review, second opinion, 找茬, 唱反调, or 第二意见. Skip 改动/提交值不值得修这类交付裁决 → product-rd-workflow;本技能执行评审,不裁决交付价值。
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Code Review
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
After changing code or executable tests, invoke this skill automatically before completion or landing handoff; follow `references/development-completion.md`. Compatible hosts obtain independent review/challenge here, never delegate implementation. The caller supplies the implementer's model family so the router excludes same-family reviewers.
|
|
9
9
|
|
|
10
10
|
## Modes
|
|
11
11
|
|
|
@@ -13,7 +13,7 @@ Choose the smallest useful mode:
|
|
|
13
13
|
|
|
14
14
|
- **Review mode**: normal pre-merge or plan review. Find blocking or materially misleading issues.
|
|
15
15
|
- **Challenge mode**: adversarial pass modeled after `codex challenge`. Try to break the diff or decision by finding production failure paths.
|
|
16
|
-
- **Complete mode**: local exact-candidate
|
|
16
|
+
- **Complete mode**: local exact-candidate checkpoint after passing review or bound source refutations under the staged contract. It invokes no reviewer and grants no merge authority.
|
|
17
17
|
- **Consult mode**: ask Claude a bounded question when no diff or plan review is needed.
|
|
18
18
|
|
|
19
19
|
Use challenge mode when the user asks for "challenge", "poke holes", "try to break it", "adversarial", or when the change touches money, permissions, privacy, compliance, tenant/user data, production rollout, high-impact AI, architecture, economics, or IA.
|
|
@@ -74,7 +74,7 @@ Positive challenge capacity opens it at index 1; budget zero is untracked.
|
|
|
74
74
|
The sole release/high-risk budget-zero exception is a controller-proved
|
|
75
75
|
`markdown-punctuation-only` review: it requires `wording_only_boundary`, permits
|
|
76
76
|
no `complete`, and rejects an author assertion alone (recipe:
|
|
77
|
-
`references/staged-review-contract.md`). After a clean tracked
|
|
77
|
+
`references/staged-review-contract.md`). After a clean/source-refuted tracked
|
|
78
78
|
challenge, `complete` may close early and preserve unused rounds. Every result
|
|
79
79
|
exposes controller-owned `self_review_gate`; an outstanding checkpoint blocks
|
|
80
80
|
only external review or completion, not implementation or tests. Even a passed
|
|
@@ -215,10 +215,11 @@ Run the script by path while keeping `--cwd` pointed at the product repository u
|
|
|
215
215
|
|
|
216
216
|
**The packet is the reviewer's whole world — compose it deliberately.** Review and challenge are built packet-bounded — Claude runs `--tools ""` with no `--add-dir`, and the other wrappers run in an isolated run workspace or a packet-only read surface. Treat the packet as the reviewer's whole world when deciding coverage: it is the only content bound by the packet hash and scanned before egress, so anything outside it is neither reliably visible to the reviewer nor covered by the verdict; a diff-only packet surfaces defects visible inside the changed lines and little else, and `--paths` only narrows it further. Whatever is absent from the packet is unreachable, not merely missed: a contradiction with an unchanged sibling clause, drift against a carrier outside the diff, or a silent weakening of upstream wording cannot be found by a reviewer who never saw the other side — that is the packet's shape, not the reviewer's weakness.
|
|
217
217
|
|
|
218
|
+
- Codex permits frozen-packet read/search; see [tool boundaries](references/development-completion.md#review-tools).
|
|
218
219
|
- To widen the packet, assemble it yourself and pass `--diff-file`: it replaces base-derived generation, is mutually exclusive with `--base`/`--paths`, and must name a regular file (no symlink or hardlink) holding text without NUL bytes. Worth adding beyond the diff — the canonical rule or contract text the changed lines must not contradict, the sibling clauses in the same file, the derived carriers that restate the change (commit message, MR/PR body), and the actual output of a gate or script under review. The gate hard-caps a packet at 200,000 bytes; split a larger candidate as described in the next bullet.
|
|
219
220
|
- A verdict covers exactly the packet it was taken on, because the recorded packet hash is the reviewed identity. Within a packet, added context sits on top of the candidate diff and never in place of part of it. A candidate too large for one packet is split by file group or risk class into a partition that still covers the whole candidate — every part in some packet, none dropped — each partition's verdict recorded against its own packet hash, and the candidate-wide claim withheld until every partition is conclusive; one partition's `no blocking findings` is never a verdict on the landing candidate. Cross-partition contradictions are unreachable by construction, so repeat the shared canonical context in every partition's packet and review anything that spans partitions as its own packet.
|
|
220
221
|
- Added context egresses to the selected reviewer exactly like the diff does, through the same credential tripwire — which catches machine-detectable secrets only. Paste rule text, carriers, and tool output; never paste credentials or material you would not send to that provider.
|
|
221
|
-
- A finding that the input is insufficient to judge the change is an input defect, not a candidate defect: widen the packet and rerun that lane rather than editing the candidate to satisfy it.
|
|
222
|
+
- A finding that the input is insufficient to judge the change is an input defect, not a candidate defect: widen the packet and rerun that lane rather than editing the candidate to satisfy it.
|
|
222
223
|
|
|
223
224
|
When intentionally reviewing `code-review` itself, override the resolver from the ccl-skills repo under review before invoking the gate:
|
|
224
225
|
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Automatic review after development
|
|
2
|
+
|
|
3
|
+
This transition applies across implementation owners, including narrow fixes and executable-test changes. Do not wait for the user to request review. Use the actual diff to classify the work: an implementation diff triggers this transition regardless of the task label. Read-only investigation, status answers and design-only work retain their owning workflow; they do not acquire an implementation-review requirement merely by using a development skill.
|
|
4
|
+
|
|
5
|
+
## Before invoking review
|
|
6
|
+
|
|
7
|
+
1. Recover the current task, actual diff, scope and authorization. Changing the implementation or scope reopens this check; an earlier plan review cannot discharge review of the resulting code.
|
|
8
|
+
2. Finish proportionate implementer self-review and affected verification. A failed quality check calls for available in-scope diagnosis and cleanup under [refactoring discipline](../../product-rd-workflow/references/refactoring-discipline.md#responding-to-quality-gates); preserve behavior and readability, rerun the check, and escalate only a remaining real blocker. Use `testing-strategy` to select tests: changed named test properties require the killing-mutation walk on disposable or restore-guarded resources; when the same contract has two implementations or paths, use differential/equivalence checks with bounded, asserted known differences. Record a concrete applicability or unavailable-evidence reason when a test family does not run. Do not force a full mutation framework or differential suite onto an unrelated change.
|
|
9
|
+
3. Reuse a terminal independent review only when it covers the current candidate and satisfies the applicable owner gate, reviewer independence and required depth. Record the receipt location and its candidate identifier (commit or diff/packet digest), then compare with the current candidate using the owning gate's binding rules; HEAD alone cannot cover uncommitted edits. A different or missing candidate identifier cannot discharge review. A loaded skill, self-review, planned command, unfinished handle or unverified prose claim is not that evidence. A native subagent result counts only when the owning gate accepts its independence and evidence; it never silently substitutes for a required CLI receipt.
|
|
10
|
+
4. An explicit user instruction to skip review controls this task: record `skipped`, not `passed`, and preserve any separate landing restrictions. Record its original wording and current scope; a superseded or unrelated instruction is not a skip for this task. Do not ask for confirmation of ordinary review already within the authorized development task. User client restrictions and existing confidentiality boundaries still control reviewer selection; capability matters, not a numeric CLI or skill version.
|
|
11
|
+
|
|
12
|
+
## Invoke and finish
|
|
13
|
+
|
|
14
|
+
When no valid current review discharges the requirement, invoke `scripts/review_gate.sh` from this skill's actual installed/source directory with the current candidate, real implementer family, user client order and applicable risk tags. Follow the entrypoint's script contract; narrow work may use its derived-default plan. Use ordinary review for ordinary development; challenge and additional owner gates apply when triggered. Do not inflate a narrow repair into a product-design or shared-skill review ceremony.
|
|
15
|
+
|
|
16
|
+
Invoke the reviewer in the same turn once self-checks are ready. Await an existing handle to its terminal result; do not stop at “review next,” start a duplicate process, or present timeout, invalid output or authentication failure as pass. Handle operational failures using the existing bounded recovery rules; a stopped reviewer lane does not stop safe independent work or authorize completion.
|
|
17
|
+
|
|
18
|
+
Verify each finding against the actual call path and evidence. Fix confirmed defects and rerun affected checks; record evidenced rejection, deferral or acceptance under the owning gate. Pre-existing issues and optional suggestions do not automatically expand the task. After a tracked review and challenge on the unchanged candidate, when every finding is source-refuted, run the local disposition completion path in [the staged contract](staged-review-contract.md#mechanical-self-review-gate). Keep the raw findings; do not rerun merely to obtain zero findings or reset a review budget. Budget exhaustion limits reviewer calls, so finish available disposition, self-review and validation work in the same turn. A changed candidate still needs the owning gate's renewed review.
|
|
19
|
+
|
|
20
|
+
Before completion or landing handoff, report the actual diff classification and a concrete reason if review is inapplicable. Support that classification with the change-inspection command and result, including untracked implementation files. Report the actual review outcome and candidate it covers, relevant tests and their results, skips, unresolved findings and remaining restrictions. A failed or missing required review leaves review/completion pending. Review does not grant permission to commit, push, merge, publish or deploy.
|
|
21
|
+
|
|
22
|
+
## Review tools
|
|
23
|
+
|
|
24
|
+
Packet-only allows read-only tools over the frozen material. Codex exposes pathless `read_packet` and `search_packet`; the parser checks returned content against the same packet and requires completed calls. Each server read checks the packet hash. Shell execution is disabled by effective capability, and inherited MCP servers are disabled only for this invocation. Unsupported capability falls back without a CLI version requirement. A read-only sandbox alone does not disable commands.
|
|
25
|
+
|
|
26
|
+
Installed owner skills supply review lenses, not permission to execute development workflows or fetch references outside the packet. Add missing source context to the packet through the entrypoint's packet-composition contract. Read/search does not expand the verdict's coverage beyond its recorded packet.
|
|
@@ -8,10 +8,10 @@ The controller has three modes:
|
|
|
8
8
|
|
|
9
9
|
Explore/build may configure `challenge_budget=0..4`; release/high-risk requires
|
|
10
10
|
at least one challenge unless the exact candidate qualifies for the
|
|
11
|
-
proof-bound wording-only single-review exception below. The initial review consumes
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
The budget is a ceiling, not a quota: after a clean tracked challenge, local
|
|
11
|
+
proof-bound wording-only single-review exception below. The initial review consumes chain round 1;
|
|
12
|
+
each bounded chain uses at most five rounds. Necessary task-scoped review after a
|
|
13
|
+
checkpoint inherits existing task authority; attribute explicit human round requests separately.
|
|
14
|
+
The budget is a ceiling, not a quota: after a clean or fully source-refuted tracked challenge, local
|
|
15
15
|
`complete` may close the chain early. It preserves unused-round count but sets
|
|
16
16
|
`autonomous_review_allowed=false`; release/high-risk still requires at least one
|
|
17
17
|
challenge before this early close is eligible.
|
|
@@ -283,7 +283,7 @@ Multi-round Agent automation supplies `review_chain_id`, a contiguous
|
|
|
283
283
|
`autonomous_review_index` in `1..5`, and every earlier result through ordered
|
|
284
284
|
`--prior-review-result-file` arguments. Prior rounds may contain findings and
|
|
285
285
|
older candidate hashes; they remain consumed. Candidate edits, commits, plan
|
|
286
|
-
refreshes, mode changes, and renamed invocations
|
|
286
|
+
refreshes, mode changes, and renamed invocations never erase spending or broaden task authority.
|
|
287
287
|
An initial `review` with positive challenge capacity must start this chain at
|
|
288
288
|
index 1; an untracked initial review is single-round and therefore uses budget 0.
|
|
289
289
|
|
|
@@ -324,7 +324,7 @@ Envelope `schema_version` is `3`; a legacy `2` envelope predates the recorded
|
|
|
324
324
|
scope and is rejected, which requires restarting an in-flight chain. Every
|
|
325
325
|
prior round must retain the same controller digest, owner-selection source,
|
|
326
326
|
selected owner names, and selected-owner digest. Missing, substituted,
|
|
327
|
-
inconclusive, reordered, renamed-chain, or
|
|
327
|
+
inconclusive, reordered, renamed-chain, or over-budget input fails before any
|
|
328
328
|
provider runs. Scope drift returns `review_scope_changed` and requires deep
|
|
329
329
|
self-review plus explicit task reframing; it does not silently create a new
|
|
330
330
|
Agent budget. An untracked challenge is one-off advisory evidence; it cannot
|
|
@@ -332,8 +332,8 @@ enter a later Agent round or satisfy the local completion checkpoint.
|
|
|
332
332
|
|
|
333
333
|
Two consequences follow from those stable bindings and must be planned for before round 1:
|
|
334
334
|
|
|
335
|
-
- The selected-owner digest hashes each selected owner package's current working tree, and owners derive from the candidate's own paths — so a candidate edit inside any selected owner package invalidates every prior receipt and the next tracked round fails `review_chain_invalid`. For a self-hosted candidate (a skill-repo diff editing the package that owns it) that is nearly every applied fix — one confined to files outside every selected owner drifts only the candidate hash and may continue in-chain:
|
|
336
|
-
- A chain restarted after such a break
|
|
335
|
+
- The selected-owner digest hashes each selected owner package's current working tree, and owners derive from the candidate's own paths — so a candidate edit inside any selected owner package invalidates every prior receipt and the next tracked round fails `review_chain_invalid`. For a self-hosted candidate (a skill-repo diff editing the package that owns it) that is nearly every applied fix — one confined to files outside every selected owner drifts only the candidate hash and may continue in-chain: in-chain tolerance for older candidate hashes applies only while fixes stay outside selected owners. Necessary recovery uses fresh bindings after the task checkpoint below.
|
|
336
|
+
- A chain restarted after such a break never erases cumulative spending or task history. An existing task includes necessary fixes, tests and review by default. At exhaustion, first disposition findings from source, run deep self-review and tests, and change the failed method or add missing evidence before another necessary bounded sequence. Record `continuation_basis=existing-task-scope`, the original authority reference and scope, the reason and changed method/evidence, cumulative rounds, and old/new sequence links in the caller-owned task artifact. Preserve every earlier receipt, focus and disposition; do not add this field to CLI arguments or runtime receipts. Existing per-chain and consuming-owner sequence bounds still apply; the extraction recipe remains in its dual-track gate reference. No repeated calls solely to obtain an empty verdict, invented human round requests, history reset or ignored user cost/round/stop limit is allowed.
|
|
337
337
|
|
|
338
338
|
The controller is stateless and prevents accidental/cooperative resets only. A
|
|
339
339
|
trusted host or platform must retain the ledger when hostile local callers are in
|
|
@@ -370,10 +370,34 @@ allowing refreshed self-review conclusions and evidence, and is the Agent path t
|
|
|
370
370
|
round index, prior-result hashes, and prior challenge focuses. It is not a human
|
|
371
371
|
waiver or merge authorization.
|
|
372
372
|
|
|
373
|
+
For an unchanged candidate with a conclusive tracked review and challenge,
|
|
374
|
+
`complete` also accepts `--finding-dispositions-file`. Supply every earlier raw
|
|
375
|
+
receipt with ordered `--prior-review-result-file` arguments and the final one
|
|
376
|
+
with `--completion-review-result-file`. The UTF-8 JSON has `schema_version: 1`,
|
|
377
|
+
`candidate_sha256`, ordered `review_result_sha256` hashes including the final
|
|
378
|
+
receipt, and `dispositions`. Each disposition contains `receipt_sha256`, the
|
|
379
|
+
canonical-JSON `finding_sha256`, `disposition: "source_refuted"`, and a non-empty
|
|
380
|
+
`evidence` array naming the first-hand source or failure-path counter-evidence.
|
|
381
|
+
Every original finding occurrence must appear exactly once. Within one receipt,
|
|
382
|
+
findings with identical canonical content share one hash-pair identity in
|
|
383
|
+
first-seen order; retain every raw entry unchanged. Different content or a
|
|
384
|
+
different receipt remains a separate occurrence. Missing history,
|
|
385
|
+
changed candidates, inconclusive results, open findings and risk acceptance do
|
|
386
|
+
not qualify. A code fix with changed bytes requires renewed review.
|
|
387
|
+
|
|
388
|
+
This local checkpoint records `completion_basis=source_refuted_findings`, the
|
|
389
|
+
dispositions digest and resolved occurrence bindings; original external
|
|
390
|
+
findings remain unchanged. A clean external result uses `external_pass`.
|
|
391
|
+
Validation proves binding and coverage, not the truth of an evidence statement:
|
|
392
|
+
the implementer must trace the cited source, and the judgment remains open to
|
|
393
|
+
challenge. No budget is refreshed and no model is called. At the review cap,
|
|
394
|
+
finish this local work instead of requesting another round solely to obtain an
|
|
395
|
+
empty verdict. Unresolved findings still block completion, not independent work.
|
|
396
|
+
|
|
373
397
|
## Human and failure boundary
|
|
374
398
|
|
|
375
|
-
|
|
376
|
-
resume, waiver, commit, or merge authority. A `review_waiver` clears only the
|
|
399
|
+
Existing task scope covers necessary continuation; exhaustion alone creates no new grant.
|
|
400
|
+
Only an external authenticated platform action may prove new human request, stop, resume, waiver, commit, or merge authority. A `review_waiver` clears only the
|
|
377
401
|
review-process gate. A distinct exact-candidate `merge_authorization` is the
|
|
378
402
|
human's final decision: CI may keep running and reporting every failed/pending
|
|
379
403
|
gate, but none may block that authorized merge. Report
|
|
@@ -381,9 +405,9 @@ gate, but none may block that authorized merge. Report
|
|
|
381
405
|
|
|
382
406
|
Provider/input/integrity failures stop that reviewer lane, not the whole task.
|
|
383
407
|
Their stable action is `stop_reviewer_lane`, never the ambiguous `stop`.
|
|
384
|
-
Budget exhaustion
|
|
385
|
-
|
|
386
|
-
|
|
408
|
+
Budget exhaustion triggers the method/authority checkpoint, not an automatic user handoff. Check legacy
|
|
409
|
+
`human_decision_required` / `continuation_authorization_required` against existing task scope first.
|
|
410
|
+
Continue necessary bounded review; enter `awaiting_human` only for a genuine missing decision, explicit user limit or authority outside that scope.
|
|
387
411
|
|
|
388
412
|
The current result envelope is schema 3. The generic per-invocation `--timeout`
|
|
389
413
|
keeps its 600-second default and accepts 5..1200 seconds; direct wrappers clamp
|
|
@@ -5,8 +5,11 @@ parsers for Claude, Kimi, OpenCode, and Codex.
|
|
|
5
5
|
|
|
6
6
|
Rules:
|
|
7
7
|
|
|
8
|
-
- Preserve
|
|
9
|
-
|
|
8
|
+
- Preserve the packet boundary and structured output validation. A wrapper may
|
|
9
|
+
expose pathless read/search tools over its frozen, hash-bound packet; verify
|
|
10
|
+
their arguments, returned bytes and completed lifecycle. This does not permit
|
|
11
|
+
arbitrary commands or workspace access. A malformed, timeout, or inconclusive
|
|
12
|
+
wrapper result is not a pass.
|
|
10
13
|
- **Never pin the parser to a CLI version's vocabulary.** `parse_probe_result.py`
|
|
11
14
|
gates on *shape*, not on field/value names: the isolation proof is the exact
|
|
12
15
|
`tools` allowlist plus the tool_use scan, which no init field can bypass.
|