packet-tracer-skill 0.2.3 → 0.3.1

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 (54) hide show
  1. package/CHANGELOG.md +491 -73
  2. package/README.md +575 -442
  3. package/SKILL.md +513 -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 +61 -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 +62 -40
  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 +12738 -4228
  38. package/scripts/intent_parser.py +2269 -1657
  39. package/scripts/lab_coherence.py +455 -0
  40. package/scripts/local_donors.py +340 -0
  41. package/scripts/packet_tracer_env.py +846 -391
  42. package/scripts/pkt_annotate.py +218 -0
  43. package/scripts/pkt_codec.py +420 -181
  44. package/scripts/pkt_editor.py +2487 -1703
  45. package/scripts/pkt_transformer.py +1170 -727
  46. package/scripts/pkt_verify.py +461 -0
  47. package/scripts/runtime_doctor.py +80 -29
  48. package/scripts/sample_catalog.py +1425 -1250
  49. package/scripts/twofish_diagnostics.py +48 -31
  50. package/scripts/usage_ledger.py +218 -0
  51. package/scripts/vendor/README.md +44 -37
  52. package/scripts/vendor/twofish_pure.py +321 -0
  53. package/scripts/workspace_repair.py +548 -508
  54. package/templates/pt900/donors/README.md +15 -0
