@wipcomputer/wip-ldm-os 0.4.73-alpha.3 → 0.4.73-alpha.30

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 (58) hide show
  1. package/LICENSE +52 -0
  2. package/bin/ldm.js +512 -95
  3. package/dist/bridge/chunk-3RG5ZIWI.js +10 -0
  4. package/dist/bridge/{chunk-LF7EMFBY.js → chunk-7NH6JBIO.js} +127 -49
  5. package/dist/bridge/cli.js +2 -1
  6. package/dist/bridge/core.d.ts +13 -1
  7. package/dist/bridge/core.js +4 -1
  8. package/dist/bridge/mcp-server.js +52 -7
  9. package/dist/bridge/openclaw.d.ts +5 -0
  10. package/dist/bridge/openclaw.js +11 -0
  11. package/docs/doc-pipeline/README.md +74 -0
  12. package/docs/doc-pipeline/TECHNICAL.md +79 -0
  13. package/lib/deploy.mjs +94 -10
  14. package/lib/detect.mjs +20 -6
  15. package/package.json +2 -2
  16. package/shared/docs/README.md.tmpl +2 -2
  17. package/shared/docs/how-install-works.md.tmpl +22 -2
  18. package/shared/docs/how-releases-work.md.tmpl +58 -42
  19. package/shared/docs/how-worktrees-work.md.tmpl +12 -7
  20. package/shared/rules/git-conventions.md +3 -3
  21. package/shared/rules/release-pipeline.md +1 -1
  22. package/shared/rules/security.md +1 -1
  23. package/shared/rules/workspace-boundaries.md +1 -1
  24. package/shared/rules/writing-style.md +1 -1
  25. package/shared/templates/claude-md-level1.md +7 -3
  26. package/src/bridge/core.ts +160 -56
  27. package/src/bridge/mcp-server.ts +93 -8
  28. package/src/bridge/openclaw.ts +14 -0
  29. package/src/hooks/inbox-check-hook.mjs +194 -0
  30. package/src/hooks/inbox-rewake-hook.mjs +338 -0
  31. package/src/hosted-mcp/.env.example +3 -0
  32. package/src/hosted-mcp/demo/agent.html +300 -0
  33. package/src/hosted-mcp/demo/agent.txt +84 -0
  34. package/src/hosted-mcp/demo/fallback.jpg +0 -0
  35. package/src/hosted-mcp/demo/footer.js +74 -0
  36. package/src/hosted-mcp/demo/index.html +1303 -0
  37. package/src/hosted-mcp/demo/login.html +548 -0
  38. package/src/hosted-mcp/demo/privacy.html +223 -0
  39. package/src/hosted-mcp/demo/sprites.jpg +0 -0
  40. package/src/hosted-mcp/demo/sprites.png +0 -0
  41. package/src/hosted-mcp/demo/tos.html +198 -0
  42. package/src/hosted-mcp/deploy.sh +70 -0
  43. package/src/hosted-mcp/ecosystem.config.cjs +14 -0
  44. package/src/hosted-mcp/inbox.mjs +64 -0
  45. package/src/hosted-mcp/legal/internet-services/terms/site.html +205 -0
  46. package/src/hosted-mcp/legal/privacy/en-ww/index.html +230 -0
  47. package/src/hosted-mcp/nginx/mcp-oauth.conf +98 -0
  48. package/src/hosted-mcp/nginx/mcp-server.conf +17 -0
  49. package/src/hosted-mcp/nginx/wip.computer.conf +45 -0
  50. package/src/hosted-mcp/package-lock.json +2092 -0
  51. package/src/hosted-mcp/package.json +23 -0
  52. package/src/hosted-mcp/prisma/migrations/20260406233014_init/migration.sql +68 -0
  53. package/src/hosted-mcp/prisma/migrations/migration_lock.toml +3 -0
  54. package/src/hosted-mcp/prisma/schema.prisma +57 -0
  55. package/src/hosted-mcp/prisma.config.ts +14 -0
  56. package/src/hosted-mcp/server.mjs +2079 -0
  57. package/src/hosted-mcp/tools.mjs +73 -0
  58. package/templates/hooks/pre-commit +5 -0
