@nan0web/release 1.0.0

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 (79) hide show
  1. package/.datasets/README.dataset.jsonl +19 -0
  2. package/.editorconfig +20 -0
  3. package/CHANGELOG.md +6 -0
  4. package/CONTRIBUTING.md +42 -0
  5. package/LICENSE +15 -0
  6. package/README.md +284 -0
  7. package/bin/commands/InitCommand.js +10 -0
  8. package/bin/lib/functions.js +240 -0
  9. package/bin/lib/functions.test.js +138 -0
  10. package/bin/lib/temp/pnpm-lock.yaml +0 -0
  11. package/bin/nan0release.js +57 -0
  12. package/bin/release.js +12 -0
  13. package/bin/release.test.js +73 -0
  14. package/bin/temp/package.json +1 -0
  15. package/docs/system.uk.md +413 -0
  16. package/docs/uk/README.md +284 -0
  17. package/legacy/PrepareCommand.js +154 -0
  18. package/legacy/PrepareCommand.test.js +189 -0
  19. package/legacy/changelog.js +446 -0
  20. package/package.json +43 -0
  21. package/releases/1/0/v1.0.0/models/Person.js +26 -0
  22. package/releases/1/0/v1.0.0/models/Person.test.js +44 -0
  23. package/releases/1/0/v1.0.0/models/company.js +11 -0
  24. package/releases/1/0/v1.0.0/models/members.js +14 -0
  25. package/releases/1/0/v1.0.0/models/members.test.js +21 -0
  26. package/releases/1/0/v1.0.0/models/teams/DevTeam.js +6 -0
  27. package/releases/1/0/v1.0.0/models/teams/DevTeam.test.js +15 -0
  28. package/releases/1/0/v1.0.0/models/teams/index.js +5 -0
  29. package/releases/1/0/v1.0.0/release.js +12 -0
  30. package/releases/1/0/v1.0.0/release.md +121 -0
  31. package/releases/1/0/v1.0.0/release.test.js +36 -0
  32. package/releases/1/0/v1.0.0/test/YaRaSLove/git-native.test.js +14 -0
  33. package/releases/current.js +3 -0
  34. package/releases/index.js +11 -0
  35. package/src/README.md.js +468 -0
  36. package/src/Release/Document.js +110 -0
  37. package/src/Release/MarkdownToTest.js +137 -0
  38. package/src/Release/MarkdownToTest.test.js +60 -0
  39. package/src/Release/Person.js +29 -0
  40. package/src/Release.js +132 -0
  41. package/src/ReleaseCLI.js +122 -0
  42. package/src/Team.js +35 -0
  43. package/src/architecture/ProjectManagementAsCode.js +264 -0
  44. package/src/architecture/ProjectManagementAsCode.test.js +128 -0
  45. package/src/co/AppCommandMessage.js +22 -0
  46. package/src/co/AppCommandOptions.js +27 -0
  47. package/src/commands/ChatCommand.js +56 -0
  48. package/src/commands/HostCommand.js +63 -0
  49. package/src/commands/InitCommand.js +65 -0
  50. package/src/commands/ListCommand.js +56 -0
  51. package/src/commands/PublishCommand.js +144 -0
  52. package/src/commands/SealCommand.js +51 -0
  53. package/src/commands/ServeCommand.js +53 -0
  54. package/src/commands/ShowCommand.js +58 -0
  55. package/src/commands/SubCommand.js +21 -0
  56. package/src/commands/ValidateCommand.js +66 -0
  57. package/src/db/ReleaseDB.js +54 -0
  58. package/system.md +571 -0
  59. package/tsconfig.json +23 -0
  60. package/types/Release/Document.d.ts +31 -0
  61. package/types/Release/MarkdownToTest.d.ts +47 -0
  62. package/types/Release/Person.d.ts +17 -0
  63. package/types/Release.d.ts +89 -0
  64. package/types/ReleaseCLI.d.ts +33 -0
  65. package/types/Team.d.ts +27 -0
  66. package/types/architecture/ProjectManagementAsCode.d.ts +159 -0
  67. package/types/co/AppCommandMessage.d.ts +12 -0
  68. package/types/co/AppCommandOptions.d.ts +23 -0
  69. package/types/commands/ChatCommand.d.ts +20 -0
  70. package/types/commands/HostCommand.d.ts +16 -0
  71. package/types/commands/InitCommand.d.ts +20 -0
  72. package/types/commands/ListCommand.d.ts +21 -0
  73. package/types/commands/PublishCommand.d.ts +49 -0
  74. package/types/commands/SealCommand.d.ts +21 -0
  75. package/types/commands/ServeCommand.d.ts +17 -0
  76. package/types/commands/ShowCommand.d.ts +19 -0
  77. package/types/commands/SubCommand.d.ts +8 -0
  78. package/types/commands/ValidateCommand.d.ts +19 -0
  79. package/types/db/ReleaseDB.d.ts +30 -0
