contentbase 0.0.4 → 0.0.5

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 (82) hide show
  1. package/package.json +1 -1
  2. package/.mcp.json +0 -9
  3. package/MCP-DESCRIPTIONS-REVIEW.md +0 -122
  4. package/bun.lock +0 -512
  5. package/dist/cnotes +0 -0
  6. package/examples/sdlc-queries.ts +0 -161
  7. package/public/web-demo/index.html +0 -813
  8. package/scripts/examples/01-collection-setup.ts +0 -46
  9. package/scripts/examples/02-querying.ts +0 -67
  10. package/scripts/examples/03-sections.ts +0 -36
  11. package/scripts/examples/04-relationships.ts +0 -54
  12. package/scripts/examples/05-document-api.ts +0 -54
  13. package/scripts/examples/06-extract-sections.ts +0 -55
  14. package/scripts/examples/07-validation.ts +0 -46
  15. package/scripts/examples/08-serialization.ts +0 -51
  16. package/scripts/examples/lib/format.ts +0 -87
  17. package/scripts/examples/lib/setup.ts +0 -21
  18. package/scripts/examples/run-all.ts +0 -43
  19. package/showcases/national-parks/models.ts +0 -74
  20. package/showcases/national-parks/parks/acadia.mdx +0 -40
  21. package/showcases/national-parks/parks/yosemite.mdx +0 -44
  22. package/showcases/national-parks/parks/zion.mdx +0 -44
  23. package/showcases/national-parks/queries.ts +0 -103
  24. package/showcases/national-parks/trails/angels-landing.mdx +0 -19
  25. package/showcases/national-parks/trails/cathedral-lakes.mdx +0 -19
  26. package/showcases/national-parks/trails/half-dome.mdx +0 -19
  27. package/showcases/national-parks/trails/jordan-pond-path.mdx +0 -19
  28. package/showcases/national-parks/trails/mist-trail.mdx +0 -19
  29. package/showcases/national-parks/trails/observation-point.mdx +0 -19
  30. package/showcases/national-parks/trails/precipice-trail.mdx +0 -19
  31. package/showcases/national-parks/trails/the-narrows.mdx +0 -19
  32. package/showcases/node_modules/.cache/.repl_history +0 -3
  33. package/showcases/recipes/cuisines/chinese.mdx +0 -28
  34. package/showcases/recipes/cuisines/italian.mdx +0 -32
  35. package/showcases/recipes/cuisines/mexican.mdx +0 -28
  36. package/showcases/recipes/models.ts +0 -77
  37. package/showcases/recipes/queries.ts +0 -89
  38. package/showcases/recipes/recipes/chinese/egg-fried-rice.mdx +0 -43
  39. package/showcases/recipes/recipes/chinese/mapo-tofu.mdx +0 -47
  40. package/showcases/recipes/recipes/italian/bruschetta.mdx +0 -38
  41. package/showcases/recipes/recipes/italian/cacio-e-pepe.mdx +0 -39
  42. package/showcases/recipes/recipes/italian/tiramisu.mdx +0 -43
  43. package/showcases/recipes/recipes/mexican/chicken-tinga.mdx +0 -44
  44. package/showcases/recipes/recipes/mexican/guacamole.mdx +0 -39
  45. package/showcases/vinyl-collection/albums/bitches-brew.mdx +0 -36
  46. package/showcases/vinyl-collection/albums/i-put-a-spell-on-you.mdx +0 -35
  47. package/showcases/vinyl-collection/albums/in-rainbows.mdx +0 -35
  48. package/showcases/vinyl-collection/albums/kind-of-blue.mdx +0 -32
  49. package/showcases/vinyl-collection/albums/ok-computer.mdx +0 -37
  50. package/showcases/vinyl-collection/albums/wild-is-the-wind.mdx +0 -35
  51. package/showcases/vinyl-collection/artists/miles-davis.mdx +0 -27
  52. package/showcases/vinyl-collection/artists/nina-simone.mdx +0 -26
  53. package/showcases/vinyl-collection/artists/radiohead.mdx +0 -27
  54. package/showcases/vinyl-collection/models.ts +0 -73
  55. package/showcases/vinyl-collection/queries.ts +0 -87
  56. package/src/__tests__/semantic-search.integration.test.ts +0 -284
  57. package/test/ast-query.test.ts +0 -128
  58. package/test/collection.test.ts +0 -215
  59. package/test/define-model.test.ts +0 -78
  60. package/test/document.test.ts +0 -225
  61. package/test/extract-sections.test.ts +0 -356
  62. package/test/fixtures/sdlc/MODELS.md +0 -106
  63. package/test/fixtures/sdlc/SKILL.md +0 -404
  64. package/test/fixtures/sdlc/epics/authentication.mdx +0 -42
  65. package/test/fixtures/sdlc/epics/searching-and-browsing.mdx +0 -21
  66. package/test/fixtures/sdlc/index.ts +0 -9
  67. package/test/fixtures/sdlc/models.ts +0 -91
  68. package/test/fixtures/sdlc/stories/authentication/a-user-should-be-able-to-login.mdx +0 -20
  69. package/test/fixtures/sdlc/stories/authentication/a-user-should-be-able-to-register.mdx +0 -20
  70. package/test/fixtures/sdlc/templates/epic.md +0 -23
  71. package/test/fixtures/sdlc/templates/story.md +0 -19
  72. package/test/helpers.ts +0 -21
  73. package/test/model-instance.test.ts +0 -197
  74. package/test/pattern.test.ts +0 -191
  75. package/test/query-dsl.test.ts +0 -431
  76. package/test/query.test.ts +0 -196
  77. package/test/relationships.test.ts +0 -214
  78. package/test/section.test.ts +0 -160
  79. package/test/table-of-contents.test.ts +0 -135
  80. package/test/validator.test.ts +0 -62
  81. package/tsconfig.json +0 -18
  82. package/vitest.config.ts +0 -11
