Commits
Co-authored-by: opencode <noreply@opencode.ai>
The user asked whether we are now standardizing the tags/labels we
use. Partial answer: chronver (version), triage (issues), deciduous
(graph nodes) were already standardized. The commit and branch naming
vocabularies were de facto conventional-commits but not written down;
the 2026-06-03-02 task note explicitly flagged this as a future task.
- AGENTS.md Git workflow: new 'Branch and commit naming' subsection
with the conventional-commits 1.0.0 type list enumerated inline.
Branch names are <type>/<slug>; commit messages are
<type>(<scope>): <subject>; the type vocabulary is shared. The
chore(release): type is reserved for the version-bump commit.
Forks extend or trim the list via suede-kickoff Thread B Q8.
- AGENTS.md Layout: task note filename pattern formalized as
YYYY-MM-DD-NN-<slug>.md with the per-day counter rules. New
bullet for .opencode/{agents,commands,plugins,tools}/ kebab-case
file naming. New 'Task note section headings' subsection listing
the 6 required sections from the template, in order, with the
'all six required' rule.
- suede-kickoff Thread B Q8 sub-bullet 'Branch and commit naming':
rewritten to point at AGENTS.md's new rule, with the
extension/trim override path.
Co-authored-by: opencode <noreply@opencode.ai>
The turn-1 / turn-2 hand-back message overstated the agent's role.
The correct rule: the agent may push branches and may apply tags,
but may not push directly to main and may not merge to main. The
human is the one who reviews the PR and merges to main; the agent
is fine doing the release-branch push and the tag.
This matches the prior-task pattern (2026-06-04-03 SuedeButton task
involved the agent pushing the branch; 2026-06-05-06 chronver task
mentioned the human tagging the merge commit but didn't preclude
the agent from doing so).
- AGENTS.md Git workflow bullet 4: agent may push + may tag, may
not push to main, may not merge to main.
- AGENTS.md Task flow End step 5: same correction.
- AGENTS.md Releases intro: removed 'the human tags' wording; the
tag-and-push step is agent-OK, only the merge-to-main is human-only.
No version bump for this turn. If the user prefers the rule
correction to ride with 2026.6.12, can rebase/re-bump.
Co-authored-by: opencode <noreply@opencode.ai>
Six follow-up points from the user after the turn-1 commit. All land
on the same branch as a separate commit so the turn-1 / turn-2 work
is independently reviewable.
- AGENTS.md Git workflow: 'Never branch off an in-flight branch.' Only
main is a valid base. In-flight work follows up on the same branch
or waits. A branch-of-branch creates a PR whose base vanishes the
moment the first PR merges.
- AGENTS.md Authoring boundaries: 'Storybook discipline' subsection
with assume-included wording. A UI primitive change is incomplete
without a story update in the same commit. The override path lives
in suede-kickoff Thread B Q7 (a fork that rips Storybook records
the override in the kickoff follow-up task note, and the agent
rewrites AGENTS.md / tdd-supplementary to reflect the rip).
- AGENTS.md Constant process pipeline: 'Tracker preconditions' para.
Stages 4/5/8/9 need a tracker. Default: GitHub Issues. Sane
overrides: markdown-dir, Linear, GitLab. Tangled is a mirror, not
a tracker. When no tracker is configured, those stages collapse to
mental checks on the task note's Follow-ups.
- AGENTS.md Releases: rewrote intro as 'mechanics constant, scheme
variable.' The fork-invariant part is the release flow mechanics;
the scheme (chronver / semver / other) is a Thread B question.
Added 'Tracker and remotes' paragraph making GitHub Issues the
default tracker and Tangled a mirror.
- AGENTS.md Decision Graph Workflow: Session Start Checklist no
longer references 'deciduous check-update'. Added a 'Do not run
deciduous update' policy paragraph (the upstream update command
regenerates .opencode/, .claude/, AGENTS.md from defaults and
silently overwrites hand-edits).
- AGENTS.md Working style: added 'tdd-supplementary' to the
build-stage skills list.
- .opencode/plugins/version-check.ts: rewritten as a no-op. Writes
a one-time marker to .deciduous/.version_check_disabled + a single
log line, then returns silently. The deciduous auto-update toggle
is deprecated upstream; disabling the plugin is the only effective
silencing.
- .gitignore: added agent-notes/plans/ with a comment explaining
the rationale (plan files are per-task scratchpads; the compiled
form persists; handoff is the resume tool).
- .opencode/skills/task-lifecycle/SKILL.md: 'Do not write a plan
file to agent-notes/plans/' — gitignored scratchpads, handoff is
the resume tool.
- .opencode/skills/suede-kickoff/SKILL.md: Thread B Q7 strengthened
to 'Defaults: keep all' with explicit override paths (Storybook
rip rewrites AGENTS.md + tdd-supplementary; SvelteKit rip rewrites
AGENTS.md + build-test.md).
- .opencode/skills/tdd-supplementary/SKILL.md (new): three
sections — Prune pass (the rule the global tdd skill is missing;
walks the tdd/tests.md Red flags checklist; deletes in the same
commit); Storybook discipline (restates the Authoring Boundaries
rule as a workflow); What's intentionally not in this skill.
Co-authored-by: opencode <noreply@opencode.ai>
The suede process layer is constant across every fork (full-stack,
content, backend, other). What varies is the details — issue tracker,
branch convention, version policy, which global skills apply. This
commit makes that contract explicit in three places:
- AGENTS.md: new 'Constant process pipeline' section with the 11-stage
table (concept -> grill -> PRD -> issues -> triage -> build ->
diagnose -> review -> QA -> release -> handoff) and the always-on
supporting layer (decision graph, task notes, git workflow, authoring
boundaries). Working style rewritten to bucket skills by pipeline
stage. Task flow Start + During steps now reference the pipeline
section as the canonical source.
- .opencode/skills/suede-kickoff/SKILL.md: Step 3 reframed as a
/grill-me session with Thread A (project) and Thread B (process-layer
customizations). Thread B is open-ended — the process is the human's,
the agent doesn't pick which ~/.agents/skills/ to load, which issue
tracker to use, or which branch convention to enforce. Step 8 splits
the decision list into process-layer edits (lead) and runtime-layer
edits.
- .opencode/commands/work.md: fixed the 'hooks will BLOCK you' claim
on line 13. The require-action-node plugin nags to .deciduous/plugin.log;
it does not block. Same fix shape in 'Why This Matters'.
- .opencode/commands/build-test.md: rewritten from stock deciduous
(cargo + Rust) to the suede defaults (pnpm + Vitest + svelte-check +
Storybook). The 2026-06-04-01 task note originally flagged this
misalignment.
Did NOT touch the other 8 stock deciduous commands — out of scope for
this task. Did NOT introduce a branch-naming convention — out of scope.
Did NOT resolve the deciduous sync boundary — out of scope.
Co-authored-by: opencode <noreply@opencode.ai>
First suede release cut through the formal chronver flow. Bumps the
package version from 2026.6.4 to 2026.6.5 (today's date, no leading
zeros). After merge, the merge commit on main gets the annotated tag
2026.6.5 and is pushed with --follow-tags.
This release includes:
- Working style section (process skills pointer, Zed plan/build note)
- Versioning rule (every release branch ships as its own version)
- Task flow section (Start / During / End sequence)
Co-authored-by: opencode <noreply@opencode.ai>
Replaces the one-line 'Task lifecycle' pointer with a full Start / During /
End flow that consolidates the rules scattered across the rest of AGENTS.md
(Authoring boundaries, Working style, Releases, Decision Graph) into one
sequence the agent can follow turn-by-turn. The procedural detail still
lives at .opencode/skills/task-lifecycle/SKILL.md; this section is the
in-context summary.
Start: pull main, branch, log goal, design in plan mode.
During: action nodes, process skills, authoring boundaries, commits,
deciduous linking.
End: verify, task note, version bump, hand back.
Co-authored-by: opencode <noreply@opencode.ai>
First suede release cut through the formal chronver flow. Bumps the
package version from 2026.6.4 to 2026.6.5 (today's date, no leading
zeros). After merge, the merge commit on main gets the annotated tag
2026.6.5 and is pushed with --follow-tags.
Co-authored-by: opencode <noreply@opencode.ai>
Working style: pointer to ~/.agents/skills/ process skills (tdd, diagnose,
prototype, review, qa, handoff, caveman, write-a-skill) plus a one-line
note that Zed's plan/build mode toggle is the human's lever. Replaces
using-superpowers as the process-skill dispatcher after the plugin kill.
Versioning rule: every release branch (a branch ready to be reviewed and
merged to main) ships as its own chronver version. The bump is the final
commit on the release branch, before merge. No versionless merges.
Co-authored-by: opencode <noreply@opencode.ai>
Adds an in-repo skill at .opencode/skills/suede-kickoff/SKILL.md that an
agent can invoke when starting a new project forked from suede.
The skill reinstantiates git, updates package.json with the suede.from
lineage field per AGENTS.md, resets .deciduous/, runs a 6-question scope
interview with the human, and branches chore/suede-kickoff for the deep
tooling-customization follow-up. The skill removes itself as the final
action of the follow-up branch.
Built via writing-skills TDD: 3 RED-phase pressure scenarios, GREEN
draft, 1 REFACTOR re-run that closed 3 residual gaps. Rationalizations
table covers 7 anti-patterns (capture-after-delete, tag-vs-version,
'be decisive' override, deciduous-skip, git-add-dot, work-on-a-copy,
no-follow-up-task).
Co-authored-by: opencode <noreply@opencode.ai>
The task-note lifecycle (AGENTS.md task-lifecycle skill) requires
an entry per completed task; these were authored at the time of
their respective work but never committed. Closing the loop:
- 2026-06-03-03: chronver release process
- 2026-06-04-01: remove Claude-Code-specific artifacts from
deciduous install
- 2026-06-04-02: build the deciduous decision graph for Suede
from commit history
Plus the plan artifact for the chronver task
(agent-notes/plans/add-suede-release-process-chronver.md) —
plan files are write-only at task end per the skill, so this
is the canonical place for it.
- .opencode/agents/deciduous.md: specialist agent for
deciduous decision-graph operations.
- .opencode/commands/*.md (10 files): slash-command wrappers
for the most common workflows (work, build, document,
decision-graph, decision, recover, serve-ui, sync, sync-graph,
build-test).
- .opencode/plugins/*.ts (3 files): lifecycle hooks —
post-commit-reminder, require-action-node (Edit/Write
guard), version-check.
- .opencode/skills/{archaeology,narratives,pulse}/SKILL.md:
in-repo skills for narrative-driven decision-graph work.
- .opencode/tools/deciduous.ts: thin TS tool wrapper for the
deciduous CLI used by the agents/commands above.
- opencode.json: project-level opencode config (model,
agent list, MCP servers, etc.).
Also includes a stray prettier reformat of .storybook/preview.ts
(the import chain was unchanged; only whitespace/indentation
differed from the version committed in b718ad0).
Excluded: .opencode/.gitignore (workspace-internal config that
self-excludes via its own last line), .opencode/node_modules/,
.opencode/package.json, .opencode/package-lock.json
(gitignored at the repo root by the prior commit).
The .opencode directory is a pnpm-managed workspace (its own
internal .opencode/.gitignore covers node_modules + lockfiles
for the pnpm tooling). Git only reads the root .gitignore for
untracked-detection, so add the corresponding entries here to
keep 'git status' clean for downstream contributors.
The tracked .opencode/ contents (agents, commands, plugins,
skills, tools, and the .opencode/.gitignore itself) are
configuration and ship with the repo.
- .github/workflows/cleanup-decision-graphs.yml: scheduled (and
manual-dispatch) cleanup of stale deciduous event log files.
Companion to the deciduous sync export at docs/graph-data.json.
- .github/workflows/deploy-pages.yml: builds the Storybook
static site (pnpm build-storybook) and deploys storybook-static/
to GitHub Pages. This is what makes the SuedeButton docs
(and any future Storybook) browsable from the public web.
Neither workflow has been exercised against the live repo yet;
add a PR for the deploy workflow to fire on a tag or manual
dispatch only.
One-line content edit; the SvelteKit default 'Welcome to SvelteKit'
page no longer reflects the project's identity. Now reads
'<h1>suede</h1><p>a template repo.</p>'. No functional change;
the +page.svelte component is otherwise unchanged.
Removes the auto-generated example Button/Accordion wrappers and
their Vitest specs that were scaffolded in 341d364
('feat: install bits-ui and stylebase, scaffold UI wrappers') but
never replaced with real components. The matching story files
that referenced them were removed in bbdd827 (broken imports
were blocking Storybook's vite import-analysis).
What's left in src/lib/components/ui/ is the new SuedeButton
wrapper (added in c7c153b) — the only wrapper the project
currently ships. Future wrappers should be added here as
they're built.
The SuedeButton wrapper was applying the same .suede-button styles
to both the <button> and <a> renderings of bits-ui's polymorphic
Button.Root. By design, an anchor acting as a button (e.g. a
'Subscribe' link that navigates to a checkout page) should look
like a button — but a literal <a href> link should look like a
link. Until now the two were visually indistinguishable.
Added a :global(.suede-button[href]) rule that overrides the
button styling when bits-ui renders an anchor (it sets the
href attribute on the underlying element):
background-color: transparent
color: var(--hue-blue-500)
padding-inline: 0
text-decoration: underline
text-decoration-thickness: from-font
text-underline-offset: 0.2em
plus a :hover variant that darkens the color to --hue-blue-600.
The existing :hover and :active rules are now scoped with
:not([href]) so they only apply to the button variant — without
that, their higher-specificity background-color: var(--hue-blue-600)
would have re-painted the link blue on hover, defeating the
transparent background.
The user also renamed the destructured class prop from `klass`
to `className` (React convention) and updated the
'With class override' story to pass `class="u:fs-1"` instead
of `u:fs-3`, so the demo now isolates the inline-style
background override (emerald) without compounding it with a
font-size change.
Verified via Playwright computed-style inspection on all 4 stories:
Primary bg=oklch blue, white text, no underline (button)
Disabled same blue, cursor=not-allowed (button)
As link bg=transparent, blue text, underlined (link!)
With class override bg=oklch emerald, white text, no underline (button, color override)
pnpm check still 0 errors / 0 warnings project-wide.
Two-part fix for the same observable bug: SuedeButton rendered
with browser-default styles in Storybook (gray bg, black text,
0 padding, Arial font) because the stylebase custom properties
(--hue-blue-500, --space-*, --ff-ui, etc.) and utility classes
(u:fs-1) were never present in the Storybook preview iframe.
Part 1 — .storybook/preview.ts:
Import `../src/app.css` so the Storybook preview iframe gets
the same global stylesheet as the SvelteKit app (stylebase +
the :focus-visible rule). Storybook's preview iframe is
independent of the SvelteKit app's +layout.svelte, so
SvelteKit's import chain didn't reach it.
Part 2 — src/lib/components/ui/SuedeButton.svelte:
Wrap every .suede-button selector in :global(...). The class
is set as a prop on the child <Button.Root> component, not
as a class on SuedeButton's own template element. Svelte 5's
per-component CSS scoping only applies to elements rendered
by that component — the .suede-button rule was being pruned
(0 selectors in the bundle) even with the svelte-ignore
comment, because svelte-ignore suppresses the warning but
doesn't prevent the build-time strip.
:global() escapes the scoping. The `suede-button` class name
is unique enough that global leakage is safe.
Verified via Playwright on all 4 SuedeButton stories + style
introspection (computed styles + styleSheets inspection):
Primary bg=oklch(.7188 .15 240) [blue] cursor=pointer
Disabled same blue, cursor=not-allowed
As link renders <a>, cursor=pointer
With class override bg=oklch(.7109 .15 140) [emerald], font-size=20.1px
(u:fs-3 override of u:fs-1), class= 'suede-button u:fs-1 u:fs-3'
All custom properties now resolve at :root, all .suede-button
rules present in the bundle, pnpm check still 0/0 project-wide.
`src/stories/Button.stories.svelte` and `src/stories/Accordion.stories.svelte`
both imported `$lib/components/ui/{Button,Accordion}.svelte` which no longer
exist on this branch (deleted in working tree). The deletion left the
stories with unresolvable imports, and Storybook's vite import-analysis
fails at build time on those files (the same asChild-related issue
surfaced earlier would have hit if the broken imports were repaired).
`src/stories/Page.stories.svelte` and `src/stories/Header.stories.svelte`
are kept: their imports are local (`./Page.svelte`, `./Header.svelte`)
and still resolve.
Verified via Playwright across 6 story URLs (all 4 SuedeButton + the two
remaining examples): 0 console errors, 0 vite import-analysis errors.
Only warnings are Storybook 11 deprecations on Storybook's internal UI
(`ariaLabel` on its own Button/PopoverProvider), not user code.
`pnpm check` is now fully clean (0 errors, 0 warnings) — no more
pre-existing noise from the deleted stories.
@storybook/addon-svelte-csf's Story.svelte, when given both a
`component` in defineMeta and children in the <Story> block, wraps
the children in another instance of that component
(line 148: `<renderer.storyContext.component {...renderer.args} {children} />`).
In our case `component: SuedeButton` + `<SuedeButton>Click me</SuedeButton>`
as Story children produced `<button class="suede-button"><button class="suede-button">Click me</button></button>`
— an accessibility violation (interactive element nested in interactive element)
and semantically wrong markup.
`asChild` on each <Story> routes the children through the
`{@render children()}` branch (no component wrapping) so the story
renders as static markup. Trade-off: args-driven controls don't
update the canvas for `asChild` stories, which is acceptable for
discrete-variant learning demos.
Verified via Playwright against the running Storybook dev server:
Primary / Disabled / With-class-override each render exactly one
`<button data-button-root="true" class="suede-button ...">` at the
root of the story canvas; As link renders as a single
`<a data-button-root="true">`. `button button` and `a button`
nested-selector counts: 0 in every story.
Adds a Suede-wrapped bits-ui Button as a learning scaffold for the
bits-ui + stylebase + Svelte 5 pattern. Distinguishes functionality
(bits-ui's polymorphic Button.Root via ButtonRootProps) from style
(stylebase utility class + scoped <style> block in the same file).
Story at src/stories/SuedeButton.stories.svelte exercises four
variants: Primary, Disabled, As link, With class override.
TypeScript escape hatch: rest is spread via
`{...rest as Record<string, unknown>}` because bits-ui's
ButtonRootProps is a union (AnchorElement | ButtonElement) that
exceeds TypeScript's type complexity budget when re-spread into
another Svelte component. Cast is local to one line; polymorphic
behavior (button vs anchor via href) still works at runtime.
CSS pruner workaround: `<!-- svelte-ignore css_unused_selector -->`
on the <style> block, because the class name is built from a
template literal in the class attribute and is therefore invisible
to Svelte's static class-extraction pass.
Existing example stories (Button, Accordion, Header, Page) are
left untouched per option C; pre-existing pnpm check errors
(missing /components/ui/Button.svelte and Accordion.svelte
references) are out of scope for this change.
- .deciduous/ : local decision-graph database
- docs/ : generated web viewer export (regenerate via 'deciduous sync')
- CLAUDE.md : explicit Claude-Code instruction file, not part of this project
- .claude/ : explicit Claude-Code config directory, not part of this project
The last two are defensive: if 'deciduous install' re-runs, the Claude
artifacts will be re-created locally but stay untracked.
Cross-agent view of the deciduous decision-graph tool. Source content was
copied from CLAUDE.md's managed block (which we will not commit) and stripped
of tool-specific syntax:
- Removed slash command table (Claude Code only)
- Removed skills table (Claude Code only)
- Removed inline slash-command references
- Replaced the .claude/commands/decision.md git-staging example with
project-relevant paths
A header note at the top of the section explains that this is the
tool-agnostic view; tool-specific commands and skills live in
.opencode/commands/ and .opencode/skills/ (loaded at runtime by OpenCode,
not duplicated here).
First suede release. Bump placeholder 0.0.1 -> 2026.6.4 (chronver, today's date).
Tag 2026.6.4 will be applied to the merge commit on main after this PR merges.
- chronver for apps and templates, semver for packages
- release flow: bump-on-merge, bare chronver tag, --follow-tags
- downstream lineage via suede.from field in project package.json
- pnpm add @taurean/stylebase bits-ui
- src/app.css imports stylebase and provides global focus ring
- +layout.svelte wires app.css
- src/lib/components/ui/Button.svelte and Accordion.svelte are
Svelte 5 + bits-ui wrappers (script-only agent territory)
- Storybook stories for both wrappers
- vitest-browser-svelte smoke tests for both wrappers
- .gitignore: worker-configuration.d.ts (wrangler build artifact)
Wrapper styling is intentionally minimal — human territory per
AGENTS.md. The wrappers render with stylebase defaults; the
hybrid strategy (global data-attribute CSS + per-component
overrides) is the next step.
Refs agent-notes/2026-06-03-02-install-bits-ui-stylebase.md
- AGENTS.md: add Git workflow section (branch from main, PR review, no direct push)
- AGENTS.md: trim stack line to technologies only
- task-lifecycle skill: add Before starting section for branch setup
Co-authored-by: opencode <noreply@opencode.ai>
The user asked whether we are now standardizing the tags/labels we
use. Partial answer: chronver (version), triage (issues), deciduous
(graph nodes) were already standardized. The commit and branch naming
vocabularies were de facto conventional-commits but not written down;
the 2026-06-03-02 task note explicitly flagged this as a future task.
- AGENTS.md Git workflow: new 'Branch and commit naming' subsection
with the conventional-commits 1.0.0 type list enumerated inline.
Branch names are <type>/<slug>; commit messages are
<type>(<scope>): <subject>; the type vocabulary is shared. The
chore(release): type is reserved for the version-bump commit.
Forks extend or trim the list via suede-kickoff Thread B Q8.
- AGENTS.md Layout: task note filename pattern formalized as
YYYY-MM-DD-NN-<slug>.md with the per-day counter rules. New
bullet for .opencode/{agents,commands,plugins,tools}/ kebab-case
file naming. New 'Task note section headings' subsection listing
the 6 required sections from the template, in order, with the
'all six required' rule.
- suede-kickoff Thread B Q8 sub-bullet 'Branch and commit naming':
rewritten to point at AGENTS.md's new rule, with the
extension/trim override path.
Co-authored-by: opencode <noreply@opencode.ai>
The turn-1 / turn-2 hand-back message overstated the agent's role.
The correct rule: the agent may push branches and may apply tags,
but may not push directly to main and may not merge to main. The
human is the one who reviews the PR and merges to main; the agent
is fine doing the release-branch push and the tag.
This matches the prior-task pattern (2026-06-04-03 SuedeButton task
involved the agent pushing the branch; 2026-06-05-06 chronver task
mentioned the human tagging the merge commit but didn't preclude
the agent from doing so).
- AGENTS.md Git workflow bullet 4: agent may push + may tag, may
not push to main, may not merge to main.
- AGENTS.md Task flow End step 5: same correction.
- AGENTS.md Releases intro: removed 'the human tags' wording; the
tag-and-push step is agent-OK, only the merge-to-main is human-only.
No version bump for this turn. If the user prefers the rule
correction to ride with 2026.6.12, can rebase/re-bump.
Co-authored-by: opencode <noreply@opencode.ai>
Six follow-up points from the user after the turn-1 commit. All land
on the same branch as a separate commit so the turn-1 / turn-2 work
is independently reviewable.
- AGENTS.md Git workflow: 'Never branch off an in-flight branch.' Only
main is a valid base. In-flight work follows up on the same branch
or waits. A branch-of-branch creates a PR whose base vanishes the
moment the first PR merges.
- AGENTS.md Authoring boundaries: 'Storybook discipline' subsection
with assume-included wording. A UI primitive change is incomplete
without a story update in the same commit. The override path lives
in suede-kickoff Thread B Q7 (a fork that rips Storybook records
the override in the kickoff follow-up task note, and the agent
rewrites AGENTS.md / tdd-supplementary to reflect the rip).
- AGENTS.md Constant process pipeline: 'Tracker preconditions' para.
Stages 4/5/8/9 need a tracker. Default: GitHub Issues. Sane
overrides: markdown-dir, Linear, GitLab. Tangled is a mirror, not
a tracker. When no tracker is configured, those stages collapse to
mental checks on the task note's Follow-ups.
- AGENTS.md Releases: rewrote intro as 'mechanics constant, scheme
variable.' The fork-invariant part is the release flow mechanics;
the scheme (chronver / semver / other) is a Thread B question.
Added 'Tracker and remotes' paragraph making GitHub Issues the
default tracker and Tangled a mirror.
- AGENTS.md Decision Graph Workflow: Session Start Checklist no
longer references 'deciduous check-update'. Added a 'Do not run
deciduous update' policy paragraph (the upstream update command
regenerates .opencode/, .claude/, AGENTS.md from defaults and
silently overwrites hand-edits).
- AGENTS.md Working style: added 'tdd-supplementary' to the
build-stage skills list.
- .opencode/plugins/version-check.ts: rewritten as a no-op. Writes
a one-time marker to .deciduous/.version_check_disabled + a single
log line, then returns silently. The deciduous auto-update toggle
is deprecated upstream; disabling the plugin is the only effective
silencing.
- .gitignore: added agent-notes/plans/ with a comment explaining
the rationale (plan files are per-task scratchpads; the compiled
form persists; handoff is the resume tool).
- .opencode/skills/task-lifecycle/SKILL.md: 'Do not write a plan
file to agent-notes/plans/' — gitignored scratchpads, handoff is
the resume tool.
- .opencode/skills/suede-kickoff/SKILL.md: Thread B Q7 strengthened
to 'Defaults: keep all' with explicit override paths (Storybook
rip rewrites AGENTS.md + tdd-supplementary; SvelteKit rip rewrites
AGENTS.md + build-test.md).
- .opencode/skills/tdd-supplementary/SKILL.md (new): three
sections — Prune pass (the rule the global tdd skill is missing;
walks the tdd/tests.md Red flags checklist; deletes in the same
commit); Storybook discipline (restates the Authoring Boundaries
rule as a workflow); What's intentionally not in this skill.
Co-authored-by: opencode <noreply@opencode.ai>
The suede process layer is constant across every fork (full-stack,
content, backend, other). What varies is the details — issue tracker,
branch convention, version policy, which global skills apply. This
commit makes that contract explicit in three places:
- AGENTS.md: new 'Constant process pipeline' section with the 11-stage
table (concept -> grill -> PRD -> issues -> triage -> build ->
diagnose -> review -> QA -> release -> handoff) and the always-on
supporting layer (decision graph, task notes, git workflow, authoring
boundaries). Working style rewritten to bucket skills by pipeline
stage. Task flow Start + During steps now reference the pipeline
section as the canonical source.
- .opencode/skills/suede-kickoff/SKILL.md: Step 3 reframed as a
/grill-me session with Thread A (project) and Thread B (process-layer
customizations). Thread B is open-ended — the process is the human's,
the agent doesn't pick which ~/.agents/skills/ to load, which issue
tracker to use, or which branch convention to enforce. Step 8 splits
the decision list into process-layer edits (lead) and runtime-layer
edits.
- .opencode/commands/work.md: fixed the 'hooks will BLOCK you' claim
on line 13. The require-action-node plugin nags to .deciduous/plugin.log;
it does not block. Same fix shape in 'Why This Matters'.
- .opencode/commands/build-test.md: rewritten from stock deciduous
(cargo + Rust) to the suede defaults (pnpm + Vitest + svelte-check +
Storybook). The 2026-06-04-01 task note originally flagged this
misalignment.
Did NOT touch the other 8 stock deciduous commands — out of scope for
this task. Did NOT introduce a branch-naming convention — out of scope.
Did NOT resolve the deciduous sync boundary — out of scope.
Co-authored-by: opencode <noreply@opencode.ai>
First suede release cut through the formal chronver flow. Bumps the
package version from 2026.6.4 to 2026.6.5 (today's date, no leading
zeros). After merge, the merge commit on main gets the annotated tag
2026.6.5 and is pushed with --follow-tags.
This release includes:
- Working style section (process skills pointer, Zed plan/build note)
- Versioning rule (every release branch ships as its own version)
- Task flow section (Start / During / End sequence)
Co-authored-by: opencode <noreply@opencode.ai>
Replaces the one-line 'Task lifecycle' pointer with a full Start / During /
End flow that consolidates the rules scattered across the rest of AGENTS.md
(Authoring boundaries, Working style, Releases, Decision Graph) into one
sequence the agent can follow turn-by-turn. The procedural detail still
lives at .opencode/skills/task-lifecycle/SKILL.md; this section is the
in-context summary.
Start: pull main, branch, log goal, design in plan mode.
During: action nodes, process skills, authoring boundaries, commits,
deciduous linking.
End: verify, task note, version bump, hand back.
Co-authored-by: opencode <noreply@opencode.ai>
Working style: pointer to ~/.agents/skills/ process skills (tdd, diagnose,
prototype, review, qa, handoff, caveman, write-a-skill) plus a one-line
note that Zed's plan/build mode toggle is the human's lever. Replaces
using-superpowers as the process-skill dispatcher after the plugin kill.
Versioning rule: every release branch (a branch ready to be reviewed and
merged to main) ships as its own chronver version. The bump is the final
commit on the release branch, before merge. No versionless merges.
Co-authored-by: opencode <noreply@opencode.ai>
Adds an in-repo skill at .opencode/skills/suede-kickoff/SKILL.md that an
agent can invoke when starting a new project forked from suede.
The skill reinstantiates git, updates package.json with the suede.from
lineage field per AGENTS.md, resets .deciduous/, runs a 6-question scope
interview with the human, and branches chore/suede-kickoff for the deep
tooling-customization follow-up. The skill removes itself as the final
action of the follow-up branch.
Built via writing-skills TDD: 3 RED-phase pressure scenarios, GREEN
draft, 1 REFACTOR re-run that closed 3 residual gaps. Rationalizations
table covers 7 anti-patterns (capture-after-delete, tag-vs-version,
'be decisive' override, deciduous-skip, git-add-dot, work-on-a-copy,
no-follow-up-task).
Co-authored-by: opencode <noreply@opencode.ai>
The task-note lifecycle (AGENTS.md task-lifecycle skill) requires
an entry per completed task; these were authored at the time of
their respective work but never committed. Closing the loop:
- 2026-06-03-03: chronver release process
- 2026-06-04-01: remove Claude-Code-specific artifacts from
deciduous install
- 2026-06-04-02: build the deciduous decision graph for Suede
from commit history
Plus the plan artifact for the chronver task
(agent-notes/plans/add-suede-release-process-chronver.md) —
plan files are write-only at task end per the skill, so this
is the canonical place for it.
- .opencode/agents/deciduous.md: specialist agent for
deciduous decision-graph operations.
- .opencode/commands/*.md (10 files): slash-command wrappers
for the most common workflows (work, build, document,
decision-graph, decision, recover, serve-ui, sync, sync-graph,
build-test).
- .opencode/plugins/*.ts (3 files): lifecycle hooks —
post-commit-reminder, require-action-node (Edit/Write
guard), version-check.
- .opencode/skills/{archaeology,narratives,pulse}/SKILL.md:
in-repo skills for narrative-driven decision-graph work.
- .opencode/tools/deciduous.ts: thin TS tool wrapper for the
deciduous CLI used by the agents/commands above.
- opencode.json: project-level opencode config (model,
agent list, MCP servers, etc.).
Also includes a stray prettier reformat of .storybook/preview.ts
(the import chain was unchanged; only whitespace/indentation
differed from the version committed in b718ad0).
Excluded: .opencode/.gitignore (workspace-internal config that
self-excludes via its own last line), .opencode/node_modules/,
.opencode/package.json, .opencode/package-lock.json
(gitignored at the repo root by the prior commit).
The .opencode directory is a pnpm-managed workspace (its own
internal .opencode/.gitignore covers node_modules + lockfiles
for the pnpm tooling). Git only reads the root .gitignore for
untracked-detection, so add the corresponding entries here to
keep 'git status' clean for downstream contributors.
The tracked .opencode/ contents (agents, commands, plugins,
skills, tools, and the .opencode/.gitignore itself) are
configuration and ship with the repo.
- .github/workflows/cleanup-decision-graphs.yml: scheduled (and
manual-dispatch) cleanup of stale deciduous event log files.
Companion to the deciduous sync export at docs/graph-data.json.
- .github/workflows/deploy-pages.yml: builds the Storybook
static site (pnpm build-storybook) and deploys storybook-static/
to GitHub Pages. This is what makes the SuedeButton docs
(and any future Storybook) browsable from the public web.
Neither workflow has been exercised against the live repo yet;
add a PR for the deploy workflow to fire on a tag or manual
dispatch only.
Removes the auto-generated example Button/Accordion wrappers and
their Vitest specs that were scaffolded in 341d364
('feat: install bits-ui and stylebase, scaffold UI wrappers') but
never replaced with real components. The matching story files
that referenced them were removed in bbdd827 (broken imports
were blocking Storybook's vite import-analysis).
What's left in src/lib/components/ui/ is the new SuedeButton
wrapper (added in c7c153b) — the only wrapper the project
currently ships. Future wrappers should be added here as
they're built.
The SuedeButton wrapper was applying the same .suede-button styles
to both the <button> and <a> renderings of bits-ui's polymorphic
Button.Root. By design, an anchor acting as a button (e.g. a
'Subscribe' link that navigates to a checkout page) should look
like a button — but a literal <a href> link should look like a
link. Until now the two were visually indistinguishable.
Added a :global(.suede-button[href]) rule that overrides the
button styling when bits-ui renders an anchor (it sets the
href attribute on the underlying element):
background-color: transparent
color: var(--hue-blue-500)
padding-inline: 0
text-decoration: underline
text-decoration-thickness: from-font
text-underline-offset: 0.2em
plus a :hover variant that darkens the color to --hue-blue-600.
The existing :hover and :active rules are now scoped with
:not([href]) so they only apply to the button variant — without
that, their higher-specificity background-color: var(--hue-blue-600)
would have re-painted the link blue on hover, defeating the
transparent background.
The user also renamed the destructured class prop from `klass`
to `className` (React convention) and updated the
'With class override' story to pass `class="u:fs-1"` instead
of `u:fs-3`, so the demo now isolates the inline-style
background override (emerald) without compounding it with a
font-size change.
Verified via Playwright computed-style inspection on all 4 stories:
Primary bg=oklch blue, white text, no underline (button)
Disabled same blue, cursor=not-allowed (button)
As link bg=transparent, blue text, underlined (link!)
With class override bg=oklch emerald, white text, no underline (button, color override)
pnpm check still 0 errors / 0 warnings project-wide.
Two-part fix for the same observable bug: SuedeButton rendered
with browser-default styles in Storybook (gray bg, black text,
0 padding, Arial font) because the stylebase custom properties
(--hue-blue-500, --space-*, --ff-ui, etc.) and utility classes
(u:fs-1) were never present in the Storybook preview iframe.
Part 1 — .storybook/preview.ts:
Import `../src/app.css` so the Storybook preview iframe gets
the same global stylesheet as the SvelteKit app (stylebase +
the :focus-visible rule). Storybook's preview iframe is
independent of the SvelteKit app's +layout.svelte, so
SvelteKit's import chain didn't reach it.
Part 2 — src/lib/components/ui/SuedeButton.svelte:
Wrap every .suede-button selector in :global(...). The class
is set as a prop on the child <Button.Root> component, not
as a class on SuedeButton's own template element. Svelte 5's
per-component CSS scoping only applies to elements rendered
by that component — the .suede-button rule was being pruned
(0 selectors in the bundle) even with the svelte-ignore
comment, because svelte-ignore suppresses the warning but
doesn't prevent the build-time strip.
:global() escapes the scoping. The `suede-button` class name
is unique enough that global leakage is safe.
Verified via Playwright on all 4 SuedeButton stories + style
introspection (computed styles + styleSheets inspection):
Primary bg=oklch(.7188 .15 240) [blue] cursor=pointer
Disabled same blue, cursor=not-allowed
As link renders <a>, cursor=pointer
With class override bg=oklch(.7109 .15 140) [emerald], font-size=20.1px
(u:fs-3 override of u:fs-1), class= 'suede-button u:fs-1 u:fs-3'
All custom properties now resolve at :root, all .suede-button
rules present in the bundle, pnpm check still 0/0 project-wide.
`src/stories/Button.stories.svelte` and `src/stories/Accordion.stories.svelte`
both imported `$lib/components/ui/{Button,Accordion}.svelte` which no longer
exist on this branch (deleted in working tree). The deletion left the
stories with unresolvable imports, and Storybook's vite import-analysis
fails at build time on those files (the same asChild-related issue
surfaced earlier would have hit if the broken imports were repaired).
`src/stories/Page.stories.svelte` and `src/stories/Header.stories.svelte`
are kept: their imports are local (`./Page.svelte`, `./Header.svelte`)
and still resolve.
Verified via Playwright across 6 story URLs (all 4 SuedeButton + the two
remaining examples): 0 console errors, 0 vite import-analysis errors.
Only warnings are Storybook 11 deprecations on Storybook's internal UI
(`ariaLabel` on its own Button/PopoverProvider), not user code.
`pnpm check` is now fully clean (0 errors, 0 warnings) — no more
pre-existing noise from the deleted stories.
@storybook/addon-svelte-csf's Story.svelte, when given both a
`component` in defineMeta and children in the <Story> block, wraps
the children in another instance of that component
(line 148: `<renderer.storyContext.component {...renderer.args} {children} />`).
In our case `component: SuedeButton` + `<SuedeButton>Click me</SuedeButton>`
as Story children produced `<button class="suede-button"><button class="suede-button">Click me</button></button>`
— an accessibility violation (interactive element nested in interactive element)
and semantically wrong markup.
`asChild` on each <Story> routes the children through the
`{@render children()}` branch (no component wrapping) so the story
renders as static markup. Trade-off: args-driven controls don't
update the canvas for `asChild` stories, which is acceptable for
discrete-variant learning demos.
Verified via Playwright against the running Storybook dev server:
Primary / Disabled / With-class-override each render exactly one
`<button data-button-root="true" class="suede-button ...">` at the
root of the story canvas; As link renders as a single
`<a data-button-root="true">`. `button button` and `a button`
nested-selector counts: 0 in every story.
Adds a Suede-wrapped bits-ui Button as a learning scaffold for the
bits-ui + stylebase + Svelte 5 pattern. Distinguishes functionality
(bits-ui's polymorphic Button.Root via ButtonRootProps) from style
(stylebase utility class + scoped <style> block in the same file).
Story at src/stories/SuedeButton.stories.svelte exercises four
variants: Primary, Disabled, As link, With class override.
TypeScript escape hatch: rest is spread via
`{...rest as Record<string, unknown>}` because bits-ui's
ButtonRootProps is a union (AnchorElement | ButtonElement) that
exceeds TypeScript's type complexity budget when re-spread into
another Svelte component. Cast is local to one line; polymorphic
behavior (button vs anchor via href) still works at runtime.
CSS pruner workaround: `<!-- svelte-ignore css_unused_selector -->`
on the <style> block, because the class name is built from a
template literal in the class attribute and is therefore invisible
to Svelte's static class-extraction pass.
Existing example stories (Button, Accordion, Header, Page) are
left untouched per option C; pre-existing pnpm check errors
(missing /components/ui/Button.svelte and Accordion.svelte
references) are out of scope for this change.
- .deciduous/ : local decision-graph database
- docs/ : generated web viewer export (regenerate via 'deciduous sync')
- CLAUDE.md : explicit Claude-Code instruction file, not part of this project
- .claude/ : explicit Claude-Code config directory, not part of this project
The last two are defensive: if 'deciduous install' re-runs, the Claude
artifacts will be re-created locally but stay untracked.
Cross-agent view of the deciduous decision-graph tool. Source content was
copied from CLAUDE.md's managed block (which we will not commit) and stripped
of tool-specific syntax:
- Removed slash command table (Claude Code only)
- Removed skills table (Claude Code only)
- Removed inline slash-command references
- Replaced the .claude/commands/decision.md git-staging example with
project-relevant paths
A header note at the top of the section explains that this is the
tool-agnostic view; tool-specific commands and skills live in
.opencode/commands/ and .opencode/skills/ (loaded at runtime by OpenCode,
not duplicated here).
- pnpm add @taurean/stylebase bits-ui
- src/app.css imports stylebase and provides global focus ring
- +layout.svelte wires app.css
- src/lib/components/ui/Button.svelte and Accordion.svelte are
Svelte 5 + bits-ui wrappers (script-only agent territory)
- Storybook stories for both wrappers
- vitest-browser-svelte smoke tests for both wrappers
- .gitignore: worker-configuration.d.ts (wrangler build artifact)
Wrapper styling is intentionally minimal — human territory per
AGENTS.md. The wrappers render with stylebase defaults; the
hybrid strategy (global data-attribute CSS + per-component
overrides) is the next step.
Refs agent-notes/2026-06-03-02-install-bits-ui-stylebase.md