@wipcomputer/wip-ldm-os 0.4.73-alpha.2 → 0.4.73-alpha.21
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/bin/ldm.js +80 -29
- package/dist/bridge/{chunk-LF7EMFBY.js → chunk-24DJYS7Z.js} +95 -48
- package/dist/bridge/cli.js +1 -1
- package/dist/bridge/core.d.ts +1 -0
- package/dist/bridge/core.js +1 -1
- package/dist/bridge/mcp-server.js +40 -7
- package/dist/bridge/openclaw.d.ts +5 -0
- package/dist/bridge/openclaw.js +9 -0
- package/docs/doc-pipeline/README.md +74 -0
- package/docs/doc-pipeline/TECHNICAL.md +79 -0
- package/lib/deploy.mjs +66 -10
- package/lib/detect.mjs +20 -6
- package/package.json +2 -2
- package/shared/docs/how-install-works.md.tmpl +22 -2
- package/shared/docs/how-releases-work.md.tmpl +57 -43
- package/shared/rules/git-conventions.md +3 -3
- package/shared/rules/release-pipeline.md +1 -1
- package/shared/rules/security.md +1 -1
- package/shared/rules/workspace-boundaries.md +1 -1
- package/shared/rules/writing-style.md +1 -1
- package/src/bridge/core.ts +113 -53
- package/src/bridge/mcp-server.ts +77 -8
- package/src/bridge/openclaw.ts +14 -0
- package/src/hooks/inbox-check-hook.mjs +176 -0
- package/src/hosted-mcp/demo/agent.html +300 -0
- package/src/hosted-mcp/demo/agent.txt +84 -0
- package/src/hosted-mcp/demo/fallback.jpg +0 -0
- package/src/hosted-mcp/demo/footer.js +16 -0
- package/src/hosted-mcp/demo/index.html +1291 -0
- package/src/hosted-mcp/demo/privacy.html +230 -0
- package/src/hosted-mcp/demo/sprites.jpg +0 -0
- package/src/hosted-mcp/demo/sprites.png +0 -0
- package/src/hosted-mcp/demo/tos.html +205 -0
- package/src/hosted-mcp/deploy.sh +70 -0
- package/src/hosted-mcp/inbox.mjs +64 -0
- package/src/hosted-mcp/package.json +21 -0
- package/src/hosted-mcp/server.mjs +1625 -0
- package/src/hosted-mcp/tools.mjs +73 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# Documentation Pipeline: Technical Details
|
|
2
|
+
|
|
3
|
+
## File Paths
|
|
4
|
+
|
|
5
|
+
### Repo doc templates (in the LDM OS repo)
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
shared/docs/*.md.tmpl Templates for home docs
|
|
9
|
+
shared/rules/*.md Source for agent rules
|
|
10
|
+
shared/boot/ Boot sequence config
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Templates use placeholders from `~/.ldm/config.json` (workspace path, agent names, org name, etc.).
|
|
14
|
+
|
|
15
|
+
### Installed locations
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
~/.ldm/config.json Org config (agents, paths, co-authors)
|
|
19
|
+
~/.ldm/shared/rules/*.md Agent rules (source for ~/.claude/rules/)
|
|
20
|
+
~/.ldm/shared/dev-guide-*.md Org dev guide
|
|
21
|
+
~/.ldm/shared/boot/ Boot sequence config
|
|
22
|
+
~/.ldm/shared/prompts/ Cron prompts
|
|
23
|
+
~/.ldm/templates/ CLAUDE.md templates, install prompt, etc.
|
|
24
|
+
~/wipcomputerinc/library/documentation/ Personalized human docs (from templates)
|
|
25
|
+
~/.claude/rules/ Deployed rules (copied from ~/.ldm/shared/rules/)
|
|
26
|
+
~/.claude/CLAUDE.md Level 1 global (generated from template + config)
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### What ldm install deploys
|
|
30
|
+
|
|
31
|
+
| Source | Destination | When |
|
|
32
|
+
|--------|------------|------|
|
|
33
|
+
| `shared/rules/*.md` | `~/.ldm/shared/rules/` then `~/.claude/rules/` | Every install |
|
|
34
|
+
| `shared/docs/*.md.tmpl` | `~/wipcomputerinc/library/documentation/` | Every install |
|
|
35
|
+
| `shared/boot/` | `~/.ldm/shared/boot/` | Every install |
|
|
36
|
+
| `shared/prompts/` | `~/.ldm/shared/prompts/` | Every install |
|
|
37
|
+
| `shared/templates/` | `~/.ldm/templates/` | Every install |
|
|
38
|
+
|
|
39
|
+
**Known bug (April 2026):** The installer currently deploys shared rules on `ldm init` (first install) but not on every `ldm install`. This means rule updates in new versions don't propagate until the user re-initializes. This needs to be fixed so rules deploy on every install.
|
|
40
|
+
|
|
41
|
+
**Known bug (April 2026):** The installer previously deployed home docs to `settings/docs/`. This path was renamed to `library/documentation/` on March 28, 2026. The installer must deploy to the correct path.
|
|
42
|
+
|
|
43
|
+
## How templates work
|
|
44
|
+
|
|
45
|
+
Home doc templates at `shared/docs/*.md.tmpl` contain placeholders:
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
Workspace: {{workspace}}
|
|
49
|
+
Agents: {{agents}}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
The installer reads `~/.ldm/config.json`, substitutes the placeholders, and writes the personalized docs to `~/wipcomputerinc/library/documentation/`.
|
|
53
|
+
|
|
54
|
+
## CLAUDE.md cascade
|
|
55
|
+
|
|
56
|
+
Three levels. Claude Code reads all of them, walking up from CWD:
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
Level 1: ~/.claude/CLAUDE.md Global. ~30 lines. Universal rules.
|
|
60
|
+
Level 2: ~/wipcomputerinc/CLAUDE.md Workspace. ~150 lines. Org context.
|
|
61
|
+
Level 3: <repo>/CLAUDE.md Per-repo. ~50-86 lines. Repo-specific.
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
After context compaction, CWD may shift to a repo. Without Level 3, all context is lost. Every repo must have a CLAUDE.md.
|
|
65
|
+
|
|
66
|
+
## Config paths (correct as of April 2026)
|
|
67
|
+
|
|
68
|
+
References in CLAUDE.md and rules must use absolute paths:
|
|
69
|
+
|
|
70
|
+
| Reference | Correct path |
|
|
71
|
+
|-----------|-------------|
|
|
72
|
+
| Org config | `~/.ldm/config.json` |
|
|
73
|
+
| Dev guide | `~/.ldm/shared/dev-guide-wipcomputerinc.md` |
|
|
74
|
+
| Human docs | `~/wipcomputerinc/library/documentation/` |
|
|
75
|
+
| Agent rules | `~/.ldm/shared/rules/` (source) or `~/.claude/rules/` (deployed) |
|
|
76
|
+
| Workspace CLAUDE.md | `~/wipcomputerinc/CLAUDE.md` |
|
|
77
|
+
| Global CLAUDE.md | `~/.claude/CLAUDE.md` |
|
|
78
|
+
|
|
79
|
+
NOT `settings/config.json`. NOT `settings/docs/`. Those paths are from before the March 28 rename.
|
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
|
-
|
|
398
|
-
const
|
|
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
|
|
|
@@ -788,7 +812,28 @@ function registerMCP(repoPath, door, toolName) {
|
|
|
788
812
|
}
|
|
789
813
|
}
|
|
790
814
|
|
|
791
|
-
|
|
815
|
+
/**
|
|
816
|
+
* Install Claude Code hook(s) for an extension.
|
|
817
|
+
*
|
|
818
|
+
* Accepts either a single door object (legacy) or an array of door objects
|
|
819
|
+
* (new in 2026-04-05 for wip-branch-guard 1.9.73 which registers on both
|
|
820
|
+
* PreToolUse and SessionStart). Normalizes to an array and installs each
|
|
821
|
+
* door independently.
|
|
822
|
+
*
|
|
823
|
+
* Returns true if at least one door installed successfully.
|
|
824
|
+
*/
|
|
825
|
+
function installClaudeCodeHook(repoPath, doorOrDoors) {
|
|
826
|
+
const doors = Array.isArray(doorOrDoors) ? doorOrDoors : [doorOrDoors];
|
|
827
|
+
let anyOk = false;
|
|
828
|
+
for (const door of doors) {
|
|
829
|
+
if (installClaudeCodeHookEvent(repoPath, door)) {
|
|
830
|
+
anyOk = true;
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
return anyOk;
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
function installClaudeCodeHookEvent(repoPath, door) {
|
|
792
837
|
const settingsPath = join(HOME, '.claude', 'settings.json');
|
|
793
838
|
let settings = readJSON(settingsPath);
|
|
794
839
|
|
|
@@ -802,6 +847,8 @@ function installClaudeCodeHook(repoPath, door) {
|
|
|
802
847
|
const installedGuard = join(extDir, 'guard.mjs');
|
|
803
848
|
|
|
804
849
|
// Deploy guard.mjs to ~/.ldm/extensions/{toolName}/ (#85: always update, not just when missing)
|
|
850
|
+
// Idempotent across multi-door invocations: two doors on the same repo
|
|
851
|
+
// will both trigger this copy, which is a filesystem no-op after the first.
|
|
805
852
|
const srcGuard = join(repoPath, 'guard.mjs');
|
|
806
853
|
if (existsSync(srcGuard)) {
|
|
807
854
|
try {
|
|
@@ -819,21 +866,30 @@ function installClaudeCodeHook(repoPath, door) {
|
|
|
819
866
|
? `node ${installedGuard}`
|
|
820
867
|
: (door.command || `node "${srcGuard}"`);
|
|
821
868
|
|
|
869
|
+
const event = door.event || 'PreToolUse';
|
|
870
|
+
|
|
822
871
|
if (DRY_RUN) {
|
|
823
|
-
ok(`Claude Code: would add ${
|
|
872
|
+
ok(`Claude Code: would add ${event} hook (dry run)`);
|
|
824
873
|
return true;
|
|
825
874
|
}
|
|
826
875
|
|
|
827
876
|
if (!settings.hooks) settings.hooks = {};
|
|
828
|
-
const event = door.event || 'PreToolUse';
|
|
829
877
|
if (!settings.hooks[event]) settings.hooks[event] = [];
|
|
830
878
|
|
|
831
|
-
|
|
832
|
-
|
|
879
|
+
// Match existing entries by the guard command path + the matcher, so that
|
|
880
|
+
// a single extension registering on multiple events (each with its own
|
|
881
|
+
// matcher) creates one entry per event rather than all entries colliding
|
|
882
|
+
// on the same hook slot. Before this change the existing-entry check was
|
|
883
|
+
// per-extension, not per-extension-per-event.
|
|
884
|
+
const doorMatcher = door.matcher || undefined;
|
|
885
|
+
const existingIdx = settings.hooks[event].findIndex(entry => {
|
|
886
|
+
const sameMatcher = (entry.matcher || undefined) === doorMatcher;
|
|
887
|
+
if (!sameMatcher) return false;
|
|
888
|
+
return entry.hooks?.some(h => {
|
|
833
889
|
const cmd = h.command || '';
|
|
834
890
|
return cmd.includes(`/${toolName}/`) || cmd === hookCommand;
|
|
835
|
-
})
|
|
836
|
-
);
|
|
891
|
+
});
|
|
892
|
+
});
|
|
837
893
|
|
|
838
894
|
if (existingIdx !== -1) {
|
|
839
895
|
const existingCmd = settings.hooks[event][existingIdx].hooks?.[0]?.command || '';
|
|
@@ -854,7 +910,7 @@ function installClaudeCodeHook(repoPath, door) {
|
|
|
854
910
|
}
|
|
855
911
|
|
|
856
912
|
settings.hooks[event].push({
|
|
857
|
-
matcher:
|
|
913
|
+
matcher: doorMatcher,
|
|
858
914
|
hooks: [{
|
|
859
915
|
type: 'command',
|
|
860
916
|
command: hookCommand,
|
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
|
-
|
|
58
|
-
|
|
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)
|
|
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
|
+
"version": "0.4.73-alpha.21",
|
|
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'",
|
|
@@ -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.**
|
|
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,91 @@
|
|
|
1
1
|
# How Releases Work
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## Four Release Tracks
|
|
4
4
|
|
|
5
|
-
|
|
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
|
-
|
|
12
|
+
## The Alpha Flow (Development)
|
|
8
13
|
|
|
9
|
-
|
|
10
|
-
```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
|
-
|
|
18
|
-
### 2. Write Release Notes
|
|
19
|
-
|
|
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.
|
|
21
|
-
|
|
22
|
-
### 3. Push and PR
|
|
14
|
+
This is the fast path. Most work happens here.
|
|
23
15
|
|
|
24
16
|
```bash
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
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
|
|
29
21
|
|
|
30
|
-
|
|
22
|
+
# 2. Push, PR, merge
|
|
23
|
+
git push -u origin my-prefix/feature
|
|
24
|
+
gh pr create && gh pr merge --merge
|
|
31
25
|
|
|
32
|
-
|
|
26
|
+
# 3. Alpha release
|
|
27
|
+
cd /path/to/repo && git checkout main && git pull
|
|
28
|
+
wip-release alpha --notes="what changed"
|
|
33
29
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
git checkout main && git pull
|
|
37
|
-
wip-release patch # auto-detects the release notes file
|
|
30
|
+
# 4. Install and test
|
|
31
|
+
ldm install --alpha
|
|
38
32
|
```
|
|
39
33
|
|
|
40
|
-
|
|
34
|
+
Done. No deploy-public. No public repo sync. The installer pulls from npm @alpha (or finds the local private repo if offline).
|
|
41
35
|
|
|
42
|
-
|
|
36
|
+
**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.
|
|
37
|
+
|
|
38
|
+
## The Stable Flow (Public Release)
|
|
43
39
|
|
|
44
40
|
```bash
|
|
45
|
-
|
|
46
|
-
```
|
|
41
|
+
# 1-3. Same as alpha: branch, PR, merge
|
|
47
42
|
|
|
48
|
-
|
|
43
|
+
# 4. Write release notes on the branch
|
|
44
|
+
# RELEASE-NOTES-v{version}.md in repo root, committed with the code
|
|
49
45
|
|
|
50
|
-
|
|
46
|
+
# 5. Stable release
|
|
47
|
+
git checkout main && git pull
|
|
48
|
+
wip-release patch # auto-detects release notes
|
|
51
49
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
50
|
+
# 6. Deploy to public
|
|
51
|
+
deploy-public /path/to/private-repo org/public-repo
|
|
52
|
+
|
|
53
|
+
# 7. Dogfood
|
|
54
|
+
ldm install
|
|
55
55
|
```
|
|
56
56
|
|
|
57
|
-
|
|
57
|
+
`wip-release` handles: version bump, CHANGELOG.md, SKILL.md sync, npm publish, GitHub release.
|
|
58
|
+
|
|
59
|
+
`deploy-public` syncs everything except `ai/` to the public repo. Creates a matching release.
|
|
58
60
|
|
|
59
61
|
## Quality Gates
|
|
60
62
|
|
|
61
|
-
`wip-release` enforces before publishing:
|
|
63
|
+
`wip-release` enforces before publishing (stable only):
|
|
62
64
|
- Release notes must be a file (not a flag)
|
|
63
|
-
- Must reference a GitHub issue
|
|
64
65
|
- Product docs must be updated
|
|
65
|
-
- Technical docs must be updated if source changed
|
|
66
66
|
- No stale merged branches
|
|
67
67
|
- Must run from main working tree (not worktree)
|
|
68
68
|
|
|
69
|
+
Alpha/beta skip most gates for speed.
|
|
70
|
+
|
|
71
|
+
## Source Resolution
|
|
72
|
+
|
|
73
|
+
The installer resolves sources in priority order:
|
|
74
|
+
|
|
75
|
+
1. **npm** (with dist-tag for alpha/beta): works on any machine with internet
|
|
76
|
+
2. **Local private repo**: works offline on developer machines
|
|
77
|
+
3. **GitHub clone**: fallback for stable installs and third-party tools
|
|
78
|
+
|
|
79
|
+
## Version Immutability
|
|
80
|
+
|
|
81
|
+
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.
|
|
82
|
+
|
|
69
83
|
## Three Separate Steps
|
|
70
84
|
|
|
71
85
|
| Step | What happens | What it means |
|
|
72
86
|
|------|-------------|---------------|
|
|
73
87
|
| Merge | PR merged to main | Code lands. Nothing else changes. |
|
|
74
|
-
|
|
|
75
|
-
| Install |
|
|
88
|
+
| Release | `wip-release alpha/beta/patch` | Published to npm. Available for install. |
|
|
89
|
+
| Install | `ldm install [--alpha/--beta]` | Extensions updated on your machine. |
|
|
76
90
|
|
|
77
|
-
|
|
91
|
+
For stable releases, add a fourth step: `deploy-public` to sync the public GitHub repo.
|
|
@@ -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
|
|
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
|
|
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/
|
|
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/
|
|
42
|
+
Before releasing, read `~/wipcomputerinc/library/documentation/how-releases-work.md` for the full pipeline with commands.
|
package/shared/rules/security.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## Secret management
|
|
4
4
|
|
|
5
|
-
Use your org's secret management tool (configured in
|
|
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/
|
|
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
|
|
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.
|