Commit Graph

51 Commits

Author SHA1 Message Date
kashorin a3824065d5 fix(examples): install published ecosystem dependencies 2026-10-10 01:51:44 +08:00
kashorin 9c661820c5 docs: explain authored cues and Studio items 2026-10-09 00:35:27 +08:00
kashorin a4c25ea76b refactor: make narrative projection an explicit author relation 2026-10-08 15:42:44 +08:00
kashorin 91fd9328f5 docs: align production guidance with the 0.3 model 2026-10-08 14:38:45 +08:00
kashorin a54f7ee8cc docs: align public guidance with the 0.3 architecture 2026-10-07 20:45:22 +08:00
kashorin 3c9e635d01 docs: teach the 0.3 author model 2026-10-07 20:44:28 +08:00
kashorin 168c537c4f fix(seedance): require visual reference classification for 0.2.8 2026-09-19 23:02:46 +08:00
kashorin 4af8ae1b1e release: prepare 0.1.6 and align production guidance 2026-09-14 23:29:54 +08:00
kashorin b679e32192 refactor: unify adaptive timeline and presentation composition
Place prepared Takes on an independent Timeline with gaps and overlaps. Present picture, sound and captions through explicit Use rules while preserving source timing and project-authored styles.

Unify Companion bands, parameter ownership and source writeback in Studio. Migrate components, examples and authoring guidance, remove retired Speech/Semantic Track interfaces, and retain protocol identifiers at @1.

Validation: repository suite (786 tests; six sandbox-blocked tests passed on permitted rerun), 43 Studio tests after audit fixes, TypeScript, public declarations, four example-package builds, chat Source check and npm file inventory.
2026-09-13 01:01:47 +08:00
rpone 78a642df05 docs: give each page one title and put its video under the heading
Every page carried a frontmatter `title` and repeated it as a body `# `, which
the site renders as two headings with two permalinks. The heading text matched
the frontmatter on 41 of the 43 pages; on the two quickstarts it did not, so
"Make a video with your Agent" and "和 Agent 一起制作视频" give way to the
titles already in their frontmatter.

Each step's video now sits directly under that step's heading rather than after
its prose, and the avatars link keeps a blank line beneath it.
2026-09-10 21:22:19 +08:00
kashorin b8e2a9b240 docs: integrate refreshed quickstart videos and production guidance 2026-09-10 02:11:41 +08:00
kashorin e90b070c33 feat(composition): support authored clocks alongside semantic timelines 2026-09-09 23:38:46 +08:00
kashorin 1f203a4f9f refactor(composition): separate semantic performance from visual layout
Speech publishes semantic timing and original audio. Media Performance and project components consume the prepared material, preserving source offsets across Takes while controlling their own framing and motion.

