Commit Graph
533 Commits
Author SHA1 Message Date
tiennm99 e21c12eefe chore(newsletter): delete the Go engine
Parity is proven and every call site now invokes the JavaScript engine, so the
Go implementation has no callers. It remains recoverable from history.

The newsletter engine was Go's only consumer here: the Hugo theme is vendored
under themes/ and the site configuration declares no module block, so nothing
else needs a toolchain. Dropping go.mod also disposes of a latent defect, since
it declared a newer Go version than either build environment pinned and only
worked because the toolchain was fetched on demand.

The Go patterns in .gitignore go with it.
2026-09-18 16:24:42 +07:00
tiennm99 baab3d443a refactor(skills): invoke the Node engine and centralise the command reference
Switches every call site to `node scripts/newsletter` and, in the same pass,
fixes three structural problems in the skill layer.

The seven subcommands were spelled out in five files; they are now enumerated
once in docs/newsletter/engine-commands.md, and every other mention is a link
except where a skill inlines the one or two commands it actually invokes. The
shared post mechanics move out of mt-add-url's directory into docs/newsletter/,
so no skill owns another skill's documentation and both runtimes reach it by a
repository-relative path. The Codex adapters become symlinks to their canonical
counterparts, which removes the parallel frontmatter that could drift.

Two skills are renamed for a uniform mt-<verb>-<object> scheme: mt-add-post
becomes mt-add-article, since it adds an article to a post, and mt-webfetch
becomes mt-fetch-url. The other four already conformed. Note that $mt-add-post
and mt-webfetch no longer resolve; no alias directories are left behind, because
two names for one skill is the duplication this change removes.

Trigger wording in the frontmatter descriptions is left alone apart from the
renamed tokens and the corrected fetch-tier summary: those strings are how the
runtimes decide whether to invoke a skill.

Setup documentation now states the npm ci prerequisite. The engine has
dependencies, so unlike its predecessor it does not run on a bare clone.
2026-09-18 16:24:34 +07:00
tiennm99 682d5239b8 test(newsletter): add a golden-output parity suite
Captures the Go engine's stdout for 26 deterministic cases, commits those
outputs as fixtures, and asserts the JavaScript engine reproduces them through
the real CLI surface, exit codes included. This is both the migration's proof of
correctness and the regression net the engine never had.

Every fixture was generated from the Go engine rather than written by hand, and
reviewed before commit so no existing bug became a permanent contract. Each
behaviour that a JavaScript-idiomatic rewrite would silently break has a case
that goes red when the naive implementation is reintroduced; verified by
mutating the engine and re-running.

Content-scanning commands are pointed at a fixture tree through the subprocess
working directory. Both engines already resolve content/post from the process
CWD, so neither needed a test-only configuration knob, and the suite is proven
isolated from the real content by renaming it away and re-running.

Cases that depend on live upstreams are opt-in behind NEWSLETTER_NET=1: a
publication's feed window moves, and a suite that goes red on someone else's
outage teaches people to ignore red. The deterministic tier reaches the network
only through .invalid hosts, which never resolve, so it runs offline in about
two seconds.

The golden files are compared byte for byte, so scripts/newsletter is pinned to
LF; the repository otherwise checks out CRLF, which would break every comparison
on a fresh clone.
2026-09-18 16:24:16 +07:00
tiennm99 64c7b76b4e feat(newsletter): port the engine to JavaScript
Translates the seven-subcommand engine to Node ESM, one module per former Go
file, invoked as `node scripts/newsletter <command>` from the repo root. The Go
implementation stays in place for now so parity can be measured against it.

Hand-rolled HTML and XML regexes give way to cheerio, which removes the manual
string surgery in caption extraction and covers RSS and sitemap XML through
xmlMode without a second parser. fetch-via-defuddle gains a local extraction
stage ahead of the defuddle.md proxy; the proxy stays, because fetching from a
third IP is the whole point when this machine's IP is the blocked one. Both
stages now emit the same YAML frontmatter plus body, and an extraction that
looks like a bot challenge counts as a local failure so the proxy still runs.