@@ -1,404 +0,0 @@
1
- # SDLC Collection Skill
2
-
3
- You have access to a loaded contentbase collection that models a software development lifecycle (SDLC) with Epics and Stories as markdown files.
4
-
5
- ## Setup
6
-
7
- The collection is already loaded and available as `collection`. The models `Epic` and `Story` are already imported.
8
-
9
- ```ts
10
- import { Collection } from "contentbase";
11
- import { Epic, Story } from "./models";
12
-
13
- const collection = new Collection({ rootPath: "./content" });
14
- collection.register(Epic);
15
- collection.register(Story);
16
- await collection.load();
17
- ```
18
-
19
- ## Models
20
-
21
- ### Epic
22
-
23
- **Prefix:** `epics` — files live in `epics/` (e.g. `epics/authentication.mdx`)
24
-
25
- | Field | Type | Required | Default |
26
- |-------|------|----------|---------|
27
- | priority | `"low"` \| `"medium"` \| `"high"` | optional | — |
28
- | status | `"created"` \| `"in-progress"` \| `"complete"` | optional | `"created"` |
29
-
30
- **Relationships:**
31
- - `stories` — **hasMany** Story (extracted from the `## Stories` heading in the epic's markdown)
32
-
33
- **Computed:**
34
- - `isComplete` — boolean, true when `status === "complete"`
35
-
36
- ### Story
37
-
38
- **Prefix:** `stories` — files live in `stories/` (e.g. `stories/authentication/a-user-should-be-able-to-register.mdx`)
39
-
40
- | Field | Type | Required | Default |
41
- |-------|------|----------|---------|
42
- | status | `"created"` \| `"in-progress"` \| `"complete"` | optional | `"created"` |
43
- | epic | string | optional | — |
44
-
45
- **Sections:**
46
- - `acceptanceCriteria` — heading: "Acceptance Criteria" — returns `string[]` (list items)
47
- - `mockups` — heading: "Mockups" — returns `Record<string, string>` (link label → URL)
48
-
49
- **Relationships:**
50
- - `epic` — **belongsTo** Epic (via `meta.epic` foreign key)
51
-
52
- **Computed:**
53
- - `isComplete` — boolean, true when `status === "complete"`
54
-
55
- ## Example Documents
56
-
57
- An Epic markdown file (`epics/authentication.mdx`):
58
-
59
- ```mdx
60
- ---
61
- priority: high
62
- status: created
63
- ---
64
-
65
- # Authentication
66
-
67
- The Authentication stories cover users logging in and out of the application.
68
-
69
- ## Stories
70
-
71
- ### A User should be able to register.
72
-
73
- As a User I would like to register so that I can use the application.
74
-
75
- #### Acceptance Criteria
76
-
77
- - A user can visit the signup form, supply their name, email, and password
78
- - The signup form should validate the user's information and supply errors
79
-
80
- #### Mockups
81
-
82
- - [Invision: Registration Form](https://invisionapp.com)
83
- ```
84
-
85
- A Story markdown file (`stories/authentication/a-user-should-be-able-to-register.mdx`):
86
-
87
- ```mdx
88
- ---
89
- status: created
90
- epic: authentication
91
- ---
92
-
93
- # A User should be able to register.
94
-
95
- As a User I would like to register so that I can use the application.
96
-
97
- ## Acceptance Criteria
98
-
99
- - A user can visit the signup form, supply their name, email, and password
100
- - The signup form should validate the user's information and supply errors
101
- - The user should receive a confirmation email
102
-
103
- ## Mockups
104
-
105
- - [Invision: Registration Form](https://invisionapp.com)
106
- - [Invision: Registration Form Error State](https://invisionapp.com)
107
- ```
108
-
109
- ## Querying
110
-
111
- ### Fetch all instances of a model
112
-
113
- ```ts
114
- const allEpics = await collection.query(Epic).fetchAll();
115
- const allStories = await collection.query(Story).fetchAll();
116
- ```
117
-
118
- ### Filter with where clauses
119
-
120
- The `where` method supports three call signatures:
121
-
122
- ```ts
123
- // Two-arg: implicit equality
124
- .where("meta.status", "created")
125
-
126
- // Three-arg: explicit operator
127
- .where("meta.priority", "neq", "low")
128
-
129
- // Object shorthand: multiple equality conditions
130
- .where({ "meta.status": "created", "meta.priority": "high" })
131
- ```
132
-
133
- Conditions are AND-ed together when chained:
134
-
135
- ```ts
136
- const results = await collection.query(Epic)
137
- .where("meta.status", "created")
138
- .where("meta.priority", "high")
139
- .fetchAll();
140
- ```
141
-
142
- ### Available operators
143
-
144
- | Operator | Description | Example |
145
- |----------|-------------|---------|
146
- | `eq` | Equality (default) | `.where("meta.status", "created")` |
147
- | `neq` | Not equal | `.where("meta.status", "neq", "complete")` |
148
- | `gt` | Greater than | `.where("meta.priority", "gt", "low")` |
149
- | `lt` | Less than | `.where("meta.priority", "lt", "high")` |
150
- | `gte` | Greater than or equal | `.whereGte("meta.priority", "medium")` |
151
- | `lte` | Less than or equal | `.whereLte("meta.priority", "medium")` |
152
- | `in` | Value in array | `.whereIn("meta.status", ["created", "in-progress"])` |
153
- | `notIn` | Value not in array | `.whereNotIn("meta.status", ["complete"])` |
154
- | `contains` | String contains | `.whereContains("title", "auth")` |
155
- | `startsWith` | String starts with | `.whereStartsWith("id", "epics/")` |
156
- | `endsWith` | String ends with | `.whereEndsWith("title", "register.")` |
157
- | `regex` | Regex match | `.whereRegex("title", /auth/i)` |
158
- | `exists` | Field is defined | `.whereExists("meta.priority")` |
159
- | | Field is not defined | `.whereNotExists("meta.priority")` |
160
-
161
- ### Result methods
162
-
163
- ```ts
164
- const all = await collection.query(Epic).fetchAll(); // Epic[]
165
- const first = await collection.query(Epic).first(); // Epic | undefined
166
- const last = await collection.query(Epic).last(); // Epic | undefined
167
- const count = await collection.query(Epic).count(); // number
168
- ```
169
-
170
- ### Query paths
171
-
172
- Where clauses use dot-notation to reach nested properties on the model instance. Valid paths include:
173
-
174
- - `id` — the document path ID (e.g. `"epics/authentication"`)
175
- - `title` — the document title (from first heading)
176
- - `slug` — kebab-cased title
177
- - `meta.status` — frontmatter fields
178
- - `meta.priority`
179
- - `computed.isComplete`
180
-
181
- ## Model Instance Properties
182
-
183
- When you get a model instance (from a query, `getModel`, or a relationship), it has these properties:
184
-
185
- ```ts
186
- const epic = await collection.query(Epic).first();
187
-
188
- epic.id // "epics/authentication"
189
- epic.title // "Authentication"
190
- epic.slug // "authentication"
191
- epic.meta.status // "created"
192
- epic.meta.priority // "high" | undefined
193
-
194
- // Computed properties
195
- epic.computed.isComplete // false
196
-
197
- // Sections (Story only)
198
- const story = await collection.query(Story).first();
199
- story.sections.acceptanceCriteria // ["A user can visit...", "The signup form..."]
200
- story.sections.mockups // { "Invision: Registration Form": "https://..." }
201
- ```
202
-
203
- ### Get a specific instance by path ID
204
-
205
- ```ts
206
- const epic = collection.getModel("epics/authentication", Epic);
207
- const story = collection.getModel("stories/authentication/a-user-should-be-able-to-register", Story);
208
- ```
209
-
210
- ## Relationships
211
-
212
- ### hasMany (Epic → Stories)
213
-
214
- ```ts
215
- const epic = collection.getModel("epics/authentication", Epic);
216
-
217
- const stories = epic.relationships.stories.fetchAll(); // Story[]
218
- const first = epic.relationships.stories.first(); // Story | undefined
219
- const last = epic.relationships.stories.last(); // Story | undefined
220
- ```
221
-
222
- Note: `hasMany` extracts child documents from sub-headings within the parent's markdown. Each `### Heading` under `## Stories` becomes a Story instance.
223
-
224
- ### belongsTo (Story → Epic)
225
-
226
- ```ts
227
- const story = collection.getModel(
228
- "stories/authentication/a-user-should-be-able-to-register",
229
- Story
230
- );
231
-
232
- const parentEpic = story.relationships.epic.fetch(); // Epic
233
- parentEpic.title // "Authentication"
234
- ```
235
-
236
- ## Validation
237
-
238
- ```ts
239
- const result = await story.validate();
240
- result.valid // boolean
241
- result.errors // ZodIssue[] — empty if valid
242
- ```
243
-
244
- ## Serialization
245
-
246
- ```ts
247
- // Basic: id, title, meta
248
- epic.toJSON()
249
-
250
- // Include computed properties
251
- epic.toJSON({ computed: ["isComplete"] })
252
-
253
- // Include related models (serialized recursively)
254
- epic.toJSON({ related: ["stories"] })
255
-
256
- // Include sections
257
- story.toJSON({ sections: ["acceptanceCriteria", "mockups"] })
258
-
259
- // Combine all
260
- story.toJSON({
261
- sections: ["acceptanceCriteria"],
262
- computed: ["isComplete"],
263
- related: ["epic"],
264
- })
265
- ```
266
-
267
- ## Document Access
268
-
269
- Every model instance has a `.document` property with the underlying Document:
270
-
271
- ```ts
272
- const doc = epic.document;
273
-
274
- doc.id // "epics/authentication"
275
- doc.content // raw markdown body (without frontmatter)
276
- doc.meta // { priority: "high", status: "created" }
277
- doc.title // "Authentication"
278
- doc.rawContent // full markdown including frontmatter
279
- ```
280
-
281
- ### Document outline and text
282
-
283
- ```ts
284
- doc.toOutline() // indented heading tree
285
- doc.toText() // all text content concatenated
286
- ```
287
-
288
- ### AST queries on documents
289
-
290
- ```ts
291
- doc.nodes.headings // all heading nodes
292
- doc.nodes.links // all link nodes
293
- doc.nodes.lists // all list nodes
294
-
295
- doc.astQuery.select("heading") // first heading node
296
- doc.astQuery.selectAll("listItem") // all list items
297
- doc.astQuery.findHeadingByText("Stories") // specific heading
298
- ```
299
-
300
- ### Extracting sections from documents
301
-
302
- ```ts
303
- const sectionNodes = doc.extractSection("Stories"); // AST nodes under "Stories"
304
- const sectionQuery = doc.querySection("Stories"); // AstQuery scoped to section
305
- const items = sectionQuery.selectAll("listItem");
306
- ```
307
-
308
- ### Mutating documents (immutable by default)
309
-
310
- ```ts
311
- // Returns a NEW document
312
- const updated = doc.replaceSectionContent("Stories", "New content here");
313
- const removed = doc.removeSection("Mockups");
314
- const appended = doc.appendToSection("Acceptance Criteria", "- New criterion");
315
-
316
- // Mutate in place instead
317
- doc.replaceSectionContent("Stories", "New content", { mutate: true });
318
-
319
- // Persist changes to disk
320
- await doc.save();
321
- ```
322
-
323
- ## Collection Utilities
324
-
325
- ```ts
326
- // List all document IDs
327
- collection.available // ["epics/authentication", "epics/searching-and-browsing", ...]
328
-
329
- // Check if loaded
330
- collection.loaded // boolean
331
-
332
- // Generate a markdown table of contents
333
- collection.tableOfContents({ title: "SDLC Docs" })
334
-
335
- // Get a summary of all models
336
- await collection.generateModelSummary() // writes README.md and returns markdown
337
-
338
- // Export everything as JSON
339
- await collection.export()
340
- ```
341
-
342
- ## Patterns and Recipes
343
-
344
- ### Find all incomplete items across models
345
-
346
- ```ts
347
- const incompleteEpics = await collection.query(Epic)
348
- .where("meta.status", "neq", "complete")
349
- .fetchAll();
350
-
351
- const incompleteStories = await collection.query(Story)
352
- .where("meta.status", "neq", "complete")
353
- .fetchAll();
354
- ```
355
-
356
- ### Find stories for a specific epic
357
-
358
- ```ts
359
- const epic = collection.getModel("epics/authentication", Epic);
360
- const stories = epic.relationships.stories.fetchAll();
361
-
362
- // Or query standalone story files by their epic foreign key
363
- const standaloneStories = await collection.query(Story)
364
- .where("meta.epic", "authentication")
365
- .fetchAll();
366
- ```
367
-
368
- ### Check acceptance criteria coverage
369
-
370
- ```ts
371
- const stories = await collection.query(Story).fetchAll();
372
-
373
- for (const story of stories) {
374
- const criteria = story.sections.acceptanceCriteria;
375
- console.log(`${story.title}: ${criteria.length} criteria`);
376
- }
377
- ```
378
-
379
- ### Get all high-priority epics and their stories
380
-
381
- ```ts
382
- const highPriority = await collection.query(Epic)
383
- .where("meta.priority", "high")
384
- .fetchAll();
385
-
386
- for (const epic of highPriority) {
387
- const stories = epic.relationships.stories.fetchAll();
388
- console.log(`${epic.title}: ${stories.length} stories`);
389
- }
390
- ```
391
-
392
- ### Summarize project status
393
-
394
- ```ts
395
- const epics = await collection.query(Epic).fetchAll();
396
-
397
- const summary = epics.map(epic => ({
398
- title: epic.title,
399
- status: epic.meta.status,
400
- priority: epic.meta.priority,
401
- storyCount: epic.relationships.stories.fetchAll().length,
402
- isComplete: epic.computed.isComplete,
403
- }));
404
- ```
@@ -1,42 +0,0 @@
1
- ---
2
- priority: high
3
- status: created
4
- ---
5
-
6
- # Authentication
7
-
8
- The Authentication stories cover users logging in and out of the application, as well as the roles and permissions granted to these users and how they are enforced in the application.
9
-
10
- ## Stories
11
-
12
- ### A User should be able to register.
13
-
14
- As a User I would like to register so that I can use the application.
15
-
16
- #### Acceptance Criteria
17
-
18
- - A user can visit the signup form, supply their name, email, and password
19
- - The signup form should validate the user's information and supply errors
20
- - The user should receive a confirmation email
21
- - The user should show up in our database as confirmed after clicking the confirmation link
22
-
23
- #### Mockups
24
-
25
- - [Invision: Registration Form](https://invisionapp.com)
26
- - [Invision: Registration Form Error State](https://invisionapp.com)
27
-
28
- ### A User should be able to login.
29
-
30
- As a User I would like to login so that I can use the application.
31
-
32
- #### Acceptance Criteria
33
-
34
- - A user can visit the signup form, supply their name, email, and password
35
- - The signup form should validate the user's information and supply errors
36
- - The user should receive a confirmation email
37
- - The user should show up in our database as confirmed after clicking the confirmation link
38
-
39
- #### Mockups
40
-
41
- - [Invision: Login Form](https://invisionapp.com)
42
- - [Invision: Login Form Error State ](https://invisionapp.com)
@@ -1,21 +0,0 @@
1
- ---
2
- status: created
3
- ---
4
-
5
- # Searching And Browsing
6
-
7
- This epic covers the stories related to searching for a specific item.
8
-
9
- ## Stories
10
-
11
- ### Searching for a product by category
12
-
13
- As a user I want to be able to search for a product by category so that I can find the right product for me.
14
-
15
- ### Searching for a product by manufacturer
16
-
17
- As a user I want to be able to search for a product by manufacturer so that I can find the right product for me.
18
-
19
- ### Searching for a product by name
20
-
21
- As a user I want to be able to search for a product by name so that I can find the right product for me.
@@ -1,9 +0,0 @@
1
- import { Collection } from "../../../src/collection";
2
- import { Epic, Story } from "./models";
3
-
4
- export const collection = new Collection({
5
- rootPath: import.meta.dir,
6
- });
7
-
8
- collection.register(Epic);
9
- collection.register(Story);
@@ -1,91 +0,0 @@
1
- import {
2
- defineModel,
3
- section,
4
- hasMany,
5
- belongsTo,
6
- z,
7
- type ModelDefinition,
8
- type HasManyDefinition,
9
- type BelongsToDefinition,
10
- type SectionDefinition,
11
- } from "../../../src/index";
12
- import { toString } from "mdast-util-to-string";
13
-
14
- const epicMeta = z.object({
15
- priority: z.enum(["low", "medium", "high"]).optional().describe("Importance level for prioritization"),
16
- status: z
17
- .enum(["created", "in-progress", "complete"])
18
- .default("created")
19
- .describe("Current workflow state"),
20
- });
21
-
22
- const storyMeta = z.object({
23
- status: z
24
- .enum(["created", "in-progress", "complete"])
25
- .default("created")
26
- .describe("Current workflow state"),
27
- epic: z.string().optional().describe("Slug of the parent epic"),
28
- });
29
-
30
- /** Explicit type for Epic so circular Epic↔Story inference doesn’t collapse to never */
31
- export type EpicDef = ModelDefinition<
32
- "Epic",
33
- typeof epicMeta,
34
- Record<string, never>,
35
- { stories: HasManyDefinition<StoryDef> },
36
- { isComplete: (self: any) => boolean }
37
- >;
38
-
39
- /** Explicit type for Story so circular Epic↔Story inference doesn’t collapse to never */
40
- export type StoryDef = ModelDefinition<
41
- "Story",
42
- typeof storyMeta,
43
- Record<string, SectionDefinition<any>>,
44
- { epic: BelongsToDefinition<EpicDef> },
45
- { isComplete: (self: any) => boolean }
46
- >;
47
-
48
- export const Epic: EpicDef = defineModel("Epic", {
49
- prefix: "epics",
50
- meta: epicMeta,
51
- relationships: {
52
- stories: hasMany(() => Story, {
53
- heading: "Stories",
54
- }),
55
- },
56
- computed: {
57
- isComplete: (self: any) => self.meta.status === "complete",
58
- },
59
- defaults: {
60
- status: "created",
61
- },
62
- });
63
-
64
- export const Story: StoryDef = defineModel("Story", {
65
- prefix: "stories",
66
- meta: storyMeta,
67
- sections: {
68
- acceptanceCriteria: section("Acceptance Criteria", {
69
- extract: (query) =>
70
- query.selectAll("listItem").map((n) => toString(n)),
71
- schema: z.array(z.string()).describe("List of acceptance criteria as plain text strings"),
72
- }),
73
- mockups: section("Mockups", {
74
- extract: (query) =>
75
- Object.fromEntries(
76
- query
77
- .selectAll("link")
78
- .map((l: any) => [toString(l), l.url])
79
- ),
80
- schema: z.record(z.string(), z.string()).describe("Map of mockup label to URL"),
81
- }),
82
- },
83
- relationships: {
84
- epic: belongsTo(() => Epic, {
85
- foreignKey: (doc) => doc.meta.epic as string,
86
- }),
87
- },
88
- computed: {
89
- isComplete: (self: any) => self.meta.status === "complete",
90
- },
91
- });
@@ -1,20 +0,0 @@
1
- ---
2
- status: created
3
- epic: authentication
4
- ---
5
-
6
- # A User should be able to login.
7
-
8
- As a User I would like to login so that I can use the application.
9
-
10
- ## Acceptance Criteria
11
-
12
- - A user can visit the signup form, supply their name, email, and password
13
- - The signup form should validate the user's information and supply errors
14
- - The user should receive a confirmation email
15
- - The user should show up in our database as confirmed after clicking the confirmation link
16
-
17
- ## Mockups
18
-
19
- - [Invision: Login Form](https://invisionapp.com)
20
- - [Invision: Login Form Error State](https://invisionapp.com)
@@ -1,20 +0,0 @@
1
- ---
2
- status: created
3
- epic: authentication
4
- ---
5
-
6
- # A User should be able to register.
7
-
8
- As a User I would like to register so that I can use the application.
9
-
10
- ## Acceptance Criteria
11
-
12
- - A user can visit the signup form, supply their name, email, and password
13
- - The signup form should validate the user's information and supply errors
14
- - The user should receive a confirmation email
15
- - The user should show up in our database as confirmed after clicking the confirmation link
16
-
17
- ## Mockups
18
-
19
- - [Invision: Registration Form](https://invisionapp.com)
20
- - [Invision: Registration Form Error State](https://invisionapp.com)
@@ -1,23 +0,0 @@
1
- ---
2
- priority: medium
3
- status: created
4
- ---
5
-
6
- # Epic Title
7
-
8
- A brief description of this epic and its goals.
9
-
10
- ## Stories
11
-
12
- ### Story Title
13
-
14
- A brief description of this story.
15
-
16
- #### Acceptance Criteria
17
-
18
- - First acceptance criterion
19
- - Second acceptance criterion
20
-
21
- #### Mockups
22
-
23
- [Wireframe](https://example.com/wireframe)
@@ -1,19 +0,0 @@
1
- ---
2
- status: created
3
- epic: epic-slug
4
- ---
5
-
6
- # Story Title
7
-
8
- A brief description of what this story accomplishes.
9
-
10
- ## Acceptance Criteria
11
-
12
- - First acceptance criterion
13
- - Second acceptance criterion
14
- - Third acceptance criterion
15
-
16
- ## Mockups
17
-
18
- [Main View](https://example.com/main-view)
19
- [Detail View](https://example.com/detail-view)
package/test/helpers.ts DELETED
@@ -1,21 +0,0 @@
1
- import path from "path";
2
- import { Collection } from "../src/collection";
3
- import { Epic, Story } from "./fixtures/sdlc/models";
4
-
5
- const dir = import.meta.dirname ?? new URL(".", import.meta.url).pathname;
6
-
7
- export const FIXTURES_PATH = path.resolve(
8
- dir,
9
- "fixtures/sdlc"
10
- );
11
-
12
- export async function createTestCollection(): Promise<Collection> {
13
- const collection = new Collection({
14
- rootPath: FIXTURES_PATH,
15
- name: "test-sdlc",
16
- });
17
- collection.register(Epic);
18
- collection.register(Story);
19
- await collection.load();
20
- return collection;
21
- }