@wipcomputer/wip-ai-devops-toolbox 1.9.51 → 1.9.53

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.
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "name": "wip-ai-devops-toolbox",
3
- "websiteRepo": "/Users/lesa/Documents/wipcomputer--mac-mini-01/staff/Parker/Claude Code - Mini/repos/wip-web/wip-websites-private"
3
+ "websiteRepo": "/Users/lesa/wipcomputerinc/repos/wip-web/wip-websites-private"
4
4
  }
package/CHANGELOG.md CHANGED
@@ -31,6 +31,59 @@
31
31
 
32
32
 
33
33
 
34
+
35
+ ## 1.9.53 (2026-03-28)
36
+
37
+ # Release Notes: wip-ai-devops-toolbox v1.9.53
38
+
39
+ **One-line summary of what this release does**
40
+
41
+ Tell the story. What was broken or missing? What did we build? Why does the user care?
42
+ Write at least one real paragraph of prose. Not just bullets. The release notes gate
43
+ will block if there is no narrative. Bullets are fine for details, but the story comes first.
44
+
45
+ ## The story
46
+
47
+ (Write a paragraph here. What was the problem? What does this release fix? Why does it matter?
48
+ This is what users read. Make it worth reading.)
49
+
50
+ ## Issues closed
51
+
52
+ - #282
53
+
54
+ ## How to verify
55
+
56
+ ```bash
57
+ # Commands to test the changes
58
+ ```
59
+
60
+ ## 1.9.52 (2026-03-27)
61
+
62
+ # Release Notes: wip-ai-devops-toolbox v1.9.52
63
+
64
+ **Fix branch guard false-blocking bash commands targeting worktree paths**
65
+
66
+ ## What changed
67
+
68
+ - Branch guard now extracts absolute paths from any bash command (mkdir, cp, mv, touch, etc.) and resolves the git branch from the target path's repo, not the CWD
69
+ - `findRepoRoot()` improved to walk up to existing directories for paths that don't exist yet (handles mkdir for new directories)
70
+ - Added `.ldm/worktrees` to allowed worktree locations alongside `_worktrees/` and `.claude/worktrees`
71
+
72
+ ## Why
73
+
74
+ When Claude Code launches from `~/wipcomputerinc/` (on main) and runs bash commands targeting files inside a worktree (e.g., `mkdir -p /path/to/_worktrees/repo--branch/new-dir/`), the guard only knew how to extract paths from `cd` and `git -C` patterns. Any other command fell back to CWD resolution, saw "main", and blocked incorrectly. This caused minutes of wasted time every session.
75
+
76
+ ## Issues closed
77
+
78
+ - wipcomputer/wip-ldm-os#187
79
+
80
+ ## How to verify
81
+
82
+ ```bash
83
+ # From CWD on main, this should no longer be blocked:
84
+ # mkdir -p /path/to/_worktrees/repo--branch/new-directory/
85
+ # cp file.txt /path/to/_worktrees/repo--branch/
86
+ ```
34
87
 
35
88
  ## 1.9.51 (2026-03-24)
36
89
 
@@ -1,6 +1,6 @@
1
1
  # Dev Guide ... Best Practices for AI-Assisted Development
2
2
 
3
- **WIP team members: also read [the private Dev Guide](ai/DEV-GUIDE-FOR-WIP-ONLY-PRIVATE.md).** It covers WIP-specific conventions (branch prefixes, agent IDs, deploy paths, incidents) that supplement everything below. Neither guide is complete without the other.
3
+ **WIP team members: also read the private Dev Guide at `~/wipcomputerinc/settings/templates/dev-guide-private.md`.** It covers WIP-specific conventions (branch prefixes, agent IDs, deploy paths, incidents) that supplement everything below. Neither guide is complete without the other.
4
4
 
5
5
  ## Repo Structure Convention
6
6
 
@@ -648,6 +648,47 @@ Product docs drift fast. If roadmap updates only happen "when someone remembers,
648
648
 
649
649
  Release notes are the public face of the project. They must be comprehensive. One-liners like "Release v0.6.0" are unacceptable. Every feature, every change, documented section by section. This applies to both private and public GitHub releases.