Behaviour is preserved where it is load-bearing rather than where it is merely
idiomatic: query strings are rebuilt by string surgery so surviving parameters
keep their original order and encoding, duplicate detection stays an index loop
with byte-offset boundary checks so a prefix of a stored URL is not a false
match, empty optional fields are omitted rather than emitted as "", a deep-crawl
miss reports cutoff as null rather than dropping the key, bullet filtering counts
code points, tag counts keep their six-column alignment, and a malformed percent
sequence falls back to the raw substring.

The printer lives in its own module so a command module never imports the
dispatcher: index.js runs main() at module scope, so that cycle would execute
the CLI as a side effect of any import. Missing dependencies report one
actionable line instead of a module-resolution stack trace, and a reader that
closes early exits quietly instead of raising EPIPE.
2026-09-18 16:23:58 +07:00
tiennm99 fdbbc5ba42 refactor(scripts): unify module extensions on .js
The root package.json already declares "type": "module", so a .js file here is
ESM and the .mjs suffix only restates what the manifest states. Renames the three
GitHub Actions scripts and follows every reference, including the six JSDoc
import("...") type annotations that would otherwise degrade to any without
throwing.
2026-09-18 16:23:36 +07:00
tiennm99 d41176f149 feat(projects): drop in-development namespaces from the demo list 2026-09-18 13:21:41 +07:00
tiennm99 26e2ff3721 refactor(projects): rename the demo list identifiers to match the page 2026-09-18 13:18:37 +07:00
tiennm99 2b6ba57f47 docs(projects): reword section headings and intros 2026-09-18 13:13:13 +07:00
tiennm99 3c1dc203b9 docs(projects): rewrite projects page intros in a lighter voice 2026-09-18 13:04:36 +07:00
github-actions[bot] 0ca22b7025 chore(projects): refresh projects list 2026-09-18 12:58:43 +07:00
tiennm99 a0de52c877 refactor(projects): build the projects list on the octokit SDK
Replace hand-rolled REST paging, GraphQL cursor loops and header plumbing with
octokit, which also brings request retry and rate-limit backoff. Introduces the
repo's first package.json, lockfile and ESLint flat config; the Hugo site build
itself still needs no Node step.

Output verified against the previous implementation: identical counts and rows
apart from live star drift on four upstream repos.
2026-09-18 12:28:11 +07:00
tiennm99 f0b6b4904d docs(plans): record script language evaluation for repo scripts 2026-09-18 12:24:44 +07:00
tiennm99 a9bb2f0621 feat(projects): split projects page into starred, linked and contributed lists
Resolve owned namespaces from org memberships with the admin role instead of
assuming a fixed owner list, so repos under orgs I own are included.

- starred: owned public non-fork repos with at least one star, by stars then
  most recent push
- linked: owned public non-fork repos exposing a homepage or Pages URL, by most
  recent push
- contributed: public repos owned by others, by my merged PR count then most
  recent push