package/lib/deploy.mjs CHANGED
@@ -394,14 +394,38 @@ function runBuildIfNeeded(repoPath) {
394
394
 
395
395
  function compareSemver(a, b) {
396
396
  if (!a || !b) return 0;
397
- const pa = a.split('.').map(Number);
398
- const pb = b.split('.').map(Number);
397
+ if (a === b) return 0;
398
+ const [aBase, aPre] = a.split('-', 2);
399
+ const [bBase, bPre] = b.split('-', 2);
400
+ const pa = aBase.split('.').map(Number);
401
+ const pb = bBase.split('.').map(Number);
399
402
  for (let i = 0; i < 3; i++) {
400
403
  const na = pa[i] || 0;
401
404
  const nb = pb[i] || 0;
402
405
  if (na > nb) return 1;
403
406
  if (na < nb) return -1;
404
407
  }
408
+ // Base versions equal. Stable > prerelease.
409
+ if (!aPre && bPre) return 1; // a is stable, b is prerelease -> a is newer
410
+ if (aPre && !bPre) return -1; // a is prerelease, b is stable -> b is newer
411
+ // Both have prereleases. Compare segments.
412
+ if (aPre && bPre) {
413
+ const aSegs = aPre.split('.');
414
+ const bSegs = bPre.split('.');
415
+ for (let i = 0; i < Math.max(aSegs.length, bSegs.length); i++) {
416
+ const as = aSegs[i] || '';
417
+ const bs = bSegs[i] || '';
418
+ const an = Number(as);
419
+ const bn = Number(bs);
420
+ if (!isNaN(an) && !isNaN(bn)) {
421
+ if (an > bn) return 1;
422
+ if (an < bn) return -1;
423
+ } else {
424
+ if (as > bs) return 1;
425
+ if (as < bs) return -1;
426
+ }
427
+ }
428
+ }
405
429
  return 0;
406
430
  }
407
431
 
@@ -508,6 +532,32 @@ function safeDeployDir(repoPath, destDir, name) {
508
532
  }
509
533
  }
510
534
 
535
+ /**
536
+ * Update tools.allow in openclaw.json to include a newly deployed plugin.
537
+ * OpenClaw 2026.4.8+ enforces tools.allow as an exclusive allowlist.
538
+ * Without this, newly installed plugins are blocked from running.
539
+ *
540
+ * This function MUST remain at module top level. Nesting it inside another
541
+ * function puts it out of scope for its call sites in the install handlers
542
+ * and produces a ReferenceError at runtime. See:
543
+ * ai/product/bugs/installer/2026-04-11--cc-mini--update-tools-allow-reference-error.md
544
+ */
545
+ function updateToolsAllow(pluginName) {
546
+ const ocConfigPath = join(OC_ROOT, 'openclaw.json');
547
+ if (!existsSync(ocConfigPath)) return;
548
+ try {
549
+ const raw = readFileSync(ocConfigPath, 'utf8');
550
+ const config = JSON.parse(raw);
551
+ if (!config.tools?.allow || !Array.isArray(config.tools.allow)) return;
552
+ if (config.tools.allow.includes(pluginName)) return;
553
+ config.tools.allow.push(pluginName);
554
+ writeFileSync(ocConfigPath, JSON.stringify(config, null, 2) + '\n');
555
+ log(`Added "${pluginName}" to openclaw.json tools.allow`);
556
+ } catch (e) {
557
+ log(`Warning: failed to update tools.allow for ${pluginName}: ${e.message}`);
558
+ }
559
+ }
560
+
511
561
  // ── OpenClaw plugin naming (fix #8) ──
512
562
 
513
563
  function resolveOcPluginName(repoPath, toolName) {
@@ -788,7 +838,28 @@ function registerMCP(repoPath, door, toolName) {
788
838
  }
789
839
  }
790
840
 
