@maccesar/titools 5.2.2 → 5.2.4

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 (25) hide show
  1. package/README.md +87 -83
  2. package/docs/examples.md +3 -1
  3. package/package.json +1 -1
  4. package/skills/ti-game/SKILL.md +2 -0
  5. package/skills/ti-game/references/source-notes.md +20 -4
  6. package/skills/ti-synthengine/SKILL.md +26 -7
  7. package/skills/ti-synthengine/assets/example/README.md +14 -7
  8. package/skills/ti-synthengine/assets/example/app.js +20 -0
  9. package/skills/ti-synthengine/references/advanced-examples.md +27 -2
  10. package/skills/ti-synthengine/references/api.md +238 -227
  11. package/skills/ti-synthengine/references/audio-engine.md +44 -20
  12. package/skills/ti-synthengine/references/audio-pipeline-validation.md +19 -0
  13. package/skills/ti-synthengine/references/examples.md +1 -1
  14. package/skills/ti-synthengine/references/guide.md +30 -13
  15. package/skills/ti-synthengine/references/instruments-and-effects.md +157 -0
  16. package/skills/ti-synthengine/references/native-variation-proposal.md +182 -0
  17. package/skills/ti-synthengine/references/native-variation-validation.md +63 -0
  18. package/skills/ti-synthengine/references/native-variation.md +283 -0
  19. package/skills/ti-synthengine/references/recipes.md +1 -2
  20. package/skills/ti-synthengine/references/recommendations.md +3 -3
  21. package/skills/ti-synthengine/references/sound-design.md +16 -14
  22. package/skills/ti-synthengine/references/source-notes.md +75 -37
  23. package/skills/ti-synthengine/references/source-snapshot.json +203 -192
  24. package/skills/ti-synthengine/references/stats-performance.md +1 -1
  25. package/skills/ti-synthengine/references/troubleshooting.md +36 -28
@@ -1,4 +1,4 @@
1
- > Source snapshot: official TiSynthEngine 1.0.0 documentation at release source commit `e7cbbe8a6f9ab38088fd8029c7b43cef6501101f` (2026-10-24). Upstream `documentation/sound-design.md` SHA-256: `dd543e07c825aaf67a0a5f85619088a8d02721a9d33dbf4579edf760dad3e262`.
1
+ > Source snapshot: official TiSynthEngine documentation at commit `b07c97c762be5905f132cecf33e9d60ea0c21316` (2026-11-02). Published 1.0.2; local 1.1.0 candidates; public API 1.0.0. Upstream `documentation/sound-design.md` SHA-256: `3ad60c006e6ba296110b73362ebba74a30fd5e722fae6c5066cec815e500262a`.
2
2
 
3
3
  # Sound design with TiSynthEngine
4
4
 
@@ -6,6 +6,8 @@ TiSynthEngine generates sound with oscillators, without recorded samples. Pitch,
6
6
 
7
7
  Additional [curated recipes](recipes.md) provide application sound and interaction variants.
8
8
 
9
+ For the distinction between a playable timbre and a complete effect recipe, start with [instruments, sound effects and complete sequences](instruments-and-effects.md). It covers held keys, independent shots, native sequences, layered effects, demonstrations and shared output headroom.
10
+
9
11
  The examples assume the engine is running and use these constants:
10
12
 
11
13
  ```javascript
@@ -137,27 +139,27 @@ synth.playTone({
137
139
 
138
140
  ## Envelope and total duration
139
141
 
140
- Every event uses an attack, an implicit sustain section and a release:
142
+ A timed tone or chord uses an attack, an implicit sustain section and a release (with an optional decay stage described below):
141
143
 
142
144
  ```text
143
145
  silence -> attack -> full level -> release -> silence
144
146
  |<---------- duration ---------->|
