Files
tiennm99 783dd37251 docs(plans): record the JavaScript migration, parity, and review
Adds the migration plan and its phase files, the parity report, and the code
review.

Annotates the two records this work supersedes rather than rewriting them: the
2026-09-18 language-choice research, whose first recommendation was to keep the
engine in Go and was overridden the same day, and the 2026-08-18 plan that
produced that engine. Both bodies are left as written, since erasing them would
destroy the reasoning a future reader needs.

Six success criteria stay unticked with the reason inline: they need a push, a
GitHub token, or a Codex run to verify.
2026-09-18 16:24:56 +07:00

3.1 KiB
Raw Permalink Blame History

Migrate Newsletter Scripts from Node.js to Go

Status: COMPLETED (2026-08-18) — all 3 phases done; parity report in plans/reports/parity-260818-newsletter-go-migration-report.md Superseded: 2026-09-18 — the Go engine this plan delivered was ported back to JavaScript by plans/260918-0647-migrate-newsletter-engine-to-javascript/. Body left unchanged; it records the reasoning as it stood. Created: 2026-08-18 Scope: Port the 8-file shared engine in scripts/newsletter/ (~740 LoC JS, stdlib-only) to a single Go package with 6 subcommands, verify behavior parity, cut over all skill/doc call sites, delete the JS.

Design Decisions

  • One package main with subcommands at scripts/newsletter/, not 6 separate binaries. Subcommand names mirror the old script names (add-url, find-newsletter-number, list-existing-tags, detect-image-source, find-substack-post, fetch-via-defuddle) so skills stay greppable.
  • go.mod at repo root (module github.com/tiennm99/miti99). Hugo does not use Go modules here (theme vendored in themes/, no [module] config), so this is inert to the site build. Gives the simplest documented invocation: go run ./scripts/newsletter <cmd> [args] from repo root. (Alternative considered: module inside scripts/newsletter/ + go run -C scripts/newsletter . <cmd> — works, verified, but clunkier in 8 documented call sites.)
  • go run, no committed binary. Build cache makes reruns fast; no stale-binary risk across the 3 AI tools.
  • go:embed for config/substack-publications.json. go run recompiles on change, so editing the JSON still takes effect; the file stays the editable source of truth. Solves the __dirname problem (os.Executable() under go run points at the build cache, not the source dir).
  • Repo paths resolve from CWD (content/post). The documented contract is already "invoked from the repo root"; missing dir degrades gracefully exactly like the JS (0 / no duplicates).

Phases

Phase File Depends on
1. Port to Go phase-01-port-to-go.md —
2. Parity verification phase-02-parity-verification.md 1
3. Cutover, docs, cleanup phase-03-cutover-and-docs.md 2

JS and Go coexist during phases 1–2 (Go toolchain ignores .js files in the package dir); JS is deleted only after phase 2 passes.

Acceptance Criteria

  • All 6 subcommands match the Node output on the phase-02 verification matrix (byte-identical JSON, or drift explicitly documented as acceptable).
  • One real mt-add-url skill flow works end-to-end on the Go engine.
  • grep -rn "node scripts/newsletter" across the repo returns nothing (skills, AGENTS.md, README.md, docs/).
  • All .js files under scripts/newsletter/ deleted; config/substack-publications.json retained.
  • .claude/settings.json allows Bash(go *).

Resolved Decisions (user, 2026-08-18)

  1. Drop the Bash(node *) allow rule at cutover (phase 3).
  2. Module path: github.com/tiennm99/miti99 confirmed.