Private repos are excluded everywhere; forks are excluded from the owned lists
because their homepage belongs to upstream. Split the generator into API access
and rendering modules.
2026-09-18 12:24:44 +07:00
github-actions[bot] aad39d9369 chore(projects): refresh projects list 2026-09-18 02:56:03 +07:00
github-actions[bot] c76f2fc8e9 chore(projects): refresh projects list 2026-09-17 02:47:26 +07:00
tiennm99 f759f7a8ba feat(newsletter): report post entry tally after each URL add 2026-09-11 17:33:46 +07:00
tiennm99 edff23f0e3 docs(newsletter): add newsletter 132 2026-09-11 17:33:46 +07:00
tiennm99 57ff9fadf3 docs(newsletter): add newsletter 131
Drop the key-points bullet list from newsletter article entries; summaries are prose paragraphs only.
2026-09-11 09:45:02 +07:00
tiennm99 d9c605d69d docs(newsletter): remove two Redis leaderboard entries from newsletter 130 2026-09-10 11:20:41 +07:00
tiennm99 bae7b01e0a docs(newsletter): add newsletter 130 2026-09-10 10:37:39 +07:00
github-actions[bot] 59c5675491 chore(projects): refresh projects list 2026-09-10 02:32:48 +07:00
tiennm99 8884014fc8 docs(skills): document fetch fallback chain and pinned target post
Add a reader-proxy tier after defuddle, stop skipping URLs that only fail a
plain classifier fetch, let a session pin an earlier draft as the target post,
and tighten Substack image candidate handling (dedupe, stable numbering,
reuse a resolved source post across a batch).
2026-09-09 09:25:35 +07:00
tiennm99 1c986dd371 docs(newsletter): add newsletter 129 2026-09-09 09:19:25 +07:00
tiennm99 f8418b1dc3 chore: remove checked-in claude settings 2026-09-07 09:26:55 +07:00
github-actions[bot] aa03f345e6 chore(projects): refresh projects list 2026-09-01 04:41:05 +07:00
tiennm99 c121fbf91b chore: follow the miti99 -> blog repo rename 2026-08-31 17:30:27 +07:00
tiennm99 d7ea504cb8 docs(post): point taskbus source link at the jvm-labs lab 2026-08-31 16:09:58 +07:00
tiennm99 d1b9e1de35 docs(referral): rebrand ClaudeKit to AgentKit
Update the referral link to https://agentkit.best/?ref=BWA910UK and expand
the description with current kits, pricing, and the desktop app, noting the
former ClaudeKit name.
2026-08-28 11:14:35 +07:00
tiennm99 e602d05831 docs(newsletter): add newsletter 128 2026-08-28 10:21:45 +07:00
github-actions[bot] b625066d2d chore(projects): refresh projects list 2026-08-28 08:12:06 +07:00
github-actions[bot] 22291c641f chore(projects): refresh projects list 2026-08-26 00:21:32 +07:00
github-actions[bot] 54ffc0aee9 chore(projects): refresh projects list 2026-08-19 00:16:55 +07:00
tiennm99 c35a14f9bb fix(scripts): dedup URLs stored in markdown autolink form
The duplicate-check boundary set had '<' but not '>', so a URL stored
as <https://…> (autolink, used by older posts) was never detected as a
duplicate. Inherited from the JS engine; found while validating the Go
port against 2020-era posts.
2026-08-18 21:43:57 +07:00
tiennm99 e8451d8c24 refactor(scripts): migrate newsletter engine from Node to Go
One Go binary with a subcommand per former script, invoked as
'go run ./scripts/newsletter <command>' from repo root. Stdlib only;
publications config embedded via go:embed (go run recompiles on edit).
Behavior parity verified side-by-side before deleting the JS —
see plans/reports/parity-260818-newsletter-go-migration-report.md.

Permissions: allow 'Bash(go *)', drop 'Bash(node *)' and the redundant
'Write(content)' rule (Edit rules cover all file-editing tools).
2026-08-18 21:43:57 +07:00
github-actions[bot] 211863b982 chore(projects): refresh projects list 2026-08-14 00:47:31 +07:00
github-actions[bot] 49ff1d20bd chore(projects): refresh projects list 2026-08-12 00:46:41 +07:00
github-actions[bot] cce0cd7fa4 chore(projects): refresh projects list 2026-08-11 00:41:49 +07:00
github-actions[bot] 3576db0d32 chore(projects): refresh projects list 2026-08-09 00:19:32 +07:00
github-actions[bot] 2ca1283496 chore(projects): refresh projects list 2026-08-08 00:38:43 +07:00
github-actions[bot] 0aee081cf9 chore(projects): refresh projects list 2026-08-06 01:14:17 +07:00
tiennm99 68157be529 docs(referral): add OrcaRouter offers 2026-08-05 09:28:17 +07:00
github-actions[bot] ae07e3d450 chore(projects): refresh projects list 2026-08-05 01:21:14 +07:00
tiennm99 451c9d4a6b chore(claude): drop plugin toggles and use auto permission mode 2026-07-30 23:20:01 +07:00
tiennm99 90405b79c5 docs(blog): update 2026-07-29 post 2026-07-29 19:14:25 +07:00
github-actions[bot] a2d67b9095 chore(projects): refresh projects list 2026-07-28 01:17:10 +07:00
github-actions[bot] b0312aec9a chore(projects): refresh projects list 2026-07-27 00:52:30 +07:00
github-actions[bot] 19e6511a0a chore(projects): refresh projects list 2026-07-26 00:48:10 +07:00
tiennm99 cc02f0b2b3 chore: remove dependabot version-update config 2026-07-25 14:15:04 +07:00
github-actions[bot] 61a7d9a1bb chore(projects): refresh projects list 2026-07-25 01:09:30 +07:00
tiennm99 2d0b0afe25 docs(newsletter): add newsletter 126 2026-07-23 21:16:10 +07:00