package/SKILL.md CHANGED
@@ -1,262 +1,513 @@
1
- ---
2
- name: pkt
3
- description: >
4
- Create and edit Cisco Packet Tracer 9.0 `.pkt` files from hybrid natural-language
5
- requests and explicit commands. Use this skill for topology generation, VLAN/router-on-a-stick,
6
- DHCP, management VLAN, Telnet, wireless/AP-client setup, server services, and existing `.pkt` edits.
7
- ---
8
-
9
- # Cisco Packet Tracer 9.0 `.pkt` Hybrid Generator/Editor
10
-
11
- This skill targets Packet Tracer `9.0.0.0810` and treats a `.pkt` file as a single
12
- binary blob, not a zip container or folder tree.
13
-
14
- The current builder/editor is Cisco-sample-centric:
15
-
16
- - installed Packet Tracer sample saves are the primary prototype source
17
- - bundled device templates are the secondary fallback for gaps such as missing
18
- device families in Cisco's own saves
19
- - imported external labs are reference-only by default
20
- - curated external donor roots can become donor-eligible after validation, but
21
- Cisco local donors still rank first
22
-
23
- That is intentional: it avoids the invalid synthetic XML approach that Packet
24
- Tracer rejects while still keeping the skill usable when Cisco's own sample set
25
- does not cover a device family directly.
26
-
27
- The prompt-first architecture now follows a planner/validator/autofix split:
28
-
29
- 1. intent extraction
30
- 2. topology/config planning
31
- 3. donor ranking
32
- 4. donor-prune mutation
33
- 5. compatibility validation
34
-
35
- Useful ideas from `MCP-Packet-Tracer` were adopted only at the architecture
36
- level. PTBuilder live deploy and external donor usage were intentionally not
37
- adopted.
38
-
39
- ## How `.pkt` Files Work
40
-
41
- For the modern format targeted by this skill, the pipeline is:
42
-
43
- 1. Build a Packet Tracer XML document rooted at `<PACKETTRACER5>`
44
- 2. qCompress the UTF-8 XML bytes using:
45
- - 4-byte big-endian uncompressed length
46
- - raw zlib payload
47
- 3. Apply Stage-2 XOR obfuscation
48
- 4. Encrypt with Twofish in EAX mode and append the 16-byte authentication tag
49
- 5. Apply Stage-1 reverse/XOR obfuscation
50
-
51
- The XML includes a `<VERSION>` value. Compatibility is not guaranteed across Packet
52
- Tracer releases, so this skill intentionally targets the 9.0 line.
53
-
54
- ## Workflow
55
-
56
- 1. Parse the request into a hybrid intent plan:
57
- - topology, device models, links, cable types, ports
58
- - natural Azerbaijani or mixed-language counts such as `3 dene switch ve 6 komputer`
59
- - department/campus prompts such as `6 sobeli kampus sebekesi`
60
- - VLAN/trunk/access/router-on-a-stick intent
61
- - router DHCP or server DHCP/DNS intent
62
- - management VLAN / Telnet intent
63
- - AP SSID/security and wireless client association intent
64
- - existing `.pkt` edit operations when a source file is provided
65
- 2. Build an intent-first topology/config plan:
66
- - topology archetype
67
- - device list
68
- - port map
69
- - VLAN/service/config plan
70
- - assumptions and blocking gaps
71
- 3. Rank Cisco local donor candidates with capability, topology, and donor-graph scoring
72
- 4. Optionally search/import remote labs, then rank imported labs as curated donors or reference patterns
73
- 5. Apply donor-prune mutations on one working Cisco 9.0 donor lab
74
- 6. Validate workspace/runtime/scenario compatibility
75
- 7. Encode XML into a `.pkt` blob with `scripts/pkt_codec.py`
76
- 8. Save generated or edited output locally
77
-
78
- Open-first rules remain strict:
79
-
80
- - multi-source search and scoring is allowed
81
- - final `.pkt` apply is still single-donor
82
- - when no safe donor exists, return `blocking_gaps` plus a `blueprint_plan`
83
-
84
- ## Files
85
-
86
- - `scripts/pkt_builder.py`
87
- Builds Packet Tracer XML from a blueprint
88
- - `scripts/pkt_codec.py`
89
- Encodes and decodes the modern `.pkt` format
90
- - `scripts/generate_pkt.py`
91
- CLI entrypoint for generate/edit/decode/inventory/explain-plan
92
- - `scripts/intent_parser.py`
93
- Hybrid natural-language and mini-DSL parser
94
- - `scripts/pkt_editor.py`
95
- Existing `.pkt` inventory and mutation engine
96
- - `scripts/sample_catalog.py`
97
- Capability-tagged sample index and reference-pattern loader
98
- - `scripts/sample_selector.py`
99
- Sample ranking by capability, topology, trust level, and prototype eligibility
100
- - `scripts/packet_tracer_env.py`
101
- Resolves Packet Tracer install, saves root, and executable paths
102
- - `scripts/runtime_doctor.py`
103
- Unified runtime diagnostics for host OS, donor, Packet Tracer paths, and Twofish readiness
104
- - `templates/pt900/base_empty.xml`
105
- Base Packet Tracer 9.0 skeleton
106
- - `templates/pt900/device_library/*.xml`
107
- Secondary fallback device XML templates for the first supported device set
108
-
109
- The runtime builder currently prefers the installed FTP sample from the local
110
- Packet Tracer `saves/` directory. The exact path is resolved at runtime from
111
- the local Packet Tracer installation or the `PACKET_TRACER_*` environment
112
- variables.
113
-
114
- Prompt-driven donor-prune generation prefers an explicit
115
- `PACKET_TRACER_COMPAT_DONOR`, but it can also auto-detect a working local
116
- Packet Tracer 9.0 donor from common local locations when the environment
117
- override is absent.
118
-
119
- Strict compatibility rules:
120
-
121
- - keep `PACKET_TRACER_TARGET_VERSION` on `9.0.0.0810`
122
- - do not downgrade prompt generation to `5.3.0.0011`
123
- - do not use a legacy `5.3` donor/template fallback to bypass strict 9.0 mode
124
- - if the donor is missing, undecodable, or version-mismatched, stop with a
125
- blocking error instead of switching versions
126
- - if `PACKET_TRACER_COMPAT_DONOR` is explicitly set and wrong, do not silently
127
- fall back to another donor
128
- - every host process must inherit the same `PACKET_TRACER_*` and
129
- `PKT_TWOFISH_LIBRARY` environment variables; this is not host-specific
130
-
131
- ## Supported First Iteration
132
-
133
- - `Router`, `Switch`, `PC`, `Server`
134
- - `LightWeightAccessPoint` / `WirelessRouter` where sample prototypes exist
135
- - natural prompt planning for device counts, VLAN IDs, `gig` uplinks, `fa` host links,
136
- department/campus prompts, and default `chain` / `core switch` topologies
137
- - structured `blocking_gaps`, `assumptions_used`, and `confidence_score` reporting
138
- - transparent `explain-plan` output with:
139
- - `intent_plan`
140
- - `topology_plan`
141
- - `config_plan`
142
- - `estimate_plan`
143
- - `preflight_validation`
144
- - `autofix_summary`
145
- - `cisco_sample_candidates`
146
- - `curated_external_donor_candidates`
147
- - `external_reference_patterns`
148
- - `validation_report`
149
- - explicit port-to-port and cable/media mapping
150
- - VLAN create, access port, trunk port, native VLAN
151
- - router subinterfaces and router-on-a-stick
152
- - named ACL create, permit/deny rule injection, and `ip access-group` interface binding
153
- - router DHCP pool
154
- - server DHCP pool, DNS enablement, and DNS records
155
- - HTTP / HTTPS / FTP / TFTP / NTP service enable state
156
- - end-device DNS client settings
157
- - management VLAN SVI + default gateway
158
- - Telnet enablement on switches/routers via config mutations
159
- - wireless SSID/security/channel mutations
160
- - wireless client association and DHCP/static mode where compatible prototypes exist
161
- - existing `.pkt` inventory and edit flow
162
-
163
- ## Defaults
164
-
165
- If the user does not specify details:
166
-
167
- - Packet Tracer version: `9.0.0.0810`
168
- - Subnet: `192.168.1.0/24`
169
- - Default gateway: `192.168.1.1`
170
- - PC addresses: `.10`, `.11`, `.12`, ...
171
- - Layout:
172
- - router around `(400, 140)`
173
- - switch around `(400, 280)`
174
- - PCs along the bottom row
175
-
176
- ## Constraints
177
-
178
- - This skill currently plans for Packet Tracer 9.0 only
179
- - The builder currently depends on a local Packet Tracer installation with the bundled
180
- sample saves present
181
- - The bundled template library is intentionally minimal in v1
182
- - Imported external sample roots are reference-only unless you explicitly promote them
183
- - Prompt generation in the default path is donor-prune based, not full synthetic rebuild
184
- - If VLANs are requested for end hosts but host-to-VLAN distribution is not provided,
185
- the skill returns `blocking_gaps` instead of guessing and generating an unsafe `.pkt`
186
- - Manual validation in Packet Tracer is still required before claiming a topology
187
- is fully compatible with the Cisco application
188
-
189
- ## CLI Examples
190
-
191
- Generate from a blueprint file:
192
-
193
- ```powershell
194
- python scripts/generate_pkt.py --blueprint examples/blueprint_minimal.json --output output\minimal.pkt
195
- ```
196
-
197
- Generate from a hybrid prompt:
198
-
199
- ```powershell
200
- python scripts/generate_pkt.py --prompt "6 şöbəli şəbəkə qur, VLAN 10 20 30 40 50 60 və management VLAN 99 yarat" --output output\campus.pkt
201
- ```
202
-
203
- Explain the parsed plan before generation:
204
-
205
- ```powershell
206
- python scripts/generate_pkt.py --explain-plan "set SW1 vlan 10 name Finance; enable telnet on SW1 username admin password 1234"
207
- ```
208
-
209
- Explain a natural Azerbaijani prompt before generation:
210
-
211
- ```powershell
212
- python scripts/generate_pkt.py --explain-plan "3 dene switch ve 6 komputer ve 1 router vlanlarda 10,20,30 switchlerin oz aralarinda ve routerle aralarinda gig portuna qosulsun komputerler ise fa portlarla qosulsun"
213
- ```
214
-
215
- Inspect curated donor candidates from a local imported lab root:
216
-
217
- ```powershell
218
- python scripts/generate_pkt.py --explain-plan "6 şöbəli şəbəkə qur, hər şöbədə 1 switch 1 AP 1 printer 2 PC 2 tablet olsun" --donor-root C:\labs\curated-pkt-donors --reference-root C:\labs\external-pkt-samples
219
- ```
220
-
221
- Only external `9.0.0.0810` labs are promoted into the curated donor pool when
222
- their workspace validation passes cleanly, or when they are `legacy_uuid_physical`
223
- donors whose only logical warnings are repeated `MEM_ADDR` mismatch records.
224
-
225
- Search GitHub first, then auto-import matching repos into a local cache:
226
-
227
- ```powershell
228
- python scripts/generate_pkt.py --explain-plan "6 department campus with vlan dhcp dns ap" --search-remote --remote-provider github --import-cache-root output\remote-cache
229
- ```
230
-
231
- Print the aggregated capability matrix:
232
-
233
- ```powershell
234
- python scripts/generate_pkt.py --coverage-report
235
- python scripts/generate_pkt.py --coverage-report --device-family "access points"
236
- ```
237
-
238
- Inspect an existing `.pkt` inventory:
239
-
240
- ```powershell
241
- python scripts/generate_pkt.py --inventory input\lab.pkt
242
- python scripts/generate_pkt.py --inventory input\lab.pkt --inventory-capabilities
243
- ```
244
-
245
- Edit an existing `.pkt` directly from a prompt:
246
-
247
- ```powershell
248
- python scripts/generate_pkt.py --edit input\lab.pkt --prompt "set Wireless Router0 ssid FIN_WIFI security wpa2-psk passphrase fin12345 channel 6 associate PC0 to Wireless Router0 ssid FIN_WIFI dhcp" --output output\edited_lab.pkt --xml-out output\edited_lab.xml
249
- python scripts/generate_pkt.py --edit input\lab.pkt --prompt "enable dns on Server0 set Server0 dns A www.example.local 192.168.10.20 set PC0 dns 192.168.10.20" --output output\edited_services.pkt
250
- ```
251
-
252
- Decode a `.pkt` back to XML for inspection:
253
-
254
- ```powershell
255
- python scripts/generate_pkt.py --decode output\minimal.pkt --xml-out output\minimal.xml
256
- ```
257
-
258
- Launch Packet Tracer for a smoke open test:
259
-
260
- ```powershell
261
- python scripts/generate_pkt.py --validate-open output\minimal.pkt
262
- ```
1
+ ---
2
+ name: pkt
3
+ description: >
4
+ Create and edit Cisco Packet Tracer 9.0 `.pkt` files from hybrid natural-language
5
+ requests and explicit commands. Use this skill for topology generation, VLAN/router-on-a-stick,
6
+ DHCP, management VLAN, Telnet, wireless/AP-client setup, server services, and existing `.pkt` edits.
7
+ ---
8
+
9
+ # Cisco Packet Tracer 9.0 `.pkt` Hybrid Generator/Editor
10
+
11
+ This skill targets whichever Packet Tracer release is installed (detected at runtime,
12
+ 9.0 by default) and treats a `.pkt` file as a single binary blob, not a zip
13
+ container or folder tree.
14
+
15
+ The current builder/editor is Cisco-sample-centric:
16
+
17
+ - installed Packet Tracer sample saves are the primary prototype source
18
+ - bundled device templates are the secondary fallback for gaps such as missing
19
+ device families in Cisco's own saves
20
+ - imported external labs are reference-only by default
21
+ - curated external donor roots can become donor-eligible after validation, but
22
+ Cisco local donors still rank first
23
+
24
+ That is intentional: it avoids the invalid synthetic XML approach that Packet
25
+ Tracer rejects while still keeping the skill usable when Cisco's own sample set
26
+ does not cover a device family directly.
27
+
28
+ The prompt-first architecture now follows a planner/validator/autofix split:
29
+
30
+ 1. intent extraction
31
+ 2. topology/config planning
32
+ 3. donor ranking
33
+ 4. donor-prune mutation
34
+ 5. compatibility validation
35
+
36
+ Useful ideas from `MCP-Packet-Tracer` were adopted only at the architecture
37
+ level. PTBuilder live deploy and external donor usage were intentionally not
38
+ adopted.
39
+
40
+ ## Using This Skill Correctly
41
+
42
+ Read this before generating anything. Every rule below was learned by measuring
43
+ a lab that looked finished and was not.
44
+
45
+ ### A lab that opens is not a lab that works
46
+
47
+ This is the single most expensive mistake available here. Generated labs have
48
+ passed every structural check, opened cleanly in Packet Tracer, read correctly
49
+ line by line, and been unable to pass a single packet. "It opened" tells you
50
+ the container is valid. It tells you nothing about the network.
51
+
52
+ Two things separate a finished lab from a plausible one:
53
+
54
+ ```bash
55
+ python scripts/generate_pkt.py --coherence-report output/lab.pkt
56
+ ```
57
+
58
+ and a live ping. Do both. `--coherence-report` exits non-zero when the lab
59
+ contradicts itself, and generation prints the same summary as a `WARNING:` line
60
+ when it hands the file over — never ignore that line.
61
+
62
+ ### What the coherence report is telling you
63
+
64
+ Every defect this project has paid for has one shape: **a fact derived twice,
65
+ in two passes, with nothing comparing the derivations.** Each half reads
66
+ correctly on its own. The report is that comparison:
67
+
68
+ | Finding | What it means |
69
+ |---|---|
70
+ | `interface_declared_twice` | IOS keeps the last block; readers scan the first |
71
+ | `port_not_on_device` | Packet Tracer refuses to open the file |
72
+ | `port_double_booked` | two cables on one socket |
73
+ | `duplicate_address` | two interfaces claim one address |
74
+ | `real_address_is_also_virtual` | a router holds an address that is someone's HSRP virtual |
75
+ | `native_vlan_mismatch` | spanning tree blocks a cabled, configured port |
76
+ | `etherchannel_peer_does_not_bundle` | the switch behind it drops off the network |
77
+ | `gateway_answers_for_nobody` | a static host points at an address nothing holds |
78
+ | `pool_without_interface` | DHCP hands out addresses nothing can route |
79
+
80
+ The report never repairs. A checker that fixes what it finds stops being able
81
+ to tell you whether the thing it checks is working.
82
+
83
+ ### Measuring in a live Packet Tracer
84
+
85
+ Three steps, in order, every time:
86
+
87
+ 1. **Confirm which document is open.** With two windows open the bridge answers
88
+ for the other one. A pass rate measured against the wrong lab is worse than
89
+ no measurement, because it is believed. Check the device list first.
90
+ 2. **Throw the first reading away.** Spanning tree has not converged; the first
91
+ ping after opening a large lab reports 0/4 on a path that works. It is not a
92
+ measurement, it is the lab starting up.
93
+ 3. **Then measure.** A *failing* ping takes far longer than a passing one --
94
+ each packet waits out its own timeout, about 13 seconds for four -- so
95
+ budget 45-60s per call rather than reading a timeout as a failure.
96
+
97
+ Ping from a host. Routers and switches answer through a different bridge path
98
+ that is not reliable here.
99
+
100
+ ### When two repairs in a row do not change the measurement
101
+
102
+ Stop repairing. The symptom is not where the defect is. Find the pass that
103
+ wrote the state, and fix it there. The fastest way in: **diff the broken device
104
+ against a working sibling.** One switch unreachable while identical ones work
105
+ has one extra line, and reading configuration top to bottom will not find it as
106
+ quickly as `diff` will.
107
+
108
+ ### Facts about Packet Tracer that cost a lab each
109
+
110
+ - a copper cable in a fibre socket is **dropped in silence** -- the file opens,
111
+ the cable is simply not there
112
+ - a duplicate `interface` block is applied last-wins, while readers scan the first
113
+ - a subinterface `ip address` before its `encapsulation dot1Q` is refused
114
+ silently
115
+ - `PORT_DHCP_ENABLE=true` makes Packet Tracer ignore the static address in the
116
+ file; a host with both is a DHCP client, and judging it on its stale address
117
+ is a false reading
118
+ - DHCP snooping with no trusted uplink eats every offer the router sends
119
+ - port security on a trunk isolates the whole switch behind it
120
+ - a `channel-group` whose peer does not bundle takes that switch off the network
121
+ - an interface name the device does not own blocks the file from opening at all;
122
+ a double-booked port does not
123
+ - a `vlan N` line in a switch's configuration does **not** create the VLAN --
124
+ Packet Tracer keeps the database separately, and a port assigned to a VLAN
125
+ that is not in it forwards nothing
126
+ - a top-level command written straight after an indented sub-block line is
127
+ swallowed; the `!` between them is load-bearing
128
+ - a home router's sockets are named, not slotted, and the spelling is the
129
+ model's: `Ethernet 1` .. `4` on `WirelessRouter`, `GigabitEthernet 1` .. `4`
130
+ on `WirelessRouterNewGeneration`, and `Internet` for the uplink on both. It
131
+ writes no interfaces into its configuration, so nothing else can tell you
132
+ - a home router's LAN address is a **setting**, not a config line, and lives in
133
+ `ENGINE/LAN_IP_ADDRESS` with its pool under `ENGINE/DHCP_SERVER/POOLS/POOL`;
134
+ a reader that only walks running configs cannot see it
135
+ - a wireless client's addressing comes from its `WIRELESS_PROFILE`, not from
136
+ its port -- both record it, and Packet Tracer obeys the profile
137
+ - a radio link is made by **distance**. A client outside the access point's
138
+ `COVERAGERANGE` reports its port `up` and `linked` and passes nothing
139
+ - an access point's WPA key lives in `WIRELESS_COMMON/WEP_PROCESS/KEY` with
140
+ `WEP_PROCESS/ENCRYPTION`, never in `WPA_PASSPHRASE`. The names are legacy and
141
+ WPA2 uses them; the client side is the same shape. Put it in the wrong field
142
+ and the access point runs WPA2 with no key while its clients have one
143
+ - a wireless client reads `ip 0.0.0.0` at its un-negotiated rate for the first
144
+ moments after a lab opens, even in a lab Packet Tracer saved itself while it
145
+ was pinging 4/4. `pt_inspect_ports` right after opening is a **first reading**
146
+ and has to be discarded exactly like a first ping
147
+ - a home router's DHCP **lease records** are how a client gets its address back
148
+ when the file opens; move its LAN and they have to be renumbered, not dropped
149
+ - the builder MCP's device table is not authoritative about port names; it
150
+ gives the AC home router `Ethernet 1` .. `4`, and the device itself says
151
+ `GigabitEthernet 1` .. `4`. `pt_inspect_ports` answers at the IOS layer,
152
+ where those sockets are bridged into `Vlan1` and do not appear at all --
153
+ `pt_query_topology` is the one that lists them
154
+
155
+ ### Drawing the topology yourself
156
+
157
+ The generator packs switch blocks into a roughly square grid, which is fine for
158
+ a lab nobody planned. When you have already decided the shape -- which
159
+ department sits where, which switch faces which, where the core belongs -- say
160
+ so in the blueprint and set `PACKET_TRACER_LAYOUT=keep`. Every `x`/`y` in the
161
+ blueprint is then left exactly as given, and the frames are drawn around the
162
+ devices where they land.
163
+
164
+ Sketch first, build second, is the better order for anything a person will
165
+ look at: you can see the whole diagram before a single cable exists, and the
166
+ skill's job narrows to making the file match the drawing.
167
+
168
+ Without the knob the packing applies, and it is deterministic: the same
169
+ blueprint gives the same coordinates every time, so a regenerated lab does not
170
+ drift.
171
+
172
+ ### Scale
173
+
174
+ There is no artificial device limit. The only ceiling is physical: a switch has
175
+ the ports it has, and the generator says so plainly when it runs out. Ask for
176
+ more switches, not fewer hosts.
177
+
178
+ ### A generated lab becomes the next build's donor
179
+
180
+ Donor selection can pick a lab this skill produced, so every repair pass
181
+ eventually runs over its own output. Write interface configuration with
182
+ `_set_config_block`, never by appending, and check a new pass by running it
183
+ three times and asserting the document stops changing after the first.
184
+
185
+ ### The palette is not the vocabulary
186
+
187
+ Packet Tracer's device palette lists more kinds than a saved lab distinguishes:
188
+ `SMARTPHONE-PT` saves as `Pda`, `Fiber Patch Panel` saves as `Patch Panel`.
189
+ Adding an askable kind with no donor behind it produces a request that can only
190
+ come back as an undelivered device. `tests/test_askable_kinds_have_donors.py`
191
+ holds the vocabulary to what real labs actually contain, in both directions.
192
+
193
+ ### When generation refuses
194
+
195
+ A refusal returns `blocking_gaps` together with a `blueprint_plan`. That is not
196
+ a failure to work around by loosening a policy -- it is the skill saying no
197
+ donor can serve the request. Read the gaps, adjust the request or supply a
198
+ donor, and try again.
199
+
200
+ ### What works without Packet Tracer installed
201
+
202
+ Decode, inventory, edit, generate and structural verification all work from the
203
+ donor cache with no install and no environment variables -- the Twofish engine
204
+ is vendored pure Python. Only `--validate-open` and live pings need the
205
+ application itself. Tests that build a lab are marked `requires_donors` and skip
206
+ where there is nothing to build from.
207
+
208
+ ## How `.pkt` Files Work
209
+
210
+ For the modern format targeted by this skill, the pipeline is:
211
+
212
+ 1. Build a Packet Tracer XML document rooted at `<PACKETTRACER5>`
213
+ 2. qCompress the UTF-8 XML bytes using:
214
+ - 4-byte big-endian uncompressed length
215
+ - raw zlib payload
216
+ 3. Apply Stage-2 XOR obfuscation
217
+ 4. Encrypt with Twofish in EAX mode and append the 16-byte authentication tag
218
+ 5. Apply Stage-1 reverse/XOR obfuscation
219
+
220
+ The XML includes a `<VERSION>` value such as `9.0.0.0810`. This skill targets the
221
+ 9.0 line.
222
+
223
+ Packet Tracer 5.x and 6.x wrote a simpler container: qCompress output XORed
224
+ byte-wise with `(length - index)`, with no cipher and no tag. 18 of the 292
225
+ bundled samples are still in that format. `decode_pkt_auto` reads both and
226
+ reports which one matched.
227
+
228
+ Packet Tracer also writes raw control bytes into element text — a Cisco banner
229
+ delimiter is literally `banner motd `, which XML 1.0 forbids. Use
230
+ `parse_pkt_xml` / `serialize_pkt_xml` rather than `ET.fromstring` / `ET.tostring`
231
+ so those bytes survive a round trip.
232
+
233
+ The Twofish step needs no compiled binary. `scripts/vendor/twofish_pure.py` is a
234
+ vendored pure-Python implementation verified against the official Twofish test
235
+ vectors, so decode/edit/generate work on a clean checkout with no environment
236
+ variables. A compiled `_twofish` bridge is optional: when `PKT_TWOFISH_LIBRARY`
237
+ or `PKT_TWOFISH_SEARCH_ROOTS` resolves one, it is used automatically as a ~12x
238
+ accelerator for large labs.
239
+
240
+ ### Donor Version Compatibility
241
+
242
+ The build field in a `<VERSION>` string is not a schema identifier — it changes
243
+ on every point release and re-save. None of the 292 sample saves bundled with
244
+ Packet Tracer 9.0.0 carry `9.0.0.0810`; 48 are `9.0.0.x` with other builds and
245
+ the rest span 5.x through 8.x. Donors are therefore classified into tiers:
246
+
247
+ | Tier | Meaning |
248
+ |---|---|
249
+ | `exact` | build strings identical |
250
+ | `same_minor` | same `major.minor`, e.g. any `9.0.0.x` |
251
+ | `same_major` | same major, different minor |
252
+ | `upgradeable` | 6.x–8.x; Packet Tracer upgrades these on open |
253
+ | `incompatible` | 5.x and older |
254
+
255
+ `PACKET_TRACER_DONOR_POLICY` names the loosest acceptable tier. The default is
256
+ `same_minor`. When several donors qualify, the strictest tier wins.
257
+
258
+ The target version is **detected**, not hardcoded. Resolution order:
259
+ `PACKET_TRACER_TARGET_VERSION` → the installed Packet Tracer's directory name →
260
+ the compatibility donor's own `<VERSION>` → the built-in default. Installing
261
+ Packet Tracer 8.2 makes the skill target 8.2 and accept 8.2.x donors; no
262
+ configuration is needed to follow a different release.
263
+
264
+ ## Workflow
265
+
266
+ 1. Parse the request into a hybrid intent plan:
267
+ - topology, device models, links, cable types, ports
268
+ - natural Azerbaijani or mixed-language counts such as `3 dene switch ve 6 komputer`
269
+ - department/campus prompts such as `6 sobeli kampus sebekesi`
270
+ - VLAN/trunk/access/router-on-a-stick intent
271
+ - router DHCP or server DHCP/DNS intent
272
+ - management VLAN / Telnet intent
273
+ - AP SSID/security and wireless client association intent
274
+ - existing `.pkt` edit operations when a source file is provided
275
+ 2. Build an intent-first topology/config plan:
276
+ - topology archetype
277
+ - device list
278
+ - port map
279
+ - VLAN/service/config plan
280
+ - assumptions and blocking gaps
281
+ 3. Rank Cisco local donor candidates with capability, topology, and donor-graph scoring
282
+ 4. Optionally search/import remote labs, then rank imported labs as curated donors or reference patterns
283
+ 5. Apply donor-prune mutations on one working Cisco 9.0 donor lab
284
+ 6. Validate workspace/runtime/scenario compatibility
285
+ 7. Encode XML into a `.pkt` blob with `scripts/pkt_codec.py`
286
+ 8. Save generated or edited output locally
287
+
288
+ Open-first rules remain strict:
289
+
290
+ - multi-source search and scoring is allowed
291
+ - final `.pkt` apply is still single-donor
292
+ - when no safe donor exists, return `blocking_gaps` plus a `blueprint_plan`
293
+
294
+ ## Files
295
+
296
+ - `scripts/pkt_builder.py`
297
+ Thin entrypoint: selects a sample and delegates to `pkt_transformer`
298
+ - `scripts/pkt_codec.py`
299
+ Encodes and decodes the modern `.pkt` format
300
+ - `scripts/vendor/twofish_pure.py`
301
+ Vendored pure-Python Twofish; the repo-local baseline engine
302
+ - `scripts/pkt_verify.py`
303
+ Two-tier verification: headless structural checks, plus a real Packet Tracer
304
+ open test that watches for the file's window
305
+ - `scripts/usage_ledger.py`
306
+ Local, gitignored record of which donors actually worked, fed back into donor
307
+ ranking so the skill improves with use
308
+ - `scripts/generate_pkt.py`
309
+ CLI entrypoint for generate/edit/decode/inventory/explain-plan
310
+ - `scripts/intent_parser.py`
311
+ Hybrid natural-language and mini-DSL parser
312
+ - `scripts/pkt_editor.py`
313
+ Existing `.pkt` inventory and mutation engine
314
+ - `scripts/sample_catalog.py`
315
+ Capability-tagged sample index and reference-pattern loader
316
+ - `scripts/sample_selector.py`
317
+ Sample ranking by capability, topology, trust level, and prototype eligibility
318
+ - `scripts/packet_tracer_env.py`
319
+ Resolves Packet Tracer install, saves root, and executable paths
320
+ - `scripts/runtime_doctor.py`
321
+ Unified runtime diagnostics for host OS, donor, Packet Tracer paths, and Twofish readiness
322
+ - `templates/pt900/base_empty.xml`
323
+ Base Packet Tracer 9.0 skeleton
324
+ - `templates/pt900/device_library/*.xml`
325
+ Secondary fallback device XML templates for the first supported device set
326
+
327
+ The runtime builder currently prefers the installed FTP sample from the local
328
+ Packet Tracer `saves/` directory. The exact path is resolved at runtime from
329
+ the local Packet Tracer installation or the `PACKET_TRACER_*` environment
330
+ variables.
331
+
332
+ Prompt-driven donor-prune generation prefers an explicit
333
+ `PACKET_TRACER_COMPAT_DONOR`, but it can also auto-detect a working local
334
+ Packet Tracer 9.0 donor from common local locations when the environment
335
+ override is absent.
336
+
337
+ Strict compatibility rules:
338
+
339
+ - the target version is detected from the install; override with `PACKET_TRACER_TARGET_VERSION` only when you need to pin it
340
+ - never accept a `5.x` donor; Packet Tracer does not reliably upgrade those
341
+ - the donor tier that was accepted is recorded in `compatibility_tier` and
342
+ reported as an assumption, never hidden
343
+ - if the donor is missing, undecodable, or below the active policy tier, stop
344
+ with a blocking error that names the tier and the policy needed to accept it
345
+ - if `PACKET_TRACER_COMPAT_DONOR` is explicitly set and rejected, do not silently
346
+ fall back to another donor
347
+ - `PACKET_TRACER_*` variables must be inherited by every host process;
348
+ `PKT_TWOFISH_*` is optional and only selects the compiled accelerator
349
+
350
+ ## Supported First Iteration
351
+
352
+ - `Router`, `Switch`, `PC`, `Server`
353
+ - `LightWeightAccessPoint` / `WirelessRouter` where sample prototypes exist
354
+ - natural prompt planning for device counts, VLAN IDs, `gig` uplinks, `fa` host links,
355
+ department/campus prompts, and default `chain` / `core switch` topologies
356
+ - structured `blocking_gaps`, `assumptions_used`, and `confidence_score` reporting
357
+ - transparent `explain-plan` output with:
358
+ - `intent_plan`
359
+ - `topology_plan`
360
+ - `config_plan`
361
+ - `estimate_plan`
362
+ - `preflight_validation`
363
+ - `autofix_summary`
364
+ - `cisco_sample_candidates`
365
+ - `curated_external_donor_candidates`
366
+ - `external_reference_patterns`
367
+ - `validation_report`
368
+ - explicit port-to-port and cable/media mapping
369
+ - VLAN create, access port, trunk port, native VLAN
370
+ - router subinterfaces and router-on-a-stick
371
+ - named ACL create, permit/deny rule injection, and `ip access-group` interface binding
372
+ - router DHCP pool
373
+ - server DHCP pool, DNS enablement, and DNS records
374
+ - HTTP / HTTPS / FTP / TFTP / NTP service enable state
375
+ - end-device DNS client settings
376
+ - management VLAN SVI + default gateway
377
+ - Telnet enablement on switches/routers via config mutations
378
+ - wireless SSID/security/channel mutations
379
+ - wireless client association and DHCP/static mode where compatible prototypes exist
380
+ - existing `.pkt` inventory and edit flow
381
+
382
+ ## Defaults
383
+
384
+ If the user does not specify details:
385
+
386
+ - Packet Tracer version: `9.0.0.0810`
387
+ - Subnet: `192.168.1.0/24`
388
+ - Default gateway: `192.168.1.1`
389
+ - PC addresses: `.10`, `.11`, `.12`, ...
390
+ - Layout:
391
+ - router around `(400, 140)`
392
+ - switch around `(400, 280)`
393
+ - PCs along the bottom row
394
+
395
+ ## Constraints
396
+
397
+ - The builder needs Packet Tracer's bundled sample saves as prototype sources,
398
+ from a local installation on Windows, macOS or Linux **or** from the donor
399
+ cache under `~/.pkt/saves`, which a single generate run on an installed
400
+ machine populates and which can then be copied anywhere
401
+ - Donor devices the plan does not need are deleted. `PACKET_TRACER_SPARE_STRATEGY=park`
402
+ restores the older behaviour of renaming them `UNUSED-*` / `*-SPARE-*` and
403
+ moving them offscreen, if a donor turns out to depend on one staying present
404
+ - `--validate-open` needs Packet Tracer installed. Everything else — decode,
405
+ inventory, edit, generate, structural verification — does not
406
+ - The bundled template library is intentionally minimal in v1
407
+ - Imported external sample roots are reference-only unless you explicitly promote them
408
+ - Prompt generation in the default path is donor-prune based, not full synthetic rebuild
409
+ - Host-to-VLAN distribution is defaulted to an even split when not given, and the
410
+ split is reported as an assumption. `PACKET_TRACER_STRICT_VLAN_ASSIGNMENT=1`
411
+ refuses instead
412
+ - Links the donor lacks are built rather than refused. `PACKET_TRACER_LINK_STRATEGY=reuse`
413
+ restricts generation to the donor's own topology
414
+ - Manual validation in Packet Tracer is still required before claiming a topology
415
+ is fully compatible with the Cisco application
416
+
417
+ ## CLI Examples
418
+
419
+ Generate from a blueprint file:
420
+
421
+ ```powershell
422
+ python scripts/generate_pkt.py --blueprint examples/blueprint_minimal.json --output output\minimal.pkt
423
+ ```
424
+
425
+ Check what a finished lab contradicts about itself, and exit non-zero if it does:
426
+
427
+ ```powershell
428
+ python scripts/generate_pkt.py --coherence-report output\campus.pkt
429
+ ```
430
+
431
+ Generate from a hybrid prompt:
432
+
433
+ ```powershell
434
+ python scripts/generate_pkt.py --prompt "6 şöbəli şəbəkə qur, VLAN 10 20 30 40 50 60 və management VLAN 99 yarat" --output output\campus.pkt
435
+ ```
436
+
437
+ Explain the parsed plan before generation:
438
+
439
+ ```powershell
440
+ python scripts/generate_pkt.py --explain-plan "set SW1 vlan 10 name Finance; enable telnet on SW1 username admin password 1234"
441
+ ```
442
+
443
+ Explain a natural Azerbaijani prompt before generation:
444
+
445
+ ```powershell
446
+ python scripts/generate_pkt.py --explain-plan "3 dene switch ve 6 komputer ve 1 router vlanlarda 10,20,30 switchlerin oz aralarinda ve routerle aralarinda gig portuna qosulsun komputerler ise fa portlarla qosulsun"
447
+ ```
448
+
449
+ Inspect curated donor candidates from a local imported lab root:
450
+
451
+ ```powershell
452
+ python scripts/generate_pkt.py --explain-plan "6 şöbəli şəbəkə qur, hər şöbədə 1 switch 1 AP 1 printer 2 PC 2 tablet olsun" --donor-root C:\labs\curated-pkt-donors --reference-root C:\labs\external-pkt-samples
453
+ ```
454
+
455
+ Only external `9.0.0.0810` labs are promoted into the curated donor pool when
456
+ their workspace validation passes cleanly, or when they are `legacy_uuid_physical`
457
+ donors whose only logical warnings are repeated `MEM_ADDR` mismatch records.
458
+
459
+ Search GitHub first, then auto-import matching repos into a local cache:
460
+
461
+ ```powershell
462
+ python scripts/generate_pkt.py --explain-plan "6 department campus with vlan dhcp dns ap" --search-remote --remote-provider github --import-cache-root output\remote-cache
463
+ ```
464
+
465
+ Print the aggregated capability matrix:
466
+
467
+ ```powershell
468
+ python scripts/generate_pkt.py --coverage-report
469
+ python scripts/generate_pkt.py --coverage-report --device-family "access points"
470
+ ```
471
+
472
+ Inspect an existing `.pkt` inventory:
473
+
474
+ ```powershell
475
+ python scripts/generate_pkt.py --inventory input\lab.pkt
476
+ python scripts/generate_pkt.py --inventory input\lab.pkt --inventory-capabilities
477
+ ```
478
+
479
+ Edit an existing `.pkt` directly from a prompt:
480
+
481
+ ```powershell
482
+ python scripts/generate_pkt.py --edit input\lab.pkt --prompt "set Wireless Router0 ssid FIN_WIFI security wpa2-psk passphrase fin12345 channel 6 associate PC0 to Wireless Router0 ssid FIN_WIFI dhcp" --output output\edited_lab.pkt --xml-out output\edited_lab.xml
483
+ python scripts/generate_pkt.py --edit input\lab.pkt --prompt "enable dns on Server0 set Server0 dns A www.example.local 192.168.10.20 set PC0 dns 192.168.10.20" --output output\edited_services.pkt
484
+ ```
485
+
486
+ Decode a `.pkt` back to XML for inspection:
487
+
488
+ ```powershell
489
+ python scripts/generate_pkt.py --decode output\minimal.pkt --xml-out output\minimal.xml
490
+ ```
491
+
492
+ Verify a generated file. The structural tier is headless; `--open` launches
493
+ Packet Tracer and waits until the file's own window appears:
494
+
495
+ ```powershell
496
+ python scripts/pkt_verify.py output\minimal.pkt
497
+ python scripts/pkt_verify.py output\minimal.pkt --open
498
+ python scripts/generate_pkt.py --validate-open output\minimal.pkt
499
+ ```
500
+
501
+ A file that fails the structural tier is never handed to Packet Tracer.
502
+
503
+ Inspect what the skill has learned from previous runs:
504
+
505
+ ```powershell
506
+ python scripts/usage_ledger.py
507
+ ```
508
+
509
+ Learning is local and on by default. Prompts are stored only as a non-reversible
510
+ fingerprint, the ledger lives under gitignored `output/`, and it is never
511
+ committed or packaged. Set `PKT_USAGE_LEDGER=off` to disable it, or point it at
512
+ another path. Deleting the ledger changes results in no way except donor
513
+ ordering.