@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/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/codex_review.sh
CHANGED
|
@@ -140,10 +140,15 @@ CODEX_EXEC_HELP="$(timeout --kill-after=1s 5s "$CODEX_BIN_PATH" exec --disable h
|
|
|
140
140
|
# supported lifecycle state: `features list` still prints removed keys, and a
|
|
141
141
|
# removed or unknown-state row means `--disable hooks` may be a silent no-op
|
|
142
142
|
# that lets user-trusted hooks run during packet-only review.
|
|
143
|
-
CODEX_FEATURES_LIST="$(timeout --kill-after=1s 5s "$CODEX_BIN_PATH" features list 2>/dev/null)" \
|
|
143
|
+
CODEX_FEATURES_LIST="$(timeout --kill-after=1s 5s "$CODEX_BIN_PATH" features list --disable hooks --disable shell_tool 2>/dev/null)" \
|
|
144
144
|
|| die_inconclusive codex_hook_disable_unavailable capability_missing true
|
|
145
|
-
grep -Eq '^hooks[[:space:]]+(stable|under development|experimental)
|
|
145
|
+
grep -Eq '^hooks[[:space:]]+(stable|under development|experimental)[[:space:]]+false[[:space:]]*$' <<<"$CODEX_FEATURES_LIST" \
|
|
146
146
|
|| die_inconclusive codex_hook_disable_unavailable capability_missing true
|
|
147
|
+
# A read-only sandbox still exposes command execution. Disable the actual
|
|
148
|
+
# shell surface, including its unified-exec implementation, before inference.
|
|
149
|
+
# Check effective capability rather than a CLI release number or flag parsing.
|
|
150
|
+
grep -Eq '^shell_tool[[:space:]]+(stable|under development|experimental)[[:space:]]+false[[:space:]]*$' <<<"$CODEX_FEATURES_LIST" \
|
|
151
|
+
|| die_inconclusive codex_shell_disable_unavailable capability_missing true
|
|
147
152
|
if [ -n "${CODEX_HOME:-}" ]; then
|
|
148
153
|
SOURCE_HOME="$CODEX_HOME"
|
|
149
154
|
else
|
|
@@ -240,6 +245,72 @@ fi
|
|
|
240
245
|
DIFF_TEXT="$(cat "$DIFF_FILE" || exit 1; printf '\001')" \
|
|
241
246
|
|| die_inconclusive diff_read_failed local_tool_failure false
|
|
242
247
|
DIFF_TEXT="${DIFF_TEXT%$'\001'}"
|
|
248
|
+
PACKET_FILE="$RUN_ROOT/packet.txt"
|
|
249
|
+
PACKET_SERVER="$SCRIPT_DIR/kimi_packet_mcp.py"
|
|
250
|
+
[ -f "$PACKET_SERVER" ] && [ -r "$PACKET_SERVER" ] && [ ! -L "$PACKET_SERVER" ] \
|
|
251
|
+
|| die_inconclusive packet_server_missing local_tool_failure false
|
|
252
|
+
printf '%s' "$DIFF_TEXT" >"$PACKET_FILE"
|
|
253
|
+
PACKET_SHA256="$(python3 - "$PACKET_FILE" <<'PY_HASH'
|
|
254
|
+
import hashlib, sys
|
|
255
|
+
from pathlib import Path
|
|
256
|
+
print(hashlib.sha256(Path(sys.argv[1]).read_bytes()).hexdigest())
|
|
257
|
+
PY_HASH
|
|
258
|
+
)" || die_inconclusive packet_hash_failed local_tool_failure false
|
|
259
|
+
MCP_CONFIG="$(python3 - "$PACKET_FILE" "$PACKET_SERVER" "$PACKET_SHA256" <<'PY_MCP_CONFIG'
|
|
260
|
+
import json, sys
|
|
261
|
+
values = [sys.argv[2], "--packet", sys.argv[1], "--sha256", sys.argv[3], "--allow-search"]
|
|
262
|
+
print('mcp_servers={code_review_packet={command=' + json.dumps(sys.executable)
|
|
263
|
+
+ ',args=[' + ','.join(json.dumps(value) for value in values)
|
|
264
|
+
+ '],enabled=true,enabled_tools=["read_packet","search_packet"]}}')
|
|
265
|
+
PY_MCP_CONFIG
|
|
266
|
+
)" || die_inconclusive packet_config_failed local_tool_failure false
|
|
267
|
+
# TOML overrides merge server tables. Disable inherited servers for this run
|
|
268
|
+
# without changing user configuration, then verify the effective public list.
|
|
269
|
+
CODEX_PACKET_CONFIG=(-c "$MCP_CONFIG" -c 'web_search="disabled"' -c 'approval_policy="never"')
|
|
270
|
+
CODEX_HOME="$SOURCE_HOME" timeout --kill-after=1s 5s "$CODEX_BIN_PATH" mcp list --json "${CODEX_PACKET_CONFIG[@]}" >"$RUN_ROOT/mcp.json" 2>"$STDERR_FILE" \
|
|
271
|
+
|| die_inconclusive codex_packet_tools_unavailable capability_missing true
|
|
272
|
+
MCP_CONFIG="$(python3 - "$RUN_ROOT/mcp.json" "$MCP_CONFIG" <<'PY_MCP_OVERRIDES'
|
|
273
|
+
import json, sys
|
|
274
|
+
from pathlib import Path
|
|
275
|
+
try:
|
|
276
|
+
rows = json.loads(Path(sys.argv[1]).read_text())
|
|
277
|
+
if not isinstance(rows, list):
|
|
278
|
+
raise ValueError()
|
|
279
|
+
disabled = []
|
|
280
|
+
for row in rows:
|
|
281
|
+
if not isinstance(row, dict) or not isinstance(row.get("name"), str) or not row["name"]:
|
|
282
|
+
raise ValueError()
|
|
283
|
+
if row["name"] != "code_review_packet":
|
|
284
|
+
disabled.append(json.dumps(row["name"]) + "={enabled=false}")
|
|
285
|
+
print(sys.argv[2][:-1] + "".join("," + entry for entry in disabled) + "}")
|
|
286
|
+
except (OSError, ValueError, TypeError):
|
|
287
|
+
sys.exit(1)
|
|
288
|
+
PY_MCP_OVERRIDES
|
|
289
|
+
)" || die_inconclusive codex_packet_tools_unavailable capability_missing true
|
|
290
|
+
CODEX_PACKET_CONFIG=(-c "$MCP_CONFIG" -c 'web_search="disabled"' -c 'approval_policy="never"')
|
|
291
|
+
CODEX_HOME="$SOURCE_HOME" timeout --kill-after=1s 5s "$CODEX_BIN_PATH" mcp list --json "${CODEX_PACKET_CONFIG[@]}" >"$RUN_ROOT/mcp.json" 2>"$STDERR_FILE" \
|
|
292
|
+
|| die_inconclusive codex_packet_tools_unavailable capability_missing true
|
|
293
|
+
python3 - "$RUN_ROOT/mcp.json" "$PACKET_FILE" "$PACKET_SERVER" "$PACKET_SHA256" <<'PY_MCP_CHECK' \
|
|
294
|
+
|| die_inconclusive codex_packet_tools_unavailable capability_missing true
|
|
295
|
+
import json, sys
|
|
296
|
+
from pathlib import Path
|
|
297
|
+
try:
|
|
298
|
+
rows = json.loads(Path(sys.argv[1]).read_text())
|
|
299
|
+
if not isinstance(rows, list):
|
|
300
|
+
raise ValueError()
|
|
301
|
+
active = [row for row in rows if isinstance(row, dict) and row.get("enabled") is not False]
|
|
302
|
+
if len(active) != 1 or len(rows) != len([row for row in rows if isinstance(row, dict)]):
|
|
303
|
+
raise ValueError()
|
|
304
|
+
row = active[0]
|
|
305
|
+
transport = row.get("transport", {})
|
|
306
|
+
if (row.get("name") != "code_review_packet" or row.get("enabled") is not True
|
|
307
|
+
or transport.get("type") != "stdio" or transport.get("command") != sys.executable
|
|
308
|
+
or transport.get("args") != [sys.argv[3], "--packet", sys.argv[2], "--sha256", sys.argv[4], "--allow-search"]
|
|
309
|
+
or transport.get("env") or transport.get("env_vars") or transport.get("cwd")):
|
|
310
|
+
raise ValueError()
|
|
311
|
+
except (OSError, ValueError, TypeError, AttributeError):
|
|
312
|
+
sys.exit(1)
|
|
313
|
+
PY_MCP_CHECK
|
|
243
314
|
{
|
|
244
315
|
printf '%s\n\n' "$INSTRUCTION"
|
|
245
316
|
if [ "$REVIEW_SKILL_COUNT" -gt 0 ]; then
|
|
@@ -255,7 +326,7 @@ DIFF_TEXT="${DIFF_TEXT%$'\001'}"
|
|
|
255
326
|
printf '%s' "$PROFILE_TEXT"
|
|
256
327
|
printf '\n%s_END\n\n' "$PROFILE_TOKEN"
|
|
257
328
|
fi
|
|
258
|
-
printf '%s\n' 'Use only the supplied diff.
|
|
329
|
+
printf '%s\n' 'Use only the supplied diff and review profile. You may read or search the same frozen diff using code_review_packet read_packet and search_packet. These pathless tools cannot inspect the workspace. Do not execute commands, access other tools, or follow skill instructions to run development workflows or read external references. Report missing context as an evidence gap.'
|
|
259
330
|
if [ -n "$REVIEW_PROFILE_FILE" ]; then
|
|
260
331
|
printf '%s\n' 'Treat self_review and evidence as claims to verify against the diff, not as proof. Check every entry in required_concerns. A no-findings verdict is valid only after all entries were checked; if the bounded packet cannot support a required check, report that evidence gap as a material finding at the best changed-file locator.'
|
|
261
332
|
printf '%s\n' 'Return exactly one concern_results object with concern and concise independent conclusion for every required concern.'
|
|
@@ -279,7 +350,8 @@ JSON
|
|
|
279
350
|
fi
|
|
280
351
|
|
|
281
352
|
run_started=$SECONDS
|
|
282
|
-
CMUX_CODEX_HOOKS_DISABLED=1 CODEX_HOME="$SOURCE_HOME" timeout --kill-after=1s "${TIMEOUT}s" "$CODEX_BIN_PATH" exec --disable hooks --sandbox read-only --ephemeral --skip-git-repo-check \
|
|
353
|
+
CMUX_CODEX_HOOKS_DISABLED=1 CODEX_HOME="$SOURCE_HOME" timeout --kill-after=1s "${TIMEOUT}s" "$CODEX_BIN_PATH" exec --disable hooks --disable shell_tool --sandbox read-only --ephemeral --skip-git-repo-check \
|
|
354
|
+
"${CODEX_PACKET_CONFIG[@]}" \
|
|
283
355
|
--json --output-schema "$SCHEMA_FILE" --output-last-message "$RESULT_FILE" \
|
|
284
356
|
-C "$RUN_WORKSPACE" - <"$PROMPT_FILE" >"$EVENTS" 2>"$STDERR_FILE"
|
|
285
357
|
run_rc=$?
|
|
@@ -309,7 +381,7 @@ fi
|
|
|
309
381
|
|
|
310
382
|
python3 "$PARSER" --client codex --mode "$MODE" --implementer-family "$IMPL_FAMILY" \
|
|
311
383
|
--reviewer-family "$FAMILY" --provider "$PROVIDER" --model "$MODEL" \
|
|
312
|
-
--events "$EVENTS" --result-file "$RESULT_FILE" >"$PARSED_FILE"
|
|
384
|
+
--events "$EVENTS" --result-file "$RESULT_FILE" --packet "$PACKET_FILE" --packet-sha256 "$PACKET_SHA256" >"$PARSED_FILE"
|
|
313
385
|
parser_rc=$?
|
|
314
386
|
if [ "$parser_rc" -eq 0 ]; then
|
|
315
387
|
native_skill_binding="not_requested"
|
package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/kimi_packet_mcp.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
-
"""Expose one SHA-256-bound review packet through
|
|
2
|
+
"""Expose one SHA-256-bound review packet through pathless stdio MCP tools."""
|
|
3
3
|
|
|
4
4
|
from __future__ import annotations
|
|
5
5
|
|
|
@@ -12,8 +12,11 @@ from typing import Any
|
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
TOOL_NAME = "read_packet"
|
|
15
|
+
SEARCH_TOOL_NAME = "search_packet"
|
|
15
16
|
MAX_PAGE_BYTES = 48_000
|
|
16
17
|
MAX_CHUNK_BYTES = 46_000
|
|
18
|
+
MAX_QUERY_BYTES = 1_024
|
|
19
|
+
MAX_SEARCH_RESULTS = 100
|
|
17
20
|
|
|
18
21
|
|
|
19
22
|
def packet_bytes(path: Path, expected_sha256: str) -> bytes:
|
|
@@ -57,6 +60,84 @@ def tool_result(text: str, *, error: bool = False) -> dict[str, Any]:
|
|
|
57
60
|
return {"content": [{"type": "text", "text": text}], "isError": error}
|
|
58
61
|
|
|
59
62
|
|
|
63
|
+
def search_tool_definition() -> dict[str, Any]:
|
|
64
|
+
return {
|
|
65
|
+
"name": SEARCH_TOOL_NAME,
|
|
66
|
+
"description": (
|
|
67
|
+
"Find non-overlapping, case-sensitive literal substrings in the one "
|
|
68
|
+
"controller-frozen review packet. No regex or filesystem paths. "
|
|
69
|
+
"Query is at most 1024 UTF-8 bytes; byte_offset must be a UTF-8 "
|
|
70
|
+
"boundary. Returns byte offsets and 1-based line numbers, with "
|
|
71
|
+
"next_byte_offset for more matches or null when exhausted. "
|
|
72
|
+
"Use read_packet at a match offset to inspect its context."
|
|
73
|
+
),
|
|
74
|
+
"inputSchema": {
|
|
75
|
+
"type": "object",
|
|
76
|
+
"properties": {
|
|
77
|
+
"query": {"type": "string", "minLength": 1, "maxLength": MAX_QUERY_BYTES},
|
|
78
|
+
"byte_offset": {"type": "integer", "minimum": 0},
|
|
79
|
+
"limit": {"type": "integer", "minimum": 1, "maximum": MAX_SEARCH_RESULTS},
|
|
80
|
+
},
|
|
81
|
+
"required": ["query", "byte_offset", "limit"],
|
|
82
|
+
"additionalProperties": False,
|
|
83
|
+
},
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def search_packet(path: Path, expected_sha256: str, arguments: Any) -> dict[str, Any]:
|
|
88
|
+
if not isinstance(arguments, dict) or set(arguments) != {"query", "byte_offset", "limit"}:
|
|
89
|
+
return tool_result("invalid packet search arguments", error=True)
|
|
90
|
+
query = arguments.get("query")
|
|
91
|
+
byte_offset = arguments.get("byte_offset")
|
|
92
|
+
limit = arguments.get("limit")
|
|
93
|
+
if (
|
|
94
|
+
not isinstance(query, str)
|
|
95
|
+
or not isinstance(byte_offset, int)
|
|
96
|
+
or isinstance(byte_offset, bool)
|
|
97
|
+
or byte_offset < 0
|
|
98
|
+
or not isinstance(limit, int)
|
|
99
|
+
or isinstance(limit, bool)
|
|
100
|
+
or not 1 <= limit <= MAX_SEARCH_RESULTS
|
|
101
|
+
):
|
|
102
|
+
return tool_result("invalid packet search arguments", error=True)
|
|
103
|
+
try:
|
|
104
|
+
needle = query.encode("utf-8")
|
|
105
|
+
except UnicodeEncodeError:
|
|
106
|
+
return tool_result("invalid packet search arguments", error=True)
|
|
107
|
+
if not 1 <= len(needle) <= MAX_QUERY_BYTES:
|
|
108
|
+
return tool_result("invalid packet search arguments", error=True)
|
|
109
|
+
try:
|
|
110
|
+
data = packet_bytes(path, expected_sha256)
|
|
111
|
+
except (OSError, ValueError):
|
|
112
|
+
return tool_result("packet binding changed", error=True)
|
|
113
|
+
if byte_offset > len(data):
|
|
114
|
+
return tool_result("packet search starts beyond end", error=True)
|
|
115
|
+
try:
|
|
116
|
+
data[:byte_offset].decode("utf-8")
|
|
117
|
+
except UnicodeDecodeError:
|
|
118
|
+
return tool_result("packet search starts inside a UTF-8 character", error=True)
|
|
119
|
+
|
|
120
|
+
matches = []
|
|
121
|
+
cursor = byte_offset
|
|
122
|
+
while len(matches) < limit:
|
|
123
|
+
found = data.find(needle, cursor)
|
|
124
|
+
if found < 0:
|
|
125
|
+
break
|
|
126
|
+
matches.append({"byte_offset": found, "line": data.count(b"\n", 0, found) + 1})
|
|
127
|
+
cursor = found + len(needle)
|
|
128
|
+
rendered = json.dumps(
|
|
129
|
+
{
|
|
130
|
+
"matches": matches,
|
|
131
|
+
"next_byte_offset": cursor if data.find(needle, cursor) >= 0 else None,
|
|
132
|
+
"total_bytes": len(data),
|
|
133
|
+
},
|
|
134
|
+
separators=(",", ":"),
|
|
135
|
+
)
|
|
136
|
+
if len(rendered.encode("utf-8")) > MAX_PAGE_BYTES:
|
|
137
|
+
return tool_result("packet search exceeds result bound", error=True)
|
|
138
|
+
return tool_result(rendered)
|
|
139
|
+
|
|
140
|
+
|
|
60
141
|
def read_chunk(path: Path, expected_sha256: str, arguments: Any) -> dict[str, Any]:
|
|
61
142
|
if not isinstance(arguments, dict) or set(arguments) != {"byte_offset", "max_bytes"}:
|
|
62
143
|
return tool_result("invalid packet chunk arguments", error=True)
|
|
@@ -119,7 +200,9 @@ def response(request_id: Any, *, result: Any = None, error: Any = None) -> dict[
|
|
|
119
200
|
return payload
|
|
120
201
|
|
|
121
202
|
|
|
122
|
-
def handle(
|
|
203
|
+
def handle(
|
|
204
|
+
message: Any, path: Path, expected_sha256: str, *, allow_search: bool = False
|
|
205
|
+
) -> dict[str, Any] | None:
|
|
123
206
|
if not isinstance(message, dict) or message.get("jsonrpc") != "2.0":
|
|
124
207
|
return response(None, error={"code": -32600, "message": "Invalid Request"})
|
|
125
208
|
request_id = message.get("id")
|
|
@@ -140,9 +223,17 @@ def handle(message: Any, path: Path, expected_sha256: str) -> dict[str, Any] | N
|
|
|
140
223
|
if method == "ping":
|
|
141
224
|
return response(request_id, result={})
|
|
142
225
|
if method == "tools/list":
|
|
143
|
-
|
|
226
|
+
definitions = [tool_definition()]
|
|
227
|
+
if allow_search:
|
|
228
|
+
definitions.append(search_tool_definition())
|
|
229
|
+
return response(request_id, result={"tools": definitions})
|
|
144
230
|
if method == "tools/call":
|
|
145
231
|
params = message.get("params")
|
|
232
|
+
if isinstance(params, dict) and allow_search and params.get("name") == SEARCH_TOOL_NAME:
|
|
233
|
+
return response(
|
|
234
|
+
request_id,
|
|
235
|
+
result=search_packet(path, expected_sha256, params.get("arguments")),
|
|
236
|
+
)
|
|
146
237
|
if not isinstance(params, dict) or params.get("name") != TOOL_NAME:
|
|
147
238
|
return response(request_id, result=tool_result("unknown tool", error=True))
|
|
148
239
|
return response(
|
|
@@ -156,6 +247,9 @@ def main() -> int:
|
|
|
156
247
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
157
248
|
parser.add_argument("--packet", required=True)
|
|
158
249
|
parser.add_argument("--sha256", required=True)
|
|
250
|
+
parser.add_argument(
|
|
251
|
+
"--allow-search", action="store_true", help="also expose bounded literal packet search"
|
|
252
|
+
)
|
|
159
253
|
args = parser.parse_args()
|
|
160
254
|
if not len(args.sha256) == 64 or any(ch not in "0123456789abcdef" for ch in args.sha256):
|
|
161
255
|
parser.error("--sha256 must be a lowercase SHA-256 digest")
|
|
@@ -169,7 +263,7 @@ def main() -> int:
|
|
|
169
263
|
for raw_line in sys.stdin:
|
|
170
264
|
try:
|
|
171
265
|
message = json.loads(raw_line)
|
|
172
|
-
payload = handle(message, path, args.sha256)
|
|
266
|
+
payload = handle(message, path, args.sha256, allow_search=args.allow_search)
|
|
173
267
|
except (json.JSONDecodeError, UnicodeError):
|
|
174
268
|
payload = response(None, error={"code": -32700, "message": "Parse error"})
|
|
175
269
|
if payload is not None:
|
package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/parse_cli_review.py
CHANGED
|
@@ -10,6 +10,7 @@ import re
|
|
|
10
10
|
from typing import Any
|
|
11
11
|
|
|
12
12
|
from concern_excerpt import bounded_reason_detail, concern_fields
|
|
13
|
+
import kimi_packet_mcp as packet_tools
|
|
13
14
|
from kimi_packet_mcp import MAX_CHUNK_BYTES
|
|
14
15
|
|
|
15
16
|
|
|
@@ -652,6 +653,18 @@ def audit_codex(
|
|
|
652
653
|
def invalid(reason: str) -> dict[str, Any]:
|
|
653
654
|
return invalid_model_output(args, reason, "\n".join(concern_fragments))
|
|
654
655
|
|
|
656
|
+
packet_path = getattr(args, "packet", None)
|
|
657
|
+
packet_sha256 = getattr(args, "packet_sha256", None)
|
|
658
|
+
if packet_path or packet_sha256:
|
|
659
|
+
try:
|
|
660
|
+
if not packet_path or not packet_sha256:
|
|
661
|
+
raise ValueError()
|
|
662
|
+
packet_tools.packet_bytes(Path(packet_path), packet_sha256)
|
|
663
|
+
except (OSError, ValueError):
|
|
664
|
+
return inconclusive(args, "Codex packet binding changed", "binding_mismatch", False)
|
|
665
|
+
pending_packet_calls: dict[str, tuple[str, Any]] = {}
|
|
666
|
+
completed_packet_calls: set[str] = set()
|
|
667
|
+
|
|
655
668
|
for event in events:
|
|
656
669
|
event_type = event.get("type")
|
|
657
670
|
if event_type == "turn.completed":
|
|
@@ -678,6 +691,39 @@ def audit_codex(
|
|
|
678
691
|
attempted_tool=event_type,
|
|
679
692
|
)
|
|
680
693
|
item_type = item.get("type")
|
|
694
|
+
if item_type == "mcp_tool_call" and packet_path and packet_sha256:
|
|
695
|
+
tool = item.get("tool")
|
|
696
|
+
if item.get("server") != "code_review_packet" or tool not in {"read_packet", "search_packet"}:
|
|
697
|
+
return inconclusive(args, "Codex attempted a tool outside the frozen packet", "tool_boundary_violation", False)
|
|
698
|
+
reader = packet_tools.read_chunk if tool == "read_packet" else packet_tools.search_packet
|
|
699
|
+
expected = reader(Path(packet_path), packet_sha256, item.get("arguments"))
|
|
700
|
+
content = expected["content"]
|
|
701
|
+
if expected.get("isError") and content[0]["text"] == "packet binding changed":
|
|
702
|
+
return inconclusive(args, "Codex packet binding changed", "binding_mismatch", False)
|
|
703
|
+
if expected.get("isError") and content[0]["text"].startswith("invalid packet"):
|
|
704
|
+
return inconclusive(args, "Codex supplied arguments outside the packet tool schema", "tool_boundary_violation", False)
|
|
705
|
+
call_id = item.get("id")
|
|
706
|
+
signature = (tool, item.get("arguments"))
|
|
707
|
+
if (not isinstance(call_id, str) or not call_id or call_id in completed_packet_calls
|
|
708
|
+
or (call_id in pending_packet_calls and pending_packet_calls[call_id] != signature)):
|
|
709
|
+
return inconclusive(args, "Codex packet tool lifecycle is unverifiable", "transport_unverifiable", False)
|
|
710
|
+
if event_type != "item.completed":
|
|
711
|
+
if item.get("status") != "in_progress":
|
|
712
|
+
return inconclusive(args, "Codex packet tool lifecycle is unverifiable", "transport_unverifiable", False)
|
|
713
|
+
pending_packet_calls[call_id] = signature
|
|
714
|
+
continue
|
|
715
|
+
result = item.get("result")
|
|
716
|
+
if not isinstance(result, dict):
|
|
717
|
+
return invalid("Codex packet tool returned no verifiable result")
|
|
718
|
+
if (result.get("content") != content or result.get("structured_content") not in (None, {})
|
|
719
|
+
or result.get("structuredContent") not in (None, {})):
|
|
720
|
+
return inconclusive(args, "Codex packet tool result did not match frozen bytes", "binding_mismatch", False)
|
|
721
|
+
allowed_statuses = {"completed", "failed"} if expected.get("isError") else {"completed"}
|
|
722
|
+
if item.get("status") not in allowed_statuses or (item.get("error") and not expected.get("isError")):
|
|
723
|
+
return invalid("Codex packet tool did not complete successfully")
|
|
724
|
+
pending_packet_calls.pop(call_id, None)
|
|
725
|
+
completed_packet_calls.add(call_id)
|
|
726
|
+
continue
|
|
681
727
|
if item_type == "agent_message":
|
|
682
728
|
item_text = item.get("text")
|
|
683
729
|
if isinstance(item_text, str) and item_text.strip():
|
|
@@ -729,7 +775,7 @@ def audit_codex(
|
|
|
729
775
|
)
|
|
730
776
|
if event_type == "item.completed" and item_type == "agent_message":
|
|
731
777
|
saw_completed_agent_message = True
|
|
732
|
-
if not saw_completed_agent_message or not saw_completed_turn:
|
|
778
|
+
if pending_packet_calls or not saw_completed_agent_message or not saw_completed_turn:
|
|
733
779
|
return inconclusive(
|
|
734
780
|
args,
|
|
735
781
|
"Codex event stream lacked positive completion evidence",
|
|
@@ -926,6 +972,7 @@ def main() -> int:
|
|
|
926
972
|
parser.add_argument("--model", default="")
|
|
927
973
|
parser.add_argument("--events", required=True)
|
|
928
974
|
parser.add_argument("--packet")
|
|
975
|
+
parser.add_argument("--packet-sha256")
|
|
929
976
|
parser.add_argument("--packet-delivery", choices=("mcp", "inline"), default="mcp")
|
|
930
977
|
parser.add_argument("--packet-receipt", default="")
|
|
931
978
|
parser.add_argument("--result-file")
|