get-tbd 0.1.13 → 0.1.14
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.
- package/README.md +37 -24
- package/dist/bin.mjs +410 -170
- package/dist/bin.mjs.map +1 -1
- package/dist/cli.mjs +202 -94
- package/dist/cli.mjs.map +1 -1
- package/dist/docs/README.md +37 -24
- package/dist/docs/SKILL.md +61 -18
- package/dist/docs/guidelines/cli-agent-skill-patterns.md +77 -4
- package/dist/docs/guidelines/error-handling-rules.md +66 -0
- package/dist/docs/guidelines/release-notes-guidelines.md +140 -0
- package/dist/docs/guidelines/typescript-yaml-handling-rules.md +195 -0
- package/dist/docs/install/claude-header.md +13 -6
- package/dist/docs/shortcuts/standard/agent-handoff.md +1 -0
- package/dist/docs/shortcuts/standard/checkout-third-party-repo.md +50 -0
- package/dist/docs/shortcuts/standard/{cleanup-all.md → code-cleanup-all.md} +3 -2
- package/dist/docs/shortcuts/standard/{cleanup-update-docstrings.md → code-cleanup-docstrings.md} +1 -0
- package/dist/docs/shortcuts/standard/{cleanup-remove-trivial-tests.md → code-cleanup-tests.md} +1 -0
- package/dist/docs/shortcuts/standard/{commit-code.md → code-review-and-commit.md} +1 -0
- package/dist/docs/shortcuts/standard/create-or-update-pr-simple.md +1 -0
- package/dist/docs/shortcuts/standard/create-or-update-pr-with-validation-plan.md +1 -0
- package/dist/docs/shortcuts/standard/implement-beads.md +1 -0
- package/dist/docs/shortcuts/standard/merge-upstream.md +1 -0
- package/dist/docs/shortcuts/standard/new-architecture-doc.md +1 -0
- package/dist/docs/shortcuts/standard/new-guideline.md +8 -0
- package/dist/docs/shortcuts/standard/new-plan-spec.md +1 -0
- package/dist/docs/shortcuts/standard/new-research-brief.md +1 -0
- package/dist/docs/shortcuts/standard/new-shortcut.md +27 -1
- package/dist/docs/shortcuts/standard/new-validation-plan.md +1 -0
- package/dist/docs/shortcuts/standard/plan-implementation-with-beads.md +1 -0
- package/dist/docs/shortcuts/standard/precommit-process.md +1 -0
- package/dist/docs/shortcuts/standard/review-code-python.md +1 -0
- package/dist/docs/shortcuts/standard/review-code-typescript.md +1 -0
- package/dist/docs/shortcuts/standard/review-code.md +1 -0
- package/dist/docs/shortcuts/standard/review-github-pr.md +1 -0
- package/dist/docs/shortcuts/standard/revise-all-architecture-docs.md +1 -0
- package/dist/docs/shortcuts/standard/revise-architecture-doc.md +1 -0
- package/dist/docs/shortcuts/standard/setup-github-cli.md +1 -0
- package/dist/docs/shortcuts/standard/sync-failure-recovery.md +6 -53
- package/dist/docs/shortcuts/standard/update-specs-status.md +1 -0
- package/dist/docs/shortcuts/standard/welcome-user.md +2 -1
- package/dist/docs/shortcuts/system/skill-brief.md +1 -1
- package/dist/docs/shortcuts/system/skill.md +48 -12
- package/dist/docs/skill-brief.md +1 -1
- package/dist/docs/tbd-design.md +13 -1
- package/dist/index.d.mts +20 -6
- package/dist/index.mjs +2 -2
- package/dist/{src-BfhjLZXE.mjs → src-DdSZ1dgK.mjs} +154 -22
- package/dist/src-DdSZ1dgK.mjs.map +1 -0
- package/dist/tbd +410 -170
- package/package.json +1 -1
- package/dist/src-BfhjLZXE.mjs.map +0 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Welcome User
|
|
3
3
|
description: Welcome message for users after tbd installation or setup
|
|
4
|
+
category: session
|
|
4
5
|
author: Joshua Levy (github.com/jlevy) with LLM assistance
|
|
5
6
|
---
|
|
6
7
|
Welcome the user with the message below.
|
|
@@ -38,7 +39,7 @@ Here are examples of things you can say and what happens:
|
|
|
38
39
|
| "Let's plan a new feature" | Walks you through creating a planning spec (`tbd shortcut new-plan-spec`) |
|
|
39
40
|
| "Break the spec into issues" | Creates implementation beads from your spec (`tbd shortcut plan-implementation-with-beads`) |
|
|
40
41
|
| "Implement these issues" | Works through beads systematically (`tbd shortcut implement-beads`) |
|
|
41
|
-
| "Commit this code" | Reviews changes and commits properly (`tbd shortcut commit
|
|
42
|
+
| "Commit this code" | Reviews changes and commits properly (`tbd shortcut code-review-and-commit`) |
|
|
42
43
|
| "Create a PR" | Creates a pull request with summary (`tbd shortcut create-or-update-pr-simple`) |
|
|
43
44
|
| "Review this for best practices" | Performs a code review with guidelines |
|
|
44
45
|
|
|
@@ -27,7 +27,7 @@ tbd sync # Sync with remote
|
|
|
27
27
|
| --- | --- |
|
|
28
28
|
| Found a bug | `tbd create "..." --type=bug` |
|
|
29
29
|
| Plan a feature | `tbd shortcut new-plan-spec` |
|
|
30
|
-
| Commit code | `tbd shortcut commit
|
|
30
|
+
| Commit code | `tbd shortcut code-review-and-commit` |
|
|
31
31
|
| Create a PR | `tbd shortcut create-or-update-pr-simple` |
|
|
32
32
|
| TypeScript review | `tbd guidelines typescript-rules` |
|
|
33
33
|
|
|
@@ -6,16 +6,19 @@ description: Full tbd workflow guide for agents
|
|
|
6
6
|
|
|
7
7
|
1. **Beads**: Git-native issue tracking (tasks, bugs, features).
|
|
8
8
|
Never lose work across sessions.
|
|
9
|
+
Drop-in replacement for `bd`.
|
|
9
10
|
2. **Spec-Driven Workflows**: Plan features → break into beads → implement
|
|
10
11
|
systematically.
|
|
11
|
-
3. **
|
|
12
|
-
|
|
12
|
+
3. **Knowledge Injection**: 17+ engineering guidelines (TypeScript, Python, TDD,
|
|
13
|
+
testing, Convex, monorepos) available on demand.
|
|
14
|
+
4. **Shortcuts**: Reusable instruction templates for common workflows (code review,
|
|
15
|
+
commits, PRs, cleanup, handoffs).
|
|
13
16
|
|
|
14
17
|
## Installation
|
|
15
18
|
|
|
16
19
|
```bash
|
|
17
20
|
npm install -g get-tbd@latest
|
|
18
|
-
tbd setup --auto --prefix=<name> # Fresh project (--prefix is REQUIRED
|
|
21
|
+
tbd setup --auto --prefix=<name> # Fresh project (--prefix is REQUIRED: 2-8 alphabetic chars recommended. ALWAYS ASK THE USER FOR THE PREFIX; do not guess it)
|
|
19
22
|
tbd setup --auto # Existing tbd project (prefix already set)
|
|
20
23
|
tbd setup --from-beads # Migration from .beads/ if `bd` has been used
|
|
21
24
|
```
|
|
@@ -48,20 +51,42 @@ or want help → run `tbd shortcut welcome-user`
|
|
|
48
51
|
|
|
49
52
|
| User Says | You (the Agent) Run |
|
|
50
53
|
| --- | --- |
|
|
54
|
+
| **Issues/Beads** | |
|
|
51
55
|
| "There's a bug where ..." | `tbd create "..." --type=bug` |
|
|
52
|
-
| "
|
|
53
|
-
| "
|
|
54
|
-
| "
|
|
55
|
-
| "
|
|
56
|
-
| "
|
|
57
|
-
| "
|
|
58
|
-
| "
|
|
56
|
+
| "Create a task/feature for ..." | `tbd create "..." --type=task` or `--type=feature` |
|
|
57
|
+
| "Let's work on issues/beads" | `tbd ready` |
|
|
58
|
+
| "Show me issue X" | `tbd show <id>` |
|
|
59
|
+
| "Close this issue" | `tbd close <id>` |
|
|
60
|
+
| "Search issues for X" | `tbd search "X"` |
|
|
61
|
+
| "Add label X to issue" | `tbd label add <id> <label>` |
|
|
62
|
+
| "What issues are stale?" | `tbd stale` |
|
|
63
|
+
| **Planning & Specs** | |
|
|
64
|
+
| "Plan a new feature" / "Create a spec" | `tbd shortcut new-plan-spec` |
|
|
59
65
|
| "Break spec into beads" | `tbd shortcut plan-implementation-with-beads` |
|
|
60
66
|
| "Implement these beads" | `tbd shortcut implement-beads` |
|
|
61
|
-
|
|
|
62
|
-
| "
|
|
67
|
+
| **Code Review & Commits** | |
|
|
68
|
+
| "Review this code" / "Code review" | `tbd shortcut review-code` |
|
|
69
|
+
| "Review this PR" | `tbd shortcut review-github-pr` |
|
|
70
|
+
| "Commit this" / "Use the commit shortcut" | `tbd shortcut code-review-and-commit` |
|
|
71
|
+
| "Create a PR" / "File a PR" | `tbd shortcut create-or-update-pr-simple` |
|
|
72
|
+
| "Merge main into my branch" | `tbd shortcut merge-upstream` |
|
|
73
|
+
| **Guidelines & Knowledge** | |
|
|
74
|
+
| "Use TypeScript best practices" | `tbd guidelines typescript-rules` |
|
|
75
|
+
| "Use Python best practices" | `tbd guidelines python-rules` |
|
|
76
|
+
| "Build a TypeScript CLI" | `tbd guidelines typescript-cli-tool-rules` |
|
|
77
|
+
| "Improve monorepo setup" | `tbd guidelines typescript-monorepo-patterns` |
|
|
78
|
+
| "Add golden/e2e testing" | `tbd guidelines golden-testing-guidelines` |
|
|
79
|
+
| "Use TDD" / "Test-driven development" | `tbd guidelines general-tdd-guidelines` |
|
|
80
|
+
| "Convex best practices" | `tbd guidelines convex-rules` |
|
|
81
|
+
| **Documentation** | |
|
|
63
82
|
| "Research this topic" | `tbd shortcut new-research-brief` |
|
|
64
83
|
| "Document architecture" | `tbd shortcut new-architecture-doc` |
|
|
84
|
+
| **Cleanup & Maintenance** | |
|
|
85
|
+
| "Clean up this code" / "Remove dead code" | `tbd shortcut code-cleanup-all` |
|
|
86
|
+
| "Fix repository problems" | `tbd doctor --fix` |
|
|
87
|
+
| **Sessions & Handoffs** | |
|
|
88
|
+
| "Hand off to another agent" | `tbd shortcut agent-handoff` |
|
|
89
|
+
| "Check out this library's source" | `tbd shortcut checkout-third-party-repo` |
|
|
65
90
|
| *(your choice whenever appropriate)* | `tbd list`, `tbd dep add`, `tbd close`, `tbd sync`, etc. |
|
|
66
91
|
|
|
67
92
|
## CRITICAL: Session Closing Protocol
|
|
@@ -115,6 +140,17 @@ or want help → run `tbd shortcut welcome-user`
|
|
|
115
140
|
| `tbd sync` | Sync with git remote (run at session end) |
|
|
116
141
|
| `tbd stats` | Project statistics |
|
|
117
142
|
| `tbd doctor` | Check for problems |
|
|
143
|
+
| `tbd doctor --fix` | Auto-fix repository problems |
|
|
144
|
+
|
|
145
|
+
### Labels & Search
|
|
146
|
+
|
|
147
|
+
| Command | Purpose |
|
|
148
|
+
| --- | --- |
|
|
149
|
+
| `tbd search <query>` | Search issues by text |
|
|
150
|
+
| `tbd label add <id> <label>` | Add label to issue |
|
|
151
|
+
| `tbd label remove <id> <label>` | Remove label from issue |
|
|
152
|
+
| `tbd label list` | List all labels in use |
|
|
153
|
+
| `tbd stale` | List issues not updated recently |
|
|
118
154
|
|
|
119
155
|
### Documentation
|
|
120
156
|
|
package/dist/docs/skill-brief.md
CHANGED
|
@@ -27,7 +27,7 @@ tbd sync # Sync with remote
|
|
|
27
27
|
| --- | --- |
|
|
28
28
|
| Found a bug | `tbd create "..." --type=bug` |
|
|
29
29
|
| Plan a feature | `tbd shortcut new-plan-spec` |
|
|
30
|
-
| Commit code | `tbd shortcut commit
|
|
30
|
+
| Commit code | `tbd shortcut code-review-and-commit` |
|
|
31
31
|
| Create a PR | `tbd shortcut create-or-update-pr-simple` |
|
|
32
32
|
| TypeScript review | `tbd guidelines typescript-rules` |
|
|
33
33
|
|
package/dist/docs/tbd-design.md
CHANGED
|
@@ -1143,6 +1143,8 @@ Lexicographically Sortable Identifier):
|
|
|
1143
1143
|
- **Required prefix**: Project-specific (e.g., `proj`, `myapp`, `tk`) via
|
|
1144
1144
|
`display.id_prefix`
|
|
1145
1145
|
- Set during `tbd init --prefix=<name>` or automatically from beads import
|
|
1146
|
+
- Recommended: 2-8 alphabetic characters (use `--force` for other formats)
|
|
1147
|
+
- Must not contain dashes (would conflict with ID separator)
|
|
1146
1148
|
- **Short code**: 1+ alphanumeric characters (a-z, 0-9)
|
|
1147
1149
|
- Imported issues: Preserve original short ID (e.g., `100` from `tbd-100`)
|
|
1148
1150
|
- New issues: Generate random 4-char base36
|
|
@@ -2348,7 +2350,8 @@ tbd <command> [subcommand] [args] [options]
|
|
|
2348
2350
|
tbd init --prefix=<name> [options]
|
|
2349
2351
|
|
|
2350
2352
|
Options:
|
|
2351
|
-
--prefix=<name> Required: project prefix for display IDs (
|
|
2353
|
+
--prefix=<name> Required: project prefix for display IDs (2-8 alphabetic recommended)
|
|
2354
|
+
--force Allow non-recommended prefix format
|
|
2352
2355
|
--sync-branch=<name> Sync branch name (default: tbd-sync)
|
|
2353
2356
|
--remote=<name> Remote name (default: origin)
|
|
2354
2357
|
```
|
|
@@ -2356,6 +2359,15 @@ Options:
|
|
|
2356
2359
|
The `--prefix` option is **required** unless you’re importing from an existing beads
|
|
2357
2360
|
repository (which automatically detects and uses the beads prefix).
|
|
2358
2361
|
|
|
2362
|
+
**Prefix validation rules:**
|
|
2363
|
+
|
|
2364
|
+
- **Recommended** (no --force needed): 2-8 alphabetic characters (e.g., `tbd`, `proj`,
|
|
2365
|
+
`myapp`)
|
|
2366
|
+
- **Valid with --force**: 1-20 lowercase characters, starting with a letter, ending with
|
|
2367
|
+
alphanumeric, middle characters can include dots (`.`) and underscores (`_`)
|
|
2368
|
+
- **Never allowed**: Dashes (`-`) are not allowed as they break ID syntax (e.g.,
|
|
2369
|
+
`tbd-a1b2` would be ambiguous)
|
|
2370
|
+
|
|
2359
2371
|
**What it does:**
|
|
2360
2372
|
|
|
2361
2373
|
1. Creates `.tbd/` directory with `config.yml` (including display.id_prefix) and
|
package/dist/index.d.mts
CHANGED
|
@@ -15,8 +15,16 @@ declare const IssueId: z.ZodString;
|
|
|
15
15
|
* Short ID: 1+ base36 characters used for external/display IDs.
|
|
16
16
|
* Typically 4 chars for new IDs (e.g., a7k2, b3m9).
|
|
17
17
|
* Imports may preserve longer numeric IDs (e.g., "100" from "tbd-100").
|
|
18
|
+
* Legacy imports may include dots (e.g., "208.1" from hierarchical numbering).
|
|
19
|
+
* Imports may include dashes/underscores (e.g., "stat-in_progress" from JSONL).
|
|
18
20
|
*/
|
|
19
21
|
declare const ShortId: z.ZodString;
|
|
22
|
+
/**
|
|
23
|
+
* ULID: 26 lowercase alphanumeric characters.
|
|
24
|
+
* Used in internal IDs and ID mappings.
|
|
25
|
+
* Example: 01hx5zzkbkactav9wevgemmvrz
|
|
26
|
+
*/
|
|
27
|
+
declare const Ulid: z.ZodString;
|
|
20
28
|
/**
|
|
21
29
|
* External Issue ID input: accepts {prefix}-{short} or just {short}.
|
|
22
30
|
* Examples: bd-a7k2, a7k2, bd-100, 100
|
|
@@ -198,15 +206,15 @@ declare const GitRemoteName: z.ZodString;
|
|
|
198
206
|
/**
|
|
199
207
|
* Doc cache configuration - maps destination paths to source locations.
|
|
200
208
|
*
|
|
201
|
-
* Keys are destination paths relative to .tbd/docs/ (e.g., "shortcuts/standard/commit
|
|
209
|
+
* Keys are destination paths relative to .tbd/docs/ (e.g., "shortcuts/standard/code-review-and-commit.md")
|
|
202
210
|
* Values are source locations:
|
|
203
|
-
* - internal: prefix for bundled docs (e.g., "internal:shortcuts/standard/commit
|
|
211
|
+
* - internal: prefix for bundled docs (e.g., "internal:shortcuts/standard/code-review-and-commit.md")
|
|
204
212
|
* - Full URL for external docs (e.g., "https://raw.githubusercontent.com/org/repo/main/file.md")
|
|
205
213
|
*
|
|
206
214
|
* Example:
|
|
207
215
|
* ```yaml
|
|
208
216
|
* doc_cache:
|
|
209
|
-
* shortcuts/standard/commit
|
|
217
|
+
* shortcuts/standard/code-review-and-commit.md: internal:shortcuts/standard/code-review-and-commit.md
|
|
210
218
|
* shortcuts/custom/my-shortcut.md: https://raw.githubusercontent.com/org/repo/main/shortcuts/my-shortcut.md
|
|
211
219
|
* ```
|
|
212
220
|
*/
|
|
@@ -222,7 +230,7 @@ declare const DocsCacheSchema: z.ZodObject<{
|
|
|
222
230
|
* Files to sync: maps destination paths to source locations.
|
|
223
231
|
* Keys are destination paths relative to .tbd/docs/
|
|
224
232
|
* Values are source locations:
|
|
225
|
-
* - internal: prefix for bundled docs (e.g., "internal:shortcuts/standard/commit
|
|
233
|
+
* - internal: prefix for bundled docs (e.g., "internal:shortcuts/standard/code-review-and-commit.md")
|
|
226
234
|
* - Full URL for external docs (e.g., "https://raw.githubusercontent.com/org/repo/main/file.md")
|
|
227
235
|
*/
|
|
228
236
|
files: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
@@ -318,7 +326,7 @@ declare const ConfigSchema: z.ZodObject<{
|
|
|
318
326
|
* Files to sync: maps destination paths to source locations.
|
|
319
327
|
* Keys are destination paths relative to .tbd/docs/
|
|
320
328
|
* Values are source locations:
|
|
321
|
-
* - internal: prefix for bundled docs (e.g., "internal:shortcuts/standard/commit
|
|
329
|
+
* - internal: prefix for bundled docs (e.g., "internal:shortcuts/standard/code-review-and-commit.md")
|
|
322
330
|
* - Full URL for external docs (e.g., "https://raw.githubusercontent.com/org/repo/main/file.md")
|
|
323
331
|
*/
|
|
324
332
|
files: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
@@ -456,6 +464,12 @@ declare const AtticEntrySchema: z.ZodObject<{
|
|
|
456
464
|
remote_updated_at: string;
|
|
457
465
|
};
|
|
458
466
|
}>;
|
|
467
|
+
/**
|
|
468
|
+
* ID mapping YAML file schema for ids.yml.
|
|
469
|
+
* Maps short IDs to ULIDs.
|
|
470
|
+
* Format: { "a7k2": "01hx5zzkbkactav9wevgemmvrz", ... }
|
|
471
|
+
*/
|
|
472
|
+
declare const IdMappingYamlSchema: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
459
473
|
//#endregion
|
|
460
474
|
//#region src/lib/types.d.ts
|
|
461
475
|
/**
|
|
@@ -580,5 +594,5 @@ declare function serializeIssue(issue: Issue): string;
|
|
|
580
594
|
*/
|
|
581
595
|
declare const VERSION: string;
|
|
582
596
|
//#endregion
|
|
583
|
-
export { AtticEntry, AtticEntrySchema, BaseEntity, Config, ConfigSchema, CreateIssueOptions, Dependency, DependencyRelationType, DependencyType, DocCacheConfigSchema, DocSection, DocsCacheSchema, EntityType, ExternalIssueIdInput, GitBranchName, GitRemoteName, Issue, IssueId, IssueKind, IssueKindType, IssueSchema, IssueStatus, IssueStatusType, ListIssuesOptions, LocalState, LocalStateSchema, Meta, MetaSchema, Priority, PriorityType, SearchIssuesOptions, ShortId, Timestamp, UpdateIssueOptions, VERSION, Version, parseIssue, serializeIssue };
|
|
597
|
+
export { AtticEntry, AtticEntrySchema, BaseEntity, Config, ConfigSchema, CreateIssueOptions, Dependency, DependencyRelationType, DependencyType, DocCacheConfigSchema, DocSection, DocsCacheSchema, EntityType, ExternalIssueIdInput, GitBranchName, GitRemoteName, IdMappingYamlSchema, Issue, IssueId, IssueKind, IssueKindType, IssueSchema, IssueStatus, IssueStatusType, ListIssuesOptions, LocalState, LocalStateSchema, Meta, MetaSchema, Priority, PriorityType, SearchIssuesOptions, ShortId, Timestamp, Ulid, UpdateIssueOptions, VERSION, Version, parseIssue, serializeIssue };
|
|
584
598
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { C as
|
|
1
|
+
import { A as Ulid, C as IssueSchema, D as Priority, E as MetaSchema, O as ShortId, S as IssueKind, T as LocalStateSchema, _ as ExternalIssueIdInput, b as IdMappingYamlSchema, d as ConfigSchema, f as Dependency, g as EntityType, h as DocsCacheSchema, i as serializeIssue, j as Version, k as Timestamp, l as AtticEntrySchema, m as DocCacheConfigSchema, n as parseIssue, p as DependencyRelationType, t as VERSION, u as BaseEntity, v as GitBranchName, w as IssueStatus, x as IssueId, y as GitRemoteName } from "./src-DdSZ1dgK.mjs";
|
|
2
2
|
|
|
3
|
-
export { AtticEntrySchema, BaseEntity, ConfigSchema, Dependency, DependencyRelationType, DocCacheConfigSchema, DocsCacheSchema, EntityType, ExternalIssueIdInput, GitBranchName, GitRemoteName, IssueId, IssueKind, IssueSchema, IssueStatus, LocalStateSchema, MetaSchema, Priority, ShortId, Timestamp, VERSION, Version, parseIssue, serializeIssue };
|
|
3
|
+
export { AtticEntrySchema, BaseEntity, ConfigSchema, Dependency, DependencyRelationType, DocCacheConfigSchema, DocsCacheSchema, EntityType, ExternalIssueIdInput, GitBranchName, GitRemoteName, IdMappingYamlSchema, IssueId, IssueKind, IssueSchema, IssueStatus, LocalStateSchema, MetaSchema, Priority, ShortId, Timestamp, Ulid, VERSION, Version, parseIssue, serializeIssue };
|
|
@@ -23,8 +23,16 @@ const IssueId = z.string().regex(/^is-[0-9a-z]{26}$/);
|
|
|
23
23
|
* Short ID: 1+ base36 characters used for external/display IDs.
|
|
24
24
|
* Typically 4 chars for new IDs (e.g., a7k2, b3m9).
|
|
25
25
|
* Imports may preserve longer numeric IDs (e.g., "100" from "tbd-100").
|
|
26
|
+
* Legacy imports may include dots (e.g., "208.1" from hierarchical numbering).
|
|
27
|
+
* Imports may include dashes/underscores (e.g., "stat-in_progress" from JSONL).
|
|
26
28
|
*/
|
|
27
|
-
const ShortId = z.string().regex(/^[0-9a-z]+$/);
|
|
29
|
+
const ShortId = z.string().regex(/^[0-9a-z._-]+$/);
|
|
30
|
+
/**
|
|
31
|
+
* ULID: 26 lowercase alphanumeric characters.
|
|
32
|
+
* Used in internal IDs and ID mappings.
|
|
33
|
+
* Example: 01hx5zzkbkactav9wevgemmvrz
|
|
34
|
+
*/
|
|
35
|
+
const Ulid = z.string().regex(/^[0-9a-z]{26}$/);
|
|
28
36
|
/**
|
|
29
37
|
* External Issue ID input: accepts {prefix}-{short} or just {short}.
|
|
30
38
|
* Examples: bd-a7k2, a7k2, bd-100, 100
|
|
@@ -129,15 +137,15 @@ const GitRemoteName = z.string().min(1).max(255).regex(/^[a-zA-Z0-9._-]+$/, "Inv
|
|
|
129
137
|
/**
|
|
130
138
|
* Doc cache configuration - maps destination paths to source locations.
|
|
131
139
|
*
|
|
132
|
-
* Keys are destination paths relative to .tbd/docs/ (e.g., "shortcuts/standard/commit
|
|
140
|
+
* Keys are destination paths relative to .tbd/docs/ (e.g., "shortcuts/standard/code-review-and-commit.md")
|
|
133
141
|
* Values are source locations:
|
|
134
|
-
* - internal: prefix for bundled docs (e.g., "internal:shortcuts/standard/commit
|
|
142
|
+
* - internal: prefix for bundled docs (e.g., "internal:shortcuts/standard/code-review-and-commit.md")
|
|
135
143
|
* - Full URL for external docs (e.g., "https://raw.githubusercontent.com/org/repo/main/file.md")
|
|
136
144
|
*
|
|
137
145
|
* Example:
|
|
138
146
|
* ```yaml
|
|
139
147
|
* doc_cache:
|
|
140
|
-
* shortcuts/standard/commit
|
|
148
|
+
* shortcuts/standard/code-review-and-commit.md: internal:shortcuts/standard/code-review-and-commit.md
|
|
141
149
|
* shortcuts/custom/my-shortcut.md: https://raw.githubusercontent.com/org/repo/main/shortcuts/my-shortcut.md
|
|
142
150
|
* ```
|
|
143
151
|
*/
|
|
@@ -220,13 +228,147 @@ const AtticEntrySchema = z.object({
|
|
|
220
228
|
remote_updated_at: Timestamp
|
|
221
229
|
})
|
|
222
230
|
});
|
|
231
|
+
/**
|
|
232
|
+
* ID mapping YAML file schema for ids.yml.
|
|
233
|
+
* Maps short IDs to ULIDs.
|
|
234
|
+
* Format: { "a7k2": "01hx5zzkbkactav9wevgemmvrz", ... }
|
|
235
|
+
*/
|
|
236
|
+
const IdMappingYamlSchema = z.record(ShortId, Ulid);
|
|
237
|
+
|
|
238
|
+
//#endregion
|
|
239
|
+
//#region src/lib/settings.ts
|
|
240
|
+
/**
|
|
241
|
+
* Default line width for YAML serialization.
|
|
242
|
+
* 88 characters is a good balance between readability and avoiding excessive wrapping.
|
|
243
|
+
* (Matches Python's Black formatter default.)
|
|
244
|
+
*/
|
|
245
|
+
const YAML_LINE_WIDTH = 88;
|
|
246
|
+
/**
|
|
247
|
+
* Default string type for YAML serialization.
|
|
248
|
+
* 'PLAIN' means no forced quoting - YAML only quotes when necessary.
|
|
249
|
+
*/
|
|
250
|
+
const YAML_DEFAULT_STRING_TYPE = "PLAIN";
|
|
251
|
+
/**
|
|
252
|
+
* Default key type for YAML serialization.
|
|
253
|
+
* 'PLAIN' means object keys are unquoted unless required.
|
|
254
|
+
*/
|
|
255
|
+
const YAML_DEFAULT_KEY_TYPE = "PLAIN";
|
|
256
|
+
/**
|
|
257
|
+
* Default YAML serialization options for readable output.
|
|
258
|
+
*
|
|
259
|
+
* Design principles:
|
|
260
|
+
* - No forced quoting: YAML only quotes when necessary for special characters
|
|
261
|
+
* - Reasonable line wrapping: 88 chars prevents overly long lines
|
|
262
|
+
* - Plain keys: No unnecessary quotes around object keys
|
|
263
|
+
* - Sorted keys: Deterministic output for diffs and version control
|
|
264
|
+
*/
|
|
265
|
+
const YAML_STRINGIFY_OPTIONS = {
|
|
266
|
+
lineWidth: YAML_LINE_WIDTH,
|
|
267
|
+
defaultStringType: YAML_DEFAULT_STRING_TYPE,
|
|
268
|
+
defaultKeyType: YAML_DEFAULT_KEY_TYPE,
|
|
269
|
+
sortMapEntries: true
|
|
270
|
+
};
|
|
271
|
+
/**
|
|
272
|
+
* YAML serialization options for compact output (e.g., frontmatter).
|
|
273
|
+
* Uses lineWidth: 0 to prevent wrapping within values.
|
|
274
|
+
*/
|
|
275
|
+
const YAML_STRINGIFY_OPTIONS_COMPACT = {
|
|
276
|
+
lineWidth: 0,
|
|
277
|
+
defaultStringType: YAML_DEFAULT_STRING_TYPE,
|
|
278
|
+
defaultKeyType: YAML_DEFAULT_KEY_TYPE,
|
|
279
|
+
sortMapEntries: true
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
//#endregion
|
|
283
|
+
//#region src/utils/yaml-utils.ts
|
|
284
|
+
/**
|
|
285
|
+
* YAML utility functions.
|
|
286
|
+
*
|
|
287
|
+
* Provides centralized YAML parsing and serialization with:
|
|
288
|
+
* - Merge conflict detection for user-editable files
|
|
289
|
+
* - Consistent, readable formatting defaults
|
|
290
|
+
* - Proper handling of special characters (colons, quotes, etc.)
|
|
291
|
+
*
|
|
292
|
+
* IMPORTANT: Always use these utilities instead of raw yaml package functions.
|
|
293
|
+
* This ensures consistent formatting and proper error handling across the codebase.
|
|
294
|
+
*/
|
|
295
|
+
/**
|
|
296
|
+
* Serialize data to YAML with readable formatting.
|
|
297
|
+
*
|
|
298
|
+
* Uses consistent defaults:
|
|
299
|
+
* - No forced quoting (YAML only quotes when necessary)
|
|
300
|
+
* - lineWidth of 88 provides reasonable wrapping for long strings
|
|
301
|
+
* - Plain keys without quotes
|
|
302
|
+
* - Sorted keys for deterministic output
|
|
303
|
+
*
|
|
304
|
+
* @param data - Data to serialize
|
|
305
|
+
* @param options - Optional overrides for default options
|
|
306
|
+
* @returns YAML string
|
|
307
|
+
*/
|
|
308
|
+
function stringifyYaml(data, options) {
|
|
309
|
+
return stringify(data, {
|
|
310
|
+
...YAML_STRINGIFY_OPTIONS,
|
|
311
|
+
...options
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Serialize data to YAML without line wrapping (compact mode).
|
|
316
|
+
* Useful for frontmatter where values should stay on single lines.
|
|
317
|
+
*
|
|
318
|
+
* @param data - Data to serialize
|
|
319
|
+
* @returns YAML string with no line wrapping
|
|
320
|
+
*/
|
|
321
|
+
function stringifyYamlCompact(data) {
|
|
322
|
+
return stringify(data, YAML_STRINGIFY_OPTIONS_COMPACT);
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Error thrown when YAML content contains unresolved merge conflict markers.
|
|
326
|
+
*/
|
|
327
|
+
var MergeConflictError = class extends Error {
|
|
328
|
+
constructor(message, filePath) {
|
|
329
|
+
super(message);
|
|
330
|
+
this.filePath = filePath;
|
|
331
|
+
this.name = "MergeConflictError";
|
|
332
|
+
}
|
|
333
|
+
};
|
|
334
|
+
/**
|
|
335
|
+
* Regex patterns for git merge conflict markers.
|
|
336
|
+
*/
|
|
337
|
+
const CONFLICT_PATTERNS = {
|
|
338
|
+
start: /^<<<<<<< /m,
|
|
339
|
+
separator: /^=======/m,
|
|
340
|
+
end: /^>>>>>>> /m
|
|
341
|
+
};
|
|
342
|
+
/**
|
|
343
|
+
* Check if content contains git merge conflict markers.
|
|
344
|
+
*/
|
|
345
|
+
function hasMergeConflictMarkers(content) {
|
|
346
|
+
return CONFLICT_PATTERNS.start.test(content) || CONFLICT_PATTERNS.separator.test(content) || CONFLICT_PATTERNS.end.test(content);
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Parse YAML content with merge conflict detection.
|
|
350
|
+
*
|
|
351
|
+
* If the content contains merge conflict markers, throws a MergeConflictError
|
|
352
|
+
* with a helpful message instead of a cryptic YAML parse error.
|
|
353
|
+
*
|
|
354
|
+
* @param content - The YAML content to parse
|
|
355
|
+
* @param filePath - Optional file path for error messages
|
|
356
|
+
* @returns Parsed YAML data
|
|
357
|
+
* @throws MergeConflictError if content has conflict markers
|
|
358
|
+
* @throws Error if YAML is invalid for other reasons
|
|
359
|
+
*/
|
|
360
|
+
function parseYamlWithConflictDetection(content, filePath) {
|
|
361
|
+
if (hasMergeConflictMarkers(content)) throw new MergeConflictError(`File${filePath ? ` in ${filePath}` : ""} contains unresolved git merge conflict markers.\nThis usually happens when 'tbd sync' encountered conflicts that weren't properly resolved.\nTo fix: manually edit the file to resolve conflicts, or run 'tbd doctor --fix'.`, filePath);
|
|
362
|
+
return parse(content);
|
|
363
|
+
}
|
|
223
364
|
|
|
224
365
|
//#endregion
|
|
225
366
|
//#region src/utils/markdown-utils.ts
|
|
226
367
|
/**
|
|
227
368
|
* Markdown utilities for processing markdown content.
|
|
228
369
|
*
|
|
229
|
-
* Uses gray-matter for
|
|
370
|
+
* Uses gray-matter for parsing and centralized yaml-utils for stringify to ensure
|
|
371
|
+
* proper handling of special YAML characters (colons, quotes, etc.).
|
|
230
372
|
*/
|
|
231
373
|
/**
|
|
232
374
|
* Normalize line endings to LF.
|
|
@@ -250,17 +392,8 @@ function parseMarkdown(content) {
|
|
|
250
392
|
const parsed = matter(normalized);
|
|
251
393
|
const data = parsed.data;
|
|
252
394
|
let frontmatter = null;
|
|
253
|
-
if (data && Object.keys(data).length > 0)
|
|
254
|
-
|
|
255
|
-
for (const [key, value] of Object.entries(data)) if (Array.isArray(value)) {
|
|
256
|
-
lines.push(`${key}:`);
|
|
257
|
-
for (const item of value) lines.push(` - ${String(item)}`);
|
|
258
|
-
} else if (typeof value === "object" && value !== null) {
|
|
259
|
-
lines.push(`${key}:`);
|
|
260
|
-
for (const [subKey, subValue] of Object.entries(value)) lines.push(` ${subKey}: ${String(subValue)}`);
|
|
261
|
-
} else lines.push(`${key}: ${String(value)}`);
|
|
262
|
-
frontmatter = lines.join("\n");
|
|
263
|
-
} else frontmatter = "";
|
|
395
|
+
if (data && Object.keys(data).length > 0) frontmatter = stringifyYamlCompact(data).trimEnd();
|
|
396
|
+
else frontmatter = "";
|
|
264
397
|
const body = parsed.content.replace(/^\n+/, "");
|
|
265
398
|
return {
|
|
266
399
|
frontmatter,
|
|
@@ -318,7 +451,7 @@ function insertAfterFrontmatter(content, toInsert) {
|
|
|
318
451
|
*/
|
|
319
452
|
const matterOptions = { engines: { yaml: {
|
|
320
453
|
parse: (str) => parse(str),
|
|
321
|
-
stringify: (obj) =>
|
|
454
|
+
stringify: (obj) => stringifyYaml(obj)
|
|
322
455
|
} } };
|
|
323
456
|
/**
|
|
324
457
|
* Parse a Markdown file with YAML front matter.
|
|
@@ -375,8 +508,7 @@ function serializeIssue(issue) {
|
|
|
375
508
|
for (const key of Object.keys(metadata).sort()) sortedMetadata[key] = metadata[key];
|
|
376
509
|
const parts = [
|
|
377
510
|
"---",
|
|
378
|
-
|
|
379
|
-
sortMapEntries: true,
|
|
511
|
+
stringifyYaml(sortedMetadata, {
|
|
380
512
|
lineWidth: 0,
|
|
381
513
|
nullStr: "null"
|
|
382
514
|
}).trim(),
|
|
@@ -398,8 +530,8 @@ function serializeIssue(issue) {
|
|
|
398
530
|
* Package version, derived from git at build time.
|
|
399
531
|
* Format: X.Y.Z for releases, X.Y.Z-dev.N.hash for dev builds.
|
|
400
532
|
*/
|
|
401
|
-
const VERSION = "0.1.
|
|
533
|
+
const VERSION = "0.1.14";
|
|
402
534
|
|
|
403
535
|
//#endregion
|
|
404
|
-
export {
|
|
405
|
-
//# sourceMappingURL=src-
|
|
536
|
+
export { Ulid as A, IssueSchema as C, Priority as D, MetaSchema as E, ShortId as O, IssueKind as S, LocalStateSchema as T, ExternalIssueIdInput as _, insertAfterFrontmatter as a, IdMappingYamlSchema as b, stringifyYaml as c, ConfigSchema as d, Dependency as f, EntityType as g, DocsCacheSchema as h, serializeIssue as i, Version as j, Timestamp as k, AtticEntrySchema as l, DocCacheConfigSchema as m, parseIssue as n, stripFrontmatter as o, DependencyRelationType as p, parseMarkdownWithFrontmatter as r, parseYamlWithConflictDetection as s, VERSION as t, BaseEntity as u, GitBranchName as v, IssueStatus as w, IssueId as x, GitRemoteName as y };
|
|
537
|
+
//# sourceMappingURL=src-DdSZ1dgK.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"src-DdSZ1dgK.mjs","names":["parseYaml","parseYaml"],"sources":["../src/lib/schemas.ts","../src/lib/settings.ts","../src/utils/yaml-utils.ts","../src/utils/markdown-utils.ts","../src/file/parser.ts","../src/index.ts"],"sourcesContent":["/**\n * Zod schemas for tbd entities.\n *\n * These schemas are the normative specification for the file format.\n * See: tbd-design.md §2.6 Schemas\n */\n\nimport { z } from 'zod';\n\n// =============================================================================\n// Common Types (§2.6.1)\n// =============================================================================\n\n/**\n * ISO8601 timestamp with Z suffix (UTC).\n */\nexport const Timestamp = z.string().datetime();\n\n/**\n * Issue ID: prefix + 26 lowercase alphanumeric characters (ULID format).\n * Format: is-{ulid} where ulid is 26 chars (a-z, 0-9).\n * Example: is-01hx5zzkbkactav9wevgemmvrz\n */\nexport const IssueId = z.string().regex(/^is-[0-9a-z]{26}$/);\n\n/**\n * Short ID: 1+ base36 characters used for external/display IDs.\n * Typically 4 chars for new IDs (e.g., a7k2, b3m9).\n * Imports may preserve longer numeric IDs (e.g., \"100\" from \"tbd-100\").\n * Legacy imports may include dots (e.g., \"208.1\" from hierarchical numbering).\n * Imports may include dashes/underscores (e.g., \"stat-in_progress\" from JSONL).\n */\nexport const ShortId = z.string().regex(/^[0-9a-z._-]+$/);\n\n/**\n * ULID: 26 lowercase alphanumeric characters.\n * Used in internal IDs and ID mappings.\n * Example: 01hx5zzkbkactav9wevgemmvrz\n */\nexport const Ulid = z.string().regex(/^[0-9a-z]{26}$/);\n\n/**\n * External Issue ID input: accepts {prefix}-{short} or just {short}.\n * Examples: bd-a7k2, a7k2, bd-100, 100\n */\nexport const ExternalIssueIdInput = z.string().regex(/^([a-z]+-)?[0-9a-z]+$/);\n\n/**\n * Edit counter - incremented on every local change.\n * NOTE: Version is NOT used for conflict detection (Git push rejection is used).\n * Content hash is used as tiebreaker during merge resolution.\n * Version is informational only - set to max(local, remote) + 1 after merges.\n */\nexport const Version = z.number().int().nonnegative();\n\n/**\n * Entity type discriminator.\n */\nexport const EntityType = z.literal('is');\n\n// =============================================================================\n// BaseEntity (§2.6.2)\n// =============================================================================\n\n/**\n * All entities share common fields.\n */\nexport const BaseEntity = z.object({\n type: EntityType,\n id: IssueId,\n version: Version,\n created_at: Timestamp,\n updated_at: Timestamp,\n\n // Extensibility namespace for third-party data\n extensions: z.record(z.string(), z.unknown()).optional(),\n});\n\n// =============================================================================\n// Issue Schema (§2.6.3)\n// =============================================================================\n\n/**\n * Issue status values matching Beads.\n */\nexport const IssueStatus = z.enum(['open', 'in_progress', 'blocked', 'deferred', 'closed']);\n\n/**\n * Issue kind/type values matching Beads.\n * Note: CLI uses --type flag, which maps to this `kind` field.\n */\nexport const IssueKind = z.enum(['bug', 'feature', 'task', 'epic', 'chore']);\n\n/**\n * Priority: 0 (highest/critical) to 4 (lowest).\n */\nexport const Priority = z.number().int().min(0).max(4);\n\n/**\n * Dependency types - only \"blocks\" supported initially.\n */\nexport const DependencyRelationType = z.enum(['blocks']);\n\n/**\n * A dependency relationship.\n */\nexport const Dependency = z.object({\n type: DependencyRelationType,\n target: IssueId,\n});\n\n/**\n * Full issue schema.\n *\n * Note: Fields use .nullable() in addition to .optional() because\n * YAML parses `field: null` as JavaScript null, not undefined.\n */\nexport const IssueSchema = BaseEntity.extend({\n type: z.literal('is'),\n\n title: z.string().min(1).max(500),\n description: z.string().max(50000).nullable().optional(),\n notes: z.string().max(50000).nullable().optional(),\n\n kind: IssueKind.default('task'),\n status: IssueStatus.default('open'),\n priority: Priority.default(2),\n\n assignee: z.string().nullable().optional(),\n labels: z.array(z.string()).default([]),\n dependencies: z.array(Dependency).default([]),\n\n // Hierarchical issues\n parent_id: IssueId.nullable().optional(),\n\n // Child ordering hints - soft ordering for children under this parent.\n // Array of internal IssueIds in preferred display order.\n // May contain stale IDs; display logic filters for actual children.\n child_order_hints: z.array(IssueId).nullable().optional(),\n\n // Beads compatibility\n due_date: Timestamp.nullable().optional(),\n deferred_until: Timestamp.nullable().optional(),\n\n created_by: z.string().nullable().optional(),\n closed_at: Timestamp.nullable().optional(),\n close_reason: z.string().nullable().optional(),\n\n // Spec linking - path to related spec/doc (relative to repo root)\n spec_path: z.string().nullable().optional(),\n});\n\n// =============================================================================\n// Config Schema (§2.6.4)\n// =============================================================================\n\n/**\n * Git branch name - restricted to safe characters.\n * Allows: alphanumeric, hyphens, underscores, forward slashes, and dots.\n * Prevents shell injection in git commands.\n */\nexport const GitBranchName = z\n .string()\n .min(1)\n .max(255)\n .regex(\n /^[a-zA-Z0-9._/-]+$/,\n 'Invalid branch name: only alphanumeric, dots, underscores, hyphens, and slashes allowed',\n );\n\n/**\n * Git remote name - restricted to safe characters.\n * Allows: alphanumeric, hyphens, underscores, and dots.\n * Prevents shell injection in git commands.\n */\nexport const GitRemoteName = z\n .string()\n .min(1)\n .max(255)\n .regex(\n /^[a-zA-Z0-9._-]+$/,\n 'Invalid remote name: only alphanumeric, dots, underscores, and hyphens allowed',\n );\n\n/**\n * Doc cache configuration - maps destination paths to source locations.\n *\n * Keys are destination paths relative to .tbd/docs/ (e.g., \"shortcuts/standard/code-review-and-commit.md\")\n * Values are source locations:\n * - internal: prefix for bundled docs (e.g., \"internal:shortcuts/standard/code-review-and-commit.md\")\n * - Full URL for external docs (e.g., \"https://raw.githubusercontent.com/org/repo/main/file.md\")\n *\n * Example:\n * ```yaml\n * doc_cache:\n * shortcuts/standard/code-review-and-commit.md: internal:shortcuts/standard/code-review-and-commit.md\n * shortcuts/custom/my-shortcut.md: https://raw.githubusercontent.com/org/repo/main/shortcuts/my-shortcut.md\n * ```\n */\nexport const DocCacheConfigSchema = z.record(z.string(), z.string());\n\n/**\n * Documentation cache configuration (consolidated structure).\n *\n * Combines file sync mappings and lookup paths into a single config block.\n * See: docs/project/specs/active/plan-2026-01-26-docs-cache-config-restructure.md\n */\nexport const DocsCacheSchema = z.object({\n /**\n * Files to sync: maps destination paths to source locations.\n * Keys are destination paths relative to .tbd/docs/\n * Values are source locations:\n * - internal: prefix for bundled docs (e.g., \"internal:shortcuts/standard/code-review-and-commit.md\")\n * - Full URL for external docs (e.g., \"https://raw.githubusercontent.com/org/repo/main/file.md\")\n */\n files: z.record(z.string(), z.string()).optional(),\n /**\n * Search paths for doc lookup (like shell $PATH).\n * Earlier paths take precedence when names conflict.\n */\n lookup_path: z\n .array(z.string())\n .default(['.tbd/docs/shortcuts/system', '.tbd/docs/shortcuts/standard']),\n});\n\n/**\n * Project configuration stored in .tbd/config.yml\n *\n * ⚠️ FORMAT VERSIONING: See tbd-format.ts for version history and migration rules.\n * The tbd_format field tracks breaking changes to this schema.\n *\n * ⚠️ FORWARD COMPATIBILITY POLICY:\n * This schema uses Zod's default strip() mode, which discards unknown fields.\n * To prevent data loss when users mix tbd versions:\n *\n * 1. **When changing config schema (adding, removing, or modifying fields), ALWAYS\n * bump the format version** (e.g., f03 → f04)\n * 2. Older tbd versions will error when they see an unknown format version\n * 3. The error message tells users to upgrade tbd\n *\n * This ensures older versions fail fast rather than silently corrupting config.\n * The format version check happens in config.ts via isCompatibleFormat().\n *\n * See tbd-format.ts for format version history and migration rules.\n */\nexport const ConfigSchema = z.object({\n /**\n * Format version for the .tbd/ directory structure.\n * See tbd-format.ts for version history and migration rules.\n * Only bumped for breaking changes that require migration.\n */\n tbd_format: z.string().default('f01'),\n\n tbd_version: z.string(),\n sync: z\n .object({\n branch: GitBranchName.default('tbd-sync'),\n remote: GitRemoteName.default('origin'),\n })\n .default({}),\n display: z.object({\n id_prefix: z.string().min(1).max(20), // Required: set during init --prefix or import\n }),\n settings: z\n .object({\n auto_sync: z.boolean().default(false),\n /**\n * How often to automatically sync documentation cache (in hours).\n * - Default: 24 (sync once per day when actively using tbd)\n * - Set to 0 to disable auto-sync\n * - Only triggers when accessing docs (shortcut, guidelines, template commands)\n */\n doc_auto_sync_hours: z.number().default(24),\n /**\n * Whether to install the ensure-gh-cli.sh hook script during setup.\n * When true (default), `tbd setup` installs a SessionStart hook that\n * ensures the GitHub CLI is available in agent sessions.\n * Set to false or use `tbd setup --no-gh-cli` to disable.\n */\n use_gh_cli: z.boolean().default(true),\n })\n .default({}),\n /**\n * Documentation cache configuration (consolidated).\n * Contains files to sync and lookup paths.\n * See DocsCacheSchema for structure details.\n */\n docs_cache: DocsCacheSchema.optional(),\n});\n\n// =============================================================================\n// Meta Schema (§2.6.5)\n// =============================================================================\n\n/**\n * Shared metadata stored in .tbd/data-sync/meta.yml\n */\nexport const MetaSchema = z.object({\n schema_version: z.number().int(),\n created_at: Timestamp,\n});\n\n// =============================================================================\n// Local State Schema (§2.6.6)\n// =============================================================================\n\n/**\n * Per-node state stored in .tbd/state.yml (gitignored).\n * Tracks local timing information that shouldn't be shared across nodes.\n */\nexport const LocalStateSchema = z.object({\n /** When this node last synced issues successfully */\n last_sync_at: Timestamp.optional(),\n /** When this node last synced the doc cache successfully */\n last_doc_sync_at: Timestamp.optional(),\n /** Whether the user has seen the welcome message */\n welcome_seen: z.boolean().optional(),\n});\n\n// =============================================================================\n// Attic Entry Schema (§2.6.7)\n// =============================================================================\n\n/**\n * Preserved conflict losers.\n */\nexport const AtticEntrySchema = z.object({\n entity_id: IssueId,\n timestamp: Timestamp,\n field: z.string(),\n lost_value: z.string(),\n winner_source: z.enum(['local', 'remote']),\n loser_source: z.enum(['local', 'remote']),\n context: z.object({\n local_version: Version,\n remote_version: Version,\n local_updated_at: Timestamp,\n remote_updated_at: Timestamp,\n }),\n});\n\n// =============================================================================\n// ID Mapping Schema (§2.6.8)\n// =============================================================================\n\n/**\n * ID mapping YAML file schema for ids.yml.\n * Maps short IDs to ULIDs.\n * Format: { \"a7k2\": \"01hx5zzkbkactav9wevgemmvrz\", ... }\n */\nexport const IdMappingYamlSchema = z.record(ShortId, Ulid);\n","/**\n * Global settings and configuration constants.\n *\n * Centralized location for project-wide defaults that may need tuning.\n * These are compile-time constants, not runtime configuration.\n */\n\nimport type { DocumentOptions, SchemaOptions, ToStringOptions } from 'yaml';\n\n// =============================================================================\n// YAML Formatting\n// =============================================================================\n\n/**\n * Default line width for YAML serialization.\n * 88 characters is a good balance between readability and avoiding excessive wrapping.\n * (Matches Python's Black formatter default.)\n */\nexport const YAML_LINE_WIDTH = 88;\n\n/**\n * Default string type for YAML serialization.\n * 'PLAIN' means no forced quoting - YAML only quotes when necessary.\n */\nexport const YAML_DEFAULT_STRING_TYPE = 'PLAIN' as const;\n\n/**\n * Default key type for YAML serialization.\n * 'PLAIN' means object keys are unquoted unless required.\n */\nexport const YAML_DEFAULT_KEY_TYPE = 'PLAIN' as const;\n\n/**\n * Combined options type for YAML stringify.\n */\nexport type YamlStringifyOptions = DocumentOptions & SchemaOptions & ToStringOptions;\n\n/**\n * Default YAML serialization options for readable output.\n *\n * Design principles:\n * - No forced quoting: YAML only quotes when necessary for special characters\n * - Reasonable line wrapping: 88 chars prevents overly long lines\n * - Plain keys: No unnecessary quotes around object keys\n * - Sorted keys: Deterministic output for diffs and version control\n */\nexport const YAML_STRINGIFY_OPTIONS: YamlStringifyOptions = {\n lineWidth: YAML_LINE_WIDTH,\n defaultStringType: YAML_DEFAULT_STRING_TYPE,\n defaultKeyType: YAML_DEFAULT_KEY_TYPE,\n sortMapEntries: true,\n};\n\n/**\n * YAML serialization options for compact output (e.g., frontmatter).\n * Uses lineWidth: 0 to prevent wrapping within values.\n */\nexport const YAML_STRINGIFY_OPTIONS_COMPACT: YamlStringifyOptions = {\n lineWidth: 0, // No wrapping\n defaultStringType: YAML_DEFAULT_STRING_TYPE,\n defaultKeyType: YAML_DEFAULT_KEY_TYPE,\n sortMapEntries: true,\n};\n\n// =============================================================================\n// Text Formatting\n// =============================================================================\n\n/**\n * Default line width for text output (terminal, markdown).\n * Same as YAML for consistency.\n */\nexport const TEXT_LINE_WIDTH = 88;\n","/**\n * YAML utility functions.\n *\n * Provides centralized YAML parsing and serialization with:\n * - Merge conflict detection for user-editable files\n * - Consistent, readable formatting defaults\n * - Proper handling of special characters (colons, quotes, etc.)\n *\n * IMPORTANT: Always use these utilities instead of raw yaml package functions.\n * This ensures consistent formatting and proper error handling across the codebase.\n */\n\nimport { parse as parseYaml, stringify } from 'yaml';\n\nimport {\n YAML_LINE_WIDTH,\n YAML_STRINGIFY_OPTIONS,\n YAML_STRINGIFY_OPTIONS_COMPACT,\n type YamlStringifyOptions,\n} from '../lib/settings.js';\n\n// Re-export for convenience\nexport { YAML_LINE_WIDTH, YAML_STRINGIFY_OPTIONS, YAML_STRINGIFY_OPTIONS_COMPACT };\n\n// =============================================================================\n// Serialization Functions\n// =============================================================================\n\n/**\n * Serialize data to YAML with readable formatting.\n *\n * Uses consistent defaults:\n * - No forced quoting (YAML only quotes when necessary)\n * - lineWidth of 88 provides reasonable wrapping for long strings\n * - Plain keys without quotes\n * - Sorted keys for deterministic output\n *\n * @param data - Data to serialize\n * @param options - Optional overrides for default options\n * @returns YAML string\n */\nexport function stringifyYaml(data: unknown, options?: Partial<YamlStringifyOptions>): string {\n return stringify(data, { ...YAML_STRINGIFY_OPTIONS, ...options });\n}\n\n/**\n * Serialize data to YAML without line wrapping (compact mode).\n * Useful for frontmatter where values should stay on single lines.\n *\n * @param data - Data to serialize\n * @returns YAML string with no line wrapping\n */\nexport function stringifyYamlCompact(data: unknown): string {\n return stringify(data, YAML_STRINGIFY_OPTIONS_COMPACT);\n}\n\n/**\n * Error thrown when YAML content contains unresolved merge conflict markers.\n */\nexport class MergeConflictError extends Error {\n constructor(\n message: string,\n public readonly filePath?: string,\n ) {\n super(message);\n this.name = 'MergeConflictError';\n }\n}\n\n/**\n * Regex patterns for git merge conflict markers.\n */\nconst CONFLICT_PATTERNS = {\n start: /^<<<<<<< /m,\n separator: /^=======/m,\n end: /^>>>>>>> /m,\n};\n\n/**\n * Check if content contains git merge conflict markers.\n */\nexport function hasMergeConflictMarkers(content: string): boolean {\n return (\n CONFLICT_PATTERNS.start.test(content) ||\n CONFLICT_PATTERNS.separator.test(content) ||\n CONFLICT_PATTERNS.end.test(content)\n );\n}\n\n/**\n * Parse YAML content with merge conflict detection.\n *\n * If the content contains merge conflict markers, throws a MergeConflictError\n * with a helpful message instead of a cryptic YAML parse error.\n *\n * @param content - The YAML content to parse\n * @param filePath - Optional file path for error messages\n * @returns Parsed YAML data\n * @throws MergeConflictError if content has conflict markers\n * @throws Error if YAML is invalid for other reasons\n */\nexport function parseYamlWithConflictDetection<T = unknown>(content: string, filePath?: string): T {\n // Check for merge conflict markers first\n if (hasMergeConflictMarkers(content)) {\n const location = filePath ? ` in ${filePath}` : '';\n throw new MergeConflictError(\n `File${location} contains unresolved git merge conflict markers.\\n` +\n `This usually happens when 'tbd sync' encountered conflicts that weren't properly resolved.\\n` +\n `To fix: manually edit the file to resolve conflicts, or run 'tbd doctor --fix'.`,\n filePath,\n );\n }\n\n return parseYaml(content) as T;\n}\n","/**\n * Markdown utilities for processing markdown content.\n *\n * Uses gray-matter for parsing and centralized yaml-utils for stringify to ensure\n * proper handling of special YAML characters (colons, quotes, etc.).\n */\n\nimport matter from 'gray-matter';\n\nimport { stringifyYamlCompact } from './yaml-utils.js';\n\nexport interface ParsedMarkdown {\n /** Raw frontmatter string (without --- delimiters), or null if no frontmatter */\n frontmatter: string | null;\n /** Body content after frontmatter, with leading newlines trimmed */\n body: string;\n}\n\n/**\n * Normalize line endings to LF.\n */\nexport function normalizeLineEndings(content: string): string {\n return content.replace(/\\r\\n/g, '\\n').replace(/\\r/g, '\\n');\n}\n\n/**\n * Parse markdown content into frontmatter and body.\n * Handles both LF and CRLF line endings.\n *\n * @returns Object with frontmatter (null if none) and body\n */\nexport function parseMarkdown(content: string): ParsedMarkdown {\n const normalized = normalizeLineEndings(content);\n\n if (!matter.test(normalized)) {\n return { frontmatter: null, body: content };\n }\n\n try {\n const parsed = matter(normalized);\n\n // Extract frontmatter from parsed.data by stringifying back to YAML\n // The matter property is unreliable, so we reconstruct from data\n const data = parsed.data;\n let frontmatter: string | null = null;\n\n if (data && Object.keys(data).length > 0) {\n // Use centralized yaml-utils for proper handling of special characters\n // (colons, quotes, multiline strings, etc.)\n frontmatter = stringifyYamlCompact(data).trimEnd();\n } else {\n // Empty frontmatter (just --- followed by ---)\n frontmatter = '';\n }\n\n // Body with leading newlines trimmed\n const body = parsed.content.replace(/^\\n+/, '');\n\n return { frontmatter, body };\n } catch {\n // Invalid/unclosed frontmatter - treat as no frontmatter\n return { frontmatter: null, body: content };\n }\n}\n\n/**\n * Parse YAML frontmatter from markdown content.\n * Returns the frontmatter content (without delimiters) or null if no valid frontmatter.\n * Handles both LF and CRLF line endings.\n */\nexport function parseFrontmatter(content: string): string | null {\n return parseMarkdown(content).frontmatter;\n}\n\n/**\n * Strip YAML frontmatter from markdown content.\n * Returns the body content without frontmatter, with leading newlines trimmed.\n * Handles both LF and CRLF line endings.\n */\nexport function stripFrontmatter(content: string): string {\n return parseMarkdown(content).body;\n}\n\n/**\n * Insert content after YAML frontmatter.\n * If no frontmatter exists, prepends the content.\n * Content is inserted directly after ---. Include leading newlines in toInsert if needed.\n */\nexport function insertAfterFrontmatter(content: string, toInsert: string): string {\n const { frontmatter, body } = parseMarkdown(content);\n\n if (frontmatter === null) {\n return toInsert + content;\n }\n\n const frontmatterBlock = frontmatter ? `---\\n${frontmatter}\\n---` : '---\\n---';\n return `${frontmatterBlock}\\n${toInsert}\\n\\n${body}`;\n}\n","/**\n * YAML front matter parser and serializer for issue files.\n *\n * Issues are stored as Markdown files with YAML front matter:\n * ---\n * type: is\n * id: is-a1b2c3\n * ...\n * ---\n *\n * Description body here.\n *\n * ## Notes\n *\n * Working notes here.\n *\n * See: tbd-design.md §2.1 Markdown + YAML Front Matter Format\n */\n\nimport matter from 'gray-matter';\nimport { parse as parseYaml } from 'yaml';\n\nimport { normalizeLineEndings } from '../utils/markdown-utils.js';\nimport { stringifyYaml } from '../utils/yaml-utils.js';\nimport type { Issue } from '../lib/types.js';\nimport { IssueSchema } from '../lib/schemas.js';\n\n/**\n * gray-matter options using the 'yaml' package as engine.\n * This preserves date strings instead of converting them to Date objects.\n */\nexport const matterOptions = {\n engines: {\n yaml: {\n parse: (str: string): object => parseYaml(str) as object,\n stringify: (obj: object): string => stringifyYaml(obj),\n },\n },\n};\n\n/**\n * Parsed issue file content.\n */\nexport interface ParsedIssueFile {\n frontmatter: Record<string, unknown>;\n description: string;\n notes: string;\n}\n\n/**\n * Parse a Markdown file with YAML front matter.\n * Uses gray-matter for consistent frontmatter parsing.\n * Handles both LF and CRLF line endings.\n */\nexport function parseMarkdownWithFrontmatter(content: string): ParsedIssueFile {\n // Normalize CRLF to LF before parsing\n const normalizedContent = normalizeLineEndings(content);\n\n // Check for valid frontmatter\n if (!matter.test(normalizedContent)) {\n throw new Error('Invalid format: missing front matter opening delimiter');\n }\n\n const parsed = matter(normalizedContent, matterOptions);\n\n // gray-matter returns empty object if no closing delimiter found\n // but the raw matter string will be empty if parsing failed\n if (parsed.matter === '' && !normalizedContent.includes('---\\n---')) {\n // Check if there's actually a closing delimiter\n const lines = normalizedContent.split('\\n');\n let hasClosing = false;\n for (let i = 1; i < lines.length; i++) {\n if (lines[i]?.trim() === '---') {\n hasClosing = true;\n break;\n }\n }\n if (!hasClosing) {\n throw new Error('Invalid format: missing front matter closing delimiter');\n }\n }\n\n const frontmatter = parsed.data as Record<string, unknown>;\n\n // Parse body - split into description and notes\n const body = parsed.content.trim();\n\n // Find notes section\n const notesMatch = /\\n## Notes\\n/i.exec(body);\n let description = body;\n let notes = '';\n\n if (notesMatch?.index !== undefined) {\n description = body.slice(0, notesMatch.index).trim();\n notes = body.slice(notesMatch.index + notesMatch[0].length).trim();\n }\n\n return { frontmatter, description, notes };\n}\n\n/**\n * Parse an issue from Markdown file content.\n */\nexport function parseIssue(content: string): Issue {\n const { frontmatter, description, notes } = parseMarkdownWithFrontmatter(content);\n\n // Merge body content into frontmatter\n const data = {\n ...frontmatter,\n description: description || undefined,\n notes: notes || undefined,\n };\n\n // Validate and parse with Zod\n return IssueSchema.parse(data);\n}\n\n/**\n * Serialize an issue to Markdown file content.\n * Uses canonical serialization for deterministic output.\n */\nexport function serializeIssue(issue: Issue): string {\n // Extract body fields\n const { description, notes, ...metadata } = issue;\n\n // Sort keys alphabetically for canonical output\n const sortedMetadata: Record<string, unknown> = {};\n for (const key of Object.keys(metadata).sort()) {\n sortedMetadata[key] = metadata[key as keyof typeof metadata];\n }\n\n // Serialize YAML with compact output for frontmatter (sortMapEntries is in defaults)\n const yaml = stringifyYaml(sortedMetadata, {\n lineWidth: 0, // No wrapping\n nullStr: 'null',\n });\n\n // Build the file content\n // Note: No blank line between closing --- and body content\n const parts = ['---', yaml.trim(), '---'];\n\n if (description) {\n parts.push(description.trim());\n }\n\n if (notes) {\n parts.push('');\n parts.push('## Notes');\n parts.push('');\n parts.push(notes.trim());\n }\n\n // Single newline at end\n return parts.join('\\n') + '\\n';\n}\n","/**\n * tbd: Git-native issue tracking for AI agents and humans\n *\n * This is the library entry point. All exports here should be node-free\n * to support browser/edge runtime usage. CLI-specific code is in ./cli/.\n */\n\n// Version injected at build time\ndeclare const __TBD_VERSION__: string;\n\n/**\n * Package version, derived from git at build time.\n * Format: X.Y.Z for releases, X.Y.Z-dev.N.hash for dev builds.\n */\nexport const VERSION: string =\n typeof __TBD_VERSION__ !== 'undefined' ? __TBD_VERSION__ : 'development';\n\n// Re-export schemas for library consumers\nexport * from './lib/schemas.js';\nexport * from './lib/types.js';\n\n// Re-export core operations (these should be node-free)\nexport { parseIssue, serializeIssue } from './file/parser.js';\n"],"mappings":";;;;;;;;;;;;;;AAgBA,MAAa,YAAY,EAAE,QAAQ,CAAC,UAAU;;;;;;AAO9C,MAAa,UAAU,EAAE,QAAQ,CAAC,MAAM,oBAAoB;;;;;;;;AAS5D,MAAa,UAAU,EAAE,QAAQ,CAAC,MAAM,iBAAiB;;;;;;AAOzD,MAAa,OAAO,EAAE,QAAQ,CAAC,MAAM,iBAAiB;;;;;AAMtD,MAAa,uBAAuB,EAAE,QAAQ,CAAC,MAAM,wBAAwB;;;;;;;AAQ7E,MAAa,UAAU,EAAE,QAAQ,CAAC,KAAK,CAAC,aAAa;;;;AAKrD,MAAa,aAAa,EAAE,QAAQ,KAAK;;;;AASzC,MAAa,aAAa,EAAE,OAAO;CACjC,MAAM;CACN,IAAI;CACJ,SAAS;CACT,YAAY;CACZ,YAAY;CAGZ,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,SAAS,CAAC,CAAC,UAAU;CACzD,CAAC;;;;AASF,MAAa,cAAc,EAAE,KAAK;CAAC;CAAQ;CAAe;CAAW;CAAY;CAAS,CAAC;;;;;AAM3F,MAAa,YAAY,EAAE,KAAK;CAAC;CAAO;CAAW;CAAQ;CAAQ;CAAQ,CAAC;;;;AAK5E,MAAa,WAAW,EAAE,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE;;;;AAKtD,MAAa,yBAAyB,EAAE,KAAK,CAAC,SAAS,CAAC;;;;AAKxD,MAAa,aAAa,EAAE,OAAO;CACjC,MAAM;CACN,QAAQ;CACT,CAAC;;;;;;;AAQF,MAAa,cAAc,WAAW,OAAO;CAC3C,MAAM,EAAE,QAAQ,KAAK;CAErB,OAAO,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,IAAI,IAAI;CACjC,aAAa,EAAE,QAAQ,CAAC,IAAI,IAAM,CAAC,UAAU,CAAC,UAAU;CACxD,OAAO,EAAE,QAAQ,CAAC,IAAI,IAAM,CAAC,UAAU,CAAC,UAAU;CAElD,MAAM,UAAU,QAAQ,OAAO;CAC/B,QAAQ,YAAY,QAAQ,OAAO;CACnC,UAAU,SAAS,QAAQ,EAAE;CAE7B,UAAU,EAAE,QAAQ,CAAC,UAAU,CAAC,UAAU;CAC1C,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,QAAQ,EAAE,CAAC;CACvC,cAAc,EAAE,MAAM,WAAW,CAAC,QAAQ,EAAE,CAAC;CAG7C,WAAW,QAAQ,UAAU,CAAC,UAAU;CAKxC,mBAAmB,EAAE,MAAM,QAAQ,CAAC,UAAU,CAAC,UAAU;CAGzD,UAAU,UAAU,UAAU,CAAC,UAAU;CACzC,gBAAgB,UAAU,UAAU,CAAC,UAAU;CAE/C,YAAY,EAAE,QAAQ,CAAC,UAAU,CAAC,UAAU;CAC5C,WAAW,UAAU,UAAU,CAAC,UAAU;CAC1C,cAAc,EAAE,QAAQ,CAAC,UAAU,CAAC,UAAU;CAG9C,WAAW,EAAE,QAAQ,CAAC,UAAU,CAAC,UAAU;CAC5C,CAAC;;;;;;AAWF,MAAa,gBAAgB,EAC1B,QAAQ,CACR,IAAI,EAAE,CACN,IAAI,IAAI,CACR,MACC,sBACA,0FACD;;;;;;AAOH,MAAa,gBAAgB,EAC1B,QAAQ,CACR,IAAI,EAAE,CACN,IAAI,IAAI,CACR,MACC,qBACA,iFACD;;;;;;;;;;;;;;;;AAiBH,MAAa,uBAAuB,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,QAAQ,CAAC;;;;;;;AAQpE,MAAa,kBAAkB,EAAE,OAAO;CAQtC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,QAAQ,CAAC,CAAC,UAAU;CAKlD,aAAa,EACV,MAAM,EAAE,QAAQ,CAAC,CACjB,QAAQ,CAAC,8BAA8B,+BAA+B,CAAC;CAC3E,CAAC;;;;;;;;;;;;;;;;;;;;;AAsBF,MAAa,eAAe,EAAE,OAAO;CAMnC,YAAY,EAAE,QAAQ,CAAC,QAAQ,MAAM;CAErC,aAAa,EAAE,QAAQ;CACvB,MAAM,EACH,OAAO;EACN,QAAQ,cAAc,QAAQ,WAAW;EACzC,QAAQ,cAAc,QAAQ,SAAS;EACxC,CAAC,CACD,QAAQ,EAAE,CAAC;CACd,SAAS,EAAE,OAAO,EAChB,WAAW,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,IAAI,GAAG,EACrC,CAAC;CACF,UAAU,EACP,OAAO;EACN,WAAW,EAAE,SAAS,CAAC,QAAQ,MAAM;EAOrC,qBAAqB,EAAE,QAAQ,CAAC,QAAQ,GAAG;EAO3C,YAAY,EAAE,SAAS,CAAC,QAAQ,KAAK;EACtC,CAAC,CACD,QAAQ,EAAE,CAAC;CAMd,YAAY,gBAAgB,UAAU;CACvC,CAAC;;;;AASF,MAAa,aAAa,EAAE,OAAO;CACjC,gBAAgB,EAAE,QAAQ,CAAC,KAAK;CAChC,YAAY;CACb,CAAC;;;;;AAUF,MAAa,mBAAmB,EAAE,OAAO;CAEvC,cAAc,UAAU,UAAU;CAElC,kBAAkB,UAAU,UAAU;CAEtC,cAAc,EAAE,SAAS,CAAC,UAAU;CACrC,CAAC;;;;AASF,MAAa,mBAAmB,EAAE,OAAO;CACvC,WAAW;CACX,WAAW;CACX,OAAO,EAAE,QAAQ;CACjB,YAAY,EAAE,QAAQ;CACtB,eAAe,EAAE,KAAK,CAAC,SAAS,SAAS,CAAC;CAC1C,cAAc,EAAE,KAAK,CAAC,SAAS,SAAS,CAAC;CACzC,SAAS,EAAE,OAAO;EAChB,eAAe;EACf,gBAAgB;EAChB,kBAAkB;EAClB,mBAAmB;EACpB,CAAC;CACH,CAAC;;;;;;AAWF,MAAa,sBAAsB,EAAE,OAAO,SAAS,KAAK;;;;;;;;;AC5U1D,MAAa,kBAAkB;;;;;AAM/B,MAAa,2BAA2B;;;;;AAMxC,MAAa,wBAAwB;;;;;;;;;;AAgBrC,MAAa,yBAA+C;CAC1D,WAAW;CACX,mBAAmB;CACnB,gBAAgB;CAChB,gBAAgB;CACjB;;;;;AAMD,MAAa,iCAAuD;CAClE,WAAW;CACX,mBAAmB;CACnB,gBAAgB;CAChB,gBAAgB;CACjB;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACrBD,SAAgB,cAAc,MAAe,SAAiD;AAC5F,QAAO,UAAU,MAAM;EAAE,GAAG;EAAwB,GAAG;EAAS,CAAC;;;;;;;;;AAUnE,SAAgB,qBAAqB,MAAuB;AAC1D,QAAO,UAAU,MAAM,+BAA+B;;;;;AAMxD,IAAa,qBAAb,cAAwC,MAAM;CAC5C,YACE,SACA,AAAgB,UAChB;AACA,QAAM,QAAQ;EAFE;AAGhB,OAAK,OAAO;;;;;;AAOhB,MAAM,oBAAoB;CACxB,OAAO;CACP,WAAW;CACX,KAAK;CACN;;;;AAKD,SAAgB,wBAAwB,SAA0B;AAChE,QACE,kBAAkB,MAAM,KAAK,QAAQ,IACrC,kBAAkB,UAAU,KAAK,QAAQ,IACzC,kBAAkB,IAAI,KAAK,QAAQ;;;;;;;;;;;;;;AAgBvC,SAAgB,+BAA4C,SAAiB,UAAsB;AAEjG,KAAI,wBAAwB,QAAQ,CAElC,OAAM,IAAI,mBACR,OAFe,WAAW,OAAO,aAAa,GAE9B,gOAGhB,SACD;AAGH,QAAOA,MAAU,QAAQ;;;;;;;;;;;;;;AC5F3B,SAAgB,qBAAqB,SAAyB;AAC5D,QAAO,QAAQ,QAAQ,SAAS,KAAK,CAAC,QAAQ,OAAO,KAAK;;;;;;;;AAS5D,SAAgB,cAAc,SAAiC;CAC7D,MAAM,aAAa,qBAAqB,QAAQ;AAEhD,KAAI,CAAC,OAAO,KAAK,WAAW,CAC1B,QAAO;EAAE,aAAa;EAAM,MAAM;EAAS;AAG7C,KAAI;EACF,MAAM,SAAS,OAAO,WAAW;EAIjC,MAAM,OAAO,OAAO;EACpB,IAAI,cAA6B;AAEjC,MAAI,QAAQ,OAAO,KAAK,KAAK,CAAC,SAAS,EAGrC,eAAc,qBAAqB,KAAK,CAAC,SAAS;MAGlD,eAAc;EAIhB,MAAM,OAAO,OAAO,QAAQ,QAAQ,QAAQ,GAAG;AAE/C,SAAO;GAAE;GAAa;GAAM;SACtB;AAEN,SAAO;GAAE,aAAa;GAAM,MAAM;GAAS;;;;;;;;AAkB/C,SAAgB,iBAAiB,SAAyB;AACxD,QAAO,cAAc,QAAQ,CAAC;;;;;;;AAQhC,SAAgB,uBAAuB,SAAiB,UAA0B;CAChF,MAAM,EAAE,aAAa,SAAS,cAAc,QAAQ;AAEpD,KAAI,gBAAgB,KAClB,QAAO,WAAW;AAIpB,QAAO,GADkB,cAAc,QAAQ,YAAY,SAAS,WACzC,IAAI,SAAS,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;ACjEhD,MAAa,gBAAgB,EAC3B,SAAS,EACP,MAAM;CACJ,QAAQ,QAAwBC,MAAU,IAAI;CAC9C,YAAY,QAAwB,cAAc,IAAI;CACvD,EACF,EACF;;;;;;AAgBD,SAAgB,6BAA6B,SAAkC;CAE7E,MAAM,oBAAoB,qBAAqB,QAAQ;AAGvD,KAAI,CAAC,OAAO,KAAK,kBAAkB,CACjC,OAAM,IAAI,MAAM,yDAAyD;CAG3E,MAAM,SAAS,OAAO,mBAAmB,cAAc;AAIvD,KAAI,OAAO,WAAW,MAAM,CAAC,kBAAkB,SAAS,WAAW,EAAE;EAEnE,MAAM,QAAQ,kBAAkB,MAAM,KAAK;EAC3C,IAAI,aAAa;AACjB,OAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,IAChC,KAAI,MAAM,IAAI,MAAM,KAAK,OAAO;AAC9B,gBAAa;AACb;;AAGJ,MAAI,CAAC,WACH,OAAM,IAAI,MAAM,yDAAyD;;CAI7E,MAAM,cAAc,OAAO;CAG3B,MAAM,OAAO,OAAO,QAAQ,MAAM;CAGlC,MAAM,aAAa,gBAAgB,KAAK,KAAK;CAC7C,IAAI,cAAc;CAClB,IAAI,QAAQ;AAEZ,KAAI,YAAY,UAAU,QAAW;AACnC,gBAAc,KAAK,MAAM,GAAG,WAAW,MAAM,CAAC,MAAM;AACpD,UAAQ,KAAK,MAAM,WAAW,QAAQ,WAAW,GAAG,OAAO,CAAC,MAAM;;AAGpE,QAAO;EAAE;EAAa;EAAa;EAAO;;;;;AAM5C,SAAgB,WAAW,SAAwB;CACjD,MAAM,EAAE,aAAa,aAAa,UAAU,6BAA6B,QAAQ;CAGjF,MAAM,OAAO;EACX,GAAG;EACH,aAAa,eAAe;EAC5B,OAAO,SAAS;EACjB;AAGD,QAAO,YAAY,MAAM,KAAK;;;;;;AAOhC,SAAgB,eAAe,OAAsB;CAEnD,MAAM,EAAE,aAAa,OAAO,GAAG,aAAa;CAG5C,MAAM,iBAA0C,EAAE;AAClD,MAAK,MAAM,OAAO,OAAO,KAAK,SAAS,CAAC,MAAM,CAC5C,gBAAe,OAAO,SAAS;CAWjC,MAAM,QAAQ;EAAC;EAPF,cAAc,gBAAgB;GACzC,WAAW;GACX,SAAS;GACV,CAAC,CAIyB,MAAM;EAAE;EAAM;AAEzC,KAAI,YACF,OAAM,KAAK,YAAY,MAAM,CAAC;AAGhC,KAAI,OAAO;AACT,QAAM,KAAK,GAAG;AACd,QAAM,KAAK,WAAW;AACtB,QAAM,KAAK,GAAG;AACd,QAAM,KAAK,MAAM,MAAM,CAAC;;AAI1B,QAAO,MAAM,KAAK,KAAK,GAAG;;;;;;;;;AC3I5B,MAAa"}
|