650
650
 
651
+ ## Feature Planning: 5 Mandatory Questions
652
+
653
+ Before implementing any feature that changes how the system works (installer, config, deploy, architecture), answer these 5 questions in your plan or PR description. Not optional. Not "consider this." Answer all five or the plan is incomplete.
654
+
655
+ 1. **What source files change?** (in the repo)
656
+ 2. **What does `ldm install` deploy?** (templates, rules, docs, boot config, CLAUDE.md, skills)
657
+ 3. **What needs to update for fresh install vs existing install?**
658
+ 4. **What docs need updating?** (repo docs, settings/docs, website)
659
+ 5. **What are ALL the files the installer touches on deploy?**
660
+
661
+ If you can't answer #5, you don't understand the change well enough to ship it.
662
+
663
+ ## Doc Update Dependencies
664
+
665
+ When you change a file on the left, you MUST also update the files on the right. This is not optional.
666
+
667
+ | If you change | You must also update |
668
+ |--------------|---------------------|
669
+ | `SKILL.md` | `references/`, `settings/docs/how-install-works.md`, wip.computer/install/ (auto via wip-release) |
670
+ | `lib/deploy.mjs` | `settings/docs/how-install-works.md`, `docs/universal-installer/SPEC.md`, `docs/universal-installer/TECHNICAL.md` |
671
+ | `catalog.json` | `settings/docs/what-is-ldm-os.md`, `README.md`, `docs/skills/README.md` |
672
+ | `bin/ldm.js` (init) | `settings/docs/how-install-works.md`, `settings/docs/system-directories.md` |
673
+ | `shared/rules/*` | `settings/docs/how-rules-and-commands-work.md` |
674
+ | `shared/boot/*` | `settings/docs/how-agents-work.md` |
675
+ | `lib/detect.mjs` | `docs/universal-installer/SPEC.md`, `settings/docs/how-install-works.md` |
676
+ | Backup scripts | `settings/docs/how-backup-works.md` |
677
+ | Agent identity files | `settings/docs/how-agents-work.md` |
678
+ | Any repo `README.md` | Public repo README (via deploy-public.sh) |
679
+
680
+ Machine-readable version: `~/wipcomputerinc/settings/docs/change-dependencies.json`
681
+
682
+ ### Three doc layers
683
+
684
+ Every change flows through three layers:
685
+
686
+ 1. **Repo docs** (generic, source of truth): README.md, TECHNICAL.md, SPEC.md per repo. Written for anyone.
687
+ 2. **Settings docs** (personalized, deployed by ldm install): `~/wipcomputerinc/settings/docs/`. Written for YOUR system. Personalized from config.json.
688
+ 3. **Website docs** (public): wip.computer. SKILL.md auto-deployed by wip-release. Other docs via Mintlify or deploy script.
689
+
690
+ If repo docs change but settings docs don't update, the user's local docs drift. If settings docs change but the website doesn't, the public docs drift. All three layers must stay in sync.
691
+
651
692
  ## Repo Directory Structure
652
693
 
653
694
  ### The Standard Layout
package/SKILL.md CHANGED
@@ -5,7 +5,7 @@ license: MIT
5
5
  interface: [cli, module, mcp, skill, hook, plugin]
6
6
  metadata:
7
7
  display-name: "WIP AI DevOps Toolbox"
8
- version: "1.9.51"
8
+ version: "1.9.53"
9
9
  homepage: "https://github.com/wipcomputer/wip-ai-devops-toolbox"
10
10
  author: "Parker Todd Brooks"
11
11
  category: dev-tools