145
147
  ```
146
148
 
147
- `duration` is the total time, not the sustain time. If duration is 500 ms, attack is 50 ms and release is 100 ms, the full-level middle lasts 350 ms.
149
+ `duration` on `playTone` and `playChord` is the total time, not the sustain time. If duration is 500 ms, attack is 50 ms and release is 100 ms, the full-level middle lasts 350 ms. Held voices instead release on `noteOff`; native sequence steps use `duration` for the next-attack interval and `length` or gate for the note deadline. Their release can overlap later attacks. See [the playback contracts](instruments-and-effects.md#3-complete-sound-sequences-and-layered-effects).
148
150
 
149
151
  Short attacks feel immediate. A 0 or 1 ms attack can be useful for percussion, but an abrupt start at an unlucky phase can sound like a click. Values between 5 and 15 ms keep most game feedback crisp without a hard edge.
150
152
 
151
153
  Long attacks soften the onset. Use 100 to 500 ms for pads and slow warnings. Release controls how the sound leaves: 20 to 80 ms feels tight, while several hundred milliseconds leaves a tail.
152
154
 
153
- Explicit attack and release values must fit. These relationships are required:
155
+ For timed tones and chords, explicit attack and release values must fit. These relationships are required:
154
156
 
155
157
  ```text
156
158
  attack < duration
157
159
  release <= duration - attack
158
160
  ```
159
161
 
160
- Defaults are adjusted internally if a very short duration leaves no room, but values supplied by the caller are never reshaped silently.
162
+ Timed defaults are adjusted internally if a very short duration leaves no room; explicit values must pass validation. Native rendering has additional edge rules: held and sequence voices use at least 3 ms attack/release, while iOS timed conversion rounds an accepted zero attack/release to at least one sample and Android preserves zero. Validator acceptance does not establish identical sample envelopes.
161
163
 
162
164
  ## Decay and sustain
163
165
 
@@ -177,7 +179,7 @@ Practical starting regions:
177
179
 
178
180
  `sustain` below 1 needs a nonzero `decay`. Without one the level would jump instantly, which clicks, so the call is rejected with `sustain_without_decay`.
179
181
 
180
- The release scales the level the note has reached. If the release begins while the decay is still running, the note leaves smoothly from that point. The decay still has to fit: `attack` plus `decay` cannot exceed `duration`, and the 50 ms default attack counts. Set a short `attack` explicitly for a tight pluck.
182
+ The release scales the level the note has reached. If the release begins while the decay is still running, the note leaves smoothly from that point. For timed tones and chords, the decay still has to fit: `attack` plus `decay` cannot exceed `duration`, and the 50 ms default attack counts. Set a short `attack` explicitly for a tight pluck.
181
183
 
182
184
  ## Pan and movement
183
185
 
@@ -241,7 +243,7 @@ Filters shape harmonics, so give them a source that has some: `SAWTOOTH`, `SQUAR
241
243
 
242
244
  `filterQ` is the resonance. The default 0.7071 is flat. Values from 2 to 4 add character, and above about 6 the filter whistles around the cutoff. A low-pass or high-pass boosts the cutoff region by about `filterQ`, so Q 10 is roughly 20 dB. Lower the event `volume` as Q goes up. The limiter catches peaks, but a resonance that keeps hitting it makes the whole mix pump. The band-pass keeps unity gain at its center for every Q and only narrows.
243
245
 
244
- `filterHzEnd` moves the cutoff over the whole event. The motion is exponential, so each second covers the same musical distance. Set it above `filterHz` to open the filter and below to close it. Zero disables the sweep.
246
+ For timed tones and chords, `filterHzEnd` moves the cutoff over the whole event. A native sequence sweep instead uses the note length and holds its endpoint during release. The motion is exponential, so each second covers the same musical distance. Set it above `filterHz` to open the filter and below to close it. Zero disables the sweep.
245
247
 
