@ccoalm/ccl-skills 0.15.1 → 0.15.3

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.
Files changed (52) hide show
  1. package/README.md +3 -1
  2. package/dist/assets/marketplace/plugins/ccl-skills/agent-context/session-start.md +1 -1
  3. package/dist/assets/marketplace/plugins/ccl-skills/skills/app-cross-platform-dev/SKILL.md +2 -2
  4. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/SKILL.md +6 -5
  5. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/references/development-completion.md +26 -0
  6. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/references/staged-review-contract.md +37 -13
  7. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/AGENTS.md +5 -2
  8. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/codex_review.sh +77 -5
  9. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/kimi_packet_mcp.py +98 -4
  10. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/parse_cli_review.py +48 -1
  11. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/review_gate.py +230 -16
  12. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/test_cli_review_wrappers.sh +165 -11
  13. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/test_kimi_packet_mcp.py +143 -0
  14. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/test_review_client_compat.py +572 -0
  15. package/dist/assets/marketplace/plugins/ccl-skills/skills/defect-diagnosis/SKILL.md +3 -1
  16. package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-dev/SKILL.md +1 -1
  17. package/dist/assets/marketplace/plugins/ccl-skills/skills/llm-inference-integration/SKILL.md +2 -0
  18. package/dist/assets/marketplace/plugins/ccl-skills/skills/miniapp-product-dev/SKILL.md +1 -1
  19. package/dist/assets/marketplace/plugins/ccl-skills/skills/multi-agent-delegation/SKILL.md +1 -1
  20. package/dist/assets/marketplace/plugins/ccl-skills/skills/nodejs-service-dev/SKILL.md +2 -0
  21. package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-observability/SKILL.md +3 -1
  22. package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-release-engineering/SKILL.md +3 -1
  23. package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-service-connectivity/SKILL.md +2 -0
  24. package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/SKILL.md +7 -7
  25. package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/references/design-review-gate-mechanics.md +1 -1
  26. package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/references/pre-final-continuation-gate.md +20 -11
  27. package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/references/refactoring-discipline.md +7 -1
  28. package/dist/assets/marketplace/plugins/ccl-skills/skills/python-service-dev/SKILL.md +1 -1
  29. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/SKILL.md +2 -2
  30. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/dual-track-review-gate.md +17 -17
  31. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/harness-patterns-and-eval.md +4 -4
  32. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/resume-paused-delivery.md +3 -3
  33. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/source-register.md +12 -0
  34. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_ai_coding_implementation_gates.sh +83 -48
  35. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_body_compliance_grading.sh +80 -2
  36. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_controlled_escalation_pins.sh +3 -2
  37. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_validate_extraction_review_state.sh +190 -2
  38. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/validate_extraction_review_state.py +106 -4
  39. package/dist/assets/marketplace/plugins/ccl-skills/skills/terminal-cli-dev/SKILL.md +1 -1
  40. package/dist/assets/marketplace/plugins/ccl-skills/skills/testing-strategy/SKILL.md +3 -1
  41. package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/SKILL.md +6 -6
  42. package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/references/writing-judgments.md +63 -0
  43. package/dist/assets/marketplace/plugins/ccl-skills/skills/web-react-dev/SKILL.md +1 -1
  44. package/dist/assets/release.json +60 -50
  45. package/dist/codex-host.d.ts +1 -1
  46. package/dist/codex-host.js +39 -15
  47. package/dist/host-probe.d.ts +16 -0
  48. package/dist/host-probe.js +29 -5
  49. package/dist/operations.js +34 -8
  50. package/dist/unified.d.ts +1 -1
  51. package/dist/unified.js +11 -4
  52. package/package.json +1 -1
@@ -78,6 +78,149 @@ class PacketMcpTest(unittest.TestCase):
78
78
  [{"type": "text", "text": "PACKET_CHUNK 6:17/17\nbeta\ngamma\n"}],
79
79
  )
80
80
 
