packet-tracer-skill 0.2.3 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/CHANGELOG.md +424 -73
  2. package/README.md +557 -442
  3. package/SKILL.md +337 -262
  4. package/bin/packet-tracer-skill.js +29 -2
  5. package/docs/github-launch-ops-0.2.3.md +37 -0
  6. package/docs/github-metadata.md +6 -4
  7. package/docs/hero-demo-plan.md +1 -1
  8. package/docs/home-iot-donor-proof.md +4 -4
  9. package/docs/l2-security-qos-proof.md +1 -1
  10. package/docs/packet-tracer-feature-gap-atlas.md +4 -4
  11. package/docs/post-launch-follow-up.md +9 -5
  12. package/docs/proof-readiness-dashboard.md +69 -0
  13. package/docs/publish-preview-roadmap.md +6 -5
  14. package/docs/release-checklist.md +17 -8
  15. package/docs/release-notes-0.2.4.md +20 -0
  16. package/docs/runtime-truth.md +33 -8
  17. package/docs/security-edge-deepening-proof.md +1 -1
  18. package/examples/README.md +98 -69
  19. package/examples/complex_campus_master_edit_v4.inventory.json +12 -2
  20. package/examples/gallery.md +94 -6
  21. package/examples/home_iot_cli_edit_v1.inventory.json +11 -2
  22. package/examples/index.json +932 -4
  23. package/examples/local-sample-evidence.json +24 -0
  24. package/examples/proof-cards.json +117 -0
  25. package/examples/service_heavy_cli_edit_v1.inventory.json +11 -2
  26. package/package.json +60 -53
  27. package/pytest.ini +9 -0
  28. package/references/packettracer-sample-catalog.json +45287 -4525
  29. package/references/packettracer-sample-catalog.md +599 -259
  30. package/references/proof-readiness-candidates.json +352 -0
  31. package/scripts/build_examples_index.py +228 -35
  32. package/scripts/build_sample_catalog.py +24 -44
  33. package/scripts/corpus_runner.py +430 -0
  34. package/scripts/coverage_matrix.py +1842 -1812
  35. package/scripts/donor_cache.py +354 -0
  36. package/scripts/donor_diagnostics.py +3 -1
  37. package/scripts/generate_pkt.py +8762 -4228
  38. package/scripts/intent_parser.py +2242 -1657
  39. package/scripts/local_donors.py +340 -0
  40. package/scripts/packet_tracer_env.py +846 -391
  41. package/scripts/pkt_annotate.py +218 -0
  42. package/scripts/pkt_codec.py +420 -181
  43. package/scripts/pkt_editor.py +2405 -1703
  44. package/scripts/pkt_transformer.py +1072 -727
  45. package/scripts/pkt_verify.py +461 -0
  46. package/scripts/runtime_doctor.py +80 -29
  47. package/scripts/sample_catalog.py +1372 -1250
  48. package/scripts/twofish_diagnostics.py +48 -31
  49. package/scripts/usage_ledger.py +218 -0
  50. package/scripts/vendor/README.md +44 -37
  51. package/scripts/vendor/twofish_pure.py +321 -0
  52. package/scripts/workspace_repair.py +548 -508
  53. package/templates/pt900/donors/README.md +15 -0
@@ -39,24 +39,25 @@ def _packet_tracer_os_name(host_os: str) -> str:
39
39
 
40
40
 
41
41
  def runtime_env_examples(host_os: str) -> list[str]:
42
+ # PKT_TWOFISH_* is optional: it selects the compiled accelerator. The
43
+ # vendored pure-Python engine is used automatically when it is absent.
42
44
  if host_os == "Windows":
43
45
  return [
44
46
  r"$env:PACKET_TRACER_ROOT='C:\Program Files\Cisco Packet Tracer 9.0.0'",
45
47
  r"$env:PACKET_TRACER_COMPAT_DONOR='C:\path\to\your-working-9.0-donor.pkt'",
46
- r'$env:PKT_TWOFISH_LIBRARY="C:\path\to\_twofish.cp314-win_amd64.pyd"',
47
- r'$env:PKT_TWOFISH_SEARCH_ROOTS="C:\path\to\bridge-folder"',
48
+ r'# optional speed-up: $env:PKT_TWOFISH_LIBRARY="C:\path\to\_twofish.cp314-win_amd64.pyd"',
48
49
  ]
49
50
  if host_os == "macOS":