@@ -0,0 +1,25 @@
1
+ # Release Notes: wip-ai-devops-toolbox v1.9.52
2
+
3
+ **Fix branch guard false-blocking bash commands targeting worktree paths**
4
+
5
+ ## What changed
6
+
7
+ - Branch guard now extracts absolute paths from any bash command (mkdir, cp, mv, touch, etc.) and resolves the git branch from the target path's repo, not the CWD
8
+ - `findRepoRoot()` improved to walk up to existing directories for paths that don't exist yet (handles mkdir for new directories)
9
+ - Added `.ldm/worktrees` to allowed worktree locations alongside `_worktrees/` and `.claude/worktrees`
10
+
11
+ ## Why
12
+
13
+ When Claude Code launches from `~/wipcomputerinc/` (on main) and runs bash commands targeting files inside a worktree (e.g., `mkdir -p /path/to/_worktrees/repo--branch/new-dir/`), the guard only knew how to extract paths from `cd` and `git -C` patterns. Any other command fell back to CWD resolution, saw "main", and blocked incorrectly. This caused minutes of wasted time every session.
14
+
15
+ ## Issues closed
16
+
17
+ - wipcomputer/wip-ldm-os#187
18
+
19
+ ## How to verify
20
+
21
+ ```bash
22
+ # From CWD on main, this should no longer be blocked:
23
+ # mkdir -p /path/to/_worktrees/repo--branch/new-directory/
24
+ # cp file.txt /path/to/_worktrees/repo--branch/
25
+ ```
@@ -0,0 +1,22 @@
1
+ # Release Notes: wip-ai-devops-toolbox v1.9.53
2
+
3
+ **One-line summary of what this release does**
4
+
5
+ Tell the story. What was broken or missing? What did we build? Why does the user care?
6
+ Write at least one real paragraph of prose. Not just bullets. The release notes gate
7
+ will block if there is no narrative. Bullets are fine for details, but the story comes first.
8
+
9
+ ## The story
10
+
11
+ (Write a paragraph here. What was the problem? What does this release fix? Why does it matter?
12
+ This is what users read. Make it worth reading.)
13
+
14
+ ## Issues closed
15
+
16
+ - #282
17
+
18
+ ## How to verify
19
+
20
+ ```bash
21
+ # Commands to test the changes
22
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wipcomputer/wip-ai-devops-toolbox",
3
- "version": "1.9.51",
3
+ "version": "1.9.53",
4
4
  "type": "module",
5
5
  "description": "The complete AI DevOps toolkit for AI-assisted development teams.",
6
6
  "license": "MIT",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wipcomputer/deploy-public",
3
- "version": "1.9.51",
3
+ "version": "1.9.53",
4
4
  "description": "Private-to-public repo sync. Excludes ai/ folder, creates PR, merges, cleans up branches.",
5
5
  "bin": {
6
6
  "deploy-public": "./deploy-public.sh"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wipcomputer/post-merge-rename",
3
- "version": "1.9.51",
3
+ "version": "1.9.53",
4
4
  "description": "Post-merge branch renaming. Appends --merged-YYYY-MM-DD to preserve history.",
5
5
  "bin": {
6
6
  "post-merge-rename": "./post-merge-rename.sh"
@@ -89,13 +89,14 @@ const ALLOWED_BASH_PATTERNS = [
89
89
  /\bldm\s+(install|init|doctor|stack|updates)\b/, // LDM OS commands modify ~/.ldm/, not the repo
90
90
  /\brm\s+.*\.ldm\/state\//, // cleaning LDM state files only, not repo files
91
91
  /\bclaude\s+mcp\b/, // MCP registration, not repo files
92
+ /\bmkdir\s+.*\.worktrees\b/, // creating .worktrees/ directory is part of the process
92
93
  ];
93
94
 
94
95
  // Workflow steps for error messages (#213)
95
96
  const WORKFLOW_ON_MAIN = `
96
97
  The process: worktree -> branch -> commit -> push -> PR -> merge -> wip-release -> deploy-public.
97
98
 
98
- Step 1: git worktree add ../my-worktree -b cc-mini/your-feature
99
+ Step 1: git worktree add .worktrees/<repo>--<branch> -b cc-mini/your-feature
99
100
  Step 2: Edit files in the worktree
100
101
  Step 3: git add + git commit (with co-authors)
101
102
  Step 4: git push -u origin cc-mini/your-feature
@@ -135,6 +136,17 @@ function findRepoRoot(filePath) {
135
136
  dir = dirname(dir); // File might not exist yet
136
137
  }