81
+ response = self.request(
82
+ 4,
83
+ "tools/call",
84
+ {
85
+ "name": "search_packet",
86
+ "arguments": {"query": "alpha", "byte_offset": 0, "limit": 1},
87
+ },
88
+ )
89
+ self.assertTrue(response["result"]["isError"])
90
+ self.assertEqual(response["result"]["content"][0]["text"], "unknown tool")
91
+
92
+ def search_exchange(self, text: str, arguments: list[object]) -> list[dict]:
93
+ packet = Path(self.temp.name) / "search.txt"
94
+ packet.write_text(text, encoding="utf-8")
95
+ digest = hashlib.sha256(packet.read_bytes()).hexdigest()
96
+ requests = [{"jsonrpc": "2.0", "id": 1, "method": "tools/list"}]
97
+ requests.extend(
98
+ {
99
+ "jsonrpc": "2.0",
100
+ "id": index,
101
+ "method": "tools/call",
102
+ "params": {"name": "search_packet", "arguments": item},
103
+ }
104
+ for index, item in enumerate(arguments, 2)
105
+ )
106
+ completed = subprocess.run(
107
+ [sys.executable, str(SERVER), "--packet", str(packet), "--sha256", digest,
108
+ "--allow-search"],
109
+ input="\n".join(json.dumps(item) for item in requests) + "\n",
110
+ capture_output=True,
111
+ text=True,
112
+ timeout=5,
113
+ check=False,
114
+ )
115
+ self.assertEqual(completed.returncode, 0, completed.stderr)
116
+ return [json.loads(line)["result"] for line in completed.stdout.splitlines()]
117
+
118
+ def test_search_opt_in_tool_surface(self) -> None:
119
+ response = self.search_exchange("alpha", [])[0]
120
+ self.assertEqual(
121
+ [tool["name"] for tool in response["tools"]],
122
+ ["read_packet", "search_packet"],
123
+ )
124
+ schema = response["tools"][1]["inputSchema"]
125
+ self.assertEqual(schema["required"], ["query", "byte_offset", "limit"])
126
+ self.assertEqual(set(schema["properties"]), {"query", "byte_offset", "limit"})
127
+ self.assertFalse(schema["additionalProperties"])
128
+
129
+ def test_search_literal_utf8_matches_use_byte_offsets_and_bounded_pagination(self) -> None:
130
+ responses = self.search_exchange("é alpha\n你.* 你.*\nalpha\n", [
131
+ {"query": "你.*", "byte_offset": 0, "limit": 1},
132
+ {"query": "你.*", "byte_offset": 14, "limit": 1},
133
+ {"query": ".*", "byte_offset": 0, "limit": 100},
134
+ {"query": "missing", "byte_offset": 0, "limit": 1},
135
+ {"query": "alpha", "byte_offset": 27, "limit": 1},
136
+ ])
137
+ expected = [
138
+ {"matches": [{"byte_offset": 9, "line": 2}], "next_byte_offset": 14, "total_bytes": 27},
139
+ {"matches": [{"byte_offset": 15, "line": 2}], "next_byte_offset": None, "total_bytes": 27},
140
+ {"matches": [{"byte_offset": 12, "line": 2}, {"byte_offset": 18, "line": 2}], "next_byte_offset": None, "total_bytes": 27},
141
+ {"matches": [], "next_byte_offset": None, "total_bytes": 27},
142
+ {"matches": [], "next_byte_offset": None, "total_bytes": 27},
143
+ ]
144
+ for response, result in zip(responses[1:], expected, strict=True):
145
+ self.assertFalse(response["isError"])
146
+ self.assertEqual(json.loads(response["content"][0]["text"]), result)
147
+
148
+ def test_search_rejects_invalid_arguments_and_offsets(self) -> None:
149
+ valid = {"query": "a", "byte_offset": 0, "limit": 1}
150
+ invalid = [None, [], {}, {**valid, "path": "/etc/passwd"},
151
+ {**valid, "query": ""}, {**valid, "query": 1},
152
+ {**valid, "query": "你" * 341 + "xy"}, {**valid, "query": "\ud800"},
153
+ {**valid, "byte_offset": -1}, {**valid, "byte_offset": True},
154
+ {**valid, "byte_offset": False},
155
+ {**valid, "byte_offset": 1.5}, {**valid, "limit": 0},
156
+ {**valid, "limit": 101}, {**valid, "limit": True},
157
+ {**valid, "limit": 1.5}, {**valid, "byte_offset": 1},
158
+ {**valid, "byte_offset": 4}]
159
+ responses = self.search_exchange("你", invalid)
160
+ self.assertEqual(len(responses), len(invalid) + 1)
161
+ for arguments, response in zip(invalid, responses[1:], strict=True):
162
+ with self.subTest(arguments=arguments):
163
+ self.assertTrue(response["isError"])
164
+
165
+ def test_search_is_case_sensitive_and_non_overlapping(self) -> None:
166
+ responses = self.search_exchange("AaAAaaaa\n", [
167
+ {"query": "aa", "byte_offset": 0, "limit": 100},
168
+ {"query": "AA", "byte_offset": 0, "limit": 100},
169
+ ])
170
+ expected = [[{"byte_offset": 4, "line": 1}, {"byte_offset": 6, "line": 1}],
171
+ [{"byte_offset": 2, "line": 1}]]
172
+ for response, matches in zip(responses[1:], expected, strict=True):
173
+ self.assertFalse(response["isError"])
174
+ self.assertEqual(json.loads(response["content"][0]["text"]), {
175
+ "matches": matches, "next_byte_offset": None, "total_bytes": 9,
176
+ })
177
+
178
+ def test_search_accepts_the_maximum_query_byte_length(self) -> None:
179
+ query = "你" * 341 + "x"
180
+ response = self.search_exchange(query, [
181
+ {"query": query, "byte_offset": 0, "limit": 1},
182
+ ])[1]
183
+ self.assertFalse(response["isError"])
184
+ self.assertEqual(json.loads(response["content"][0]["text"]), {
185
+ "matches": [{"byte_offset": 0, "line": 1}],
186
+ "next_byte_offset": None,
187
+ "total_bytes": 1024,
188
+ })
189
+
190
+ def test_search_limits_results_without_returning_an_oversized_line(self) -> None:
191
+ responses = self.search_exchange("x" * 48_001 + "\n", [
192
+ {"query": "x", "byte_offset": 0, "limit": 100},
193
+ {"query": "x", "byte_offset": 100, "limit": 1},
194
+ ])
195
+ first = json.loads(responses[1]["content"][0]["text"])
196
+ self.assertEqual(first, {
197
+ "matches": [{"byte_offset": offset, "line": 1} for offset in range(100)],
198
+ "next_byte_offset": 100,
199
+ "total_bytes": 48_002,
200
+ })
201
+ second = json.loads(responses[2]["content"][0]["text"])
202
+ self.assertEqual(second["matches"], [{"byte_offset": 100, "line": 1}])
203
+ for response in responses[1:]:
204
+ self.assertFalse(response["isError"])
205
+ self.assertLessEqual(len(response["content"][0]["text"].encode("utf-8")), 48_000)
206
+
207
+ def test_search_rechecks_exact_packet_binding_after_each_call(self) -> None:
208
+ self.process.terminate()
209
+ self.process.communicate(timeout=5)
210
+ digest = hashlib.sha256(self.packet.read_bytes()).hexdigest()
211
+ self.process = subprocess.Popen(
212
+ [sys.executable, str(SERVER), "--packet", str(self.packet), "--sha256", digest,
213
+ "--allow-search"],
214
+ stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True,
215
+ )
216
+ self.initialize()
217
+ params = {"name": "search_packet", "arguments": {"query": "alpha", "byte_offset": 0, "limit": 1}}
218
+ self.assertFalse(self.request(2, "tools/call", params)["result"]["isError"])
219
+ self.packet.write_text("ALPHA\nbeta\ngamma\n", encoding="utf-8")
220
+ response = self.request(3, "tools/call", params)["result"]
221
+ self.assertTrue(response["isError"])
222
+ self.assertEqual(response["content"][0]["text"], "packet binding changed")
223
+
81
224
  def test_rejects_path_arguments_and_packet_mutation(self) -> None:
82
225
  self.initialize()
83
226
  response = self.request(