246
248
  ```javascript
247
249
  synth.playTone({
@@ -319,7 +321,7 @@ Choose the profile once in `start()`:
319
321
  | `speakerSafe` | Lower source gain and a 0.70 ceiling for small speakers. |
320
322
  | `raw` | Full source gain; useful only when the app owns all gain staging. |
321
323
 
322
- Protected profiles calibrate source gain by waveform and event voice count. The final stereo-linked limiter catches exceptional peaks with 10 ms of lookahead and a 100 ms release. Its ceiling is 0.85, or 0.70 for `speakerSafe`.
324
+ Protected profiles calibrate source gain by waveform and event voice count. The final stereo-linked sample protector applies immediate reduction with no retained samples and a 100 ms exponential recovery. Overload changes the waveform; fixed per-event gain and chord compensation remain unchanged. Its ceiling is 0.85, or 0.70 for `speakerSafe`.
323
325
 
324
326
  The limiter protects against peaks. If it engages on every note, lower event volume or choose a more conservative profile instead of using it to raise loudness. Repeatedly starting the same long sound before its previous release ends raises and lowers the sum, which can produce audible pumping. That overlap is useful as a stress test, but it is a poor reference for the tone's normal quality.
325
327
 
@@ -636,12 +638,12 @@ The two additional voice LFOs move filter cutoff, square PWM or sine FM index us
636
638
 
637
639
  ## Native space and creative drive
638
640
 
639
- | Processor | What changes | Useful starting region |
640
- | --- | --- | --- |
641
- | Stereo chorus | A short interpolated delay with offset LFO phases adds width and movement. | Rate 0.3 to 0.8 Hz, depth 0.15 to 0.35, mix 0.08 to 0.2. |
642
- | Ping-pong delay | Alternating echoes create rhythmic or spatial repeats. | 180 to 350 ms or synced eighths, feedback 0.15 to 0.35, mix 0.08 to 0.18. |
643
- | Stereo reverb | Damped comb/allpass reflections create a diffuse decay. | Decay 0.8 to 1.8 seconds, damping 0.5 to 0.7, mix 0.08 to 0.18. |
644
- | Optional saturation | Soft waveshaping adds harmonics and changes attack/timbre. | Drive 1.2 to 1.6 with a small blend; compare at matched levels. |
641
+ | Processor | What changes | Useful starting region |
642
+ | ------------------- | -------------------------------------------------------------------------- | ------------------------------------------------------------------------- |
643
+ | Stereo chorus | A short interpolated delay with offset LFO phases adds width and movement. | Rate 0.3 to 0.8 Hz, depth 0.15 to 0.35, mix 0.08 to 0.2. |
644
+ | Ping-pong delay | Alternating echoes create rhythmic or spatial repeats. | 180 to 350 ms or synced eighths, feedback 0.15 to 0.35, mix 0.08 to 0.18. |
645
+ | Stereo reverb | Damped comb/allpass reflections create a diffuse decay. | Decay 0.8 to 1.8 seconds, damping 0.5 to 0.7, mix 0.08 to 0.18. |
646
+ | Optional saturation | Soft waveshaping adds harmonics and changes attack/timbre. | Drive 1.2 to 1.6 with a small blend; compare at matched levels. |
645
647
 
646
648
  All processors are off initially, with input gain 1. Enable one shared chain through `setMasterProcessing`; select `applyTo` categories such as `music` and `ambience` to keep explosions dry. Per-voice `effectSend` overrides that category selection. [Configuration](advanced-examples.md#chorus-delay-reverb-and-creative-saturation) and [exact ranges](api.md#setmasterprocessingoptions) explain chorus, delay, reverb and optional saturation.
647
649
 
@@ -1,38 +1,39 @@
1
1
  # Maintaining the synthesis snapshot
2
2
 
3
- These references mirror the **public TiSynthEngine 1.0.0 release** at
4
- `e7cbbe8a6f9ab38088fd8029c7b43cef6501101f`, recorded in
5
- [source-snapshot.json](source-snapshot.json). The clean local checkout and remote
6
- main matched that commit on 2026-10-24. The repository is public; the Android
7
- and iOS releases are published, neither draft nor prerelease. Module availability
8
- is independent of publishing a new TiTools version.
3
+ These references cover **published module 1.0.2 and local 1.1.0 candidates**, both with public API 1.0.0. All fifteen official Markdown documents were reviewed against the native module. Thirteen are mirrored into fourteen parts; the index and notices retain explicit reviewed exclusions. The official documentation corrections are committed at `b07c97c762be5905f132cecf33e9d60ea0c21316`. Complete source/mirror hashes are recorded in [source-snapshot.json](source-snapshot.json). Review date: 2026-11-02.
9
4
 
10
5
  ## Public downloads and artifact provenance
11
6
 
12
- | Platform | Published release | Package SHA-256 |
13
- | --- | --- | --- |
14
- | Android | [android-1.0.0](https://github.com/macCesar/TiSynthEngine/releases/tag/android-1.0.0) | `cf3510f290eca6dd00e8e0742a7db4f09dd2b8c4ef9270ed1f34d30eb32389cf` |
15
- | iOS / Mac Catalyst | [ios-1.0.0](https://github.com/macCesar/TiSynthEngine/releases/tag/ios-1.0.0) | `bc2e3f88c2945df721dd2196dfbb852c64aa98954b04460adf56ca41c75e6e91` |
7
+ The published replacement packages were downloaded and verified on 2026-10-30 UTC (2026-10-29 locally). The following records are that historical artifact verification, not new downloads during this audit. GitHub release metadata was checked on 2026-11-02: public platform releases remain 1.0.2; local 1.1.0 candidates have no published release.
16
8
 
17
- Both platform tags and `v1.0.0` point at the reviewed commit; only the two
18
- platform tags have GitHub release pages. Downloaded ZIPs were independently
19
- hashed and inspected: module ID `ti.synthengine`, version `1.0.0`, minimum
20
- Titanium `13.2.0.GA`; Android includes four ABIs and the Apple manifest enables
21
- Mac Catalyst. See the [guide](guide.md) for Android API35 and iOS15 requirements,
22
- app-root ZIP installation and both `tiapp.xml` declarations. These checks do not
23
- constitute a fresh device installation or audio acceptance run.
9
+ | Platform | Published release | Replacement package SHA-256 |
10
+ | --- | --- | --- |
11
+ | Android | [android-1.0.2](https://github.com/macCesar/TiSynthEngine/releases/tag/android-1.0.2) | `8698104f188782a77699fbd6308a779ca0b190833ceebf398557b628af1b8bbe` |
12
+ | iOS / Mac Catalyst | [ios-1.0.2](https://github.com/macCesar/TiSynthEngine/releases/tag/ios-1.0.2) | `779e77d018d5b3f686d69cb1b4b0162281803ea12691487df565c1fd15175c58` |
13
+
14
+ Both ZIPs passed full CRC checks and matched the GitHub asset SHA-256 digests at that verification. These hashes replace the original 1.0.2 packages' hashes; filenames and
15
+ release URLs did not change. Manifests report module `ti.synthengine`, version
16
+ `1.0.2`, minimum Titanium `13.2.0.GA`, four Android ABIs and Apple Mac Catalyst
17
+ support. The manifest's native `apiversion` field is distinct from the JavaScript
18
+ contract's `apiVersion: '1.0.0'`, which remains unchanged.
19
+
20
+ All eight Android native libraries (inside the AAR) and three Apple static
21
+ libraries match the preserved original 1.0.2 release packages byte for byte.
22
+ Corrected guide, example and platform README HTML was inspected in both new
23
+ packages. Source/package checks do not constitute a fresh device installation or
24
+ listening acceptance. See the [guide](guide.md) for API35/iOS15 requirements,
25
+ app-root ZIP installation and both `tiapp.xml` declarations.
24
26
 
25
27
  ## Sources and permitted transformations
26
28
 
27
- Eight official Markdown documents are mirrored into nine parts, including the
28
- ordered examples/advanced-examples split. The current snapshot inventories all
29
+ Thirteen official Markdown documents are mirrored into fourteen parts, including the ordered examples/advanced-examples split. New references preserve the complete [instruments/effects guide](instruments-and-effects.md), [implemented variation contract](native-variation.md), [historical proposal](native-variation-proposal.md) and [variation verification](native-variation-validation.md). The proposal is historical design context, not an outstanding implementation plan. The current snapshot inventories all
29
30
  complete JSON reports, bundled example assets and linked raw-evidence archives.
30
- The new [performance review](performance-review.json) and its raw archive are
31
+ The historical [performance review](performance-review.json) and its raw archive are
31
32
  preserved alongside historical reports; none is replaced by a favorable summary.
32
33
  Read snapshot records for exact counts and hashes. Example JavaScript and raw
33
34
  reports/archives remain byte-identical to source.
34
35
 
35
- Each Markdown part and the example README have a local-commit provenance header and recorded navigation transformations. Native-backed corrections to stale official prose are also declared as reversible `link_fixes`; the source hash still identifies the original official text, not the corrected mirror. Reversible `link_fixes` rebase links into the split advanced examples, preserve [curated recipes](recipes.md), and resolve current example links to bundled assets. The example README points back to this skill's current API and guides. All three example JavaScript files remain byte-identical to source; none requires a historical GitHub snapshot.
36
+ Each Markdown part and the example README have a committed-source provenance header and recorded navigation transformations. Verified API, timing, spatial, panic, processing and diagnostic corrections were applied to the official module documentation before synchronization. They are shared source content, not mirror-only errata. Remaining `link_fixes` record navigation and curated entry points; the source hash identifies the corrected official committed text. Reversible `link_fixes` rebase links into the split advanced examples, preserve [curated recipes](recipes.md), and resolve current example links to bundled assets. The example README points back to this skill's current API and guides. All three example JavaScript files remain byte-identical to source; none requires a historical GitHub snapshot.
36
37
 
37
38
  The fidelity regression strips provenance/navigation, concatenates example parts, reverses declared transformations and compares the complete source hash. Raw records must remain byte-identical. Update transformations intentionally; never change hashes merely to hide unexplained source drift.
38
39
 
@@ -48,6 +49,42 @@ Focused executable recipe tests inspect submitted intervals, envelope lengths, p
48
49
 
49
50
  Selective `music`, `effects`, `ui` and `ambience` categories feed one shared effect chain; an explicit per-voice send overrides category selection. Live spatial position, noise clock, low-pass cutoff and compatible continuous voice controls ramp over 10 ms while preserving history. Priorities protect higher-priority voices without reserved quotas. See the [API](api.md) for exact limits, source compatibility, return values and event delivery.
50
51
 
52
+ ### Module 1.0.1 and 1.0.2 corrections
53
+
54
+ Michael Gangolf's [Android PR #1](https://github.com/macCesar/TiSynthEngine/pull/1)
55
+ updates Oboe to 1.11.0, recovers closed streams after all stream errors, keeps a
56
+ single demand-driven sequence-event poll chain and shuts down on root activity
57
+ destruction. Removing the unused Java Thread inheritance changes no public API.
58
+ The subsequent Apple correction polls only while sequence events or held-voice
59
+ metadata need retirement and guards shutdown/restart reentry. Neither poller is
60
+ a musical scheduler; explicit engine ownership/teardown remains required.
61
+
62
+ Module 1.0.2 shares final output processing in `shared/synth_output.h`: zero
63
+ retained samples, immediate stereo-linked sample protection, ceilings 0.85/0.70,
64
+ 100 ms exponential recovery and reset after two consecutive quiet stereo frames.
65
+ Master volume ramps linearly over 10 ms on both platforms, independently of the
66
+ protector. The iOS `raw` startup correction now applies its documented gain;
67
+ existing raw mixes need review. Overload changes the waveform, and sample
68
+ ceilings do not certify inter-sample peaks or speaker behavior.
69
+
70
+ [Pipeline validation](audio-pipeline-validation.md) preserves the new production
71
+ callback/CI checks, five-rate output comparisons and physical scope. Preset
72
+ calibration measures both renderers and six scenarios at 1/2/4/8/16/32 voices;
73
+ fixed-gain recommendations target the measured 1–8-voice configuration, with
74
+ 16/32 kept as stress diagnostics. It never edits Studio. The Android startup
75
+ underrun remains unresolved, including independent silent Oboe reproduction.
76
+ Route-wide latency, Bluetooth and extended maximum-load acceptance remain open.
77
+
78
+ Official documentation corrections preserve panic cancellation (`stopAll` stops every
79
+ sequence and invalidates effect histories), compatible live `updateVoice`
80
+ noise/low-pass/spatial/send edits, and category selection with `applyTo` plus
81
+ explicit `effectSend` overrides. The matching mirror-only errata were removed from the transformation list; curated recipe navigation remains reversible.
82
+ Android and Apple production callback tests now run in CI; the historical Java
83
+ DSP model is not the production audio oracle. No native binaries were installed
84
+ or device/listening tests rerun during this skill update.
85
+
86
+ ### Historical evidence
87
+
51
88
  The [performance review](performance-review.json) documents the accepted
52
89
  control-thread changes: partial sequence-bank preparation and removal of idle
53
90
  allocations/orphan held-position metadata. The Apple rendering bundle was
@@ -65,12 +102,10 @@ bypass, memory and strict Frontier presentation criteria. Current evidence and
65
102
  rejected candidates must not be combined into a general pass. This skill update
66
103
  did not rerun devices, install binaries or alter native source.
67
104
 
68
- The October 23 native findings were independently rechecked against the
69
- published source on October 24. These current differences remain explicit;
70
- hash fidelity alone cannot establish them:
105
+ The native differences below were rechecked against current sources on November 2 and are now documented accurately in the official API/engine guides as well as the mirrors. They describe implementation differences, not unresolved documentation contradictions:
71
106
 
72
- - iOS timed tone/chord command construction still rounds accepted zero attack
73
- and release to at least one sample; Android preserves zero. Validator
107
+ - iOS timed tone/chord command construction initially rounds accepted zero attack
108
+ and release to one sample before duration-budget trimming; Android preserves zero. Validator
74
109
  acceptance does not establish identical sample envelopes.
75
110
  - iOS early tempo/sequence/processing rejections and incompatible held spatial/
76
111
  modulation edits can bypass rejection counters. Android also leaves some
@@ -79,20 +114,23 @@ hash fidelity alone cannot establish them:
79
114
  - Sequence cutoff coefficients currently refresh every 16 samples on Android
80
115
  and every 8 samples on Apple; both use note length but do not promise identical
81
116
  sample output. See [engine details](audio-engine.md).
82
- - Android `getDefaults()` includes capabilities and additional limit metadata
83
- that the current iOS dictionary omits. Both expose the corresponding APIs;
84
- detect methods rather than requiring Android-only metadata flags. Sequence
85
- intervals use different beat and millisecond ranges; see [API](api.md).
86
- - Remaining stale official claims are corrected only where verified against
87
- current native behavior, with exact reversible transformations. Corrections
88
- already adopted upstream are removed from the transformation list.
117
+ - Local 1.1.0 returns `capabilities.variation: true` and `variationSchemaVersion: 1` on both platforms. Android also reports native sequence/master processing/modulation flags and `limits.stepDurationMs`; iOS omits those additional entries. Published 1.0.2 does not accept variation. Both platforms return sequence-capacity, priority and send limits; use the [API](api.md) for exact beat/millisecond ranges.
118
+ - Official examples now bind their waveform constants and document native sequence modulation, complete effect fidelity and publication ownership correctly. The mirrors preserve the same facts.
89
119
 
90
120
 
91
- These findings are skill corrections and module implementation findings, not
92
- native fixes. No module code, public range or hardware acceptance was changed.
121
+ These are official-documentation and skill corrections, not native implementation fixes. No module code, public range or hardware acceptance was changed.
93
122
  A validator corpus establishes accepted/rejected dictionaries, not sample-identical
94
- rendering on a physical device. Consumer scenarios and exact native locators
95
- are recorded in the maintainer's October 23 audit evidence.
123
+ rendering on a physical device. Current source-first coverage ledgers and native locators are recorded in the maintainer's November 2 audit evidence.
124
+
125
+ ## Local 1.1.0 attack variation
126
+
127
+ Both platforms validate eight bounded parameter ranges and select once per admitted attack. Require the capability/schema pair and omit the property entirely on published 1.0.2, including amount zero. The [variation guide](native-variation.md) preserves exact bounds, linear amount, pitch ratio, source prerequisites, per-chord ordinals, held stability, whole-dictionary step replacement, revision merging and deterministic seed identity. `updateVoice` rejects the attack dictionary. Preserve all of the authored envelope, cadence, routing and layer gains.
128
+
129
+ The [verification report](native-variation-validation.md) separates initial host/build checks from later consumer installations and scoped listening feedback. It records the 144-byte configuration and four-transport growth from 8,627,712 to 9,537,152 bytes, excluding other engine/bridge/process storage. Earlier 1.0.2 memory reports remain historical. Host callback timings do not prove device overhead or sustained acceptance.
130
+
131
+ This audit reran the paired production validators (156 cases per platform), the affected documentation checks and TiTools mirror/recipe checks. New source inspection verified sampling/admission and sequence seed identity. Historical renderer PCM, native build, consumer install and listening results were read with their original boundaries; they were not repeated or expanded into general device acceptance. No native source or binary was changed.
132
+
133
+ All thirteen raw JSON/ZIP records moved upstream from `documentation/` to `docs/validation/` without changing bytes. Their distributed skill paths are preserved; the snapshot now records their actual upstream locations. All five ZIPs passed CRC checks. The three example JavaScript assets remain byte-identical; `app.js` now includes the capability-gated attack-variation action.
96
134
 
97
135
  ## Upstream documents outside the mirror set
98
136