Merge remote-tracking branch 'origin/master' into worktree-i18n-update-workflow
# Conflicts: # .agents/notes/implemented/process/2026-07-02-bilingual-docs-and-pairing-gate.i18n.yaml # .agents/skills/dsh-translate-docs/SKILL.md # docs/i18n/README.i18n.yaml
This commit is contained in:
64
.agents/skills/dsh-archive-agent-notes/SKILL.md
Normal file
64
.agents/skills/dsh-archive-agent-notes/SKILL.md
Normal file
@@ -0,0 +1,64 @@
|
||||
---
|
||||
name: dsh-archive-agent-notes
|
||||
description: Use when auditing, pruning, archiving, restoring, or reviewing Agent Notes in deepseek-harness; classifies implemented notes by future decision value, deletes rejected notes that no longer prevent a tempting fallacy, and applies the frozen archived/{kind} triplet and manifest contract.
|
||||
---
|
||||
|
||||
# Archive DeepSeek Harness Agent Notes
|
||||
|
||||
Reduce the active decision corpus without erasing history that can still guide work. Judge every note semantically; word count and age are discovery aids, never archive criteria.
|
||||
|
||||
## Read the contracts
|
||||
|
||||
Read [the Agent Note contract](../../notes/README.md), [the archive instructions](../../notes/archived/AGENTS.md), and the applicable active lifecycle instructions before classifying. Use current code, configuration, package docs, generated catalogs, newer Agent Notes, and inbound links to establish whether a rationale still owns or constrains anything.
|
||||
|
||||
## Classify by future value
|
||||
|
||||
Apply these lifecycle-specific outcomes:
|
||||
|
||||
- **Implemented — keep active:** retain a note when its rationale, alternatives, negative guarantees, durable/wire semantics, ownership boundary, security rule, or reintroduction condition is likely to guide a future change. Length does not matter.
|
||||
- **Implemented — archive:** archive a note when the shipped decision is complete and its body is unlikely to guide future work, such as one-off UI chrome, a narrow adapter, a minor closed bug, superseded implementation detail, or process history whose current contract is obvious elsewhere.
|
||||
- **Proposed — never archive:** keep a live proposal active; if it is no longer worth pursuing, reject it with an honest reason and satisfy the rejected lifecycle format.
|
||||
- **Rejected — keep only as a guardrail:** retain a rejection only when the losing proposal remains a tempting, meaningful mistake and the note explains why it loses.
|
||||
- **Rejected — delete:** delete the whole triplet when the rejected idea is obsolete, superseded, no longer plausible, or unlikely to prevent re-litigation. Repair or delete inbound links.
|
||||
|
||||
Do not archive toward a quota. Inspect every note in scope, classify analogous groups under one principle, use best judgment for close cases, and record genuinely borderline decisions for the handoff.
|
||||
|
||||
## Calibrated examples
|
||||
|
||||
These examples set the bar; the word counts demonstrate that size is not the test.
|
||||
|
||||
Archive implemented notes such as:
|
||||
|
||||
- collapsed sidebar control rail — 533 words: closed, minor UI behavior;
|
||||
- Commander argument adapter — 1,498 words: substantial implementation detail with little future design leverage;
|
||||
- documentation graph atlas — 920 words: completed documentation machinery whose current generators are authoritative.
|
||||
|
||||
Keep implemented notes such as:
|
||||
|
||||
- event-sourced sessions — 248 words: foundational authority and durability boundary;
|
||||
- single Harness-home resolver — 596 words: cross-product ownership rule;
|
||||
- project session directories — 628 words: durable storage and identity policy;
|
||||
- parallel pre-push gates — 400 words: borderline, but still guides gate scheduling and resource tuning;
|
||||
- dropped image content block — 334 words: keep until multimodal support lands, because it states the coordinated reintroduction condition.
|
||||
|
||||
For rejected notes:
|
||||
|
||||
- keep folding the compaction package split — 426 words: the package-boundary temptation remains meaningful;
|
||||
- delete streaming workflow progress through tool calls — 972 words: its ACP/UI premise is obsolete;
|
||||
- delete dropping ACP terminal metadata — 362 words: the later automation-only ACP decision resolved the question.
|
||||
|
||||
## Archive one implemented triplet
|
||||
|
||||
1. Move the complete `foo.md`, `foo.zh.md`, and `foo.i18n.yaml` triplet from `implemented/<kind>/` to `archived/<kind>/`; `implemented` is deliberately absent from the archive path.
|
||||
2. Make no body edits. Insert only `Archived: YYYY-MM-DD` immediately below `Status: implemented` in both language files, using the archival date and the same value on both sides.
|
||||
3. Re-record the sidecar hashes mechanically for the two metadata-only edits. Do not translate, reformat, update facts, or repair links inside the note.
|
||||
4. Search for inbound links from active prose. Redirect them to current authority, retarget them to the archived path only when the historical snapshot is intentionally cited, or delete them. Never verify or repair links out of the archived note.
|
||||
5. Run `pnpm run verify-archived-agent-notes --write`. Its append-only mode first proves every existing seal still matches, then adds only the new triplet hashes. Run the normal verifier afterward.
|
||||
|
||||
After the triplet is sealed, never edit, move, translate, reformat, or delete it. Archived notes remain valid inbound-link targets but are historical snapshots, not authority for current behavior.
|
||||
|
||||
## Validate and report
|
||||
|
||||
Run the archive verifier's focused test, `pnpm run verify-archived-agent-notes`, `pnpm run doc-sync`, `pnpm run lint`, and `git diff --check`; select any additional evidence through [dsh-pre-push-checks](../dsh-pre-push-checks/SKILL.md).
|
||||
|
||||
Report active implemented notes kept, implemented notes archived, rejected notes kept/deleted, proposed notes rejected if any, and every genuinely borderline case with its word count and chosen outcome. Do not claim archived outbound links are valid: the contract intentionally never checks them.
|
||||
@@ -0,0 +1,4 @@
|
||||
interface:
|
||||
display_name: "Archive Agent Notes"
|
||||
short_description: "Audit and freeze low-value Agent Notes"
|
||||
default_prompt: "Use $dsh-archive-agent-notes to audit Agent Notes, archive low-future-value implemented records, and delete low-value rejected records."
|
||||
@@ -30,7 +30,7 @@ description: Use when reviewing a pull request in the deepseek-harness repo —
|
||||
|
||||
- **Intent and seam contracts:** trace both sides of every changed interface. Confirm the implementation matches the PR and any Agent Note, including errors, cancellation, ownership, and disposal.
|
||||
- **Lifecycle and concurrency:** for async setup, callbacks, processes, or teardown, apply [defensive-patterns.md](../../../docs/defensive-patterns.md). Check races before publication, cancellation during awaits, independent error reporting, callback containment, ownership before reentry, complete detach cleanup, and quiescent disposal.
|
||||
- **Capability and consumer fit:** trace every current consumer, then flag consumer-specific behavior leaking into the interface under [the package contract](../../../packages/AGENTS.md).
|
||||
- **Capability and consumer fit:** trace every current consumer, then flag consumer-specific behavior leaking into the interface under [the package contract](../../../packages/AGENTS.md). Flag the inverse too: a new public method on a generic service (registry, session, agent) whose only caller is one internal consumer is an ad-hoc surface widening — require a private capability closure handed to that consumer at construction instead.
|
||||
- **Scope, ownership, and necessity:** map each abstraction, state machine, option, defensive copy, and compatibility path to its current contract, production consumer, and owning plugin or service. Challenge unrelated features and speculative generality, then test the PR's coherence against [the root contract](../../../AGENTS.md#conventions).
|
||||
- **Configuration and public choices:** ask what current-consumer evidence or prior art supports each default, public operation set, format, or imported external concept. Require an explicit choice or deferral when that evidence is absent.
|
||||
- **Model perspective:** inspect the exact prompts, tool schemas, results, and diagnostics the model receives across affected modes. Flag concepts outside the model's task, then verify stable text verbatim and dynamic behavior through snapshots or end-to-end coverage.
|
||||
|
||||
@@ -13,6 +13,7 @@ The contract lives in [docs/AGENTS.md](../../../docs/AGENTS.md). This workflow c
|
||||
- [.agents/notes/README.md](../../notes/README.md) — when a decision earns an Agent Note, how to file it, and what goes inside one (the header block, per-lifecycle skeleton, and Alternatives-considered mandate, gated by `verify-agent-note-format`); [docs/postmortem/README.md](../../../docs/postmortem/README.md) — when an incident earns a postmortem.
|
||||
- [docs/i18n/README.md](../../../docs/i18n/README.md) — the bilingual pairing contract; editing either side of a pair obligates the counterpart in the same change.
|
||||
- Root [AGENTS.md](../../../AGENTS.md) — the standing orders whose budget discipline this skill protects.
|
||||
- [Archived Agent Notes](../../notes/archived/AGENTS.md) — frozen historical snapshots excluded from editorial maintenance and evolving documentation gates.
|
||||
|
||||
## Placing content
|
||||
|
||||
@@ -35,6 +36,8 @@ The audit is a hunt for the standard's slop checklist, cheapest probes first. Es
|
||||
6. In `implemented/` Agent Notes, remove migration plans, acceptance-task checklists, and future-tense spec language. Keep concise verification contracts that identify the behaviors and tiers pinning the shipped decision, plus named coverage gaps.
|
||||
7. If removing prose changes a promised behavior rather than its explanation, use a proposed Agent Note first (follow [dsh-find-simplifications](../dsh-find-simplifications/SKILL.md)).
|
||||
|
||||
Exclude `.agents/notes/archived/` from corpus audits and edits. Active prose may repair, redirect, or delete an inbound link, but never follow an archive-wide cleanup into the frozen target.
|
||||
|
||||
Keep every load-bearing rule, preferably as one to three lines plus a link to its rationale. Cut stories, duplicates, status notes, and the path used to derive the rule. Do not create a new explanation merely to relocate disposable reasoning.
|
||||
|
||||
## When verify-doc-budgets goes red
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: dsh-find-simplifications
|
||||
description: 'Use when working in the deepseek-harness repo to find non-obvious simplification candidates, write proposed Agent Notes or inline TODO/FIXME/XXX notes, audit or coalesce superseded Agent Notes, or fold worthwhile simplification ideas from another PR; especially for dead, duplicated, speculative, over-built, or added-then-removed surfaces.'
|
||||
description: 'Use when working in the deepseek-harness repo to find non-obvious simplification candidates, write proposed Agent Notes or inline TODO/FIXME/XXX notes, audit or coalesce superseded Agent Notes, or fold worthwhile simplification ideas from another PR; especially for dead, duplicated, speculative, over-built, added-then-removed, or hand-rolled-where-a-dependency-exists surfaces.'
|
||||
---
|
||||
|
||||
# Finding DeepSeek Harness Simplifications
|
||||
@@ -25,6 +25,7 @@ A strong simplification removes, folds, or demotes something real and has clear
|
||||
- A package boundary exists only for test/demo/support code and adds publish or dependency overhead.
|
||||
- A feature implements speculative product generality: multi-session/session-load, background task rosters, live registry invalidation, mid-turn steering, tool-owned UI rendering, and similar shapes with no product owner.
|
||||
- An invariant, rollback path, set of expected outputs, or special-case test exists only to protect an unused surface.
|
||||
- Hand-rolled code reimplements what a well-maintained external package or a Node builtin at the engine floor already provides, and the swap would delete the implementation plus its dedicated tests ([dependency policy](../../notes/implemented/process/2026-07-26-dependencies-over-hand-rolling.md)).
|
||||
- The simplified behavior may differ slightly, but the new behavior is still reasonable and easier to explain.
|
||||
|
||||
Thin candidates are usually not enough for an Agent Note: deleting one typo, running `knip` once, removing an intentionally documented backend/adapter, or flagging "this looks complex" without call-site proof.
|
||||
@@ -49,6 +50,17 @@ Classify every defensive copy, freeze, validator, and callback capture by the bo
|
||||
|
||||
For complex asynchronous code, draw the ownership graph and map each sentinel, readiness promise, cancellation path, disposer, and state flag to a distinct owner or transition. When several mechanisms mirror the same liveness or settlement fact, propose one transaction or lifecycle controller instead. Preserve separate machinery where it protects a real boundary: synchronous publication and rollback, callback containment, first-terminal-outcome arbitration, worker/process ownership, or dispose-to-quiescence.
|
||||
|
||||
## Hand-Rolled Code Versus A Dependency
|
||||
|
||||
Introducing a dependency is a valid simplification move, not a policy exception: the [dependency policy](../../notes/implemented/process/2026-07-26-dependencies-over-hand-rolling.md) owns the bar. When surveying, ask of protocol parsers, framers, retry/backoff loops, glob matchers, diff engines, and similar infrastructure: does a well-maintained npm package or a Node builtin at the repo's engine floor already do this?
|
||||
|
||||
Prove a dependency-swap candidate like any other, plus:
|
||||
|
||||
- Read the hand-rolled implementation and name the exact surface the package covers; residual semantics the package does not cover count against the swap and stay in the Agent Note.
|
||||
- Check the package's health honestly (maintenance, adoption, transitive footprint) and prefer builtins when the engine floor has them.
|
||||
- Check the Agent Note tree first: schemastery, vendored Cordis, the twin adapters, and other recorded seams are settled — a swap that collapses one needs to beat the recorded rationale, not just cite the policy.
|
||||
- Weigh net deletion: implementation plus dedicated tests plus docs, minus the glue that remains. A wrapper that relocates the same complexity is not a win.
|
||||
|
||||
## Prove Or Reject Each Candidate
|
||||
|
||||
For every symbol or behavior, classify consumers before writing:
|
||||
@@ -70,6 +82,8 @@ Reject or downgrade a candidate when:
|
||||
|
||||
Audit the Agent Note tree when the user asks to reduce or coalesce it, or when the simplification being implemented makes an owning note obsolete. Do not expand every code-simplification survey into a repository-wide note audit.
|
||||
|
||||
Use [`dsh-archive-agent-notes`](../dsh-archive-agent-notes/SKILL.md) for retention judgment and archive mechanics. Low-future-value implemented notes move as frozen triplets to `archived/{kind}`; proposed notes are never archived; rejected notes that no longer prevent a tempting mistake are deleted. Do not edit an archived note while simplifying current prose or code.
|
||||
|
||||
Follow the deletion rule in the [Agent Note contract](../../notes/README.md#when-to-write-one); do not duplicate or weaken it here. For each candidate chain:
|
||||
|
||||
1. Identify the current owner from shipped code, configuration, generated catalogs, package docs, newer Agent Notes, and inbound links; dates and titles are discovery hints, not proof.
|
||||
|
||||
@@ -19,6 +19,8 @@ Accept `mode: automatic | interactive`; default to `automatic`. Enter interactiv
|
||||
|
||||
Always exclude `vendor/` from discovery, review, and edits, even when the requested scope is the whole repository. Do not follow a symlink into it. Put exclusions after inclusion globs so a later include cannot re-admit it: for example, end ripgrep commands with `--glob '!vendor/**'`, and give Git commands an explicit `:(exclude)vendor/**` pathspec. If the requested scope contains only `vendor/`, report that no eligible files remain.
|
||||
|
||||
Also exclude `.agents/notes/archived/` from prose review and edits. Archived Agent Notes are frozen snapshots; inspect an exact target only to understand a historical inbound citation, never to modernize its prose or outbound links.
|
||||
|
||||
Treat generated catalogs, snapshots, and fixtures as derivative. Edit the owning source or scenario first, then regenerate the artifact. When a generator extracts a summary from owner prose, make the extracted sentence complete for that surface. Bilingual pairs have no permanent owner: either language may be the authored side for an update. Update the counterpart minimally and re-record the pair.
|
||||
|
||||
## Preserve the complete proposition
|
||||
|
||||
@@ -15,6 +15,8 @@ description: Use when creating or updating the bilingual counterpart of a doc in
|
||||
- **New pair** (no counterpart yet): follow [the whole-document path](#the-whole-document-path-new-pairs).
|
||||
- **Deleted or renamed doc**: delete or rename the counterpart and the `.i18n.yaml` alongside it — the gate reports an incomplete pair otherwise.
|
||||
|
||||
Frozen Agent Notes under `.agents/notes/archived/` are not translation work. Their complete triplets are sealed by the archive verifier; never update, re-record, or repair either side after archival.
|
||||
|
||||
## The update path (briefing-driven)
|
||||
|
||||
Benchmarked on real pair updates from this repo's history, the briefing-driven path costs a fraction of a guidance-corpus-loading run at equal measured quality; the [briefed-updates Agent Note](../../notes/implemented/process/2026-07-26-briefed-minimal-translation-updates.md) holds the evidence.
|
||||
|
||||
@@ -1,27 +1,46 @@
|
||||
---
|
||||
name: record-browser-gif
|
||||
description: Record browser or Web UI interaction demos as optimized local GIFs using the available built-in browser, state-based frame capture, and deterministic encoding. Use when Codex is asked to make, record, or generate a GIF that demonstrates a browser workflow, including real-server or real-API behavior. Stop after returning the verified local artifact; do not upload it or edit a pull request.
|
||||
description: Record browser or Web UI interaction demos as optimized GIFs using the available built-in browser, state-based frame capture, and deterministic encoding, then publish to a dedicated assets branch when the task includes attaching the GIF to a pull request. Use when asked to make, record, or generate a GIF that demonstrates a browser workflow, and for every pull request that changes product-user-visible GUI behavior, which MUST include such a GIF with real provenance.
|
||||
---
|
||||
|
||||
# Record Browser GIF
|
||||
|
||||
Produce a short, truthful UI demonstration as a local GIF. Use the browser-control skill for interaction and the bundled encoder for repeatable timing, dimensions, and size.
|
||||
Produce a short, truthful UI demonstration as a local GIF, and — only when the task includes attaching it to a pull request — publish it through the assets-branch workflow at the end of this skill. Use the browser-control skill for interaction and the bundled encoder for repeatable timing, dimensions, and size.
|
||||
|
||||
## Every GUI pull request includes a GIF
|
||||
|
||||
A pull request that changes product-user-visible GUI behavior MUST include a demonstration GIF recorded with this skill and embedded in the pull request body via [the assets-branch workflow](#publish-to-an-assets-branch).
|
||||
|
||||
The GIF's provenance is part of the evidence and must be real: a real server booted from that pull request's own branch tree, a real API key, and real model rounds. Never substitute fixture queries, mock transports, synthetic event injection, or test-only hooks unless the user explicitly asked for fixture provenance. State the provenance next to the embed — which tree served, which mode flags, that a real model round ran — so reviewers know exactly what the recording proves.
|
||||
|
||||
## Keep the boundary explicit
|
||||
|
||||
- Produce frame images and one local `.gif` artifact only.
|
||||
- Never upload the artifact, post a comment, or change a pull request, issue, or document under this skill. Hand those actions to a separate workflow if the user requests them.
|
||||
- Recording produces frame images and one local `.gif` artifact only; it never mutates remote state.
|
||||
- Publication — pushing the GIF to an assets branch and embedding it in a pull request body — is the separate final step, performed only when the task includes attaching the GIF to a pull request. It never touches the pull request's own branch.
|
||||
- Preserve the requested provenance. A real-server or real-API demo must not use fixture queries, mock transports, synthetic event injection, or test-only hooks. If credentials or the server are unavailable, report that limitation instead of substituting a fixture.
|
||||
- Never read or expose credential values. Use the application's normal configuration path and a benign demonstration prompt.
|
||||
|
||||
## Stage the application
|
||||
|
||||
A GIF for a specific pull request demonstrates that pull request's tree, so stage per pull request:
|
||||
|
||||
1. Build the branch tree being demonstrated — here, `pnpm run build && pnpm run build:web` — from the worktree that holds that branch. A GIF recorded against another branch's build misattributes the evidence.
|
||||
2. Boot one server per port from that tree, giving each recording a fresh scratch workspace directory so leftover sessions cannot appear in frames. Source the root `.env` for the API key through the application's normal path; never echo the key.
|
||||
3. Start a new session for each recorded scenario so earlier turns do not pollute the frames.
|
||||
4. When switching between pull requests, stop the old server by PID or an exact match on its command line. A broad `pkill -f` pattern can match and kill the shell that launched it — including your own.
|
||||
|
||||
## Record the flow
|
||||
|
||||
1. Invoke the available browser-control skill and follow its setup, interaction, and cleanup instructions. Use the user's existing Chrome state only when requested or required.
|
||||
2. Resolve the evidence boundary before recording: identify the exact origin, whether the app is built or in development, the transport, and any fixture or mock mode. Record only claims that the observed setup supports.
|
||||
3. Choose three to six states that tell one story, such as initial, typed, submitted, and completed. Prefer semantic state changes over continuous capture; omit loading churn that does not help the viewer.
|
||||
4. Keep one viewport and crop for every frame. Store frames in an absolute artifact directory outside the Git worktree unless the user requests another location, and name them lexically: `00-initial.png`, `01-typed.png`, and so on.
|
||||
5. Before each screenshot, wait for a concrete UI condition such as a unique label, enabled control, changed document title, or completed response. Do not use a fixed delay as proof that the application reached the state.
|
||||
6. Capture no secrets, personal data, unrelated tabs, or transient notifications. Stop any unnecessarily long real-API run after the demonstrated state is visible.
|
||||
3. Choose three to six states that tell one story, such as typed, running, settled, and detail. Prefer semantic state changes over continuous capture; omit loading churn that does not help the viewer.
|
||||
4. Keep one viewport and crop for every frame, and name frames lexically: `00-initial.png`, `01-typed.png`, and so on.
|
||||
5. Store frames under the repository's gitignored `.playwright-mcp/` directory — browser-tool screenshots can only be written under the tool's allowed roots, and relative filenames resolve against the repository root. Create the frame subdirectory first (`mkdir -p .playwright-mcp/gif-frames-<label>`); writing into a missing directory fails with ENOENT at capture time.
|
||||
6. Before each screenshot, wait for a concrete UI condition such as a unique label, enabled control, changed document title, or completed response. Do not use a fixed delay as proof that the application reached the state.
|
||||
7. Make completion predicates match an exact-text element — for example, an element whose trimmed text equals the expected reply — never a substring check such as `body.textContent.includes(...)`, which the echo of the user's own prompt also satisfies.
|
||||
8. Capture a transient state (spinner, running row) by driving a slow foreground operation — for example, a `sleep 15` bash command — and polling a concrete DOM marker (a `data-*` attribute) inside one browser-script call that also takes the screenshot. State polled across separate tool calls is lost, because the turn settles between calls.
|
||||
9. Engineer the prompt so the state you need actually occurs: instruct the model to wait in the foreground when it would otherwise background a slow command, and give it a settle sentinel such as "reply with the single word done" to anchor the completion predicate.
|
||||
10. Capture no secrets, personal data, unrelated tabs, or transient notifications. Stop any unnecessarily long real-API run after the demonstrated state is visible.
|
||||
|
||||
Use the browser's own screenshot API. When it returns image bytes, save those bytes directly; the encoder detects image content independently of the filename extension.
|
||||
|
||||
@@ -29,9 +48,10 @@ Use the browser's own screenshot API. When it returns image bytes, save those by
|
||||
|
||||
Require `python3`, `ffmpeg`, and `ffprobe`. If either media binary is missing, report the dependency instead of installing software without authorization.
|
||||
|
||||
Set `GIF_SKILL_DIR` to this skill's absolute directory, then encode the lexically ordered frames:
|
||||
Export `GIF_SKILL_DIR` as this skill's absolute directory on its own line before the python command — an inline `GIF_SKILL_DIR=... python3 "$GIF_SKILL_DIR/..."` assignment fails, because the argument expands before the assignment takes effect:
|
||||
|
||||
```sh
|
||||
export GIF_SKILL_DIR=/absolute/path/to/this/skill
|
||||
python3 "$GIF_SKILL_DIR/scripts/encode_gif.py" \
|
||||
/absolute/path/to/frames \
|
||||
/absolute/path/to/demo.gif \
|
||||
@@ -41,13 +61,40 @@ python3 "$GIF_SKILL_DIR/scripts/encode_gif.py" \
|
||||
--colors 128
|
||||
```
|
||||
|
||||
One duration applies to every frame; otherwise provide one comma-separated positive duration per frame. The encoder rejects fewer than two frames, mismatched dimensions or durations, invalid limits, accidental overwrite, unexpected duration, and output above `--max-bytes`.
|
||||
One duration applies to every frame; otherwise provide one comma-separated positive duration per frame, holding the final settled state longest. The encoder rejects fewer than two frames, mismatched dimensions or durations, invalid limits, accidental overwrite, unexpected duration, and output above `--max-bytes`.
|
||||
|
||||
For a large artifact, reduce `--max-width` first, then `--colors` or `--fps`; retain readable text and the final state long enough to inspect. Use `--force` only after resolving the exact output path.
|
||||
|
||||
## Verify and deliver
|
||||
## Verify the artifact
|
||||
|
||||
1. Read the encoder's JSON summary and confirm the output path, source and encoded frame counts, dimensions, duration, and byte size.
|
||||
2. Inspect the first and final source frames and the resulting GIF. Confirm that the transition is legible, the last state is held long enough, and no sensitive content appears.
|
||||
3. If capture occurred near a repository, run `git status --short` and confirm the artifact did not dirty the worktree.
|
||||
4. Return the absolute GIF path, render it when the client supports local media, and state whether the recording used a real API, fixture, or another transport. Stop without uploading it or editing remote content.
|
||||
2. Visually read the encoded GIF itself, not only the source frames. Confirm that the transition is legible, the last state is held long enough, and no sensitive content appears.
|
||||
3. Run `git status --short` and confirm frames and the artifact landed only under ignored paths.
|
||||
4. Return the absolute GIF path, render it when the client supports local media, and state whether the recording used a real API, fixture, or another transport. When the task does not include attaching the GIF to a pull request, stop here.
|
||||
|
||||
## Publish to an assets branch
|
||||
|
||||
Perform this step only when the task includes attaching the GIF to a pull request.
|
||||
|
||||
Never commit a GIF to the pull request's own branch or any branch that merges into a long-lived branch: binary media committed there bloats the repository history for every future clone. GIFs live on a dedicated orphan assets branch — a branch with no parent commit and nothing but media — and one assets branch serves a whole pull request series (existing branches: `code-mode-ui-assets`, `pr-613-assets`).
|
||||
|
||||
For an existing assets branch, work in a shallow single-branch scratch clone so the publication cannot touch your working tree:
|
||||
|
||||
```sh
|
||||
git clone --branch <assets-branch> --single-branch --depth 1 <repo-url> /tmp/assets-checkout
|
||||
cp /absolute/path/to/demo.gif /tmp/assets-checkout/<name>.gif
|
||||
cd /tmp/assets-checkout
|
||||
git add <name>.gif
|
||||
git commit -m "assets: <what it shows> gif (#<pr>)"
|
||||
git push origin <assets-branch>
|
||||
```
|
||||
|
||||
For a new series, make a fresh shallow scratch clone (`git clone --depth 1 <repo-url> /tmp/assets-checkout`), create the orphan branch with `git switch --orphan <assets-branch>`, then add the GIF, commit, and push the same way.
|
||||
|
||||
Embed the GIF in the pull request body with the raw blob URL; the `?raw=true` suffix is required, because the plain blob URL renders GitHub's file page instead of the image:
|
||||
|
||||
```markdown
|
||||

|
||||
```
|
||||
|
||||
Never delete or rewrite an assets branch, and never force-push it: merged pull request bodies reference its URLs forever. Append new commits only.
|
||||
|
||||
Reference in New Issue
Block a user