Skip to content

Commit c7d5394

Browse files
committed
feat: prepare tiddlynmem npm CLI
1 parent 3324c34 commit c7d5394

25 files changed

Lines changed: 3195 additions & 435 deletions

.github/workflows/ci.yml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
name: CI
2+
3+
on:
4+
pull_request:
5+
push:
6+
branches:
7+
- main
8+
9+
permissions:
10+
contents: read
11+
12+
jobs:
13+
test:
14+
runs-on: ubuntu-latest
15+
timeout-minutes: 15
16+
steps:
17+
- name: Check out repository
18+
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0
19+
- name: Set up Node.js
20+
uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6.5.0
21+
with:
22+
node-version: 24.16.0
23+
- name: Install dependencies
24+
run: npm ci
25+
- name: Type-check
26+
run: npm run typecheck
27+
- name: Test
28+
run: npm test
29+
- name: Build package
30+
run: npm run build
31+
- name: Check generated CLI
32+
run: npm run check:package
33+
- name: Inspect npm package
34+
run: npm pack --dry-run --ignore-scripts

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
dist/
2+
.tiddlynmem/
3+
*.tgz
4+
.DS_Store
5+
coverage/
16
node_modules/
7+
npm-debug.log*
28
previews/
39
reports/

AGENTS.md

Lines changed: 83 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ This file is the development and contribution contract for AI coding agents work
44

55
## Project purpose
66

7-
`tiddlywiki-nmem-importer` imports tiddlers from one Node.js TiddlyWiki into Nowledge Mem. It boots the real Wiki with the npm `tiddlywiki` package, renders WikiText to HTML, converts that HTML to GitHub Flavored Markdown, and upserts each result as a Memory through the installed `nmem` CLI.
7+
`tiddlynmem` imports tiddlers from one Node.js TiddlyWiki into Nowledge Mem. It boots the real Wiki with the npm `tiddlywiki` package, renders WikiText to HTML, converts that HTML to GitHub Flavored Markdown, and upserts each result through the selected Nowledge Mem REST API.
88

99
`README.md` is the user-facing source of truth for installation and usage. Keep it synchronized whenever CLI behavior changes.
1010

@@ -13,19 +13,27 @@ This file is the development and contribution contract for AI coding agents work
1313
- The current working directory is the only Wiki input.
1414
- The command must be run from a directory containing a readable `tiddlywiki.info`.
1515
- Do not restore `--wiki`, hardcoded Wiki names, parent-directory scans, or sibling-directory scans.
16-
- Default execution is a dry-run. Only `--apply` may write to Nowledge Mem.
17-
- Never modify, move, or delete source tiddlers.
18-
- Use the installed current `nmem`; never hardcode a required nmem version.
19-
- Require the `nmem` CLI and service to report matching versions before writing.
20-
- Reject remote Nowledge Mem services by default; require `--allow-remote` for an explicit override.
21-
- Preserve deterministic Memory IDs based on source Wiki name and tiddler title so reruns remain idempotent.
16+
- The CLI uses Terraform-style `plan` and `apply` commands. Omitting the command defaults to `plan`.
17+
- Only the `apply` command may write to Nowledge Mem or modify source tiddlers. After a specific Memory write succeeds, append `$:/NowledgeMem` to that source tiddler without changing its text or duplicating the tag.
18+
- Treat `$:/NowledgeMem` as an imported marker and classify matching source tiddlers as `skipped:imported` before conversion or Memory API writes.
19+
- When `--tag <tag>` is present, filter exact matching tiddlers inside the TiddlyWiki worker before WikiText rendering. Only matching records enter scanning, reporting, classification, conversion, preview, or import. Normal safety classification still applies after this input filter.
20+
- Never tag plan-only, skipped, conversion-failed, render-failed, or Memory-API-failed tiddlers. Never move or delete source tiddlers.
21+
- Do not require the `nmem` CLI at runtime. Both `plan` and `apply` must work without it.
22+
- Resolve the REST API URL in this order: `--api-url`, `NMEM_API_URL`, then `http://127.0.0.1:14242`.
23+
- Check the selected service's `/health` endpoint directly before writing.
24+
- Accept any explicitly selected HTTP or HTTPS endpoint without an additional confirmation flag.
25+
- Read REST credentials only from `NMEM_API_KEY`, send them as Bearer authentication, never pass them to TiddlyWiki workers, and never log them.
26+
- Never follow HTTP redirects for health checks or Memory writes. Users must configure the final Nowledge Mem API URL directly.
27+
- Preserve deterministic Memory IDs based on a collision-resistant Wiki identity and tiddler title so reruns remain idempotent. The default identity combines the Wiki directory name with a resolved-path fingerprint; `--wiki-id` provides an explicit portable override.
28+
- Preserve Unicode in source-Wiki labels and use a deterministic fallback when the normalized Wiki name contains no letters or numbers.
2229
- Preserve the default sensitive-title filter unless a deliberate behavior change includes tests and README updates.
2330

