mdrefine 0.1.0-beta.1 → 0.1.0-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/CONTRIBUTING.md +6 -0
  2. package/README.md +10 -6
  3. package/dist/cli/main.js +9 -2
  4. package/dist/cli/main.js.map +1 -1
  5. package/dist/config/resolve.d.ts +12 -0
  6. package/dist/config/resolve.js +7 -1
  7. package/dist/config/resolve.js.map +1 -1
  8. package/dist/core/engine.js +29 -9
  9. package/dist/core/engine.js.map +1 -1
  10. package/dist/core/types.d.ts +7 -1
  11. package/dist/core/types.js.map +1 -1
  12. package/dist/index.d.ts +1 -1
  13. package/dist/index.js.map +1 -1
  14. package/dist/rules/links.js +28 -5
  15. package/dist/rules/links.js.map +1 -1
  16. package/dist/rules/structure.d.ts +2 -0
  17. package/dist/rules/structure.js +24 -0
  18. package/dist/rules/structure.js.map +1 -0
  19. package/dist/rules/style.js +138 -29
  20. package/dist/rules/style.js.map +1 -1
  21. package/dist/syntax/obsidian.js +17 -0
  22. package/dist/syntax/obsidian.js.map +1 -1
  23. package/dist/workspace/files.d.ts +5 -2
  24. package/dist/workspace/files.js +15 -6
  25. package/dist/workspace/files.js.map +1 -1
  26. package/dist/workspace/index.d.ts +4 -1
  27. package/dist/workspace/index.js +53 -15
  28. package/dist/workspace/index.js.map +1 -1
  29. package/dist/workspace/selection.d.ts +2 -0
  30. package/dist/workspace/selection.js +31 -0
  31. package/dist/workspace/selection.js.map +1 -0
  32. package/docs/cli.md +18 -0
  33. package/docs/configuration.md +91 -25
  34. package/docs/contributing.md +87 -5
  35. package/docs/design.md +28 -5
  36. package/docs/plugins.md +11 -4
  37. package/docs/quick-start.md +1 -1
  38. package/docs/releases/0.1.0-beta.2.md +83 -0
  39. package/docs/releases/0.1.0-beta.3.md +61 -0
  40. package/docs/releases.md +34 -10
  41. package/package.json +1 -1
@@ -28,8 +28,8 @@ respectful and focused on reproducible behavior; harassment and disclosure of
28
28
  private data are not acceptable. Contributions are provided under the MIT
29
29
  license.
30
30
 
31
- The branch policy requires the four platform checks and resolved review threads.
32
- It does not require approval from a second account: this project is
31
+ The branch policy requires the three CI checks and resolved review threads. It
32
+ does not require approval from a second account: this project is
33
33
  agent-maintained and cannot assume another maintainer is available. Request
34
34
  independent review when available, especially for file writes and release
35
35
  automation. Passing CI is not a claim of human review.
@@ -41,6 +41,77 @@ versions and release tags are never replaced. Follow the
41
41
  reports belong in the private channel described in
