claudecode-omc 5.6.6 → 5.6.7

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 (58) hide show
  1. package/.local/skills/h5-to-swiftui/SKILL.md +201 -0
  2. package/.local/skills/h5-to-swiftui/assets/calibration/README.md +176 -0
  3. package/.local/skills/h5-to-swiftui/assets/calibration/h5-twin/index.html +52 -0
  4. package/.local/skills/h5-to-swiftui/assets/calibration/h5-twin/style.css +133 -0
  5. package/.local/skills/h5-to-swiftui/assets/calibration/swiftui-twin/Package.swift +26 -0
  6. package/.local/skills/h5-to-swiftui/assets/calibration/swiftui-twin/Sources/CalibrationScreen/CalibrationScreen.swift +142 -0
  7. package/.local/skills/h5-to-swiftui/assets/calibration/swiftui-twin-divergent/Package.swift +32 -0
  8. package/.local/skills/h5-to-swiftui/assets/calibration/swiftui-twin-divergent/Sources/CalibrationScreenDivergent/CalibrationScreenDivergent.swift +122 -0
  9. package/.local/skills/h5-to-swiftui/assets/calibration/tokens.json +42 -0
  10. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/index.html +14 -0
  11. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/package.json +20 -0
  12. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/public/api/articles/001.json +96 -0
  13. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/public/api/articles/index.json +89 -0
  14. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/App.jsx +22 -0
  15. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/App.module.css +11 -0
  16. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/components/ArticleCard.jsx +53 -0
  17. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/components/ArticleCard.module.css +139 -0
  18. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/components/NavBar.jsx +37 -0
  19. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/components/NavBar.module.css +72 -0
  20. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/components/TagCloud.jsx +30 -0
  21. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/components/TagCloud.module.css +50 -0
  22. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/components/TrendChart.jsx +159 -0
  23. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/components/TrendChart.module.css +21 -0
  24. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/main.jsx +12 -0
  25. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/screens/ArticleScreen.jsx +182 -0
  26. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/screens/ArticleScreen.module.css +294 -0
  27. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/screens/FeedScreen.jsx +147 -0
  28. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/screens/FeedScreen.module.css +161 -0
  29. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/styles/global.css +50 -0
  30. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/styles/tokens.css +103 -0
  31. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/vite.config.js +6 -0
  32. package/.local/skills/h5-to-swiftui/assets/sample-h5-vanilla/data/tasks.js +67 -0
  33. package/.local/skills/h5-to-swiftui/assets/sample-h5-vanilla/index.html +26 -0
  34. package/.local/skills/h5-to-swiftui/assets/sample-h5-vanilla/router.js +73 -0
  35. package/.local/skills/h5-to-swiftui/assets/sample-h5-vanilla/screens/detail.js +164 -0
  36. package/.local/skills/h5-to-swiftui/assets/sample-h5-vanilla/screens/home.js +53 -0
  37. package/.local/skills/h5-to-swiftui/assets/sample-h5-vanilla/screens/list.js +87 -0
  38. package/.local/skills/h5-to-swiftui/assets/sample-h5-vanilla/styles/app.css +342 -0
  39. package/.local/skills/h5-to-swiftui/assets/sample-h5-vanilla/styles/tokens.css +68 -0
  40. package/.local/skills/h5-to-swiftui/references/css-to-swiftui-map.md +205 -0
  41. package/.local/skills/h5-to-swiftui/references/design-token-extraction.md +209 -0
  42. package/.local/skills/h5-to-swiftui/references/high-risk-triage.md +209 -0
  43. package/.local/skills/h5-to-swiftui/references/render-equivalence-calibration.md +193 -0
  44. package/.local/skills/h5-to-swiftui/references/stack-detection.md +160 -0
  45. package/.local/skills/h5-to-swiftui/references/visual-diff-loop-protocol.md +365 -0
  46. package/.local/skills/h5-to-swiftui/scripts/_calib-consts.mjs +150 -0
  47. package/.local/skills/h5-to-swiftui/scripts/_imglib.mjs +547 -0
  48. package/.local/skills/h5-to-swiftui/scripts/_provenance.mjs +123 -0
  49. package/.local/skills/h5-to-swiftui/scripts/calibrate-render.mjs +625 -0
  50. package/.local/skills/h5-to-swiftui/scripts/capture-reference.mjs +386 -0
  51. package/.local/skills/h5-to-swiftui/scripts/detect-stack.mjs +305 -0
  52. package/.local/skills/h5-to-swiftui/scripts/evaluate-convergence.mjs +1093 -0
  53. package/.local/skills/h5-to-swiftui/scripts/extract-tokens.mjs +600 -0
  54. package/.local/skills/h5-to-swiftui/scripts/mark-overlay.mjs +379 -0
  55. package/.local/skills/h5-to-swiftui/scripts/pixel-diff.mjs +530 -0
  56. package/.local/skills/h5-to-swiftui/scripts/sim-screenshot.sh +544 -0
  57. package/bundled/manifest.json +1 -1
  58. package/package.json +1 -1