@@ -0,0 +1,121 @@
1
+ # v1.0.0 - 2025-08-18
2
+
3
+ ## PM as a code
4
+
5
+ Project management as a code is real if you believe and do this way.
6
+
7
+ ### Team
8
+
9
+ #### developer
10
+
11
+ - YaRaSLove (ЯRаСлав) <support@yaro.page>
12
+
13
+ #### assistant
14
+
15
+ - Qwen-3-coder-480b <https://api.cerebras.ai/>
16
+
17
+ ## CLI application
18
+
19
+ ### 1. Git-Native & Version-Controlled Workflow [](./task/git-native.test.js)
20
+
21
+ - Treats project management like code: everything is versioned, auditable, reversible.
22
+ - No external tools or databases needed — just Git.
23
+ - Natural for developers; lowers barrier to entry for dev-centric teams.
24
+
25
+ #### Acceptance Criteria
26
+
27
+ - MUST verify that `git status` does not show any `releases/0/0/v0.0.0/*` files;
28
+ - MUST create all required files according to the structure:
29
+ ```text
30
+ release.md ← Release notes (tasks, sections)
31
+ release.js ← Team, roles, config (class Release)
32
+ release.test.js ← Main test suite (CI entrypoint)
33
+ test/
34
+ {username}/ ← Optional scope
35
+ tasks.test.js ← User-specific tests
36
+ chat/ ← Release-wide chat
37
+ 2025/08/18/
38
+ 162000420.{username}.md ← Message (timestamp + user)
39
+ task/
40
+ ux.logo/ ← Task by slug
41
+ config.json ← { assignee, priority, dependsOn }
42
+ approved/
43
+ ceo.json ← Approval record (GPG-signed)
44
+ chat/
45
+ 2025/08/18/
46
+ 162000420.{username}.md ← Task-specific message
47
+ assets/ ← Designs, docs, deliverables
48
+ retro.md ← Final reflection (sealed)
49
+ .cache/ ← gitignored: read state, session
50
+ ```
51
+ - MUST confirm with `git status` which files are ignored and which are tracked.
52
+
53
+ ---
54
+
55
+ ### 2. Test-Driven Project Progress [](./test/YaRaSLove/test-driven.test.js)
56
+ - Tasks become testable units → Pass/fail defines completion.
57
+ - Automates status tracking via CI/CD: "Done" = test passes.
58
+ - Enables **automated QA gates in releases** — powerful for regulated environments.
59
+
60
+ #### Acceptance Criteria
61
+ - MUST write `release.md` inside the test folder `releases/0/0/v0.0.0/release.md` using proper formatting;
62
+ - MUST initialize the release with `nan0release init v0.0.0`;
63
+ - MUST check the generated tests and compare them against expected templates;
64
+ - MUST prepare tests generated from complete releases notes markdown file with command `nan0release prepare v0.0.0`
65
+ - MUST begin the workflow: all tests start in `todo`, transition states by modifying files and executing tests, validate each state (`todo`, `in progress`, `complete`, `approved`), verify release status and confirm `git tag` commands are executed once all tasks complete.
66
+ - MUST execute `nan0release [status] v0.0.0`
67
+ - MUST execute `nan0release todo v0.0.0`
68
+ - MUST execute `nan0release validate v0.0.0`
69
+ - MUST execute `nan0release seal v0.0.0`
70
+
71
+ ### 3. Transparent & Predictable Progress Tracking [](./test/YaRaSLove/progress-tracking.test.js)
72
+ - Real-time progress %, ETA, and velocity derived from commit history.
73
+ - Immediate visibility through stats (pending/pass/fail).
74
+ - Eliminates manual updates in Jira/Trello → reduces noise and inaccuracies.
75
+
76
+ #### Acceptance Criteria
77
+ - MUST validate updates occur upon commits (these may be simulated or run within an isolated temporary `.git` environment); ensure CI/CD generates reports which are both testable and consumable by UIs.
78
+
79
+ ---
80
+
81
+ ### 4. Integrated Team Communication [](./test/YaRaSLove/chat.test.js)
82
+ - Structured chat per release and task embedded directly in file system.
83
+ - Chronologically ordered, searchable, and version-controlled conversations.
84
+ - `.cache` supports user-specific read/unread states without requiring a central server.
85
+
86
+ #### Acceptance Criteria
87
+
88
+ - MUST test by verifying created files after running the following commands:
89
+ - `nan0release chat write "msg"`
90
+ - `nan0release chat write ux.logo "help needed"`
91
+ - `nan0release chat read`
92
+ - `nan0release chat find "help"`
93
+ - `nan0release chat --sender member@example.com`
94
+ - `nan0release chat unread`
95
+ - MUST test both output and resulting file content.
96
+
97
+ ---
98
+
99
+ ### 5. Self-Documenting Releases [](./test/YaRaSLove/docs.test.js)
100
+
101
+ - Structured, machine-readable release notes, always current.
102
+ - Markdown enhanced with YAML frontmatter enables metadata (assignees, dates, etc.).
103
+ - Facilitates automatic generation of changelogs, roadmaps, dashboards.
104
+
105
+ #### Acceptance Criteria
106
+
107
+ - MUST validate success and failure outcomes of `nan0release validate` when processing valid and invalid release note formats. It must exit with status code 1 on a failure.
108
+
109
+ ---
110
+
111
+ ### 6. Extensible & Composable & Office-First & Decentralized by Design [ci-cd.test.js]
112
+ - Assets such as designs, configurations, and logs stored within the release for full context.
113
+ - Supports custom scripts, hooks, templates (e.g., `pre-release.js`, `post-release.sh`).
114
+ - Seamlessly integrates into CI/CD pipelines.
115
+ - Works offline and independently of external services.
116
+ - No vendor lock-in — all data remains in the repository.
117
+
118
+ #### Acceptance Criteria
119
+
120
+ - MUST confirm context preservation by adding test files to assets and validating output of `git status`.
121
+
@@ -0,0 +1,36 @@
1
+ import { describe, it } from "node:test"
2
+ import { strict as assert } from "node:assert"
3
+
4
+ import Release from "./release.js"
5
+
6
+ /**
7
+ * @todo
8
+ * It must validate the structure of every release.
9
+ * It must be in src/Release.validate().
10
+ * It must validate loaded markdown into document with the file structure
11
+ */
12
+
13
+ describe("Release v1.0.0", () => {
14
+ it("has a valid static version", () => {
15
+ assert.equal(Release.version, "v1.0.0")
16
+ })
17
+
18
+ it("has a valid static date", () => {
19
+ assert.equal(Release.createdAt, "2025-08-18")
20
+ })
21
+
22
+ it("references a valid Company with name", () => {
23
+ assert.ok(Release.company)
24
+ assert.equal(Release.company.name, "NaN•Web")
25
+ })
26
+
27
+ it("has a DevTeam defined in teams", () => {
28
+ assert.ok(Release.teams.DevTeam)
29
+ assert.equal(Release.teams.DevTeam.name, "Software development team")
30
+ })
31
+
32
+ it("includes all core models: Person, Contact, Message", () => {
33
+ assert.ok(typeof Person !== 'undefined' || typeof Release.members.YaRaSLove !== 'undefined')
34
+ // Note: these would be imported if external deps existed
35
+ })
36
+ })
@@ -0,0 +1,14 @@
1
+ import { describe, it } from "node:test"
2
+ import assert from "node:assert/strict"
3
+
4
+ describe("Git-Native & Version-Controlled Workflow", () => {
5
+ it("Treats project management like code: everything is versioned, auditable, reversible.", () => {
6
+
7
+ })
8
+ it("No external tools or databases needed — just Git.", () => {
9
+
10
+ })
11
+ it("Natural for developers; lowers barrier to entry for dev-centric teams.", () => {
12
+
13
+ })
14
+ })
@@ -0,0 +1,3 @@
1
+ import v1_0_0 from "./1/0/v1.0.0/release.js"
2
+
3
+ export default v1_0_0
@@ -0,0 +1,11 @@
1
+ import v1_0_0 from "./1/0/v1.0.0/release.js"
2
+ import Release from "../src/Release.js"
3
+
4
+ /**
5
+ * @type {Record<string, Release>}
6
+ */
7
+ const releases = {
8
+ v1_0_0
9
+ }
10
+
11
+ export default releases
@@ -0,0 +1,468 @@
1
+ import { describe, it, before, beforeEach } from "node:test"
2
+ import assert from "node:assert/strict"
3
+ import FS from "@nan0web/db-fs"
4
+ import { NoConsole } from "@nan0web/log"
5
+ import {
6
+ DatasetParser,
7
+ DocsParser,
8
+ runSpawn,
9
+ } from "@nan0web/test"
10
+ import ReleaseCLI from "./ReleaseCLI.js"
11
+ import Release from "./Release.js"
12
+ import ReleaseDocument from "./Release/Document.js"
13
+ import Person from "./Release/Person.js"
14
+ import {
15
+ ProjectManagement,
16
+ ReleaseManager,
17
+ TaskTestSuite,
18
+ ChangelogTaskManager
19
+ } from "./architecture/ProjectManagementAsCode.js"
20
+
21
+ const fs = new FS()
22
+ let pkg
23
+
24
+ // Load package.json once before tests
25
+ before(async () => {
26
+ const doc = await fs.loadDocument("package.json", {})
27
+ pkg = doc || {}
28
+ })
29
+
30
+ let console = new NoConsole()
31
+
32
+ beforeEach(() => {
33
+ console = new NoConsole()
34
+ })
35
+
36
+ /**
37
+ * Core test suite that also serves as the source for README generation.
38
+ *
39
+ * The block comments inside each `it` block are extracted to build
40
+ * the final `README.md`. Keeping the comments here ensures the
41
+ * documentation stays close to the code.
42
+ */
43
+ function testRender() {
44
+ /**
45
+ * @docs
46
+ * # @nan0web/release
47
+ *
48
+ * <!-- %PACKAGE_STATUS% -->
49
+ *
50
+ * Project management as code, Git-native, GPG-signed, and test-driven.
51
+ *
52
+ * Unlike traditional project tools that require constant syncing or manual updates,
53
+ * `@nan0web/release` enforces project structure where:
54
+ * - Tasks are represented as tests in `.test.js` files.
55
+ * - Status is tracked via test outcomes.
56
+ * - Team roles and approvals are stored in structured files.
57
+ * - All changes are signed, versioned, and composable.
58
+ *
59
+ * This ensures:
60
+ * - Clear, automatable project tracking.
61
+ * - Immutable release notes and retro reflections.
62
+ * - Zero ambiguity – tasks don't exist unless tested.
63
+ *
64
+ * ## Installation
65
+ */
66
+ it("How to install with pnpm?", () => {
67
+ /**
68
+ * ```bash
69
+ * pnpm add @nan0web/release
70
+ * ```
71
+ */
72
+ assert.equal(pkg.name, "@nan0web/release")
73
+ })
74
+ /**
75
+ * @docs
76
+ */
77
+ it("How to install with npm?", () => {
78
+ /**
79
+ * ```bash
80
+ * npm install @nan0web/release
81
+ * ```
82
+ */
83
+ assert.equal(pkg.name, "@nan0web/release")
84
+ })
85
+ /**
86
+ * @docs
87
+ */
88
+ it("How to install with yarn?", () => {
89
+ /**
90
+ * ```bash
91
+ * yarn add @nan0web/release
92
+ * ```
93
+ */
94
+ assert.equal(pkg.name, "@nan0web/release")
95
+ })
96
+
97
+ /**
98
+ * @docs
99
+ * ## CLI Usage
100
+ *
101
+ * Start by initializing a new release:
102
+ */
103
+ it("How to initialize a new release version?", () => {
104
+ /**
105
+ * ```bash
106
+ * release init v1.0.0
107
+ * ```
108
+ */
109
+ const cli = new ReleaseCLI()
110
+ assert.ok(cli instanceof ReleaseCLI)
111
+ })
112
+
113
+ /**
114
+ * @docs
115
+ * Show release details:
116
+ */
117
+ it("How to show release information?", () => {
118
+ /**
119
+ * ```bash
120
+ * release show [--full]
121
+ * ```
122
+ */
123
+ const release = new Release({
124
+ version: "v1.0.0",
125
+ createdAt: new Date("2025-08-20")
126
+ })
127
+ console.info(release.version) // v1.0.0
128
+ assert.strictEqual(console.output()[0][1], "v1.0.0")
129
+ })
130
+
131
+ /**
132
+ * @docs
133
+ * List all releases in the project:
134
+ */
135
+ it("How to list all releases?", () => {
136
+ /**
137
+ * ```bash
138
+ * release list [--json]
139
+ * ```
140
+ */
141
+ const cli = new ReleaseCLI()
142
+ assert.ok(cli.releases)
143
+ })
144
+
145
+ /**
146
+ * @docs
147
+ * Add a chat message to the current release:
148
+ */
149
+ it("How to write a release chat message?", () => {
150
+ /**
151
+ * ```bash
152
+ * release chat write --user alice "Issue with the build pipeline"
153
+ * ```
154
+ */
155
+ const cli = new ReleaseCLI()
156
+ assert.ok(cli instanceof ReleaseCLI)
157
+ })
158
+
159
+ /**
160
+ * @docs
161
+ * Host a static server for viewing releases:
162
+ */
163
+ it("How to host release UI?", () => {
164
+ /**
165
+ * ```bash
166
+ * release host [--webui] [--port 3000]
167
+ * ```
168
+ */
169
+ const cli = new ReleaseCLI()
170
+ assert.ok(cli instanceof ReleaseCLI)
171
+ })
172
+
173
+ /**
174
+ * @docs
175
+ * Serve all release files for local inspection:
176
+ */
177
+ it("How to serve release static assets?", () => {
178
+ /**
179
+ * ```bash
180
+ * release serve [--port 8080]
181
+ * ```
182
+ */
183
+ const cli = new ReleaseCLI()
184
+ assert.ok(cli instanceof ReleaseCLI)
185
+ })
186
+
187
+ /**
188
+ * @docs
189
+ * Validate release tasks and integrity:
190
+ */
191
+ it("How to validate release tasks?", () => {
192
+ /**
193
+ * ```bash
194
+ * release validate [--ignore-fail]
195
+ * ```
196
+ */
197
+ const release = new Release({
198
+ version: "v1.0.0",
199
+ createdAt: new Date("2025-08-20")
200
+ })
201
+ assert.ok(release instanceof Release)
202
+ })
203
+
204
+ /**
205
+ * @docs
206
+ * Seal the release with retro reflection:
207
+ */
208
+ it("How to seal a release?", () => {
209
+ /**
210
+ * ```bash
211
+ * release seal [--message "All core APIs are stable and tested"]
212
+ * ```
213
+ */
214
+ const cli = new ReleaseCLI()
215
+ assert.ok(cli instanceof ReleaseCLI)
216
+ })
217
+
218
+ /**
219
+ * @docs
220
+ * ## Core Concepts
221
+ *
222
+ * ### 1. Release as Object
223
+ *
224
+ * A `Release` is a structured class containing:
225
+ * - `version`: release identifier (vX.Y.Z).
226
+ * - `createdAt`, `startAt`, `planAt`, `completeAt`: datetime milestones.
227
+ * - `document`: parsed markdown document with structure-aware parsing.
228
+ *
229
+ * Each property is typed and validated automatically via JSDoc and runtime parsing.
230
+ */
231
+ it("How to instantiate a Release?", () => {
232
+ //import { Release } from '@nan0web/release'
233
+ const release = new Release({
234
+ version: "v1.0.0",
235
+ createdAt: "2025-08-20T10:00:00Z"
236
+ })
237
+ console.info(release.version) // ← v1.0.0
238
+ console.info(release.createdAt instanceof Date) // ← true
239
+
240
+ assert.strictEqual(console.output()[0][1], "v1.0.0")
241
+ assert.strictEqual(console.output()[1][1], true)
242
+ })
243
+
244
+ /**
245
+ * @docs
246
+ * ### 2. Release Document Parsing
247
+ *
248
+ * A `ReleaseDocument` extends `@nan0web/markdown` with:
249
+ * - Structured parsing of markdown release notes
250
+ * - Extraction of sections and tasks
251
+ * - Team and role parsing from markdown frontmatter or code
252
+ */
253
+ it("How to parse release notes markdown into structured data?", () => {
254
+ //import { ReleaseDocument } from '@nan0web/release'
255
+ const md = `# v1.0.0 - 2025-08-20
256
+
257
+ ## Overview
258
+ Release milestone includes UI polish and core API stabilization.
259
+
260
+ ### Tasks
261
+ ### Done **Implement core UI design** [ui.core-design]
262
+ ### InProgress **Fix responsive issues in mobile layout** [ui.mobile-fixes]`
263
+
264
+ const doc = ReleaseDocument.from(md)
265
+ console.info(doc.version) // ← v1.0.0
266
+ console.info(doc.date instanceof Date) // ← true
267
+ console.info(doc.document.children instanceof Array) // ← true
268
+
269
+ assert.strictEqual(console.output()[0][1], "v1.0.0")
270
+ assert.strictEqual(console.output()[1][1], true)
271
+ assert.strictEqual(console.output()[2][1], true)
272
+ })
273
+
274
+ /**
275
+ * @docs
276
+ * ### 3. Person & Team Structures
277
+ *
278
+ * A `Person` instance includes:
279
+ * - `name`: HumanName
280
+ * - `gender`: HumanGender
281
+ * - `contacts`: array of HumanContact
282
+ */
283
+ it("How to create a Person with typed properties?", () => {
284
+ //import { Person } from '@nan0web/release'
285
+ const person = new Person({
286
+ name: ["Alice", "Developer"],
287
+ gender: "female",
288
+ contacts: ["mailto:alice@example.com"]
289
+ })
290
+ console.info(person.name.firstName) // ← Alice
291
+ console.info(person.contacts.length >= 0) // ← true
292
+
293
+ assert.strictEqual(console.output()[0][1], "Alice")
294
+ assert.strictEqual(console.output()[1][1], true)
295
+ })
296
+
297
+ /**
298
+ * @docs
299
+ * ## Architecture: Project Management as Code
300
+ *
301
+ * This architecture treats tasks as tests, roles as classes, and progress as validated outcomes.
302
+ *
303
+ * ### Task Management
304
+ *
305
+ * Tasks are registered as `taskId` → `testFilePath` in `ProjectManagement`.
306
+ * Their status is derived by running `node:test` suites.
307
+ */
308
+ it("How to register and validate tasks as tests?", async () => {
309
+ //import { ProjectManagement } from '@nan0web/release'
310
+ const pm = new ProjectManagement()
311
+ pm.registerTask("task-1", "./tests/task1.test.js")
312
+ pm.registerTask("task-2", "./tests/task2.test.js")
313
+
314
+ const mockResults = {
315
+ passed: ["task-1"],
316
+ failed: [],
317
+ pending: ["task-2"]
318
+ }
319
+
320
+ pm.validateProjectState = async () => mockResults
321
+ const results = await pm.validateProjectState()
322
+
323
+ console.info(results.passed.includes("task-1")) // ← true
324
+ console.info(results.pending.includes("task-2")) // ← true
325
+
326
+ assert.strictEqual(console.output()[0][1], true)
327
+ assert.strictEqual(console.output()[1][1], true)
328
+ })
329
+
330
+ /**
331
+ * @docs
332
+ * ### Release Processing
333
+ *
334
+ * The `ReleaseManager` coordinates releases and validates readiness.
335
+ * It ensures:
336
+ * - All registered tests pass
337
+ * - Version is correctly incremented
338
+ * - Git tag is applied if all validations succeed
339
+ */
340
+ it("How to execute a release after validation?", async () => {
341
+ //import { ReleaseManager, ProjectManagement } from '@nan0web/release'
342
+ const pm = new ProjectManagement()
343
+ const rm = new ReleaseManager(pm)
344
+
345
+ rm.calculateVersion = () => "v1.0.1"
346
+ rm.publish = async () => true
347
+
348
+ const result = await rm.executeRelease("patch")
349
+ console.info(result.version) // ← v1.0.1
350
+ console.info(result.published) // ← true
351
+
352
+ assert.strictEqual(console.output()[0][1], "v1.0.1")
353
+ assert.strictEqual(console.output()[1][1], true)
354
+ })
355
+
356
+ /**
357
+ * @docs
358
+ * ### Changelog Integration
359
+ *
360
+ * Using `ChangelogTaskManager`, you can:
361
+ * - Extract task definitions from changelog entries
362
+ * - Generate corresponding test files
363
+ * - Automate task progression in CI
364
+ */
365
+ it("How to parse changelog and extract tasks?", () => {
366
+ //import { ChangelogTaskManager } from '@nan0web/release'
367
+ const ctm = new ChangelogTaskManager()
368
+ const changelog = `# Changelog
369
+
370
+ ## [1.0.0] - 2025-08-20
371
+ ### Added
372
+ - Initial structure [core.init]
373
+ - Release notes support [docs.release-notes]`
374
+
375
+ const tasks = ctm.parseChangelog(changelog)
376
+ console.info(Array.isArray(tasks)) // ← true
377
+ console.info(tasks.length >= 0) // ← true
378
+
379
+ assert.strictEqual(console.output()[0][1], true)
380
+ assert.strictEqual(console.output()[1][1], true)
381
+ })
382
+
383
+ /**
384
+ * @docs
385
+ * ## Java•Script Features
386
+ */
387
+ it("Uses JSDoc and .d.ts files for autocompletion", () => {
388
+ assert.ok(pkg.types)
389
+ assert.ok(pkg.types.includes(".d.ts"))
390
+ })
391
+
392
+ /**
393
+ * @docs
394
+ * ## CLI Playground
395
+ *
396
+ * Try the package in the terminal:
397
+ */
398
+ it("How to run playground demo?", async () => {
399
+ /**
400
+ * ```bash
401
+ * git clone https://github.com/nan0web/release.git
402
+ * cd release
403
+ * pnpm install
404
+ * pnpm run playground
405
+ * ```
406
+ */
407
+ assert.ok(pkg.scripts?.playground)
408
+ const response = await runSpawn("git", ["remote", "get-url", "origin"])
409
+ assert.ok(response.code === 0)
410
+ assert.ok(response.text.trim().endsWith(":nan0web/release.git"))
411
+ })
412
+
413
+ /**
414
+ * @docs
415
+ * ## Project Status
416
+ *
417
+ * To verify the project is ready, run:
418
+ */
419
+ it("How to check project status before publishing?", async () => {
420
+ /**
421
+ * ```bash
422
+ * npm test
423
+ * npm run test:coverage
424
+ * npm run test:status
425
+ * ```
426
+ */
427
+ assert.ok(pkg.scripts?.test)
428
+ assert.ok(pkg.scripts?.["test:coverage"])
429
+ assert.ok(pkg.scripts?.["test:status"])
430
+ })
431
+
432
+ /**
433
+ * @docs
434
+ * ## Contributing
435
+ */
436
+ it("How to contribute? - [check here](./CONTRIBUTING.md)", async () => {
437
+ assert.equal(pkg.scripts?.precommit, "npm test")
438
+ assert.equal(pkg.scripts?.prepush, "npm test")
439
+ assert.equal(pkg.scripts?.prepare, "husky")
440
+ })
441
+
442
+ /**
443
+ * @docs
444
+ * ## License
445
+ */
446
+ it("How to license ISC? - [check here](./LICENSE)", async () => {
447
+ /** @docs */
448
+ const text = await fs.loadDocument("LICENSE")
449
+ assert.ok(String(text).includes("ISC"))
450
+ })
451
+ }
452
+
453
+ describe("README.md testing", testRender)
454
+
455
+ describe("Rendering README.md", async () => {
456
+ let text = ""
457
+ const format = new Intl.NumberFormat("en-US").format
458
+ const parser = new DocsParser()
459
+ text = String(parser.decode(testRender))
460
+ await fs.saveDocument("README.md", text)
461
+ const dataset = DatasetParser.parse(text, pkg.name)
462
+ await fs.saveDocument(".datasets/README.dataset.jsonl", dataset)
463
+
464
+ it(`document is rendered [${format(Buffer.byteLength(text))}b]`, async () => {
465
+ const text = await fs.loadDocument("README.md")
466
+ assert.ok(text.includes("## License"))
467
+ })
468
+ })