791
- function installClaudeCodeHook(repoPath, door) {
841
+ /**
842
+ * Install Claude Code hook(s) for an extension.
843
+ *
844
+ * Accepts either a single door object (legacy) or an array of door objects
845
+ * (new in 2026-04-05 for wip-branch-guard 1.9.73 which registers on both
846
+ * PreToolUse and SessionStart). Normalizes to an array and installs each
847
+ * door independently.
848
+ *
849
+ * Returns true if at least one door installed successfully.
850
+ */
851
+ function installClaudeCodeHook(repoPath, doorOrDoors) {
852
+ const doors = Array.isArray(doorOrDoors) ? doorOrDoors : [doorOrDoors];
853
+ let anyOk = false;
854
+ for (const door of doors) {
855
+ if (installClaudeCodeHookEvent(repoPath, door)) {
856
+ anyOk = true;
857
+ }
858
+ }
859
+ return anyOk;
860
+ }
861
+
862
+ function installClaudeCodeHookEvent(repoPath, door) {
792
863
  const settingsPath = join(HOME, '.claude', 'settings.json');
793
864
  let settings = readJSON(settingsPath);
794
865
 
@@ -802,6 +873,8 @@ function installClaudeCodeHook(repoPath, door) {
802
873
  const installedGuard = join(extDir, 'guard.mjs');
803
874
 
804
875
  // Deploy guard.mjs to ~/.ldm/extensions/{toolName}/ (#85: always update, not just when missing)
876
+ // Idempotent across multi-door invocations: two doors on the same repo
877
+ // will both trigger this copy, which is a filesystem no-op after the first.
805
878
  const srcGuard = join(repoPath, 'guard.mjs');
806
879
  if (existsSync(srcGuard)) {
807
880
  try {
@@ -819,21 +892,30 @@ function installClaudeCodeHook(repoPath, door) {
819
892
  ? `node ${installedGuard}`
820
893
  : (door.command || `node "${srcGuard}"`);
821
894
 
895
+ const event = door.event || 'PreToolUse';
896
+
822
897
  if (DRY_RUN) {
823
- ok(`Claude Code: would add ${door.event || 'PreToolUse'} hook (dry run)`);
898
+ ok(`Claude Code: would add ${event} hook (dry run)`);
824
899
  return true;
825
900
  }
826
901
 
827
902
  if (!settings.hooks) settings.hooks = {};
828
- const event = door.event || 'PreToolUse';
829
903
  if (!settings.hooks[event]) settings.hooks[event] = [];
830
904
 
831
- const existingIdx = settings.hooks[event].findIndex(entry =>
832
- entry.hooks?.some(h => {
905
+ // Match existing entries by the guard command path + the matcher, so that
906
+ // a single extension registering on multiple events (each with its own
907
+ // matcher) creates one entry per event rather than all entries colliding
908
+ // on the same hook slot. Before this change the existing-entry check was
909
+ // per-extension, not per-extension-per-event.
910
+ const doorMatcher = door.matcher || undefined;
911
+ const existingIdx = settings.hooks[event].findIndex(entry => {
912
+ const sameMatcher = (entry.matcher || undefined) === doorMatcher;
913
+ if (!sameMatcher) return false;
914
+ return entry.hooks?.some(h => {
833
915
  const cmd = h.command || '';
834
916
  return cmd.includes(`/${toolName}/`) || cmd === hookCommand;
835
- })
836
- );
917
+ });
918
+ });
837
919
 
838
920
  if (existingIdx !== -1) {
839
921
  const existingCmd = settings.hooks[event][existingIdx].hooks?.[0]?.command || '';
@@ -854,7 +936,7 @@ function installClaudeCodeHook(repoPath, door) {
854
936
  }
855
937
 
856
938
  settings.hooks[event].push({
857
- matcher: door.matcher || undefined,
939
+ matcher: doorMatcher,
858
940
  hooks: [{
859
941
  type: 'command',
860
942
  command: hookCommand,
@@ -1016,6 +1098,8 @@ export function installSingleTool(toolPath) {
1016
1098
  installed++;
1017
1099
  registryInfo.ldmPath = join(LDM_EXTENSIONS, toolName);
1018
1100
  registryInfo.ocPath = join(OC_EXTENSIONS, toolName);
1101
+ // Update tools.allow in openclaw.json so OC 2026.4.8+ doesn't block the plugin
1102
+ updateToolsAllow(toolName);
1019
1103
  }
1020
1104
  } else if (interfaces.mcp) {
1021
1105
  const extName = basename(toolPath);
package/lib/detect.mjs CHANGED
@@ -53,16 +53,27 @@ export function detectInterfaces(repoPath) {
53
53
  interfaces.skill = { path: join(repoPath, 'SKILL.md') };
54
54
  }
55
55
 
56
- // 6. Claude Code Hook: guard.mjs or claudeCode.hook in package.json
57
- if (pkg?.claudeCode?.hook) {
58
- interfaces.claudeCodeHook = pkg.claudeCode.hook;
56
+ // 6. Claude Code Hook: guard.mjs or claudeCode.hook(s) in package.json
57
+ //
58
+ // Supports three shapes:
59
+ // - Legacy singular: pkg.claudeCode.hook = { event, matcher, ... }
60
+ // - New plural array: pkg.claudeCode.hooks = [{ event, matcher, ... }, ...]
61
+ // (one extension can register on multiple events, e.g. both PreToolUse
62
+ // and SessionStart. Added 2026-04-05 for wip-branch-guard 1.9.73.)
63
+ // - Implicit: a bare guard.mjs file with no package.json declaration.
64
+ //
65
+ // Normalized to an array internally so deploy.mjs has one code path.
66
+ if (Array.isArray(pkg?.claudeCode?.hooks)) {
67
+ interfaces.claudeCodeHook = pkg.claudeCode.hooks;
68
+ } else if (pkg?.claudeCode?.hook) {
69
+ interfaces.claudeCodeHook = [pkg.claudeCode.hook];
59
70
  } else if (existsSync(join(repoPath, 'guard.mjs'))) {
60
- interfaces.claudeCodeHook = {
71
+ interfaces.claudeCodeHook = [{
61
72
  event: 'PreToolUse',
62
73
  matcher: 'Edit|Write',
63
74
  command: `node "${join(repoPath, 'guard.mjs')}"`,
64
75
  timeout: 5,
65
- };
76
+ }];
66
77
  }
67
78
 
68
79
  // 7. Claude Code Plugin: .claude-plugin/plugin.json
@@ -93,7 +104,10 @@ export function describeInterfaces(interfaces) {
93
104
  if (interfaces.mcp) lines.push(`MCP Server: ${interfaces.mcp.file}`);
94
105
  if (interfaces.openclaw) lines.push(`OpenClaw Plugin: ${interfaces.openclaw.config?.name || 'detected'}`);
95
106
  if (interfaces.skill) lines.push(`Skill: SKILL.md`);
96
- if (interfaces.claudeCodeHook) lines.push(`Claude Code Hook: ${interfaces.claudeCodeHook.event || 'PreToolUse'}`);
107
+ if (interfaces.claudeCodeHook) {
108
+ const events = interfaces.claudeCodeHook.map(h => h.event || 'PreToolUse');
109
+ lines.push(`Claude Code Hook: ${events.join(', ')}`);
110
+ }
97
111
  if (interfaces.claudeCodePlugin) lines.push(`Claude Code Plugin: ${interfaces.claudeCodePlugin.manifest?.name || 'detected'}`);
98
112
 
99
113
  return `${names.length} interface(s): ${names.join(', ')}\n${lines.map(l => ` ${l}`).join('\n')}`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wipcomputer/wip-ldm-os",
3
- "version": "0.4.73-alpha.3",
3
+ "version": "0.4.73-alpha.30",
4
4
  "type": "module",
5
5
  "description": "LDM OS: identity, memory, and sovereignty infrastructure for AI agents",
6
6
  "engines": {
@@ -16,7 +16,7 @@
16
16
  "lesa": "dist/bridge/cli.js"
17
17
  },
18
18
  "scripts": {
19
- "build:bridge": "cd src/bridge && npm install && npx tsup core.ts mcp-server.ts cli.ts --format esm --dts --clean --outDir ../../dist/bridge",
19
+ "build:bridge": "cd src/bridge && npm install && npx tsup core.ts mcp-server.ts cli.ts openclaw.ts --format esm --dts --clean --outDir ../../dist/bridge",
20
20
  "build": "npm run build:bridge",
21
21
  "prepublishOnly": "npm run build:bridge",
22
22
  "fmt": "npx prettier --write 'src/**/*.{ts,mjs}' 'lib/**/*.mjs' 'bin/**/*.js'",
@@ -6,7 +6,7 @@ Updates come from two sources:
6
6
  - **config.json** ... when you change your org settings, the "Your System" sections regenerate
7
7
  - **System hooks** ... when tools are installed, updated, or reconfigured, the relevant docs update automatically
8
8
 
9
- If something is wrong, update `settings/config.json` or run `ldm install`. The docs will follow.
9
+ If something is wrong, update `~/.ldm/config.json` or run `ldm install`. The docs will follow.
10
10
 
11
11
  ## What's Here
12
12
 
@@ -32,4 +32,4 @@ Each doc has two sections:
32
32
  1. **Universal** ... how the feature works for everyone (top of file)
33
33
  2. **Your System** ... your specific configuration (bottom, after the `---` separator)
34
34
 
35
- Universal content comes from the LDM OS repo. "Your System" content is generated from your `settings/config.json`.
35
+ Universal content comes from the LDM OS repo. "Your System" content is generated from your `~/.ldm/config.json`.
@@ -16,11 +16,31 @@ Your AI reads the spec, explains what LDM OS is, checks if it's already installe
16
16
  1. **Self-update.** Checks npm for a newer version of itself. Updates first, then re-runs with new code.
17
17
  2. **System scan.** Reads `~/.ldm/extensions/`, `~/.openclaw/extensions/`, Claude Code MCP config, CLI binaries on PATH.
18
18
  3. **Catalog check.** Matches installed extensions against the catalog. Shows what's available, what's behind.
19
- 4. **npm version check.** Checks every installed extension against npm for newer versions.
20
- 5. **Update.** Clones from GitHub, builds if needed, deploys to extensions dirs, registers MCP/hooks/skills.
19
+ 4. **npm version check.** Checks every installed extension against npm for newer versions (uses dist-tags for alpha/beta).
20
+ 5. **Update.** Resolves the install source (see Source Resolution below), deploys to extensions dirs, registers MCP/hooks/skills.
21
21
  6. **Health check.** Verifies CLIs exist, no broken symlinks, no stale configs.
22
22
  7. **Cleanup.** Removes staging dirs, prunes ghost entries from registry.
23
23
 
24
+ ## Release Tracks
25
+
26
+ ```bash
27
+ ldm install # stable (npm @latest)
28
+ ldm install --alpha # alpha track (npm @alpha)
29
+ ldm install --beta # beta track (npm @beta)
30
+ ```
31
+
32
+ Each track overwrites whatever is installed. Alpha, beta, and stable all use the same install path. The flag only changes which npm dist-tag is checked for updates.
33
+
34
+ ## Source Resolution
35
+
36
+ When updating, the installer finds the package in priority order:
37
+
38
+ 1. **npm** (when `--alpha` or `--beta`): downloads from npm dist-tag. Works on any machine.
39
+ 2. **Local private repo** (developer machine): finds the repo at `~/wipcomputerinc/repos/ldm-os/`. Works offline, no npm or internet needed.
40
+ 3. **GitHub clone** (fallback): clones the public repo. Existing behavior.
41
+
42
+ Alpha/beta installs never require `deploy-public`. Merge to private main, `wip-release alpha`, `ldm install --alpha`, done.
43
+
24
44
  ## Dry Run
25
45
 
26
46
  Always preview first:
@@ -1,77 +1,93 @@
1
1
  # How Releases Work
2
2
 
3
- ## The Pipeline
3
+ ## Four Release Tracks
4
4
 
5
- Every release follows these steps. No shortcuts.
5
+ | Track | npm tag | Who | Purpose |
6
+ |-------|---------|-----|---------|
7
+ | **Alpha** | `@alpha` | Developer | Moving fast. Fix, test, iterate. No deploy-public needed. |
8
+ | **Beta** | `@beta` | Testers | Testing the distribution pipeline. npm + installer verified. |
9
+ | **Hotfix** | `@latest` | Everyone | Emergency fix. Goes straight to stable. No deploy-public. |
10
+ | **Stable** | `@latest` | Everyone | Full release. deploy-public syncs the public repo. |
6
11
 
7
- ### 1. Branch and Code
12
+ ## The Alpha Flow (Development)
13
+
14
+ This is the fast path. Most work happens here.
8
15
 
9
- Create a worktree, make your changes, commit:
10
16
  ```bash
11
- ldm worktree add my-prefix/feature-name
12
- cd _worktrees/repo--my-prefix--feature-name/
13
- # edit files
14
- git add <files>
15
- git commit -m "description"
16
- ```
17
+ # 1. Branch and code
18
+ git worktree add .worktrees/repo--my-prefix--feature -b my-prefix/feature
19
+ cd .worktrees/repo--my-prefix--feature/
20
+ # edit, commit
17
21
 
18
- ### 2. Write Release Notes
22
+ # 2. Push, PR, merge
23
+ git push -u origin my-prefix/feature
24
+ gh pr create && gh pr merge --merge
19
25
 
20
- Create `RELEASE-NOTES-v{version}.md` (dashes, not dots) in the repo root. Commit it on the branch with the code. It gets reviewed in the PR.
26
+ # 3. ALWAYS pull to main after merge (not optional)
27
+ cd /path/to/repo && git checkout main && git pull
21
28
 
22
- ### 3. Push and PR
29
+ # 4. Alpha release
30
+ wip-release alpha --notes="what changed"
23
31
 
24
- ```bash
25
- git push -u origin my-prefix/feature-name
26
- gh pr create --title "..." --body "..."
27
- gh pr merge --merge --delete-branch
32
+ # 4. Install and test
33
+ ldm install --alpha
28
34
  ```
29
35
 
30
- Never squash merge. Always `--merge`.
31
-
32
- ### 4. Release
33
-
34
- ```bash
35
- cd /path/to/repo # main working tree, not worktree
36
- git checkout main && git pull
37
- wip-release patch # auto-detects the release notes file
38
- ```
36
+ Done. No deploy-public. No public repo sync. The installer pulls from npm @alpha (or finds the local private repo if offline).
39
37
 
40
- `wip-release` handles: version bump, CHANGELOG.md, SKILL.md version sync, npm publish, GitHub release, website skill publish.
38
+ **Sub-tool versions:** If you changed a sub-tool's code, bump its `package.json` version in the PR. Same version = same code. `wip-release` warns if files changed without a version bump.
41
39
 
42
- ### 5. Deploy to Public
40
+ ## The Stable Flow (Public Release)
43
41
 
44
42
  ```bash
45
- bash deploy-public.sh /path/to/private-repo org/public-repo
46
- ```
43
+ # 1-3. Same as alpha: branch, PR, merge
47
44
 
48
- Syncs everything except `ai/` to the public repo. Creates matching release with notes.
45
+ # 4. Write release notes on the branch
46
+ # RELEASE-NOTES-v{version}.md in repo root, committed with the code
49
47
 
50
- ### 6. Install (Dogfood)
48
+ # 5. Stable release
49
+ git checkout main && git pull
50
+ wip-release patch # auto-detects release notes
51
51
 
52
- Open a new AI session and paste:
53
- ```
54
- Read https://wip.computer/install/wip-ldm-os.txt
52
+ # 6. Deploy to public
53
+ deploy-public /path/to/private-repo org/public-repo
54
+
55
+ # 7. Dogfood
56
+ ldm install
55
57
  ```
56
58
 
57
- The AI walks through: explain, dry run, install. Never `npm install -g` directly.
59
+ `wip-release` handles: version bump, CHANGELOG.md, SKILL.md sync, npm publish, GitHub release.
60
+
61
+ `deploy-public` syncs everything except `ai/` to the public repo. Creates a matching release.
58
62
 
59
63
  ## Quality Gates
60
64
 
61
- `wip-release` enforces before publishing:
65
+ `wip-release` enforces before publishing (stable only):
62
66
  - Release notes must be a file (not a flag)
63
- - Must reference a GitHub issue
64
67
  - Product docs must be updated
65
- - Technical docs must be updated if source changed
66
68
  - No stale merged branches
67
69
  - Must run from main working tree (not worktree)
68
70
 
71
+ Alpha/beta skip most gates for speed.
72
+
73
+ ## Source Resolution
74
+
75
+ The installer resolves sources in priority order:
76
+
77
+ 1. **npm** (with dist-tag for alpha/beta): works on any machine with internet
78
+ 2. **Local private repo**: works offline on developer machines
79
+ 3. **GitHub clone**: fallback for stable installs and third-party tools
80
+
81
+ ## Version Immutability
82
+
83
+ Same version = same code. Always. If code changed, the version must change. The installer uses version comparison to decide whether to deploy. `wip-release` validates that sub-tools with changed files have bumped versions.
84
+
69
85
  ## Three Separate Steps
70
86
 
71
87
  | Step | What happens | What it means |
72
88
  |------|-------------|---------------|
73
89
  | Merge | PR merged to main | Code lands. Nothing else changes. |
74
- | Deploy | wip-release + deploy-public | Published to npm + GitHub. Not on your machine yet. |
75
- | Install | Run the install prompt | Extensions updated on your machine. |
90
+ | Release | `wip-release alpha/beta/patch` | Published to npm. Available for install. |
91
+ | Install | `ldm install [--alpha/--beta]` | Extensions updated on your machine. |
76
92
 
77
- After Deploy, stop. Don't copy files. Don't npm install. Dogfood the install prompt.
93
+ For stable releases, add a fourth step: `deploy-public` to sync the public GitHub repo.
@@ -10,8 +10,8 @@ A git worktree is a second checkout of the same repo. Same history, same remote,
10
10
 
11
11
  ```
12
12
  my-repo/ <- main branch (read-only)
13
- _worktrees/my-repo--fix-bug/ <- your worktree (editable)
14
- _worktrees/my-repo--new-feature/ <- someone else's worktree
13
+ .worktrees/my-repo--fix-bug/ <- your worktree (editable)
14
+ .worktrees/my-repo--new-feature/ <- someone else's worktree
15
15
  ```
16
16
 
17
17
  All share the same `.git` database. Commits in any worktree are visible to all. But each has its own branch and files on disk.
@@ -23,22 +23,27 @@ cd my-repo
23
23
  ldm worktree add my-prefix/fix-bug
24
24
  ```
25
25
 
26
- This creates `_worktrees/my-repo--my-prefix--fix-bug/`.
26
+ This creates `.worktrees/my-repo--my-prefix--fix-bug/`.
27
27
 
28
28
  ## How to Work
29
29
 
30
30
  Edit files in the worktree directory. Commit, push, PR, merge as normal:
31
31
 
32
32
  ```bash
33
- cd _worktrees/my-repo--my-prefix--fix-bug/
33
+ cd .worktrees/my-repo--my-prefix--fix-bug/
34
34
  # edit, then:
35
35
  git add <files>
36
36
  git commit -m "description"
37
37
  git push -u origin my-prefix/fix-bug
38
38
  gh pr create
39
39
  gh pr merge --merge --delete-branch
40
+
41
+ # CRITICAL: pull to main immediately after merge
42
+ cd /path/to/repo && git checkout main && git pull
40
43
  ```
41
44
 
45
+ **Always pull to main after merging a PR.** If you don't, the main working tree is stale and files won't show up. This is not optional. Every merge, every time.
46
+
42
47
  ## How to Clean Up
43
48
 
44
49
  ```bash
@@ -65,13 +70,13 @@ Switching branches changes every file in the directory. If another process (an a
65
70
 
66
71
  ## Your System
67
72
 
68
- **Worktree location:** `~/wipcomputerinc/repos/_worktrees/`
73
+ **Worktree location:** `~/wipcomputerinc/repos/.worktrees/`
69
74
 
70
75
  **Branch prefixes:**
71
76
  - `cc-mini/` ... Claude Code on Mac mini
72
77
  - `cc-air/` ... Claude Code on MacBook Air
73
78
  - `lesa-mini/` ... Lesa on Mac mini
74
79
 
75
- **Guard:** The branch guard warns if you create a worktree outside `_worktrees/`. Suggests `ldm worktree add` instead.
80
+ **Guard:** The branch guard warns if you create a worktree outside `.worktrees/`. Suggests `ldm worktree add` instead.
76
81
 
77
- **Auto-cleanup:** `wip-release` prunes merged worktrees from `_worktrees/` after every release.
82
+ **Auto-cleanup:** `wip-release` prunes merged worktrees from `.worktrees/` after every release.
@@ -14,11 +14,11 @@ Always use a branch and PR.
14
14
 
15
15
  ## Co-authors on every commit
16
16
 
17
- List all contributors. Read co-author lines from `settings/config.json` in your workspace.
17
+ List all contributors. Read co-author lines from `~/.ldm/config.json` coAuthors field.
18
18
 
19
19
  ## Branch prefixes
20
20
 
21
- Each agent uses a prefix from `settings/config.json` agents section. Prevents collisions.
21
+ Each agent uses a prefix from `~/.ldm/config.json` agents section. Prevents collisions.
22
22
 
23
23
  ## Worktrees
24
24
 
@@ -30,4 +30,4 @@ For private/public repo pairs, all issues go on the public repo.
30
30
 
31
31
  ## On-demand reference
32
32
 
33
- Before doing repo work, read `~/wipcomputerinc/settings/docs/how-worktrees-work.md` for the full worktree workflow with commands.
33
+ Before doing repo work, read `~/wipcomputerinc/library/documentation/how-worktrees-work.md` for the full worktree workflow with commands.
@@ -39,4 +39,4 @@ Installed tools are for execution. Repo clones are for development. Use the inst
39
39
 
40
40
  ## On-demand reference
41
41
 
42
- Before releasing, read `~/wipcomputerinc/settings/docs/how-releases-work.md` for the full pipeline with commands.
42
+ Before releasing, read `~/wipcomputerinc/library/documentation/how-releases-work.md` for the full pipeline with commands.
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## Secret management
4
4
 
5
- Use your org's secret management tool (configured in settings/config.json). Never hardcode API keys, tokens, or credentials.
5
+ Use your org's secret management tool (configured in `~/.ldm/config.json`). Never hardcode API keys, tokens, or credentials.
6
6
 
7
7
  ## Security audit before installing anything
8
8
 
@@ -22,4 +22,4 @@ Installed tools are for execution. Repo clones are for development. Use the inst
22
22
 
23
23
  ## On-demand reference
24
24
 
25
- For the full directory map, read `~/wipcomputerinc/settings/docs/system-directories.md`.
25
+ For the full directory map, read `~/wipcomputerinc/library/documentation/system-directories.md`.
@@ -1,5 +1,5 @@
1
1
  # Writing Style
2
2
 
3
- Read writing conventions from your org's `settings/config.json` writingStyle section.
3
+ Read writing conventions from `~/.ldm/config.json` writingStyle section.
4
4
 
5
5
  **Full paths in documentation.** Never truncate paths. Always show the complete path so there's no ambiguity.
@@ -5,9 +5,13 @@
5
5
  Never use em dashes. Use periods, colons, semicolons, or ellipsis (...) instead.
6
6
  Timezone: PST (Pacific), 24-hour clock. Parker is in Los Angeles.
7
7
 
8
+ ## Don't Hedge
9
+
10
+ Never ask "should I stop?", "is this too much?", "what should we do now?", or "do you want me to continue?". If you have work to do, do it. If you're stuck, say what you're stuck on specifically. Don't express existential doubt about the task. Don't ask permission to keep working. Don't narrate your own uncertainty. Just work.
11
+
8
12
  ## Co-Authors on Every Commit
9
13
 
10
- Read co-author lines from `~/wipcomputerinc/settings/config.json` coAuthors field. All contributors listed on every commit. No exceptions.
14
+ Read co-author lines from `~/.ldm/config.json` coAuthors field. All contributors listed on every commit. No exceptions.
11
15
 
12
16
  ## 1Password CLI: Always Use Service Account Token
13
17
 
@@ -30,8 +34,8 @@ Before reaching for any external service or workaround: search memory first. Use
30
34
 
31
35
  ## Dev Conventions
32
36
 
33
- For git workflow, releases, worktrees, and repo conventions: read `~/wipcomputerinc/settings/docs/` on demand when doing repo work. Key docs:
37
+ For git workflow, releases, worktrees, and repo conventions: read `~/wipcomputerinc/library/documentation/` on demand when doing repo work. Key docs:
34
38
  - `how-worktrees-work.md` ... git worktrees, the convention, commands
35
39
  - `how-releases-work.md` ... the full release pipeline
36
40
  - `system-directories.md` ... what lives where
37
- - Also read `~/wipcomputerinc/settings/templates/dev-guide-private.md` for org-specific conventions
41
+ - Also read `~/.ldm/shared/dev-guide-wipcomputerinc.md` for org-specific conventions