42
42
  [SECURITY.md](https://github.com/viell-dev/slop-markdown-tools/blob/main/SECURITY.md).
43
43
 
44
+ ## Issue and pull request labels
45
+
46
+ Use one primary `Type:` label on every issue and PR, and at most one `Status:`
47
+ label describing the current disposition or next action. The type describes what
48
+ the item is about; a feature implementation PR also uses
49
+ `Type: Feature Request`. For mixed historical items, choose the main purpose and
50
+ explain separate decisions in comments. Split new requests when their parts need
51
+ independent scope decisions. Do not add priority labels.
52
+
53
+ The
54
+ [label catalog](https://github.com/viell-dev/slop-markdown-tools/blob/main/.github/labels.json)
55
+ is the source of truth for exact names, descriptions, and hexadecimal colors.
56
+ Keep it, this guide, GitHub, issue templates, and Dependabot settings aligned.
57
+ Use the GitHub UI or the existing `gh` CLI; no label-sync service is required.
58
+
59
+ | Label | Color | Use |
60
+ | --------------------------- | --------- | ---------------------------------------------------------------------------- |
61
+ | `Type: Bug` | `#d73a4a` | Incorrect behavior, broken functionality, or a regression. |
62
+ | `Type: Enhancement` | `#a2eeef` | Improve an existing capability, including usability or performance. |
63
+ | `Type: Feature Request` | `#0e8a16` | Add a new independently useful capability or rule. |
64
+ | `Type: Maintenance` | `#6a737d` | Dependencies, CI, releases, refactoring, or repository upkeep. |
65
+ | `Type: Documentation` | `#0075ca` | Documentation, examples, or contributor instructions. |
66
+ | `Type: Discussion` | `#5319e7` | Explore a design or project direction before an actionable proposal. |
67
+ | `Type: Question` | `#d876e3` | Ask how the project works or how to use it. |
68
+ | `Status: Needs Triage` | `#ededed` | Awaiting maintainer review and a scope decision. |
69
+ | `Status: Confirmed` | `#0e8a16` | Reproduced defect or accepted actionable request; not a delivery commitment. |
70
+ | `Status: Needs Information` | `#fbca04` | Waiting for reporter details, answers, or validation results. |
71
+ | `Status: Blocked` | `#d93f0b` | Accepted work is waiting on an identified external dependency. |
72
+ | `Status: Can't Reproduce` | `#fef2c0` | A documented reproduction attempt did not reproduce the report. |
73
+ | `Status: Duplicate` | `#cfd3d7` | Already tracked elsewhere; link the canonical issue or PR. |
74
+ | `Status: Won't Do` | `#666666` | Declined as out of scope or unsuitable in its proposed form. |
75
+ | `Good First Issue` | `#7057ff` | A scoped, ready task with a clear approach and beginner-friendly validation. |
76
+ | `Help Wanted` | `#008672` | A scoped, accepted task for which outside contributions are welcome. |
77
+
78
+ Review labels whenever answering, triaging, implementing, closing, reopening, or
79
+ otherwise updating an issue or PR:
80
+
81
+ - Replace `Status: Needs Triage` after review. Use `Status: Confirmed` only for
82
+ a reproduced defect or an accepted request within project scope; neither
83
+ reproduction nor acceptance follows automatically from a report.
84
+ - When waiting on the reporter, use `Status: Needs Information` and state what
85
+ evidence is needed. Use `Status: Blocked` for an identified external
86
+ dependency, with a link and an unblock condition. Choose the immediate next
87
+ action rather than stacking statuses.
88
+ - Use `Status: Can't Reproduce` only after documenting the attempted version,
89
+ input, and result. An incomplete report first needs information.
90
+ - On duplicate closure, link the canonical item and retain `Status: Duplicate`.
91
+ On rejection, explain the scope or suitability decision and retain
92
+ `Status: Won't Do`. A declined proposal can be reconsidered with new evidence.
93
+ - On successful completion or merge, remove transient status labels and retain
94
+ the type. GitHub's open/closed/merged state records completion; there is no
95
+ redundant Done or Merged label. A closed, unmerged PR should retain its
96
+ applicable disposition, rather than being labeled as completed.
97
+ - On reopening, reassess the evidence and replace the old disposition; do not
98
+ carry a stale rejection, duplicate, or information request forward.
99
+ - Apply `Good First Issue` only to a ready, well-explained beginner task,
100
+ together with `Help Wanted`. Remove both when the item closes or is no longer
101
+ ready for contribution. Waiting for a reporter's private-workspace benchmark
102
+ is not a general help request.
103
+
104
+ Colors follow familiar GitHub cues: red for defects, blue for documentation,
105
+ green for accepted work, yellow/orange for missing information or blockers, and
106
+ gray for neutral or declined dispositions. Names carry the meaning without
107
+ relying on color. The unprefixed contributor labels follow
108
+ [GitHub's label conventions](https://docs.github.com/en/issues/using-labels-and-milestones-to-track-work/managing-labels);
109
+ the readiness criteria draw on the
110
+ [Kubernetes contributor guide](https://www.kubernetes.dev/docs/guide/help-wanted/).
111
+ The `Type:` / `Status:` grouping also appears in
112
+ [community label catalogs](https://gist.github.com/dysfunc/fc722e865a6a960a2d9c5ecf43f5a963);
113
+ this repository intentionally uses a smaller set.
114
+
44
115
  ## Develop locally
45
116
 
46
117
  Follow the [checkout setup](quick-start.md#install-from-the-repository), then:
@@ -55,9 +126,20 @@ site build, and regression/property/CLI tests. `test:package` packs the tool,
55
126
  installs it into a temporary consumer project, and exercises the installed CLI
56
127
  and library. It can require access to the npm registry.
57
128
 
58
- GitHub Actions verifies Linux with Node.js 22 and 24, plus macOS and Windows
59
- with Node.js 24. Keep changes scoped and describe remaining limitations in the
60
- pull request. Agent contributors should also read the repository's
129
+ GitHub Actions runs the full `check` and dependency audit on Linux with
130
+ Node.js 24. Linux with Node.js 22 and Windows with Node.js 24 run the build and
131
+ tests; all three jobs verify the installed package. Linting, formatting checks,
132
+ and documentation builds run once rather than on every platform. Superseded PR
133
+ runs are canceled.
134
+
135
+ Runtime dependencies have no OS-specific installation constraints. Development
136
+ tooling does include native platform packages, but that alone does not justify
137
+ repeating the full toolchain matrix. Windows coverage protects filesystem path
138
+ handling and installed command behavior; it has already caught a path-alias
139
+ regression. macOS is not a routine CI target.
140
+
141
+ Keep changes scoped and describe remaining limitations in the pull request.
142
+ Agent contributors should also read the repository's
61
143
  [AGENTS.md](https://github.com/viell-dev/slop-markdown-tools/blob/main/AGENTS.md).
62
144
 
63
145
  ## Write and preview documentation
package/docs/design.md CHANGED
@@ -59,11 +59,34 @@ Heading nesting paths, property aliases, PDF subpaths, and every Obsidian
59
59
  plugin's syntax are not fully supported. Embeds are preserved as embeds; image
60
60
  dimensions in their aliases remain intact.
61
61
 
62
- All eligible Markdown is currently parsed into an in-memory workspace index.
63
- There is no persistent cache, watch service, editor extension, or language
64
- server yet. Use directory selection to scope output; indexing still needs the
65
- containing workspace for cross-document links. The library has a pluggable
66
- workspace interface for specialized hosts.
62
+ The workspace indexes eligible paths first and parses target Markdown only when
63
+ a fragment is checked, caching the result for that invocation. CLI discovery
64
+ also defers reading Markdown until it is selected or needed for a fragment.
65
+ Built-in rule-schema validators are reused across documents. A suffix lookup
66
+ index is built on first use instead of scanning every path for each shortened
67
+ link. There is no persistent cache, worker pool, watch service, editor
68
+ extension, or language server yet. The library has a pluggable workspace
69
+ interface for specialized hosts.
70
+
71
+ Run `npm run build` and `node scripts/benchmark.mjs 1000` for a reproducible
72
+ synthetic library benchmark. It reports path-index construction and lint time
73
+ separately for 1,000 short interlinked notes; pass a different count to scale
74
+ it. These timings exclude filesystem traversal and do not predict a particular
75
+ vault's throughput. Measure the original workload before adding caches or
76
+ workers.
77
+
78
+ Formatting retains the current parsed document within one call, reusing it
79
+ between phases and for final diagnostics. Every changed candidate is parsed and
80
+ checked against the original semantic fingerprint before becoming the next
81
+ phase's input. No-op edits still undergo range and overlap validation. This
82
+ retains the plugin contract that rules must not mutate documents.
83
+
84
+ Run `node scripts/benchmark-format.mjs 100` after building to compare 100
85
+ formatting calls on a synthetic 4.8 KB note needing edits with 100 calls on its
86
+ already-formatted output. It warms both cases, checks output and diagnostics,
87
+ and prints a result hash for comparing implementations. Run several times
88
+ without competing workloads; timings exclude discovery, I/O, CLI serialization,
89
+ and custom plugins.
67
90
 
68
91
  ## Maintenance priorities
69
92
 
package/docs/plugins.md CHANGED
@@ -26,10 +26,17 @@ const result = format(files["note.md"], options);
26
26
 
27
27
  Library calls do not read or write files. `path` and workspace keys use
28
28
  forward-slash paths relative to the workspace root. Use `null` values for
29
- non-Markdown attachments. Without a workspace, local target checks and path
30
- rewriting are unavailable. Obsidian reflow also requires an explicit
31
- `workspace.strictLineBreaks: true`; callers are responsible for verifying that
32
- renderer setting.
29
+ non-Markdown attachments. A Markdown value can also be a synchronous loader
30
+ `() => string`; `createWorkspace` calls it only when that target needs fragment
31
+ validation, then caches its parsed heading/block index. Callers must provide a
32
+ stable source snapshot for each workspace instance. The CLI provides its own
33
+ per-invocation file loaders. `WorkspaceOptions.directories` can list existing
34
+ empty directories; parent directories of file entries are inferred. Resolution
35
+ returns `status: "directory"` for a directory instead of `"missing"`.
36
+
37
+ Without a workspace, local target checks and path rewriting are unavailable.
38
+ Obsidian reflow also requires an explicit `workspace.strictLineBreaks: true`;
39
+ callers are responsible for verifying that renderer setting.
33
40
 
34
41
  `parse`, `range`, `textContent`, `resolveConfig`, `configSchema`, `presets`,
35
42
  `builtInRules`, `ruleRegistry`, `applyEdits`, and `semanticFingerprint` are also
@@ -9,7 +9,7 @@ The CLI requires Node.js 22.12 or newer. Install the package in your document
9
9
  workspace:
10
10
 
11
11
  ```sh
12
- npm install --save-dev --save-exact mdrefine@0.1.0-beta.1
12
+ npm install --save-dev --save-exact mdrefine@0.1.0-beta.3
13
13
  npx --no-install mdtools --help
14
14
  ```
15
15
 
@@ -0,0 +1,83 @@
1
+ # mdrefine 0.1.0-beta.2
2
+
3
+ Second public beta of Markdown Tools. npm package: `mdrefine`; executable:
4
+ `mdtools`. Requires Node.js 22.12 or newer. Upgrade with:
5
+
6
+ ```sh
7
+ npm install --save-dev --save-exact mdrefine@0.1.0-beta.2
8
+ ```
9
+
10
+ ## Correctness fixes
11
+
12
+ - Measure protected Markdown markers together with their preceding word before
13
+ wrapping, avoiding preventable line-width overflow.
14
+ - Prefer exact Obsidian workspace-root targets before suffix matches, respect
15
+ explicit relative paths, and verify target identity before rewriting links.
16
+ - Preserve compliant literal destination spelling, including `?` and `%`, and
17
+ escape literal percent/hash characters correctly when generating paths.
18
+ - Recognize existing directory targets instead of reporting them as missing.
19
+ Obsidian receives a directory-specific diagnostic; CommonMark/GitHub links can
20
+ resolve to directories. Directories are not rewritten to README files.
21
+ - Compare code-span line endings using their rendered space value while keeping
22
+ other code whitespace significant, allowing safe inline-code formatting.
23
+ - Fix parsing of inline Obsidian comments spanning several physical lines.
24
+
25
+ ## New controls
26
+
27
+ - Opt-in `style/inline-code` joins multiline code spans without changing their
28
+ parsed content, including spans in lists and blockquotes.
29
+ - `style/wrap.measure: "codepoints"` counts Unicode scalar values instead of
30
+ display columns. Display columns remain the default.
31
+ - `style/wrap.reportUnreflowed` and `reportUnbreakable` optionally explain
32
+ protected paragraphs and remaining unbreakable overflow without changing
33
+ formatting safety or check-mode semantics.
34
+ - `resolve.gitIgnored` and `resolve.nestedRepositories` opt into additional link
35
+ targets independently of files selected for linting or writing.
36
+ - Repeatable `--exclude <path>` omits literal files or directory subtrees from
37
+ processing while preserving them in the link index. Filesystem aliases are
38
+ canonicalized consistently, including Windows short paths.
39
+ - Opt-in `structure/initial-heading` checks for an initial level-1 heading after
40
+ optional YAML/TOML front matter. It never edits content.
41
+
42
+ See
43
+ [configuration](https://viell-dev.github.io/slop-markdown-tools/configuration.html)
44
+ and [CLI workflows](https://viell-dev.github.io/slop-markdown-tools/cli.html)
45
+ for options, defaults, and examples.
46
+
47
+ ## Performance and library API
48
+
49
+ Workspace indexing is path-only until a target's headings or block IDs are
50
+ needed. Fragment parsing, suffix lookups, and built-in schema validation reuse
51
+ cached work within their documented lifetimes; custom schema IDs stay isolated
52
+ between calls. A synthetic benchmark is available in `scripts/benchmark.mjs` in
53
+ the source checkout. Validation on the original large workspace remains pending
54
+ in [#23](https://github.com/viell-dev/slop-markdown-tools/issues/23); no
55
+ persistent index cache or worker pool is included.
56
+
57
+ `createWorkspace` accepts lazy Markdown source loaders and explicit directory
58
+ entries. Exhaustive consumers of `LinkResolution.status` must handle the new
59
+ `"directory"` result. Consumers constructing `ResolvedConfig` directly must
60
+ provide `resolve` (use `{}` for the defaults); `resolveConfig()` provides it for
61
+ normal callers. See the
62
+ [library API](https://viell-dev.github.io/slop-markdown-tools/plugins.html).
63
+
64
+ ## Compatibility and project scope
65
+
66
+ Beta.1 configurations remain supported. The CLI name and Node.js minimum are
67
+ unchanged; new formatting and structural controls are opt-in.
68
+
69
+ For users of intermediate source checkouts, these additions were removed before
70
+ this release: `style/wrap.keepLabelWithAtom`, `--changed`, `--staged`,
71
+ `structure/title-matches-filename`, `structure/metadata-line`, and
72
+ `style/accidental-marker`. Remove those settings and implement consumer-specific
73
+ policies in plugins or wrappers. Git callers can supply explicit paths while
74
+ retaining workspace resolution; skip the CLI invocation for an empty selection.
75
+ These removals do not remove any published beta.1 feature.
76
+
77
+ Modified-date mutation remains consumer-owned. Semantic guards, conservative
78
+ handling of unsupported constructs, and Obsidian's verified strict-line-break
79
+ requirement remain in force. The plugin API and configuration are provisional.
80
+
81
+ Repository maintenance now includes explicit issue-scope review and a documented
82
+ label taxonomy. Full CI runs on Linux/Node.js 24, with compatibility and
83
+ installed-package checks on Linux/Node.js 22 and Windows/Node.js 24.
@@ -0,0 +1,61 @@
1
+ # mdrefine 0.1.0-beta.3
2
+
3
+ Third public beta of Markdown Tools. npm package: `mdrefine`; executable:
4
+ `mdtools`. Requires Node.js 22.12 or newer. Upgrade with:
5
+
6
+ ```sh
7
+ npm install --save-dev --save-exact mdrefine@0.1.0-beta.3
8
+ ```
9
+
10
+ ## Correct wrap diagnostics
11
+
12
+ Protected paragraphs now distinguish breakable prose from indivisible inline
13
+ atoms. A hard-break paragraph whose only over-width content is a long link, code
14
+ span, or other protected atom no longer triggers `reportUnreflowed`. That
15
+ overflow follows `reportUnbreakable`, including when reflow is skipped. A
16
+ paragraph containing both causes can report both when enabled.
17
+
18
+ Whitespace inside protected inline nodes is not a wrapping opportunity.
19
+ Container prefixes count toward width; hard-break markers are excluded from
20
+ protected-line width. Both diagnostic options remain disabled by default and
21
+ propose no edits. Protected paragraph source remains unchanged.
22
+
23
+ Fixed in [PR #36](https://github.com/viell-dev/slop-markdown-tools/pull/36),
24
+ resolving [#34](https://github.com/viell-dev/slop-markdown-tools/issues/34).
25
+ Regression coverage includes both hard-break forms, LF/CRLF, lists, quotes, task
26
+ items, Unicode width measurement, and Obsidian's strict-line-break gate.
27
+
28
+ ## Faster formatting
29
+
30
+ The formatter reuses the current parsed document between phases and for final
31
+ diagnostics. It parses each changed candidate and validates its meaning before
32
+ accepting it. Edit-range, overlap, oscillation, and convergence checks remain in
33
+ force; no persistent cache or worker pool is introduced.
34
+
35
+ A warmed synthetic benchmark improved approximately 2.3 times for input needing
36
+ edits and 2.6 times for already-formatted input, with identical result hashes.
37
+ On the reporter's 8,362-document, 36 MB workspace, `format --check --json` fell
38
+ from 314 to 121 seconds, with the same 6,960 would-change files and no remaining
39
+ diagnostics after formatting. These are workload-specific results, not a
40
+ throughput guarantee.
41
+
42
+ Implemented in
43
+ [PR #37](https://github.com/viell-dev/slop-markdown-tools/pull/37), resolving
44
+ [#35](https://github.com/viell-dev/slop-markdown-tools/issues/35).
45
+ Original-workload validation in
46
+ [#23](https://github.com/viell-dev/slop-markdown-tools/issues/23#issuecomment-5735871369)
47
+ also confirms the beta.2 indexing improvements and correct link diagnostics; the
48
+ performance issue is now closed. The source checkout includes
49
+ `scripts/benchmark-format.mjs` for reproducible formatting measurements.
50
+
51
+ ## Compatibility
52
+
53
+ No dependency, public API, configuration-schema, or Node.js minimum changes.
54
+ Existing beta.2 configurations remain valid. Consumers enabling wrap diagnostics
55
+ may see findings move from `reportUnreflowed` to `reportUnbreakable`; this is
56
+ the intentional classification correction described above.
57
+
58
+ The API and configuration remain provisional. Semantic guards, conservative
59
+ handling of unsupported constructs, and Obsidian's verified strict-line-break
60
+ requirement remain in force. Repository agent instructions now also prohibit
61
+ self-references in GitHub issue and PR posts.
package/docs/releases.md CHANGED
@@ -2,14 +2,16 @@
2
2
 
3
3
  ## Versions and availability
4
4
 
5
- These documents cover `mdrefine@0.1.0-beta.1`. The executable is `mdtools`;
5
+ These documents cover `mdrefine@0.1.0-beta.3`. The executable is `mdtools`;
6
6
  prereleases use npm's `beta` channel. Read the
7
- [beta.1 release notes](releases/0.1.0-beta.1.md) for changes and limitations.
7
+ [beta.3 release notes](releases/0.1.0-beta.3.md) for changes and limitations.
8
+ Previous releases: [beta.2](releases/0.1.0-beta.2.md) and
9
+ [beta.1](releases/0.1.0-beta.1.md).
8
10
 
9
11
  The registry is the source of truth for package availability:
10
12
 
11
13
  ```sh
12
- npm view mdrefine@0.1.0-beta.1 version --registry=https://registry.npmjs.org/
14
+ npm view mdrefine@0.1.0-beta.3 version --registry=https://registry.npmjs.org/
13
15
  ```
14
16
 
15
17
  An `E404` means the requested package or version is unavailable. A version in
@@ -17,6 +19,12 @@ this repository or its documentation does not imply publication. Check
17
19
  [GitHub releases](https://github.com/viell-dev/slop-markdown-tools/releases) for
18
20
  release announcements and downloadable artifacts.
19
21
 
22
+ The initial beta was published locally under npm account `viell`. npm assigned
23
+ both `beta` and `latest` to `0.1.0-beta.1` despite an explicit `--tag beta`;
24
+ removing `latest` returned E400. Both tags were accepted for that release.
25
+ Continue using `--tag beta` for subsequent betas and verify tags after
26
+ publishing.
27
+
20
28
  ## Prepare without publishing
21
29
 
22
30
  Use Node.js 24 and npm 10 or newer from a clean checkout:
@@ -24,7 +32,7 @@ Use Node.js 24 and npm 10 or newer from a clean checkout:
24
32
  ```sh
25
33
  npm ci
26
34
  npm run release:prepare
27
- npm publish ./artifacts/mdrefine-0.1.0-beta.1.tgz --dry-run --ignore-scripts --access public --tag beta
35
+ npm publish ./artifacts/mdrefine-0.1.0-beta.3.tgz --dry-run --ignore-scripts --access public --tag beta
28
36
  ```
29
37
 
30
38
  Preparation runs all checks, packs the allowlisted files, installs that exact
@@ -36,12 +44,15 @@ change.
36
44
 
37
45
  The manual **Release** GitHub Actions workflow performs the same checks plus a
38
46
  dependency audit and uploads the artifact for 14 days. Leave `publish` false to
39
- prepare only. CI independently checks Linux, macOS, Windows, and Node.js 22/24.
47
+ prepare only. CI runs full checks on Linux/Node.js 24, compatibility tests on
48
+ Linux/Node.js 22 and Windows/Node.js 24, and installed-package checks on all
49
+ three targets.
40
50
 
41
51
  ## Publication prerequisites
42
52
 
43
53
  Publication requires explicit operator authorization. Preparing a PR or artifact
44
- does not supply that authorization. Before the first publication:
54
+ does not supply that authorization. For subsequent releases, verify these
55
+ prerequisites rather than repeating the completed bootstrap:
45
56
 
46
57
  1. Merge the release PR with all required checks passing. Review the tarball
47
58
  manifest, release notes, version, and registry name again.
@@ -56,10 +67,16 @@ does not supply that authorization. Before the first publication:
56
67
  token is stored in GitHub.
57
68
  4. Restrict the GitHub `npm-release` environment to `main` and configure an
58
69
  approval gate if an independent approver is available. Verify branch rules
59
- still require PRs and the four CI checks. The workflow uses Node.js 24 and
70
+ still require PRs and the three CI checks. The workflow uses Node.js 24 and
60
71
  checks that npm supports trusted publishing.
61
- 5. Only after authorization and authentication setup, set repository variable
62
- `NPM_PUBLISH_ENABLED` to `true`. It is disabled during preparation.
72
+ 5. Repository variable `NPM_PUBLISH_ENABLED` is `true` after verified trusted
73
+ publisher setup. This enables the workflow's capability; it does not
74
+ authorize a release. Preparation uses `publish: false` regardless of this
75
+ variable's value.
76
+
77
+ Trusted-publisher settings were verified on 2026-09-18. The first release used
78
+ local authentication and has no OIDC provenance. For workflow releases, verify
79
+ the publication job and the registry provenance attestations after each release.
63
80
 
64
81
  ## Publish an authorized beta
65
82
 
@@ -69,7 +86,8 @@ builds and checks the package again, verifies the artifact checksum, publishes
69
86
  that tarball to npm's `beta` channel with provenance, and creates a GitHub
70
87
  prerelease at the workflow's commit. Tags use exact versions without a `v`
71
88
  prefix. Stable publication deliberately needs a separate policy change; this
72
- workflow accepts only beta versions and never assigns npm's `latest` tag.
89
+ workflow accepts only beta versions and requests the `beta` tag. See the
90
+ initial-publication exception above before interpreting `latest`.
73
91
 
74
92
  For an authenticated first publication that cannot use OIDC yet, use the exact
75
93
  reviewed tarball with `npm publish <tarball> --ignore-scripts --access public
@@ -85,6 +103,12 @@ versions, tags, and release assets must never be overwritten; corrections use a
85
103
  new version. The workflow refuses an existing npm version or tag to make a
86
104
  partial release visible instead of silently accepting it.
87
105
 
106
+ GitHub enforces immutability for future releases and their assets. Attach all
107
+ assets before publishing a release. The existing beta.1 release predates that
108
+ setting, so its assets are not retroactively locked; its version tag remains
109
+ protected by the repository ruleset. Do not replace its assets or recreate the
110
+ release to change that history.
111
+
88
112
  After publication, verify registry metadata, the `beta` dist-tag, a fresh
89
113
  installation, the GitHub release and its assets, and the documentation site. All
90
114
  subsequent changes, including prerelease maintenance, continue through PRs.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mdrefine",
3
- "version": "0.1.0-beta.1",
3
+ "version": "0.1.0-beta.3",
4
4
  "description": "Configurable Markdown linting and formatting for CommonMark, GitHub, and Obsidian",
5
5
  "type": "module",
6
6
  "license": "MIT",