@@ -0,0 +1,123 @@
1
+ /**
2
+ * _provenance.mjs — Shared provenance binding for h5-to-swiftui calibration.
3
+ *
4
+ * Single source of truth for the deterministic source-tree hash used to bind
5
+ * the IDENTITY of the SHIPPED bundled calibration twin SOURCE FILES (NOT the
6
+ * measured `floor` value) into a `calibration.json`. Both
7
+ * `calibrate-render.mjs` (producer) and `evaluate-convergence.mjs` (consumer)
8
+ * import THIS function so the hash is computed identically on both sides.
9
+ *
10
+ * Scope of what this binds (precise — no over-claim): it binds the *identity*
11
+ * of the bundled twin source files. It does NOT bind the measured `floor`
12
+ * value: an attacker who keeps the real, public, unmodified bundled-twin
13
+ * source hashes but writes a loose `floor` is NOT caught by this hash. The
14
+ * grader narrows that path with FIX A (the floor must satisfy
15
+ * calibrate-render's own sanity envelope, see `_calib-consts.mjs`); a floor
16
+ * *within* that envelope yet looser than the true measured floor is a
17
+ * disclosed irreducible residual (the grader cannot re-render to re-measure
18
+ * it). See the Trust-model header in `evaluate-convergence.mjs`.
19
+ *
20
+ * Why a source-tree hash (not the rendered PNG hash):
21
+ * The rendered PNGs are produced at runtime by sim-screenshot.sh /
22
+ * capture-reference.mjs and will NOT be byte-identical across machines
23
+ * (renderer/OS/font differences). The SOURCE the calibration must derive
24
+ * from is fixed and shippable, so we content-hash the source tree instead.
25
+ *
26
+ * Determinism rules (must hold across OS / cwd / clone):
27
+ * - file list is sorted by POSIX relative path (forward slashes)
28
+ * - each file contributes: `<relpath>\0<sha256-of-bytes>\n`
29
+ * - directories that do not exist contribute a sentinel (so a missing tree
30
+ * is detected, never silently treated as "matches")
31
+ * - the `.build/`, `.swiftpm/`, `xcuserdata/` SwiftPM artifact dirs and
32
+ * dotfiles are excluded (gitignored build output, not source) — so what
33
+ * is pinned is the SOURCE FILES (excluding build output/dotfiles), not
34
+ * the whole on-disk tree; see the EXCLUSION RATIONALE on SKIP_DIR below
35
+ *
36
+ * No npm dependencies — node:crypto + node:fs + node:path only.
37
+ */
38
+
39
+ import { readFileSync, readdirSync, statSync, existsSync } from 'node:fs';
40
+ import { join, relative, sep } from 'node:path';
41
+ import { createHash } from 'node:crypto';
42
+
43
+ // EXCLUSION RATIONALE (FIX D — MAJOR-1, precise):
44
+ // Excluded-path content — dotfiles/dotdirs (the `name.startsWith('.')` skip
45
+ // in walk()), `.git`, `.build`, `.swiftpm`, `xcuserdata`, `node_modules`
46
+ // (this SKIP_DIR set) — is INTENTIONALLY NOT bound by the source-tree hash.
47
+ // This is SAFE FOR THE BUNDLED CALIBRATION ASSETS SPECIFICALLY because those
48
+ // trees (`assets/calibration/{h5-twin,swiftui-twin,swiftui-twin-divergent}`)
49
+ // are HTML/CSS/Swift SOURCE containing no dotfiles, and `.build/` /
50
+ // `.swiftpm/` / `xcuserdata/` are gitignored SwiftPM/Xcode BUILD OUTPUT (not
51
+ // source) that is regenerated per machine and would make the hash unstable.
52
+ // Consequence (stated, not hidden): only the bundled twin SOURCE FILES are
53
+ // hash-pinned — build output and dotfiles are not. For non-source-only trees
54
+ // this exclusion would be a gap; for the calibration assets it is correct by
55
+ // construction (see assets/calibration/.gitignore + README.md).
56
+ const SKIP_DIR = new Set(['.build', '.swiftpm', 'xcuserdata', '.git', 'node_modules']);
57
+
58
+ /** Recursively collect files under `dir` as POSIX relpaths (sorted). */
59
+ function walk(dir, base, acc) {
60
+ let entries;
61
+ try {
62
+ entries = readdirSync(dir, { withFileTypes: true });
63
+ } catch {
64
+ return;
65
+ }
66
+ for (const e of entries) {
67
+ const name = e.name;
68
+ if (name.startsWith('.')) continue; // dotfiles/dotdirs excluded
69
+ if (e.isDirectory()) {
70
+ if (SKIP_DIR.has(name)) continue;
71
+ walk(join(dir, name), base, acc);
72
+ } else if (e.isFile()) {
73
+ const rel = relative(base, join(dir, name)).split(sep).join('/');
74
+ acc.push(rel);
75
+ }
76
+ }
77
+ }
78
+
79
+ /**
80
+ * Deterministic SHA-256 content hash of a source tree.
81
+ * Returns a 64-hex string. A non-existent directory yields a STABLE sentinel
82
+ * hash of the literal string `__MISSING__:<basename>` so absence is bound
83
+ * (never confused with a real tree).
84
+ */
85
+ export function sourceTreeHash(dir) {
86
+ const h = createHash('sha256');
87
+ if (!existsSync(dir)) {
88
+ const baseName = dir.split(sep).filter(Boolean).pop() ?? dir;
89
+ h.update(`__MISSING__:${baseName}`);
90
+ return h.digest('hex');
91
+ }
92
+ let st;
93
+ try {
94
+ st = statSync(dir);
95
+ } catch {
96
+ h.update('__UNSTATABLE__');
97
+ return h.digest('hex');
98
+ }
99
+ if (!st.isDirectory()) {
100
+ // A file where a directory was expected — bind that fact deterministically.
101
+ h.update('__NOT_A_DIR__:');
102
+ h.update(createHash('sha256').update(readFileSync(dir)).digest('hex'));
103
+ return h.digest('hex');
104
+ }
105
+ const files = [];
106
+ walk(dir, dir, files);
107
+ files.sort();
108
+ for (const rel of files) {
109
+ const bytesHash = createHash('sha256')
110
+ .update(readFileSync(join(dir, rel)))
111
+ .digest('hex');
112
+ h.update(rel);
113
+ h.update('\0');
114
+ h.update(bytesHash);
115
+ h.update('\n');
116
+ }
117
+ return h.digest('hex');
118
+ }
119
+
120
+ /** SHA-256 of a single file's raw bytes (64-hex). */
121
+ export function sha256File(p) {
122
+ return createHash('sha256').update(readFileSync(p)).digest('hex');
123
+ }