Files
hyperframes/skills-manifest.json
T
WaterrrForever d287e5244c fix(cli): persist authoring skill in hyperframes.json for durable render attribution (#2762)
* fix(cli): persist authoring skill in hyperframes.json for durable render attribution

authoring_skill was stamped only on the first render through a workflow
passing --skill, so re-renders, `npm run render`, --batch, existing-project
renders, and general-video lost it — leaving 77-96% of real-human render
volume un-attributed and the skills-penetration metric misleadingly low.

Persist the owning skill in hyperframes.json: `init --skill` stamps it at
creation, `render` resolves the flag then falls back to the stored value, and
an explicit --skill seeds it (seed-once, never overwriting the creating
workflow's identity). Activate all render-producing creation workflows to
declare their skill at init.

Forward-only: does not rewrite historical telemetry.

* fix(cli): patch hyperframes.json in place when seeding the authoring skill

seedProjectAuthoringSkill is the only writer that touches an already existing
hyperframes.json — every other writeProjectConfig call site is guarded to write
only when the file is absent, which made the whole-file overwrite safe by
construction. Round-tripping the seed through normalizeConfig broke that: it
rebuilds the object from a field whitelist with no rest-spread, so any key
outside the schema was silently dropped, a media block was materialized in
projects that never had one, and key order was rewritten. hyperframes.json is
normally committed, so a render introduced a diff the user never asked for, and
any field added to the schema later would be deleted by a render on an older
CLI.

Parse the raw JSON, set authoringSkill, write it back, reusing the file's own
indentation. Unknown keys and formatting survive; the only delta is the key
being added. A corrupt config is now left untouched instead of clobbered.

Seed-once semantics are unchanged, still normalized so a hand-edited garbage
slug neither reaches telemetry nor wedges the seed.

Reported independently by both reviewers on #2762.

* fix(cli): create the docker build context with mkdtempSync

The `--docker` build context was created at a guessable path derived from
`Date.now()` in the world-writable OS temp dir. Another local user can
pre-create or symlink that path and have the build read a Dockerfile they
control. mkdtempSync gets a random suffix and 0o700 from the kernel, and it
creates the directory itself, so the separate mkdirSync goes away.

Pre-existing on main (alert #432, 2026-06-04, packages/cli/src/commands/render.ts),
surfaced against this branch only because the seed commit shifted line numbers in
the same file. Fixed here to unblock the CodeQL gate on #2762 rather than left for
a follow-up; the remaining 10 js/insecure-temporary-file alerts elsewhere in the
repo are untouched and still want their own pass.

* fix(cli): drop the check-then-use race when seeding the authoring skill

The seed tested for the config with existsSync and then wrote, which is a
check-then-use race: the file can be created or swapped between the check and
the write (CodeQL js/file-system-race).

Read once and branch on the failure reason instead. Only ENOENT creates a
config from scratch; any other read failure (permissions, I/O) now leaves an
existing file alone rather than overwriting it with a default, so this is also
strictly safer than the version it replaces.

Also replaces the `as Record<string, unknown>` assertion with an isJsonObject
type guard, per the repo's no-assertion convention.

Behaviour unchanged: all 4 seed regression tests still pass, and the
create/preserve/seed-once/corrupt-untouched paths were re-verified end to end.
2026-07-28 19:27:09 +08:00

82 lines
1.6 KiB
JSON

{
"source": "heygen-com/hyperframes",
"skills": {
"embedded-captions": {
"hash": "ed4dc7b850b92ff5",
"files": 140
},
"faceless-explainer": {
"hash": "b772a9b6c8118c2c",
"files": 22
},
"figma": {
"hash": "517e4dc53c13ea05",
"files": 2
},
"general-video": {
"hash": "87f292b572cad3f9",
"files": 4
},
"hyperframes": {
"hash": "02b48855a5321e48",
"files": 17
},
"hyperframes-animation": {
"hash": "3d9855346af7d51c",
"files": 121
},
"hyperframes-cli": {
"hash": "8c791e330873b1bd",
"files": 11
},
"hyperframes-core": {
"hash": "773fc6d15d9e87b3",
"files": 19
},
"hyperframes-creative": {
"hash": "bacb5205ea5eb3d8",
"files": 78
},
"hyperframes-keyframes": {
"hash": "a568c05c01b27461",
"files": 3
},
"hyperframes-registry": {
"hash": "3a864992e765b9bf",
"files": 10
},
"media-use": {
"hash": "68500ab488f7a5ef",
"files": 151
},
"motion-graphics": {
"hash": "0212a19069119e72",
"files": 23
},
"music-to-video": {
"hash": "55a2b5fdcd6f892c",
"files": 132
},
"pr-to-video": {
"hash": "44a9877e7ea1289e",
"files": 29
},
"product-launch-video": {
"hash": "8cce4a32487eaf80",
"files": 26
},
"remotion-to-hyperframes": {
"hash": "3a0e6c2affb9f74e",
"files": 70
},
"slideshow": {
"hash": "71368acf61074198",
"files": 2
},
"talking-head-recut": {
"hash": "2f5d99f823c48e75",
"files": 28
}
}
}