feat(modules): editor modules declared in YAML; News module replaces the List module #155
No reviewers
Labels
No labels
bug
enhancement
needs-triage
ready-for-agent
ready-for-human
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Cloonar/deckle!155
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "afk/153"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #153
What
editor/modules/<name>.yaml, new packageinternal/editormodule):sidecardirscan rules.page,view,media,edit,api,internal.pagetree.AnnotatesetscontainerFor,managedByandhiddenon/api/treenodes.hideChildPagesnow hides only managed children, and hides nothing when no loaded module manages them.GET /api/moduleslists the loaded modules and their load errors.GET /api/module/entriesdoes search, sort, filters and paging on the server. Datetimes go out as RFC3339 through one shared helper (content.DateRFC3339), native TOML datetimes included.returnvalidation and the error banner know them. Nothing judges a module id before the module list has loaded.PageEditorChrome.harness addfills gaps: re-running it on an installed feature writes only the missing bundle files and never touches an existing path. The receipt records just the written files, and its version becomes the bundle's current one. It reportsadded;--jsonstaysformatVersion: 1.editor/modules/news.yaml; manifest version 2.scaffold/site/AGENTS.mdand the README cover all of the above.Verification
make test: web 65 files / 1804 tests and all Go packages pass.go vet ./...andnpx tsc --noEmitare clean.harness serve, on a site with news, two News pages and a git remote, I went through every acceptance criterion and all passed:editor/modules/news.yamland reportsaddedwith only that file and version 2.already-installed.harness remove newsdeletes the module file.Notes
search: []oredit: []; a page type, filter or tab listed twice;columnson a cards view orcardon a list view; a filter field that isselectin one listed type andmultiselectin another.🤖 Generated with Claude Code
Validation: FAIL (one blocker)
Signal relied on: CI
ci / build-and-testis green (not re-run). The title is Conventional Commits,Closes #153is present, and the head already containsmain(no conflict). The diff was reviewed against #153's spec.Blocker
After Undo, Discard… or a title-only Rename…, the entry editor's Properties form shows stale values, and the next Save writes them back.
web/src/components/EntryEditor.tsx:533-538, withweb/src/components/PageSettings.tsx:75andweb/src/stores/pageEditor.ts:249-290.createResource(() => props.page, fetchPageSettings)only re-runs when the page's identity changes, and that identity survives tree refetches.mutate/refetchinpageEditor) but not the settings.EntryEditor.tsx:285-301), so the next save silently reverts the Undo, the Discard or the new title.Concerns (non-blocking)
web/src/stores/modules.ts:132), while/api/tree's module annotations (hidden,containerFor,managedBy) are recomputed on every 2 s poll.harness add news, or writing a module file, while the editor is open hides the news items in the tree, but the rail gets no News entry until a reload. "Manage in news" then leads to route repair back to/page/….internal/content/meta.go:87,DateRFC3339).date = 2026-12-24astoml.LocalDate, and a datetime without an offset astoml.LocalDateTime.cast.ToTimeErejects both.values.dateand sort last underdate desc. Offset datetimes work.Node.Datealready had this gap before this PR, but this helper is now the single place to fix it: handleinterface{ AsTime(*time.Location) time.Time }first, as Hugo'shtime.ToTimeInDefaultLocationEdoes.web/src/components/ModuleScreen.tsx:295-319). After the 300 ms debounce it copies the trimmedqback into the input, so typing "summer ", pausing, then "party" gives "summerparty".EntryEditor.tsx:285-287). Save & close switches to Properties on failure, but Save doesn't, so the inline errors land on the hidden panel.titlepanics when a listed page type declarestitleasnumberordatetime(internal/server/modules.go:417-426).resolveSortpicks the kind from the declared type, butkey()always returns a string fortitle, socomparefails a type assertion.FieldTitlefirst.README.md:1397-1399). It says an olderinstalledVersion"is brought up to date by re-runningharness add".editor/modules/news.yaml.addthen reportsalready-installedand the version stays at 1.ModuleScreen.tsx:256-283);add's partial-write recording (internal/addcmd/add.go:474);Minor
internal/editormodule/load.go:474-478: cardtext: titleis rejected unless the type declarestitle. That matches the spec's wording, butdoc.gosays "Built-ins count as title=text", and the error message contradicts itself. Align the doc and the message, or allow it.Checked and correct
hideChildPages.harness addgap filling: Lstat and O_EXCL safety, receipt merge,already-installed.returnhandling before the module list loads.PagePanerefactor: no regressions found.[autoland] verdict: pass
Validation: CONCERNS (non-blocking) — approved
Signal relied on: CI
ci / build-and-testis green on head2b3600e(run 140: web build and tests,go vet,go test,go build), so it was not re-run. The title is Conventional Commits,Closes #153is present, and the head already containsmain(3df59bd), so there is no conflict.The full diff was reviewed in the earlier FAIL pass. This pass reviewed the fix commit
2b3600eagainst each finding from that pass.Earlier findings: all addressed
editor.reloads()(restores plus sync reloads) and on a same-path rename counter. This is the same keyed pattern EditPane already uses.DateRFC3339checks forAsTimebefore falling back to cast.FieldTitleis checked first.text: title): the rule,doc.go, the error message, AGENTS.md and the README now agree.Concern (non-blocking)
Undo, then "Save & continue" in the prompt, reverts the edits the author chose to save.
web/src/components/EntryEditor.tsx(afterUnsavedPromptandundoAction).internal/server/git.gohandlePageUndo). Saving takes a new snapshot, so the Undo that follows reverts exactly that save, not the earlier change the author wanted undone.