50
51
  return [
51
52
  "export PACKET_TRACER_ROOT='/Applications/Cisco Packet Tracer.app/Contents/Resources'",
52
53
  "export PACKET_TRACER_COMPAT_DONOR=\"$HOME/path/to/your-working-9.0-donor.pkt\"",
53
- "export PKT_TWOFISH_SEARCH_ROOTS=\"$HOME/path/to/bridge-folder:$HOME/pkt-bridges\"",
54
+ "# optional speed-up: export PKT_TWOFISH_SEARCH_ROOTS=\"$HOME/pkt-bridges\"",
54
55
  ]
55
56
  if host_os == "Linux":
56
57
  return [
57
58
  "export PACKET_TRACER_ROOT='/opt/pt/bin'",
58
59
  "export PACKET_TRACER_COMPAT_DONOR=\"$HOME/path/to/your-working-9.0-donor.pkt\"",
59
- "export PKT_TWOFISH_SEARCH_ROOTS=\"$HOME/path/to/bridge-folder:$HOME/pkt-bridges\"",
60
+ "# optional speed-up: export PKT_TWOFISH_SEARCH_ROOTS=\"$HOME/pkt-bridges\"",
60
61
  ]
61
62
  return []
62
63
 
@@ -71,8 +72,8 @@ def _best_next_fix(runtime_blockers: list[str], recommended_next_steps: list[str
71
72
  "missing_twofish_bridge": "Fix the Twofish bridge next so strict decode/edit/generate can run locally.",
72
73
  "missing_packet_tracer_root": "Fix PACKET_TRACER_ROOT so the doctor can resolve the install layout deterministically.",
73
74
  "missing_packet_tracer_executable": "Fix the Packet Tracer install root or executable path before relying on validate_open.",
74
- "windows_first_runtime": "Do not assume non-Windows strict runtime support without a custom native bridge and explicit Packet Tracer paths.",
75
- "using_external_bridge_only": "Move the external bridge into the repo-local vendor path if you need a self-contained runtime claim.",
75
+ "windows_first_runtime": "Set PACKET_TRACER_ROOT so the Packet Tracer executable resolves on this host.",
76
+ "using_external_bridge_only": "Verify the vendored pure-Python Twofish engine; the external compiled bridge is only an accelerator.",
76
77
  }
77
78
  for blocker in runtime_blockers:
78
79
  if blocker in blocker_map:
@@ -94,7 +95,7 @@ def _why_it_is_blocked(runtime_blockers: list[str], bridge_resolution: str) -> s
94
95
  reasons.append("Packet Tracer executable is not resolved")
95
96
  if "windows_first_runtime" in runtime_blockers:
96
97
  reasons.append("strict bundled validation is still Windows-first")
97
- if bridge_resolution == "external_env":
98
+ if bridge_resolution == "external_env" and "using_external_bridge_only" in runtime_blockers:
98
99
  reasons.append("strict runtime currently relies on an external bridge override")
99
100
  return "; ".join(reasons) + "."
100
101
 
@@ -116,9 +117,9 @@ def build_recommended_next_steps(
116
117
  ) -> list[str]:
117
118
  guidance: list[str] = []
118
119
  if not runtime_supported:
119
- guidance.append(f"Real runtime is still Windows-first: {runtime_message}")
120
+ guidance.append(runtime_message)
120
121
  if python_support_status != "ok":
121
- guidance.append("Use Python 3.14.x for Packet Tracer 9.0 encode/decode.")
122
+ guidance.append("Use Python 3.10 or newer.")
122
123
  if packet_tracer_root is None and recommended_root:
123
124
  guidance.append(f"Set PACKET_TRACER_ROOT to {recommended_root}.")
124
125
  if donor_status != "ok":
@@ -147,7 +148,7 @@ def build_recommended_next_steps(
147
148
  message.append("or set PKT_TWOFISH_LIBRARY / PKT_TWOFISH_SEARCH_ROOTS.")
148
149
  guidance.append(" ".join(message))
149
150
  if host_os in {"macOS", "Linux"} and not runtime_supported:
150
- guidance.append("For non-Windows hosts, install a native Twofish bridge before expecting real .pkt runtime support.")
151
+ guidance.append("On non-Windows hosts set PACKET_TRACER_ROOT explicitly; the codec itself needs no extra setup.")
151
152
  return guidance
152
153
 
153
154
 
@@ -176,14 +177,27 @@ def collect_runtime_doctor() -> dict[str, object]:
176
177
  bridge_resolution = "external_env"
177
178
  else:
178
179
  bridge_resolution = "missing"
180
+ twofish_backend = str(twofish.get("twofish_backend") or "")
179
181
 
180
- runtime_supported = host_os == "Windows"
181
- if runtime_supported:
182
- runtime_message = "validated Windows Packet Tracer 9.0 runtime path"
183
- elif twofish.get("resolved_twofish_path"):
184
- runtime_message = "custom native runtime may work, but bundled validation is still Windows-first"
182
+ # The Windows-only restriction existed because the codec needed a compiled
183
+ # Twofish bridge that was only ever built for Windows. The vendored
184
+ # pure-Python engine removed that dependency, and `packet_tracer_env` already
185
+ # resolves install layouts for macOS and Linux, so any host with Packet Tracer
186
+ # installed is supported. What differs by platform is how much has been
187
+ # exercised in practice, which is a confidence note, not a blocker.
188
+ runtime_supported = packet_tracer_exe is not None
189
+ if runtime_supported and host_os == "Windows":
190
+ runtime_message = f"resolved Windows Packet Tracer runtime at {packet_tracer_exe}"
191
+ elif runtime_supported:
192
+ runtime_message = (
193
+ f"resolved {host_os} Packet Tracer runtime at {packet_tracer_exe}. "
194
+ "Non-Windows hosts are supported but less exercised; verify a generated file opens."
195
+ )
185
196
  else:
186
- runtime_message = "needs custom Packet Tracer paths and a non-Windows native Twofish bridge"
197
+ runtime_message = (
198
+ "no Packet Tracer executable was resolved. Decode, inventory and edit still work; "
199
+ "set PACKET_TRACER_ROOT to enable validate_open."
200
+ )
187
201
 
188
202
  blocking_reasons: list[str] = []
189
203
  if twofish.get("python_support_status") != "ok":
@@ -201,7 +215,7 @@ def collect_runtime_doctor() -> dict[str, object]:
201
215
  if packet_tracer_root is None:
202
216
  blocking_reasons.append("packet_tracer_root:not_set")
203
217
  if not runtime_supported:
204
- blocking_reasons.append(f"runtime_os:{host_os}")
218
+ blocking_reasons.append("packet_tracer_executable:not_resolved")
205
219
 
206
220
  recommended_next_steps = build_recommended_next_steps(
207
221
  host_os=host_os,
@@ -235,9 +249,18 @@ def collect_runtime_doctor() -> dict[str, object]:
235
249
  runtime_blockers.append("missing_packet_tracer_root")
236
250
  if packet_tracer_exe is None:
237
251
  runtime_blockers.append("missing_packet_tracer_executable")
238
- if not runtime_supported:
239
- runtime_blockers.append("windows_first_runtime")
240
- if bridge_resolution == "external_env" and "using_external_bridge_only" not in runtime_blockers:
252
+ # `windows_first_runtime` is no longer raised: a missing Packet Tracer
253
+ # executable is already reported as `missing_packet_tracer_executable`, and
254
+ # the host OS by itself no longer blocks anything.
255
+ # An externally-resolved compiled bridge is no longer a runtime blocker: it is
256
+ # an optional accelerator over the vendored pure-Python engine, which is always
257
+ # repo-local. Only flag it when the pure engine itself could not be verified.
258
+ if (
259
+ bridge_resolution == "external_env"
260
+ and twofish_backend != "pure_python"
261
+ and str(twofish.get("twofish_load_status")) != "ok"
262
+ and "using_external_bridge_only" not in runtime_blockers
263
+ ):
241
264
  runtime_blockers.append("using_external_bridge_only")
242
265
  if runtime_blockers:
243
266
  runtime_grade = "blocked" if len(ready_operations) == 0 else "partially_ready"
@@ -281,20 +304,43 @@ def collect_runtime_doctor() -> dict[str, object]:
281
304
  )
282
305
  why_it_is_blocked = _why_it_is_blocked(runtime_blockers, bridge_resolution)
283
306
  best_next_fix = _best_next_fix(runtime_blockers, recommended_next_steps)
284
- bridge_recommendation = (
285
- "Use or install a repo-local vendor bridge for fully self-contained runtime readiness."
286
- if bridge_resolution == "external_env"
287
- else "Provide PKT_TWOFISH_LIBRARY or PKT_TWOFISH_SEARCH_ROOTS to resolve a local bridge."
288
- if bridge_resolution == "missing"
289
- else "Repo-local bridge is resolved."
290
- )
307
+ if twofish_backend == "pure_python":
308
+ bridge_recommendation = (
309
+ "Vendored pure-Python Twofish is in use; no bridge is required. "
310
+ "A compiled bridge is optional and only speeds up large labs (~12x)."
311
+ )
312
+ elif bridge_resolution == "external_env":
313
+ bridge_recommendation = (
314
+ "A compiled accelerator is being used from an external path. "
315
+ "This is optional; the vendored pure-Python engine is the supported baseline."
316
+ )
317
+ elif bridge_resolution == "missing":
318
+ bridge_recommendation = "Provide PKT_TWOFISH_LIBRARY or PKT_TWOFISH_SEARCH_ROOTS to resolve a local bridge."
319
+ else:
320
+ bridge_recommendation = "Repo-local bridge is resolved."
291
321
  runtime_contract_notes = (
292
- "Repo-local bridge and donor are present, so this checkout can run strict decode/edit/generate locally."
322
+ "The vendored pure-Python Twofish engine is repo-local, so this checkout can run strict "
323
+ "decode/edit/generate with no binaries and no environment variables."
324
+ if twofish_backend == "pure_python"
325
+ else "Repo-local bridge and donor are present, so this checkout can run strict decode/edit/generate locally."
293
326
  if bridge_resolution == "repo_local"
294
327
  else "Strict decode/edit/generate currently rely on an external bridge path. Repo-local runtime packaging is still incomplete."
295
328
  if bridge_resolution == "external_env"
296
329
  else "No bridge is resolved. validate_open may still work when Packet Tracer is installed, but strict decode/edit/generate remain blocked."
297
330
  )
331
+ strict_gate_ready = twofish.get("twofish_load_status") == "ok"
332
+ runtime_gate_status = {
333
+ "default_gate": "unit/doc surface can pass; requires_twofish tests skip when the bridge is missing",
334
+ "strict_gate": "requires PKT_REQUIRE_TWOFISH_TESTS=1 plus PKT_TWOFISH_LIBRARY or PKT_TWOFISH_SEARCH_ROOTS",
335
+ "strict_gate_ready": strict_gate_ready,
336
+ "strict_gate_command": "PKT_REQUIRE_TWOFISH_TESTS=1 python -m pytest tests -q",
337
+ }
338
+ user_summary = {
339
+ "status": runtime_grade,
340
+ "message": doctor_summary,
341
+ "next_best_action": best_next_fix,
342
+ "runtime_gate_status": runtime_gate_status,
343
+ }
298
344
 
299
345
  return {
300
346
  "host_os": host_os,
@@ -303,7 +349,7 @@ def collect_runtime_doctor() -> dict[str, object]:
303
349
  "message": "supported" if installer_supported else "unknown host platform",
304
350
  },
305
351
  "real_pkt_runtime_support": {
306
- "status": "validated" if runtime_supported else "windows_first",
352
+ "status": "validated" if runtime_supported else "packet_tracer_not_resolved",
307
353
  "message": runtime_message,
308
354
  },
309
355
  "env_examples": runtime_env_examples(host_os),
@@ -320,6 +366,7 @@ def collect_runtime_doctor() -> dict[str, object]:
320
366
  "twofish_search_roots": resolved_search_roots,
321
367
  "resolved_twofish_path": resolved_twofish_path,
322
368
  "twofish_source": twofish.get("twofish_source", ""),
369
+ "twofish_backend": twofish.get("twofish_backend", ""),
323
370
  "twofish_load_status": twofish.get("twofish_load_status", "unknown"),
324
371
  "twofish_message": twofish.get("twofish_message", "unknown"),
325
372
  "twofish_sha256": twofish.get("twofish_sha256", ""),
@@ -330,6 +377,8 @@ def collect_runtime_doctor() -> dict[str, object]:
330
377
  "target_version": donor.get("target_version", ""),
331
378
  "resolved_donor_path": donor.get("resolved_donor_path", ""),
332
379
  "donor_version": donor.get("donor_version", ""),
380
+ "donor_policy": donor.get("donor_policy", ""),
381
+ "donor_compatibility_tier": donor.get("compatibility_tier", ""),
333
382
  "donor_source": donor.get("donor_source", ""),
334
383
  "donor_status": donor.get("status", "unknown"),
335
384
  "donor_message": donor.get("message", "unknown"),
@@ -343,6 +392,8 @@ def collect_runtime_doctor() -> dict[str, object]:
343
392
  "what_is_blocked": what_is_blocked,
344
393
  "why_it_is_blocked": why_it_is_blocked,
345
394
  "best_next_fix": best_next_fix,
395
+ "user_summary": user_summary,
396
+ "runtime_gate_status": runtime_gate_status,
346
397
  "doctor_summary": doctor_summary,
347
398
  "runtime_grade": runtime_grade,
348
399
  "recommended_next_steps": recommended_next_steps,