Add explicit renderer programs for coordinated HTML/CSS/JavaScript scenes, with typed media children, backdrop filtering and blending. Remove stand-in and estimated-take preview paths, migrate Sources and documentation, and demonstrate a Moment-driven video-to-diagram handoff.
2026-09-09 17:30:30 +08:00
rpone f478c616db docs: remove stale ranking component references 2026-08-29 23:19:58 +08:00
rpone 712cef9294 docs: make author package guidance self-sufficient 2026-08-29 23:17:15 +08:00
kashorin edddf3b612 feat(caption-fine): add tracked cue presentation 2026-08-29 18:58:22 +08:00
rponeawa 3115fb0ef8 Three defects a reconstruction round ran into (#91)
* fix: a token window is two numbers before it decides which words render

The type said two numbers and nothing checked it. A batch entry is JSON a
caller writes by hand, so `"79:86"` arrived as a string, and destructuring one
yields its first two characters: `from` became `"7"` and `to` became `"9"`.
The guard below compared strings — `"9" > "7"` holds, and `"9" <= 135` holds
once it coerces — so the window passed as valid and words 7 to 9 rendered
under the name of words 79 to 86, with the call reporting success.

Checked where the window enters: the render path, and the two tools that log a
stretch without rendering one. The CLI flag already parsed `from:to` into a
pair, so only the hand-written batch reached this.

* fix: an authoring check resolves the standard vocabulary from the Distribution

A project installs its own packages against itself, and `@hypit/*` comes from
the Distribution the command was launched from. The check loaded against the
project root alone, so every standard import resolved nowhere and the report
opened with `17 imported packages could not be resolved from <project>, so
nothing is known about what the Source draws` — on any project whose Source
imports the ordinary vocabulary, which is all of them.

`previewCheck` a few lines above already reads `videoCliDistribution` and every
other loader call site in the repository passes `fallbackRoots`. This one did
not.

* fix: a Media unit's source forms are the three the surface accepts

`video=` and `audio=` were removed from Item, Member and Layer in fbfcce3a,
which put purpose-written refusals in their place. The manifest kept
advertising both, so `inspect_svml_vocabulary` handed authors an attribute the
loader answers with `media-track:Item does not accept video.` The quickstarts
taught it too, in both languages, alongside a paragraph explaining how `video=`
expanded into the graph.

A generated or imported Blob reaches a Track through `<pipeline:Normalize>`,
whose `.media` output connects to `media=`; `audio="default"` on the Normalize
carries the source's own sound where `audio="include"` used to.
2026-08-27 00:35:38 +08:00
kashorin a74e109ac2 fix: preserve fine caption paint overflow 2026-08-26 15:55:15 +08:00
kashorin 9d8c4bbc1d docs: describe semantic Studio writeback 2026-08-26 03:06:53 +08:00
kashorin a12d5fa709 feat: complete fine caption where how when protocol 2026-08-24 14:54:43 +08:00
kashorin 490fe1125a refactor: externalize temporal windows and simplify studio adapters 2026-08-23 04:11:52 +08:00
rpone 429a2275e9 Say what the tools take, not what they stopped taking
Two problems in the same pages, found by reading them as a newcomer would.

The tables contradicted the examples printed directly above them. Every author
surface now takes `semantic`; `map` is gone from all ten, and `space` with it.
The code samples were updated when the attribute changed, the attribute tables
were not — fourteen rows across `quickstart/tracks.md`, `composition.md` and
both `zh` mirrors still listed `map` as required, so a reader following the
table wrote SVML the surface rejects.

Ranking had drifted further than the rename. `triggers` and `terminal` survive
only on `TierBoard` and `TopThree`; `Column` takes `canvas` instead, and its
items carry `rank` plus their own reveal window, with `during` required unless
`preset="true"`. The worked example still passed `triggers`/`terminal` to a
`Column` and omitted `rank`, so the one example a reader would copy was
invalid. Deck, Screen and Comment are corrected the same way — Comment now
requires `semantic` unconditionally rather than only when a sticker binds to
the Script.

The rest is my own mess. Describing Studio, I wrote what it no longer does
rather than what it does — "no stand-ins", "no black frames", "no estimated
mode", "does not degrade" — four times across the skill alone, plus a section
explaining two badges that can only read `measured`, plus two example READMEs
whose headline was that they cannot be opened. A reader who never knew about
stand-ins learns nothing from being told they are gone; they need to know that
Studio opens a Run whose material is satisfied, which is one sentence. Where a
limit is genuinely current behaviour — one unresolved capability refusing the
whole Run — it stays, because that is how the thing works rather than a note
about how it used to.

Removed the same way from `quickstart/timing.md` and its mirror, where the
whole-program transcription pass was announced as absent instead of the
per-Take alignment simply being described. Also unwrapped one `zh` paragraph
that had been split mid-sentence.

`pnpm check` clean; `pnpm test` 510 pass, 0 fail; `pnpm test:release` 8 pass;
`preview-check` still passes `talking-film-graph-check` and still fails
`image-only.svrun`.
2026-08-21 01:04:03 +08:00
rpone 03d0257b0b Rename the Playground to Studio wherever a reader is sent
`b32e8253` replaced both Playgrounds with `packages/studio`, but the rename
stopped at `examples/`. The skill and the docs still named the tool, the
command and the recipe sheet that no longer exist.

`studio.svs` becomes `recipes.svs` with its import alias, in the 39 files the
examples rename had left behind — docs, the `docs/zh` mirrors, the skill
references and the package manifests whose authoring snippets show the alias.
The old name was already loose, since an `.svs` file is a parameter-recipe
sheet rather than anything Studio reads; once `studio` names the application
it reads as Studio's own config file, which it is not. Two test fixtures keyed
the alias as a plain string rather than inside `{}`, so they moved with it —
`packages/text` had a real reference to `recipes.shot` resolving against a
`studio.shot` fixture.

`pnpm svml:playground -- --source main.svml` becomes `pnpm studio -- --run
build.svrun` throughout. The Run Source is not an optional extra any more:
Studio's unit of work is the Run, and it reads the Author SVML back out of it.

`preview-check.mjs` imported `svml-playground/src/pipeline/preview.js`, which
this branch deleted, so the skill's own build gate had been dead since
`b32e8253`. It is rebuilt on Studio's real entry path — `loadStudioDomain`,
`loadStudioRun`, `inspectStudioRun`, `readStudioSession` — and reports
`provenance.errors` and unresolved Candidates instead of the `waiting` and
`stand-in` fields Studio no longer has. It stays in URL space for Windows, as
`e0ecccb9` established, and closes the archive before exiting rather than
leaving it open behind a `process.exit` in a `try`.

The preview pages are rewritten rather than renamed, because what they
describe is gone. Studio has no stand-ins, no black frames and no estimated
timing; it refuses to open and names what is missing. So the pages document
the five refusals verbatim, and say plainly that a Source still declaring
ungenerated shots will not open — including the warning that no example in
this repository currently does. Running the ported check over all nine
committed Run Sources: six refuse on unresolved capabilities or a target that
is not a Film, and three on footage under the gitignored `examples/**/assets/`.
Claiming otherwise would have shipped a quickstart whose first command fails.

`pnpm check` clean; `pnpm test` 510 pass, 0 fail; `pnpm test:release` 8 pass.
2026-08-21 00:40:42 +08:00
kashorin f3d319db22 refactor: make SemanticTrack the program skeleton 2026-08-21 00:11:28 +08:00
rpone 47c7dff9ba refactor: remove the ranking Typewriter family
TierBoard, Column and TopThree remain. The Typewriter variant's Types,
Producers, Surface, schedule, render, fragment and Style paths are gone, along
with the helpers that only it used: grapheme splitting, its stage fit, the
package's only text-flow element, and the prefix and defaults generality of the
typography decoder.

Three chains had the Typewriter branch as their terminal else. Each one now
ends on a surviving variant with an explicit failure for an unknown one, rather
than relying on a fall-through. The browser visual test's canvas shrinks to the
content that remains.
2026-08-19 20:47:39 +08:00
rpone df23c73d97 refactor: rebrand Narratage as Hypit 2026-08-19 15:51:58 +08:00
rpone cca2df02f1 docs: document the components a reader could not find
Seven packages an author can write had no page: ranking, deck-track,
comment-sticker and screen-overlay all produce a VisualTrack and now sit
beside the Tracks that already had one, which is also why that page is
simply Tracks now. image-compose, image-transform and background-removal
hand back a picture rather than a Track, so they get a page of their own
after Media & Generation, where the images they make are used.

Every attribute name was read out of each package's Surface rather than
recalled, and checked back against the sources. The three image packages
each need an endpoint no example in this repository binds, which the page
says rather than leaving a reader to discover it at plan time.
2026-08-14 17:41:35 +08:00
rpone 6b9dab8d05 docs: say which Media the Tracks page means
Media & Generation documents the media: tags, where a Media is an asset a
Source declares. The other page documents media-track, where a Media is a
Track that carries one. Both said Media, and a reader had no way to tell
which from the title.

All four of that page's subjects are Track types, so naming them as such
settles Caption and Typography and Audio at the same time.
2026-08-14 17:27:47 +08:00
rponeawa c331c379e5 fix: follow main's Frontend, Record, and Semantic Map contracts (#6)
* fix: Frame edges are positions, not insets

`frameFromEdges` reads `right` and `bottom` as absolute edge positions within
the parent and derives width as `right - left`, but every authored Frame in the
examples and the quickstart wrote them as insets from each side. `left="10%"
right="10%"` resolves to zero width, which `assertSpatialFrame` rejects, so none
of these Frames could ever have been placed.

They went unnoticed because no example that uses a non-full-bleed Frame has been
built: `talking-film-graph-check` only graph-checks, and `talking-film-live`
needs credentials. `packages/spatial/test/spatial.test.ts` already pins the
intended semantics.

Convert each to the edge it meant, and say so once in the quickstart where an
author first writes a Frame of their own — nothing documented the two attributes,
which is likely how the mistake spread.

* feat: SVML Playground, a read-only preview of a Source (#4)

* feat: SVML Playground, a read-only preview of a Source

Read a `.svml` as a timeline before anything has been generated: the code on the
right, the picture top-left, and a Premiere-style timeline bottom-left. It
answers "where does this B-roll land, how long is it, and is the card in the
right part of the frame" without a Seedance generation, a WhisperX alignment, an
FFmpeg render or a headless browser.

    pnpm svml:playground -- --source examples/street-interview-preview/main.svml \
      --run examples/street-interview-preview/build.svrun

A shallow interpreter, not the compiler. It walks the authored markup with
`@narratage/markup`'s own parser and calls each package's own pure projection
functions, so placement, padding, stacking, motion and Caption layout are the
build's, not an approximation. It never elaborates the graph, never resolves a
package lock and never constructs a Host, so it runs on a directory holding
nothing but `main.svml` and its `.svs`.

Nothing is guessed silently. Timings come from a completed build if there is
one, from what the Run Source names if not, and from `@narratage/estimate`
otherwise; material shows real frames per element where it exists and a painted
box where it does not; and the header says which of those you are looking at.
Footage of another frame rate is refused with a reason rather than resampled,
because normalizing is a real transcode and belongs to the media pipeline.

Three views of one selection. Clicking a timeline clip, marked text, or the
picture selects in all three, and everything the playhead is inside is outlined
as it passes. A Segment encloses a Selection which can enclose another, each
level in its own colour, and an enclosing range stays outlined while an inner
one is — the nesting is what the markers are for.

Two things needed correcting in the process. HyperFrames cancels its CSS
animations once it has sampled them and drives motion from an `hf-seek` event,
so the shim copied from the Caption Playground found nothing to move and left
every animation frozen on its first keyframe. And the box drawn over the picture
is now measured from the rendered element rather than recomputed, which is exact
through padding, motion and clipping instead of drifting from all three.

Ships two examples: one synthetic, and one that reads the documentation site's
own street-interview footage with timings aligned from its transcript by the
real `locateSpeechTiming`.

* fix: skip the probing tests when ffprobe is absent

Two tests read a real frame rate off a file, which needs ffprobe. CI has no
ffmpeg, so both failed there while passing locally — an undeclared dependency on
a tool that happened to be installed on the machine they were written on.

Detect ffprobe and skip only the cases that genuinely need a probe, following
the repository's practice for externally-dependent tests.

The behaviour without it was already correct and is now asserted unconditionally:
material an author supplied is either shown or refused with a reason, never
silently absent. A placeholder with no explanation reads as a bug in the preview
rather than as a missing tool, so say which it is.

Verified both ways: 16 pass with ffprobe, 14 pass and 2 skip without.

* fix: stop shouting the inspector labels

`selected`, `clip`, `binding` and the rest were forced to capitals by CSS. They
are ordinary words describing what is beside them, not headings, and reading them
as written is enough. The letter-spacing went with it — it only ever existed to
keep the capitals legible.

* feat: clicking empty space lets go of the selection

Open track, the room around the picture, and the space below the last line of
source all plainly mean "not that one". Only the timeline said so; the other two
silently kept whatever was selected, so the only way to deselect was Escape.

* fix(ranking): let a board with icons compile and run

Every board Surface seals a Header Record and one Item Spec Record per child,
but none of the four declared those Types as outputs, so a Source that wrote
<ranking:TierBoard> or <ranking:Column> was rejected by the frontend before it
could be elaborated. The Producers then read the icon input as an inline value
although its Type is an Artifact Blob, which stores the reference itself, so a
board that did compile failed the moment it ran.

Neither showed up because nothing drove a ranking Producer: the tests call the
projection functions directly. The new test compiles the Surface, elaborates
what it returns and runs it, which is the only way either fault is visible.

* feat(video-domain): assemble the installed packages into one domain

Compiling a Source outside the CLI meant re-stating which packages exist and
which Surfaces, Producers and Validators they contribute. Each package already
declares all of that in its own activation, and its package.json says where that
activation lives, so this reads them off disk the way the package loader does
rather than carrying a list that can fall behind.

A caller now gets the five registries a compile needs without a lock, a
filesystem scan of package bytes, or a Provider. The test compiles every
committed example, which is what makes a Surface that nobody writes in a real
Source stop being untested.

* refactor(playground): read a Source with the compiler instead of interpreting it

The preview decoded every tag itself: a second implementation of each package's
Surface, which could accept a Source no build would accept and could drift from
what the packages actually do. It did, twice - a test fixture was not valid SVML,
and a Caption Track only worked against a shape the real Surface does not emit.

Now the packages decode their own tags. Two decorators keep the source positions
the compiler discards, both delegating to the same decoder rather than repeating
it, and the timeline is assembled from Presents and Clips - the whole of what a
Track says - so a package that grows a new Track appears without this changing.
Fields that encoded which package made a clip are gone; the box on the picture is
measured from what was drawn, because motion moves it.

Tracks are built one at a time, so a Track waiting on a Provider costs only
itself and the rest of the programme still plays.

* docs(examples): add the ranking board example

A board is the one Surface family nothing in the repository wrote, which is why
its Types and its icon input were both wrong. This is a Source that writes one:
five apps named worst first, each landing on its own Moment, with the cutaways
and the icons authored as the files they are rather than as material a Provider
has to make.

* test(playground): do not require ffmpeg to check the preview opens

Standing in for material nobody has shot needs a tool to draw with, and a
machine without ffmpeg has none. The tests assumed one, so on CI every Track was
correctly reported as undrawable and four assertions read that as a fault.

What must hold either way is asserted either way: timings come from the Script's
own words, a Run Source is still read, and a Track with no picture still says
why. Only the assertions about a picture existing now wait for a tool that can
make one.

* feat(playground): stand in for a shot with the picture it points at

A shot nobody has generated became a black frame, which shows where it sits and
nothing else. But a Source that has not been shot still says what the shot is
of: a reference frame, a first frame, some picture it already holds. Showing
that, held for as long as the shot was declared to run, is the difference
between seeing the shape of a programme and seeing it.

The rule names no package. An unsupplied output whose element points at material
already in hand is shown as that material; the length comes from what the
element declared, or from whatever it referenced that declares one, because a
Source that estimates its own speech names that estimate rather than repeating a
number. Where there is no such picture the black frame remains.

Two faults surfaced alongside it. Records the Source read at compile time were
being stood in for, replacing pictures the author had supplied. And a finished
film was treated as a shot, although nothing consumes it.

* fix(playground): place word ranges in estimated timings, so captions can be cut

An estimated map carried anchors but no token ranges. Anchors are how a marker
addresses time, so every Track placed by a marker worked; a Caption reads the
window over the words it covers, and found nothing there. The effect was that a
Source with no recording could never show captions - which is most Sources, most
of the time.

The frames were already being computed to place the anchors, so the ranges cost
nothing to keep.

The new example is what found it. It writes every kind of Track at once over a
take nobody has generated, which is the state a Source is in for most of its
life, and the state where a preview earns its keep.

* fix(playground): colour a clip by the marker that placed it, and say what is a stand-in

Every clip on the timeline was grey. A clip took its tone from the tag that drew
it, and tones are keyed by Script marker, so nothing matched. What colours a clip
is what placed it: the marker its element points at, or the one its own identity
names, which is how a cutaway and the words that call for it read as one thing.

The note under the picture said the timings were estimated and stopped there,
although the takes were reference pictures rather than footage and the captions
had been cut by counting words. Both are now said, because a preview that shows
an estimate without naming it is worse than one that shows nothing.

* feat(playground): say on the clip itself what is a stand-in

The note under the picture said some shots were stand-ins, but a timeline of
twenty clips gave no way to tell which. A preview that shows an estimate has to
show it where it is looked at, not only where it is summarised.

A clip now carries what is actually on screen for it, and reaches that through
whatever consumed the shot - a Take, an Item, or the Track's own element - since
a Present is named after what drew it rather than after the material behind it.
Stand-ins are hatched on the timeline and named in full when one is selected.

* feat(playground): read material earlier builds produced, and refuse what a build would

A Source that reuses an accepted take names the Build it came from, and until
now the preview had nowhere to read that: it opened, showed a stand-in, and gave
no way to see the shot that already exists. Given the Runtime profile that says
where the archive lives, it now reads the Build's own Record and the Artifact
bytes behind it, so a take generated yesterday is the take on screen today.

The stand-in follows the same path. A picture may be a file the Source read, a
value a Run Source supplied, or something an earlier Build made; all three are
addressed by digest, so the shot that has not been made still shows the picture
it names rather than falling back to black.

And the boundary a build enforces is now enforced here. The preview read any
path an author wrote, so a Source reading outside its own directory previewed
and then failed to build with SOURCE_ASSET_OUTSIDE_ROOT - exactly the drift this
tool exists to remove.

Verified against a real build: gpt-image-2 through KIE, its Record reused by
build-record, every Track drawn from it.

* feat(playground): fit the estimate to what the Source already declares

A syllable model says which word takes longer than which, and nothing about how
fast this speaker talks. So where a Segment's own material declares a length,
that length is the truth and the words are spread across it; the guess supplies
only the shape. The last thing said now lands where the programme ends, which is
where it will land once real audio is aligned.

Black stand-ins are as long as the shot they stand in for, for the same reason:
a one-second stand-in for an eight-second take made the timeline and the picture
disagree about how long the programme was.

The rule names no package. An element that points at both a Segment and
something with a declared duration is that Segment's material, whoever wrote it.

* fix: make the preview agree with itself on a machine that cannot draw

CI failed on every commit for one reason: the timeline measured the programme
by the clips it managed to draw. A machine with no ffmpeg draws no stand-ins, so
the programme collapsed to a single frame while the words still ran to the end,
and a marker past the end read as live. How long a programme runs is what the
Source says, not what this machine can picture, so the Program Space decides it
and every machine agrees. A test now asserts that, and passes with ffmpeg absent.

deck-track declared five of the nine Types its Track Surface emits, so any
Source writing a deck was rejected before it could be elaborated - the same
fault as ranking, unnoticed for the same reason: nothing wrote the tag. The
all-components example now writes every kind of Track, which is what caught it.

Also: the timeline reads a pointer against the window it is showing rather than
the whole programme, which was putting the playhead in the wrong place once
zoomed; rows within a Track are ordered front to back and folded to the front
one until opened; and the guides and docs describe the tool as it is rather than
the interpreter it replaced.

* test(video-domain): say why every example is compiled

A Surface may only emit Types its manifest declares, and the frontend is the
only thing that checks. Two packages shipped Surfaces that emitted more than
they admitted, and nothing noticed because no Source in the repository wrote
those tags. This is the test that notices, so it should say so.

* fix(video-domain): declare every package it names

The domain reaches for contract manifests directly, and three of them were
imported without being declared. Repository hygiene caught it; the list is now
derived from the imports rather than kept beside them, so the two cannot drift.

---------

---------
2026-08-14 11:00:36 +08:00
kashorin 75f3e752b7 refactor: simplify extension boundaries and runtime presentation 2026-08-13 23:25:19 +08:00
kashorin ff64c17bcb docs: make the first Narratage workflow clear 2026-08-12 16:23:06 +08:00
rpone 45e93ac66b docs: complete Narratage skill and Quickstart 2026-08-12 06:04:13 +08:00
rpone f395a23953 Move Narratage skill and document Seedance kits 2026-08-11 12:55:39 +08:00
kashorin 80bcd3d8e1 feat: isolate caption authoring and close package dependencies
Replace the generic playground with a file-backed Caption Playground, separate source workspaces from installed package roots, and derive exact transitive Module providers in Node package locks.
2026-08-10 22:33:02 +08:00
kashorin 0066ab51c5 feat: normalize generated media at consumer surfaces 2026-08-10 20:16:14 +08:00
rpone 1c363c3771 Revert "docs: align all documentation with v2-bootstrap package restructure"
This reverts commit f8b7c0243a5f6255678ea8d237a3958d62406ebc.
2026-08-10 16:09:36 +08:00
rpone 349844dcd6 docs: align all documentation with v2-bootstrap package restructure
Update 30 doc files (EN+ZH) to match the visual layer rewrite:
- broll → media-track with SpatialFrame positioning and appearance/motion split
- caption:Style/Track → caption-fine:Style/Track with cue bounds and font binding
- text position props removed, text:Style/text:Area with explicit font bytes
- Film Recipe loses canvas dimensions → space:Canvas graph value
- speech:Spine gains canvas= attribute
- prompt-kit → @narratage/text, run-text → run-markup, compiler-text-node → compiler-markup-node
- SemanticMap simplified: final word windows only, no quality labels
- Four layers → five layers (Application became Layer 5)
2026-08-10 16:04:51 +08:00
kashorin cdb29b16e0 feat: complete estimate and media authoring paths 2026-08-10 13:22:42 +08:00
kashorin 76cae8eaab refactor: separate markup text and typography
Rename the author frontend around Markup, replace PromptKit with graph-native Text templates, and keep video typography in its own package. Wire ordinary Text through explicit graph edges into model and visible consumers, refresh examples, locks, tests, and architecture documentation.
2026-08-10 10:55:46 +08:00
kashorin 81aeb2d169 Normalize logical identities and migration docs 2026-08-10 03:58:39 +08:00
kashorin 21c7b8fd8e feat: freeze the visual ir compatibility waist 2026-08-09 23:01:12 +08:00
kashorin 56e3e8f6db feat: complete unified media track 2026-08-09 17:19:10 +08:00
kashorin 4d714877aa feat: establish shared track authoring foundations 2026-08-09 13:36:28 +08:00
kashorin 59afccb75d feat: complete fine caption visual system 2026-08-09 10:14:30 +08:00
kashorin f70f7ad55c feat: add locked open font assets 2026-08-09 08:54:49 +08:00
kashorin 71924dfcc1 feat: finish fine caption evidence 2026-08-09 08:26:41 +08:00
kashorin 872fc521de feat: bind exact fonts to fine captions 2026-08-09 08:13:04 +08:00
kashorin 6ac042df6d feat: complete fine caption rendering 2026-08-09 08:00:29 +08:00
kashorin a3114f992b refactor: make caption planning atom-safe 2026-08-09 07:14:59 +08:00
kashorin f3d47a43c2 refactor: separate caption planning from style rendering 2026-08-09 05:22:35 +08:00