2431
## Language and runtime
2532

2633
- TypeScript everywhere.
2734
- Do not add `.js` or `.mjs` source files.
2835
- Run TypeScript directly with [Nub](https://github.com/nubjs/nub); do not use Bun.
36+
- Keep `@nubjs/nub` as a development dependency for source execution and package builds.
2937
- Keep `strict` TypeScript enabled.
3038
- Use ESM imports with explicit `.ts` extensions, matching the existing codebase.
3139
- Prefer small functions and declarative data transformations over unnecessary classes.
@@ -36,54 +44,95 @@ This file is the development and contribution contract for AI coding agents work
3644
- `src/cli.ts`: CLI orchestration, current-directory validation, reporting, previews, and concurrent imports.
3745
- `src/core.ts`: tiddler classification, metadata, stable IDs, HTML-to-Markdown conversion, and media warnings.
3846
- `src/tiddlywiki-worker.ts`: boots TiddlyWiki and sends records over IPC.
39-
- `src/tiddlywiki.ts`: owns worker lifecycle, IPC validation, and diagnostics.
40-
- `src/nmem.ts`: validates the active nmem service and invokes `nmem memories add`.
47+
- `src/tiddlywiki-tag-worker.ts`: boots TiddlyWiki after successful imports and persists the source marker tag.
48+
- `src/tiddlywiki.ts`: owns read and tag worker lifecycles, IPC validation, and diagnostics.
49+
- `src/nmem.ts`: resolves and validates the selected service URL, checks REST health, and posts native Memory requests.
4150
- `src/options.ts`: parses supported command-line options.
51+
- `scripts/build-package.ts`: compiles the npm package and changes only the generated CLI shebang from Nub to Node.
4252
- `test/`: Node test runner coverage and a minimal TiddlyWiki fixture.
53+
- `dist/`: generated npm package output; ignored, never edited, and never committed.
4354
- `reports/`, `previews/`: generated output; both are ignored and must not be committed.
4455

56+
## npm CLI contract
57+
58+
- The npm package name is `tiddlynmem`.
59+
- The executable name is `tiddlynmem`, mapped to generated `dist/cli.js` through `package.json#bin`.
60+
- Source and build scripts remain TypeScript and run directly with Nub during development.
61+
- `npm prepack` must type-check, test, and generate `dist/`; the generated JavaScript is package output, not source.
62+
- `npm prepack` must also start the generated CLI under plain Node through `npm run check:package`.
63+
- Do not hand-edit or commit generated `.js` files, and do not add a handwritten `.js` or `.mjs` launcher.
64+
- The published package must not depend on Nub at runtime; plain Node executes the generated CLI.
65+
- The default report belongs to the current Wiki and is written under `.tiddlynmem/reports/`.
66+
- Every report entry must include the complete source tiddler tag list for ready, skipped, and failed states. Do not include tiddler bodies in reports.
67+
- Never include raw Nowledge Mem API response bodies in errors or reports.
68+
- Treat a Memory write as successful only when the native response contains `memory.id` matching the requested deterministic ID. Malformed or mismatched success responses must not trigger source tagging.
69+
- Keep npm package metadata, CLI help, README commands, and tests synchronized with the package and executable names.
70+
- Keep `plan` as the default command and `apply` as the only mutating command. Do not restore the legacy `--apply` flag.
71+
- Keep `--tag` as a single exact, case-sensitive input filter unless a deliberate CLI contract change updates tests and documentation.
72+
- Keep `--wiki-id` as the portable Wiki identity override, and expose its resolved value in report options and native Memory metadata.
73+
- Keep `-V` and `--version` available outside a TiddlyWiki directory, with the value read from the installed `package.json`.
74+
- Preserve the historical `tiddlywiki-nmem-importer` string used by `stableMemoryId`; it is an ID compatibility namespace, not the current product name. Changing it would duplicate previously imported Memories.
75+
4576
## Architecture constraints
4677

4778
Keep TiddlyWiki execution in the child worker. TiddlyWiki boot diagnostics must not be mixed with structured tiddler records; records travel through IPC and stderr is collected separately.
4879

80+
During `apply`, scan and classify the Wiki before checking Nowledge Mem health. Skip the health check when no tiddlers are ready. If preflight fails, send no Memory requests, mark ready report entries as `failed:preflight`, write the report, and exit unsuccessfully.
81+
82+
Source tagging is a post-import phase. Collect only titles whose Memory REST request succeeded, send titles over IPC instead of command-line arguments, and persist tags serially through TiddlyWiki's file serializer. On later scans, classify an existing `$:/NowledgeMem` tag as `imported` and skip it; the tag worker still treats an existing marker as success to remain race-safe. Only rewrite regular `application/x-tiddler` files or independently editable files with an existing `.meta` sidecar; fail safely for shared or unsupported formats. A tag failure must be visible in the report and produce an unsuccessful exit without misreporting the already completed Memory write.
83+
4984
Conversion behavior is type-dependent:
5085

5186
- `text/vnd.tiddlywiki` and the empty/default type are rendered by TiddlyWiki before Turndown conversion.
52-
- `text/markdown` and `text/plain` use their source text directly.
53-
- Unsupported binary types, system tiddlers, drafts, empty tiddlers, and sensitive-title tiddlers are classified and reported instead of imported.
87+
- `text/markdown` retains its source Markdown after media safety processing; `text/plain` uses its source text directly.
88+
- Unsupported binary types, system tiddlers, drafts, previously imported tiddlers, empty tiddlers, and sensitive-title tiddlers are classified and reported instead of imported.
5489

55-
Memory content includes TiddlyWiki source metadata in front matter. Keep source Wiki, title, tags, created time, and modified time available unless a documented migration replaces them.
90+
Memory content is the converted Markdown body without importer front matter. Sanitize embedded data-URI images in inline Markdown images, full/collapsed/shortcut reference images, and raw HTML images with quoted or unquoted `src` attributes. Report preserved local image references as warnings. Map every source tag to a native Memory label, and preserve Wiki identity, source Wiki, original title, exact tags, created time, and modified time in the native Memory `metadata` object. Use `source: "tiddlywiki"` and `source_app: "tiddlynmem"`. Nowledge Mem owns its lifecycle `created_at` and `updated_at`; do not misuse event dates as source-file timestamps.
5691

57-
The nmem process must receive Memory content through stdin. Do not place note content in command-line arguments or logs.
92+
Validate native Memory request limits during `plan`: title length is at most 200 Unicode characters and content length is at most 32,768 Unicode characters. Report a validation failure instead of truncating, splitting, or sending an invalid request. Retry only transient network failures, request timeouts, HTTP 408, HTTP 429, and HTTP 5xx responses. Bound workers and HTTP calls with timeouts.
93+
94+
Send Memory content only in the REST request body. Do not place note content or API credentials in command-line arguments or logs.
5895

5996
## Setup
6097

6198
```bash
62-
mise install
99+
mise trust && mise install
63100
npm ci
64101
```
65102

66-
The repository pins its Node, Nub, npm package, and TypeScript toolchain through `mise.toml`, `package.json`, and `package-lock.json`. The nmem version is intentionally not pinned in source code.
103+
The repository pins its Node, Nub, npm package, and TypeScript toolchain through `mise.toml`, `package.json`, and `package-lock.json`. Nowledge Mem is an external REST service and its CLI is not a project dependency.
67104

68105
## Required validation
69106

70-
Run both commands after every source or test change:
107+
Run these commands after every source or test change:
71108

72109
```bash
73-
mise exec -- nub run typecheck
74-
mise exec -- nub run test
110+
npm run typecheck
111+
npm test
112+
npm run build
113+
npm run check:package
75114
```
76115

77-
For CLI behavior involving Wiki discovery or rendering, also run a dry-run from `test/fixtures/wiki` or another disposable Wiki root. Never use `--apply` in tests or validation unless the user explicitly authorizes writes to Nowledge Mem.
116+
For CLI behavior involving Wiki discovery or rendering, also run `plan` from `test/fixtures/wiki` or another disposable Wiki root. Never run `apply` against the user's real Nowledge Mem in tests or validation unless the user explicitly authorizes those writes; apply tests must use a disposable fake API.
78117

79118
Tests must cover behavior, not implementation details. Add or update tests when changing:
80119

81120
- CLI options and defaults
121+
- exact tag input filtering with and without `--tag`
122+
- tag filtering before WikiText rendering
82123
- tiddler classification
83124
- WikiText/HTML/Markdown conversion
84125
- deterministic IDs or metadata
85-
- nmem compatibility and command arguments
126+
- default and explicit portable Wiki identities, including same-named Wiki directories
127+
- API URL precedence, direct service health checks, remote endpoint support, and REST request fields
128+
- native title/content limits, transient retry classification, and request timeouts
129+
- Markdown data-URI omission and local-media warnings
86130
- worker IPC and multiline content
131+
- worker credential isolation and apply preflight reporting
132+
- post-import source tagging, idempotence, and source-text preservation
133+
- npm package name, executable mapping, and packed CLI startup
134+
135+
Every GitHub Actions `uses:` reference must be pinned to a full commit SHA with the readable action version in an inline comment.
87136

88137
## Contribution workflow
89138

@@ -95,11 +144,25 @@ Tests must cover behavior, not implementation details. Add or update tests when
95144
6. Review the final diff for generated files, note content, credentials, and accidental dependency changes.
96145
7. Do not commit, push, publish, or create a pull request unless the user explicitly asks.
97146

147+
## Release workflow
148+
149+
- Use Semantic Versioning. For npm version `X.Y.Z`, use `vX.Y.Z` as the corresponding Git tag and GitHub Release name.
150+
- Update `CHANGELOG.md` before a release and keep an empty `Unreleased` section above the released version.
151+
- Run `npm ci`, `npm run typecheck`, `npm test`, `npm run build`, `npm run check:package`, and `npm publish --dry-run` from a clean checkout of the release commit.
152+
- The first npm publication must be performed interactively by an npm maintainer with account-level 2FA because npm requires a package to exist before a Trusted Publisher can be configured.
153+
- After the first publication, configure npm Trusted Publishing for a pinned GitHub Actions workflow and use OIDC instead of storing a long-lived npm publish token.
154+
- While the GitHub repository is private, npm Trusted Publishing remains available but npm provenance cannot be generated.
155+
- Never publish, create a tag, create a GitHub Release, or change repository visibility without explicit user authorization.
156+
98157
## Documentation contract
99158

100159
Every project must contain both files:
101160

102161
- `README.md`: written for human users, centered on setup and practical usage.
103162
- `AGENTS.md`: written for AI coding agents, centered on architecture, development constraints, validation, and contribution.
104163

164+
End every repository README with author information and a License section. Add an Acknowledgements section before them when people, projects, or communities deserve credit.
165+
166+
Use Apache-2.0 as the default license for this and future user-owned projects unless the user explicitly selects another license or an existing project has a deliberate incompatible licensing decision. Keep `LICENSE`, package metadata, README attribution, and acknowledgements synchronized.
167+
105168
When project behavior changes, update the relevant sections rather than allowing either document to become historical or aspirational.

CHANGELOG.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Changelog
2+
3+
All notable changes to this project will be documented in this file.
4+
5+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7+
8+
## [Unreleased]
9+
10+
## [0.1.0] - 2026-08-15
11+
12+
### Added
13+
14+
- Added the `tiddlynmem` npm CLI for importing a Node.js TiddlyWiki into Nowledge Mem.
15+
- Added Terraform-style `plan` and `apply` commands, with non-mutating planning as the default.
16+
- Added exact TiddlyWiki tag filtering through `--tag`, bounded imports through `--limit`, and concurrent writes through `--jobs`.
17+
- Added WikiText-to-GitHub-Flavored-Markdown conversion using the active TiddlyWiki runtime.
18+
- Added native Nowledge Mem titles, bodies, labels, source fields, stable IDs, and TiddlyWiki metadata.
19+
- Added detailed JSON reports containing source tags, outcomes, warnings, errors, and source-tagging status without exposing tiddler bodies.
20+
- Added post-import `$:/NowledgeMem` tagging so successfully imported tiddlers are skipped on later runs.
21+
- Added direct REST health checks, a zero-config local API default, HTTP and HTTPS URL overrides, sensitive-title filtering, and retries without requiring the `nmem` CLI.
22+
23+
### Fixed
24+
25+
- Prevented same-named Wiki directories from sharing Memory IDs and added `--wiki-id` for an explicit portable identity.
26+
- Prevented TiddlyWiki workers from receiving `NMEM_API_KEY` and omitted raw API response bodies from errors and reports.
27+
- Required successful Memory API responses to confirm the requested stable ID before source tiddlers are tagged.
28+
- Rejected health-check and Memory API redirects so tiddler data is never forwarded to an unexpected address.
29+
- Wrote `failed:preflight` reports when service health checks fail and skipped health checks when an apply has no ready tiddlers.
30+
- Filtered `--tag` selections before WikiText rendering so unrelated tiddlers are not processed.
31+
- Skipped WikiText rendering for drafts, previously imported tiddlers, and sensitive-title tiddlers excluded by default.
32+
- Removed embedded data-URI images from inline, reference, shortcut-reference, and raw HTML Markdown images, and reported preserved local Markdown images.
33+
- Reported native Memory title and content limit failures during `plan` instead of retrying invalid writes during `apply`.
34+
- Limited retries to transient failures and added timeouts for health checks, TiddlyWiki workers, and Memory API requests.
35+
- Preserved non-Latin Wiki directory names in generated source labels.
36+
- Removed the unnecessary `--allow-remote` confirmation flag so explicitly configured endpoints work directly.
37+
38+
[Unreleased]: https://github.com/ThaddeusJiang/tiddlynmem/compare/v0.1.0...HEAD
39+
[0.1.0]: https://github.com/ThaddeusJiang/tiddlynmem/releases/tag/v0.1.0

0 commit comments

Comments
 (0)