137
138
 
139
+ // Walk up until we find an existing directory (handles mkdir for new paths)
140
+ while (dir && dir !== '/') {
141
+ try {
142
+ const s = statSync(dir);
143
+ if (s.isDirectory()) break;
144
+ dir = dirname(dir);
145
+ } catch {
146
+ dir = dirname(dir);
147
+ }
148
+ }
149
+
138
150
  // Use git rev-parse from the directory
139
151
  const result = execSync('git rev-parse --show-toplevel 2>/dev/null', {
140
152
  cwd: dir,
@@ -146,6 +158,18 @@ function findRepoRoot(filePath) {
146
158
  return null;
147
159
  }
148
160
 
161
+ function extractPathsFromCommand(command) {
162
+ // Extract absolute paths from a bash command
163
+ // Matches paths like /Users/foo/bar, /tmp/something, etc.
164
+ const paths = [];
165
+ const regex = /(\/(?:Users|home|tmp|var|opt|etc|private)[^\s"'|;&>)]+)/g;
166
+ let match;
167
+ while ((match = regex.exec(command)) !== null) {
168
+ paths.push(match[1]);
169
+ }
170
+ return paths;
171
+ }
172
+
149
173
  function getCurrentBranch(cwd) {
150
174
  try {
151
175
  return execSync('git branch --show-current 2>/dev/null', {
@@ -226,15 +250,15 @@ async function main() {
226
250
  } catch {}
227
251
  }
228
252
 
229
- // Warn when creating worktrees outside _worktrees/ (#212)
253
+ // Warn when creating worktrees outside .worktrees/ (#212)
230
254
  const wtMatch = cmd.match(/\bgit\s+worktree\s+add\s+["']?([^\s"']+)/);
231
255
  if (wtMatch) {
232
256
  const wtPath = wtMatch[1];
233
- if (!wtPath.includes('_worktrees') && !wtPath.includes('.claude/worktrees')) {
234
- deny(`WARNING: Creating worktree outside _worktrees/. Use: ldm worktree add <branch>
257
+ if (!wtPath.includes('.worktrees')) {
258
+ deny(`WARNING: Creating worktree outside .worktrees/. Use: ldm worktree add <branch>
235
259
 
236
- The convention is _worktrees/<repo>--<branch>/ so worktrees don't mix with real repos.
237
- Manual equivalent: git worktree add ../_worktrees/<repo>--<branch> -b <branch>
260
+ The convention is .worktrees/<repo>--<branch>/ so worktrees are hidden and don't mix with real repos.
261
+ Manual equivalent: git worktree add .worktrees/<repo>--<branch> -b <branch>
238
262
 
239
263
  This is a warning, not a block. If you need to create it here, retry.`);
240
264
  process.exit(0);
@@ -274,6 +298,17 @@ This is a warning, not a block. If you need to create it here, retry.`);
274
298
  if (!repoDir && gitCMatch) {
275
299
  repoDir = findRepoRoot(gitCMatch[1].trim());
276
300
  }
301
+ // Extract absolute paths from the command itself (handles mkdir, cp, mv, etc.)
302
+ if (!repoDir) {
303
+ const paths = extractPathsFromCommand(command);
304
+ for (const p of paths) {
305
+ const resolved = findRepoRoot(p);
306
+ if (resolved) {
307
+ repoDir = resolved;
308
+ break;
309
+ }
310
+ }
311
+ }
277
312
  }
278
313
 
279
314
  // Fall back to CWD
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wipcomputer/wip-branch-guard",
3
- "version": "1.9.51",
3
+ "version": "1.9.53",
4
4
  "description": "PreToolUse hook that blocks all writes on main branch. Forces agents to work on branches or worktrees.",
5
5
  "type": "module",
6
6
  "main": "guard.mjs",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wipcomputer/wip-file-guard",
3
- "version": "1.9.51",
3
+ "version": "1.9.53",
4
4
  "type": "module",
5
5
  "description": "Hook that blocks destructive edits to protected identity files. For Claude Code CLI and OpenClaw.",
6
6
  "main": "guard.mjs",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wipcomputer/wip-license-guard",
3
- "version": "1.9.51",
3
+ "version": "1.9.53",
4
4
  "description": "License compliance for your own repos. Ensures correct copyright, dual-license blocks, and LICENSE files.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wipcomputer/wip-license-hook",
3
- "version": "1.9.51",
3
+ "version": "1.9.53",
4
4
  "description": "License rug-pull detection and dependency license compliance for open source projects",
5
5
  "type": "module",
6
6
  "main": "dist/cli/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wipcomputer/wip-readme-format",
3
- "version": "1.9.51",
3
+ "version": "1.9.53",
4
4
  "description": "Reformat any repo's README to follow the WIP Computer standard. Agent-first, human-readable.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -155,8 +155,10 @@ function gitCommitAndTag(repoPath, newVersion, notes) {
155
155
  execFileSync('git', ['add', f], { cwd: repoPath, stdio: 'pipe' });
156
156
  }
157
157
  }
158
- // Use execFileSync to avoid shell injection via notes
159
- execFileSync('git', ['commit', '-m', msg], { cwd: repoPath, stdio: 'pipe' });
158
+ // Use execFileSync to avoid shell injection via notes.
159
+ // --no-verify: wip-release legitimately commits on main (version bump + changelog).
160
+ // The pre-commit hook blocks all commits on main, but wip-release is the one exception.
161
+ execFileSync('git', ['commit', '--no-verify', '-m', msg], { cwd: repoPath, stdio: 'pipe' });
160
162
  execFileSync('git', ['tag', `v${newVersion}`], { cwd: repoPath, stdio: 'pipe' });
161
163
  }
162
164
 
@@ -261,6 +263,24 @@ function checkReleaseNotes(notes, notesSource, level) {
261
263
  issues.push('Notes look like a changelog entry, not a narrative. Explain the impact.');
262
264
  }
263
265
 
266
+ // Narrative quality: must have at least one paragraph (not just bullets/headers)
267
+ // A paragraph is 2+ consecutive lines of prose (not starting with -, *, #, |, or ```)
268
+ const lines = notes.split('\n').filter(l => l.trim().length > 0);
269
+ const proseLines = lines.filter(l => {
270
+ const t = l.trim();
271
+ return !t.startsWith('#') && !t.startsWith('-') && !t.startsWith('*') &&
272
+ !t.startsWith('|') && !t.startsWith('```') && !t.startsWith('>') &&
273
+ t.length > 30;
274
+ });
275
+ if (proseLines.length < 2) {
276
+ issues.push('Release notes need narrative, not just bullets. Write at least one paragraph explaining what changed and why it matters. Tell the story.');
277
+ }
278
+
279
+ // Must be substantial (not just a header + bullets)
280
+ if (notes.length < 200) {
281
+ issues.push('Release notes are too short (under 200 chars). Every release deserves a story: what was broken or missing, what we built, why the user should care.');
282
+ }
283
+
264
284
  // Release notes should reference at least one issue
265
285
  const hasIssueRef = /#\d+/.test(notes);
266
286
  if (!hasIssueRef) {
@@ -299,16 +319,14 @@ export function scaffoldReleaseNotes(repoPath, version) {
299
319
 
300
320
  **One-line summary of what this release does**
301
321
 
302
- ## What changed
303
-
304
- Describe the changes. Not a commit list. Explain:
305
- - What was built or fixed
306
- - Why it matters
307
- - What the user should know
322
+ Tell the story. What was broken or missing? What did we build? Why does the user care?
323
+ Write at least one real paragraph of prose. Not just bullets. The release notes gate
324
+ will block if there is no narrative. Bullets are fine for details, but the story comes first.
308
325
 
309
- ## Why
326
+ ## The story
310
327
 
311
- What problem does this solve? What was broken or missing?
328
+ (Write a paragraph here. What was the problem? What does this release fix? Why does it matter?
329
+ This is what users read. Make it worth reading.)
312
330
 
313
331
  ## Issues closed
314
332
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wipcomputer/wip-release",
3
- "version": "1.9.51",
3
+ "version": "1.9.53",
4
4
  "type": "module",
5
5
  "description": "One-command release pipeline. Bumps version, updates changelog + SKILL.md, publishes to npm + GitHub.",
6
6
  "main": "core.mjs",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wipcomputer/wip-repo-init",
3
- "version": "1.9.51",
3
+ "version": "1.9.53",
4
4
  "description": "Scaffold the standard ai/ directory structure in any repo",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wipcomputer/wip-repo-permissions-hook",
3
- "version": "1.9.51",
3
+ "version": "1.9.53",
4
4
  "type": "module",
5
5
  "description": "Repo visibility guard. Blocks repos from going public without a -private counterpart.",
6
6
  "main": "core.mjs",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wipcomputer/wip-repos",
3
- "version": "1.9.51",
3
+ "version": "1.9.53",
4
4
  "type": "module",
5
5
  "description": "Repo manifest reconciler. Single source of truth for repo organization. Like prettier for folder structure.",
6
6
  "main": "core.mjs",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wipcomputer/universal-installer",
3
- "version": "1.9.51",
3
+ "version": "1.9.53",
4
4
  "type": "module",
5
5
  "description": "The Universal Interface specification for agent-native software. Teaches your AI how to build repos with every interface: CLI, Module, MCP Server, OpenClaw Plugin, Skill, Claude Code Hook.",
6
6
  "main": "detect.mjs",
@@ -1,63 +0,0 @@
1
- # todos/
2
-
3
- One todo file per person or agent. Three sections per file: To Do, Done, Deprecated.
4
-
5
- ## What This Folder Is
6
-
7
- Todos that are specific to this repo. Each person or agent who works on this repo gets one file. The file tracks what they need to do, what they've done, and what got dropped.
8
-
9
- For cross-repo work or bigger items, use GitHub Issues. Todos here are for repo-scoped tasks that don't need the overhead of an issue.
10
-
11
- ## Files
12
-
13
- One file per person/agent. Name it `[Name]-todo.md`.
14
-
15
- Example:
16
-
17
- | File | Who |
18
- |------|-----|
19
- | `Parker-todo.md` | Parker (human tasks: reviews, credentials, approvals) |
20
- | `CC-Mini-todo.md` | Claude Code on Mac Mini (code, builds, deploys) |
21
-
22
- Create the file when that person/agent first has work to do. No empty placeholder files.
23
-
24
- ## File Format
25
-
26
- ```markdown
27
- # [Name] Todos
28
-
29
- **Last updated:** YYYY-MM-DD
30
-
31
- ## To Do
32
-
33
- - [ ] Task description
34
- - [ ] Task description (blocked by: reason)
35
-
36
- ## Done
37
-
38
- - [x] Task description (YYYY-MM-DD)
39
- - [x] Task description (YYYY-MM-DD)
40
-
41
- ## Deprecated
42
-
43
- - ~~Task description~~ ... reason. (YYYY-MM-DD)
44
- ```
45
-
46
- ## Rules
47
-
48
- - **Never delete anything.** Items move between sections, never off the page.
49
- - **To Do** ... work that needs to happen.
50
- - **Done** ... completed work. Check the box, add the date.
51
- - **Deprecated** ... planned but no longer needed. Strikethrough, add the reason and date. Not the same as Done. Done means it shipped. Deprecated means the requirement changed.
52
- - **Update the date** at the top of the file every time you edit it.
53
- - **One file per person/agent.** No dated files, no subfolders, no inboxes.
54
- - **Blocked items** stay in To Do with a `(blocked by: reason)` note. Don't move them to a separate section.
55
-
56
- ## When to Use Todos vs GitHub Issues
57
-
58
- | Use | When |
59
- |-----|------|
60
- | **Todo file** | Quick tasks, repo-scoped work, things you'll do this session or this week |
61
- | **GitHub Issue** | Bugs, feature requests, cross-repo work, things that need tracking or discussion |
62
-
63
- Both is fine. File an issue AND add a todo that references it. The todo is your personal checklist. The issue is the team's record.