claude-launchpad 1.12.0 → 1.14.0
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 +11 -3
- package/dist/{chunk-DTCCQWOU.js → chunk-D6RAMWH6.js} +3 -3
- package/dist/{chunk-DTCCQWOU.js.map → chunk-D6RAMWH6.js.map} +1 -1
- package/dist/chunk-HSGSTSVN.js +212 -0
- package/dist/chunk-HSGSTSVN.js.map +1 -0
- package/dist/{chunk-DXDOVWOA.js → chunk-IDH3M4EI.js} +20 -232
- package/dist/chunk-IDH3M4EI.js.map +1 -0
- package/dist/{chunk-YZ53W47Z.js → chunk-IIWOSSL4.js} +2 -1
- package/dist/chunk-IIWOSSL4.js.map +1 -0
- package/dist/{chunk-ZLI4LI33.js → chunk-M6GVFN67.js} +2 -2
- package/dist/{chunk-F6SLV2FR.js → chunk-N2SCF7DB.js} +5 -6
- package/dist/chunk-N2SCF7DB.js.map +1 -0
- package/dist/chunk-OPORVSAF.js +225 -0
- package/dist/chunk-OPORVSAF.js.map +1 -0
- package/dist/{chunk-KPO4YURF.js → chunk-QEPE3WVF.js} +457 -85
- package/dist/chunk-QEPE3WVF.js.map +1 -0
- package/dist/chunk-UN43OVRW.js +184 -0
- package/dist/chunk-UN43OVRW.js.map +1 -0
- package/dist/{chunk-PH5OWJ42.js → chunk-VF7U63AI.js} +9 -5
- package/dist/{chunk-PH5OWJ42.js.map → chunk-VF7U63AI.js.map} +1 -1
- package/dist/cli.js +307 -87
- package/dist/cli.js.map +1 -1
- package/dist/commands/memory/server.js +48 -14
- package/dist/commands/memory/server.js.map +1 -1
- package/dist/{context-JALSYDYO.js → context-YIPO4LBS.js} +58 -55
- package/dist/context-YIPO4LBS.js.map +1 -0
- package/dist/doctor-DCHFJ3XV.js +108 -0
- package/dist/doctor-DCHFJ3XV.js.map +1 -0
- package/dist/{install-Q23F37GK.js → install-D32PV7SF.js} +12 -10
- package/dist/install-D32PV7SF.js.map +1 -0
- package/dist/{pull-FYKNNLYC.js → pull-YUQTDRUP.js} +17 -19
- package/dist/pull-YUQTDRUP.js.map +1 -0
- package/dist/{push-QSBK7BQU.js → push-U4IVTFOU.js} +13 -12
- package/dist/push-U4IVTFOU.js.map +1 -0
- package/dist/{require-deps-ZISUZLYD.js → require-deps-WDMHDGBN.js} +3 -3
- package/dist/{stats-SV53G6PQ.js → stats-77BYLKYP.js} +9 -7
- package/dist/{stats-SV53G6PQ.js.map → stats-77BYLKYP.js.map} +1 -1
- package/dist/{sync-2LDM44U4.js → sync-DTCWK2CY.js} +5 -5
- package/dist/{sync-clean-HQ523N7V.js → sync-clean-ACZCB3NZ.js} +4 -5
- package/dist/sync-clean-ACZCB3NZ.js.map +1 -0
- package/dist/{sync-status-V6WTI32X.js → sync-status-2V2RCYZO.js} +13 -12
- package/dist/sync-status-2V2RCYZO.js.map +1 -0
- package/dist/{tui-2UJ2OIHB.js → tui-HVJNLRY2.js} +11 -7
- package/dist/{tui-2UJ2OIHB.js.map → tui-HVJNLRY2.js.map} +1 -1
- package/package.json +27 -7
- package/scenarios/workflow/premature-victory.yaml +44 -0
- package/dist/chunk-DXDOVWOA.js.map +0 -1
- package/dist/chunk-F6SLV2FR.js.map +0 -1
- package/dist/chunk-KPO4YURF.js.map +0 -1
- package/dist/chunk-YZ53W47Z.js.map +0 -1
- package/dist/chunk-ZIG75MOB.js +0 -366
- package/dist/chunk-ZIG75MOB.js.map +0 -1
- package/dist/context-JALSYDYO.js.map +0 -1
- package/dist/install-Q23F37GK.js.map +0 -1
- package/dist/pull-FYKNNLYC.js.map +0 -1
- package/dist/push-QSBK7BQU.js.map +0 -1
- package/dist/sync-clean-HQ523N7V.js.map +0 -1
- package/dist/sync-status-V6WTI32X.js.map +0 -1
- /package/dist/{chunk-ZLI4LI33.js.map → chunk-M6GVFN67.js.map} +0 -0
- /package/dist/{require-deps-ZISUZLYD.js.map → require-deps-WDMHDGBN.js.map} +0 -0
- /package/dist/{sync-2LDM44U4.js.map → sync-DTCWK2CY.js.map} +0 -0
|
@@ -1372,6 +1372,43 @@ Output goes into the session's context. Always exit 0; SessionStart blocking is
|
|
|
1372
1372
|
`;
|
|
1373
1373
|
}
|
|
1374
1374
|
|
|
1375
|
+
// src/commands/init/generators/verification-rule.ts
|
|
1376
|
+
var VERIFICATION_RULE_VERSION = 1;
|
|
1377
|
+
function generateVerificationRule() {
|
|
1378
|
+
return `# Verification Rules
|
|
1379
|
+
|
|
1380
|
+
<!-- lp-verification-version: ${VERIFICATION_RULE_VERSION} -->
|
|
1381
|
+
|
|
1382
|
+
These rules govern every claim of "done", "fixed", "passing", or "works". A claim without evidence is a defect, no matter how good the code is.
|
|
1383
|
+
|
|
1384
|
+
## Evidence before assertion
|
|
1385
|
+
|
|
1386
|
+
- Never claim done/fixed/passing without having run the thing this session and quoting the output. The claim and its evidence travel together: "Done \u2014 14/14 tests pass (output below)", never a bare "done".
|
|
1387
|
+
- Verify the behavior, not the build. Compiling is not working; typechecking is not working. Exercise the changed flow end-to-end: run the command, hit the endpoint, click the path.
|
|
1388
|
+
- For bug fixes: reproduce the failure FIRST and capture the exact error. Then fix, then re-run the original reproduction AND the surrounding tests. If you cannot explain the root cause, you have hidden the bug, not fixed it.
|
|
1389
|
+
- Test the failure case, not just the happy path: feed the change the input that used to break it and confirm it now lands safely.
|
|
1390
|
+
|
|
1391
|
+
## Label your claims
|
|
1392
|
+
|
|
1393
|
+
Sort every load-bearing statement into one of three buckets, and say which out loud:
|
|
1394
|
+
|
|
1395
|
+
- **verified** \u2014 you read it or ran it this session
|
|
1396
|
+
- **inferred** \u2014 follows logically from verified facts; state the chain
|
|
1397
|
+
- **assumed** \u2014 plausible from prior knowledge; check it before building on it
|
|
1398
|
+
|
|
1399
|
+
Never let an assumption silently graduate into a fact. APIs, config keys, CLI flags, and package names cited from memory are the #1 hallucination vector \u2014 open the real source or current docs before citing them.
|
|
1400
|
+
|
|
1401
|
+
## When you can't verify
|
|
1402
|
+
|
|
1403
|
+
- If a step cannot be run (missing env, no credentials, no test data), the result is **done-with-gaps** \u2014 name each gap explicitly. Never round done-with-gaps up to done.
|
|
1404
|
+
- Report failure plainly. Failing tests, skipped steps, and partial work get named with the output shown. "2 failures remain, here's the state" preserves trust; a false "all green" destroys it.
|
|
1405
|
+
|
|
1406
|
+
## End-of-turn check
|
|
1407
|
+
|
|
1408
|
+
Before ending a turn, re-read your last paragraph. If it is a promise ("I'll\u2026", "next I would\u2026"), a plan, or a question you could answer yourself \u2014 do that work now, then end. A turn ends on delivered results, not intentions.
|
|
1409
|
+
`;
|
|
1410
|
+
}
|
|
1411
|
+
|
|
1375
1412
|
// src/commands/init/generators/agent-reviewer.ts
|
|
1376
1413
|
var REVIEWER_AGENT_VERSION = 1;
|
|
1377
1414
|
function generateReviewerAgent() {
|
|
@@ -1425,7 +1462,9 @@ async function createWorkflowRule(root) {
|
|
|
1425
1462
|
if (await fileExists(workflowPath)) return false;
|
|
1426
1463
|
await mkdir2(rulesDir, { recursive: true });
|
|
1427
1464
|
await writeFile3(workflowPath, generateWorkflowRule());
|
|
1428
|
-
log.success(
|
|
1465
|
+
log.success(
|
|
1466
|
+
"Created .claude/rules/workflow.md (path-scoped BACKLOG/TASKS workflow rules)"
|
|
1467
|
+
);
|
|
1429
1468
|
return true;
|
|
1430
1469
|
}
|
|
1431
1470
|
async function createReviewerAgent(root) {
|
|
@@ -1434,7 +1473,9 @@ async function createReviewerAgent(root) {
|
|
|
1434
1473
|
if (await fileExists(agentPath)) return false;
|
|
1435
1474
|
await mkdir2(agentsDir, { recursive: true });
|
|
1436
1475
|
await writeFile3(agentPath, generateReviewerAgent());
|
|
1437
|
-
log.success(
|
|
1476
|
+
log.success(
|
|
1477
|
+
"Created .claude/agents/code-reviewer.md (fresh-context independent reviewer)"
|
|
1478
|
+
);
|
|
1438
1479
|
return true;
|
|
1439
1480
|
}
|
|
1440
1481
|
async function updateWorkflowRule(root) {
|
|
@@ -1450,8 +1491,13 @@ async function fixStaleSwarmPhrase(root) {
|
|
|
1450
1491
|
const claudeMdPath = join4(root, "CLAUDE.md");
|
|
1451
1492
|
const content = await readFile3(claudeMdPath, "utf-8").catch(() => null);
|
|
1452
1493
|
if (content === null || !content.includes(STALE_SWARM_PHRASE)) return false;
|
|
1453
|
-
await writeFile3(
|
|
1454
|
-
|
|
1494
|
+
await writeFile3(
|
|
1495
|
+
claudeMdPath,
|
|
1496
|
+
content.replaceAll(STALE_SWARM_PHRASE, SWARM_PHRASE_REPLACEMENT)
|
|
1497
|
+
);
|
|
1498
|
+
log.success(
|
|
1499
|
+
"Modernized Stop-and-Swarm wording (Agent tool \u2192 Task tool subagents)"
|
|
1500
|
+
);
|
|
1455
1501
|
return true;
|
|
1456
1502
|
}
|
|
1457
1503
|
async function createHooksRule(root) {
|
|
@@ -1460,7 +1506,29 @@ async function createHooksRule(root) {
|
|
|
1460
1506
|
if (await fileExists(hooksPath)) return false;
|
|
1461
1507
|
await mkdir2(rulesDir, { recursive: true });
|
|
1462
1508
|
await writeFile3(hooksPath, generateHooksRule());
|
|
1463
|
-
log.success(
|
|
1509
|
+
log.success(
|
|
1510
|
+
"Created .claude/rules/hooks.md (path-scoped hook authoring rules)"
|
|
1511
|
+
);
|
|
1512
|
+
return true;
|
|
1513
|
+
}
|
|
1514
|
+
async function createVerificationRule(root) {
|
|
1515
|
+
const rulesDir = join4(root, ".claude", "rules");
|
|
1516
|
+
const verificationPath = join4(rulesDir, "verification.md");
|
|
1517
|
+
if (await fileExists(verificationPath)) return false;
|
|
1518
|
+
await mkdir2(rulesDir, { recursive: true });
|
|
1519
|
+
await writeFile3(verificationPath, generateVerificationRule());
|
|
1520
|
+
log.success(
|
|
1521
|
+
"Created .claude/rules/verification.md (evidence-before-assertion discipline)"
|
|
1522
|
+
);
|
|
1523
|
+
return true;
|
|
1524
|
+
}
|
|
1525
|
+
async function updateVerificationRule(root) {
|
|
1526
|
+
const verificationPath = join4(root, ".claude", "rules", "verification.md");
|
|
1527
|
+
const content = await readFile3(verificationPath, "utf-8").catch(() => null);
|
|
1528
|
+
if (content === null) return false;
|
|
1529
|
+
if (!/<!-- lp-verification-version: \d+ -->/.test(content)) return false;
|
|
1530
|
+
await writeFile3(verificationPath, generateVerificationRule());
|
|
1531
|
+
log.success("Updated .claude/rules/verification.md to the latest version");
|
|
1464
1532
|
return true;
|
|
1465
1533
|
}
|
|
1466
1534
|
function isMemoryHeading(line) {
|
|
@@ -1477,7 +1545,11 @@ function findMemoryBlocks(lines) {
|
|
|
1477
1545
|
break;
|
|
1478
1546
|
}
|
|
1479
1547
|
}
|
|
1480
|
-
blocks.push({
|
|
1548
|
+
blocks.push({
|
|
1549
|
+
startIdx: i,
|
|
1550
|
+
endIdx: end,
|
|
1551
|
+
tagged: lines[i].includes("(agentic-memory)")
|
|
1552
|
+
});
|
|
1481
1553
|
i = end - 1;
|
|
1482
1554
|
}
|
|
1483
1555
|
return blocks;
|
|
@@ -1512,7 +1584,9 @@ async function collapseMemoryHeadings(root) {
|
|
|
1512
1584
|
(line) => /^## Memory\s*$/.test(line) ? "## Memory (agentic-memory)" : line
|
|
1513
1585
|
);
|
|
1514
1586
|
await writeFile3(claudeMdPath, canonical.join("\n"));
|
|
1515
|
-
log.success(
|
|
1587
|
+
log.success(
|
|
1588
|
+
`Collapsed ${blocks.length - 1} duplicate ## Memory section(s) in CLAUDE.md`
|
|
1589
|
+
);
|
|
1516
1590
|
return true;
|
|
1517
1591
|
}
|
|
1518
1592
|
|
|
@@ -1753,13 +1827,13 @@ async function addSessionStartPullHook(root, placement) {
|
|
|
1753
1827
|
const target = placement === "local" ? "settings.local.json" : "settings.json";
|
|
1754
1828
|
return addPlacementHook(root, placement, "SessionStart", "memory pull", {
|
|
1755
1829
|
matcher: "startup",
|
|
1756
|
-
hooks: [{ type: "command", command: "claude-launchpad memory pull -y 2>/dev/null; exit 0" }]
|
|
1830
|
+
hooks: [{ type: "command", command: "npx claude-launchpad memory pull -y 2>/dev/null; exit 0" }]
|
|
1757
1831
|
}, true, `Added SessionStart hook for memory sync to ${target}`);
|
|
1758
1832
|
}
|
|
1759
1833
|
async function addSessionEndPushHook(root, placement) {
|
|
1760
1834
|
const target = placement === "local" ? "settings.local.json" : "settings.json";
|
|
1761
1835
|
return addPlacementHook(root, placement, "SessionEnd", "memory push", {
|
|
1762
|
-
hooks: [{ type: "command", command: "nohup claude-launchpad memory push -y </dev/null >/dev/null 2>&1 & exit 0" }]
|
|
1836
|
+
hooks: [{ type: "command", command: "nohup npx claude-launchpad memory push -y </dev/null >/dev/null 2>&1 & exit 0" }]
|
|
1763
1837
|
}, false, `Added SessionEnd hook for memory sync to ${target}`);
|
|
1764
1838
|
}
|
|
1765
1839
|
async function upgradeStaleSessionEndPushHook(root) {
|
|
@@ -1780,7 +1854,7 @@ async function upgradeStaleSessionEndPushHook(root) {
|
|
|
1780
1854
|
const cmd = typeof h.command === "string" ? h.command : "";
|
|
1781
1855
|
if (!cmd.includes("memory push") || cmd.includes("nohup")) return h;
|
|
1782
1856
|
changed = true;
|
|
1783
|
-
return { ...h, command: "nohup claude-launchpad memory push -y </dev/null >/dev/null 2>&1 & exit 0" };
|
|
1857
|
+
return { ...h, command: "nohup npx claude-launchpad memory push -y </dev/null >/dev/null 2>&1 & exit 0" };
|
|
1784
1858
|
});
|
|
1785
1859
|
return { ...group, hooks: rewritten };
|
|
1786
1860
|
});
|
|
@@ -1868,6 +1942,38 @@ async function addAllowedMcpServers(root, placement) {
|
|
|
1868
1942
|
log.success(`Added allowedMcpServers from configured servers to ${target}`);
|
|
1869
1943
|
return true;
|
|
1870
1944
|
}
|
|
1945
|
+
async function upgradeBareMemoryHooks(root) {
|
|
1946
|
+
let any = false;
|
|
1947
|
+
for (const placement of ["shared", "local"]) {
|
|
1948
|
+
const read = placement === "local" ? readSettingsLocalJson : readSettingsJson;
|
|
1949
|
+
const write = placement === "local" ? writeSettingsLocalJson : writeSettingsJson;
|
|
1950
|
+
const settings = await read(root);
|
|
1951
|
+
if (settings === null) continue;
|
|
1952
|
+
const hooks = settings.hooks;
|
|
1953
|
+
if (!hooks) continue;
|
|
1954
|
+
let changed = false;
|
|
1955
|
+
const upgradedHooks = {};
|
|
1956
|
+
for (const [event, groups] of Object.entries(hooks)) {
|
|
1957
|
+
upgradedHooks[event] = groups.map((group) => {
|
|
1958
|
+
const inner = group.hooks;
|
|
1959
|
+
if (!inner) return group;
|
|
1960
|
+
const rewritten = inner.map((h) => {
|
|
1961
|
+
const cmd = typeof h.command === "string" ? h.command : "";
|
|
1962
|
+
if (!cmd.includes("claude-launchpad memory") || cmd.includes("npx claude-launchpad")) return h;
|
|
1963
|
+
changed = true;
|
|
1964
|
+
return { ...h, command: cmd.replace("claude-launchpad memory", "npx claude-launchpad memory") };
|
|
1965
|
+
});
|
|
1966
|
+
return { ...group, hooks: rewritten };
|
|
1967
|
+
});
|
|
1968
|
+
}
|
|
1969
|
+
if (!changed) continue;
|
|
1970
|
+
await write(root, { ...settings, hooks: upgradedHooks });
|
|
1971
|
+
const target = placement === "local" ? "settings.local.json" : "settings.json";
|
|
1972
|
+
log.success(`Rewrote bare memory hook commands to npx form in ${target}`);
|
|
1973
|
+
any = true;
|
|
1974
|
+
}
|
|
1975
|
+
return any;
|
|
1976
|
+
}
|
|
1871
1977
|
|
|
1872
1978
|
// src/commands/doctor/fixer.ts
|
|
1873
1979
|
async function applyFixes(issues, projectRoot) {
|
|
@@ -1887,74 +1993,311 @@ async function applyFixes(issues, projectRoot) {
|
|
|
1887
1993
|
return { fixed, skipped };
|
|
1888
1994
|
}
|
|
1889
1995
|
var FIX_TABLE = [
|
|
1890
|
-
{
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1996
|
+
{
|
|
1997
|
+
analyzer: "Hooks",
|
|
1998
|
+
match: "$TOOL_INPUT_* env var",
|
|
1999
|
+
fix: (root) => rewriteEnvVarHooks(root)
|
|
2000
|
+
},
|
|
2001
|
+
{
|
|
2002
|
+
analyzer: "Hooks",
|
|
2003
|
+
match: "No hooks configured",
|
|
2004
|
+
fix: async (root, detected) => {
|
|
2005
|
+
const a = await addEnvProtectionHook(root);
|
|
2006
|
+
const b = await addAutoFormatHook(root, detected);
|
|
2007
|
+
const c = await addForcePushProtection(root);
|
|
2008
|
+
const d = await addSessionStartHook(root);
|
|
2009
|
+
return a || b || c || d;
|
|
2010
|
+
}
|
|
2011
|
+
},
|
|
2012
|
+
{
|
|
2013
|
+
analyzer: "Hooks",
|
|
2014
|
+
match: ".env file protection",
|
|
2015
|
+
fix: (root) => addEnvProtectionHook(root)
|
|
2016
|
+
},
|
|
2017
|
+
{
|
|
2018
|
+
analyzer: "Hooks",
|
|
2019
|
+
match: "auto-format",
|
|
2020
|
+
fix: (root, detected) => addAutoFormatHook(root, detected)
|
|
2021
|
+
},
|
|
2022
|
+
{
|
|
2023
|
+
analyzer: "Hooks",
|
|
2024
|
+
match: "No PreToolUse",
|
|
2025
|
+
fix: (root) => addEnvProtectionHook(root)
|
|
2026
|
+
},
|
|
2027
|
+
{
|
|
2028
|
+
analyzer: "Quality",
|
|
2029
|
+
match: "Architecture",
|
|
2030
|
+
fix: (root) => addClaudeMdSection(
|
|
2031
|
+
root,
|
|
2032
|
+
"## Architecture",
|
|
2033
|
+
wrapStub(
|
|
2034
|
+
"<!-- TODO: Describe your codebase structure. Run `/lp-enhance` to auto-fill this. -->"
|
|
2035
|
+
)
|
|
2036
|
+
)
|
|
2037
|
+
},
|
|
2038
|
+
{
|
|
2039
|
+
analyzer: "Quality",
|
|
2040
|
+
match: "Off-Limits",
|
|
2041
|
+
fix: (root) => addClaudeMdSection(root, "## Off-Limits", wrapStub(OFF_LIMITS_CONTENT))
|
|
2042
|
+
},
|
|
2043
|
+
{
|
|
2044
|
+
analyzer: "Quality",
|
|
2045
|
+
match: "Commands",
|
|
2046
|
+
fix: (root) => addClaudeMdSection(
|
|
2047
|
+
root,
|
|
2048
|
+
"## Commands",
|
|
2049
|
+
wrapStub("<!-- TODO: Add your dev/build/test commands -->")
|
|
2050
|
+
)
|
|
2051
|
+
},
|
|
2052
|
+
{
|
|
2053
|
+
analyzer: "Quality",
|
|
2054
|
+
match: "Stack",
|
|
2055
|
+
fix: (root, detected) => {
|
|
2056
|
+
if (detected.language) {
|
|
2057
|
+
const content = `- **Language**: ${detected.language}${detected.framework ? `
|
|
1907
2058
|
- **Framework**: ${detected.framework}` : ""}${detected.packageManager ? `
|
|
1908
2059
|
- **Package Manager**: ${detected.packageManager}` : ""}`;
|
|
1909
|
-
|
|
2060
|
+
return addClaudeMdSection(root, "## Stack", content);
|
|
2061
|
+
}
|
|
2062
|
+
return addClaudeMdSection(
|
|
2063
|
+
root,
|
|
2064
|
+
"## Stack",
|
|
2065
|
+
wrapStub("<!-- TODO: Define your tech stack -->")
|
|
2066
|
+
);
|
|
1910
2067
|
}
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
{
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
{
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
{
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
{
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
{
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
{
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
2068
|
+
},
|
|
2069
|
+
{
|
|
2070
|
+
analyzer: "Quality",
|
|
2071
|
+
match: "Session Start",
|
|
2072
|
+
fix: (root) => addClaudeMdSection(
|
|
2073
|
+
root,
|
|
2074
|
+
"## Session Start",
|
|
2075
|
+
wrapStub(SESSION_START_CONTENT)
|
|
2076
|
+
)
|
|
2077
|
+
},
|
|
2078
|
+
{
|
|
2079
|
+
analyzer: "Quality",
|
|
2080
|
+
match: "Backlog",
|
|
2081
|
+
fix: (root) => addClaudeMdSection(root, "## Backlog", wrapStub(BACKLOG_CONTENT))
|
|
2082
|
+
},
|
|
2083
|
+
{
|
|
2084
|
+
analyzer: "Quality",
|
|
2085
|
+
match: "Stop-and-Swarm section is outdated",
|
|
2086
|
+
fix: (root) => fixStaleSwarmPhrase(root)
|
|
2087
|
+
},
|
|
2088
|
+
{
|
|
2089
|
+
analyzer: "Quality",
|
|
2090
|
+
match: "Stop-and-Swarm",
|
|
2091
|
+
fix: (root) => addClaudeMdSection(
|
|
2092
|
+
root,
|
|
2093
|
+
"## Stop-and-Swarm",
|
|
2094
|
+
wrapStub(STOP_AND_SWARM_CONTENT)
|
|
2095
|
+
)
|
|
2096
|
+
},
|
|
2097
|
+
{
|
|
2098
|
+
analyzer: "Rules",
|
|
2099
|
+
match: "workflow.md rule is outdated",
|
|
2100
|
+
fix: (root) => updateWorkflowRule(root)
|
|
2101
|
+
},
|
|
2102
|
+
{
|
|
2103
|
+
analyzer: "Rules",
|
|
2104
|
+
match: "verification.md rule is outdated",
|
|
2105
|
+
fix: (root) => updateVerificationRule(root)
|
|
2106
|
+
},
|
|
2107
|
+
{
|
|
2108
|
+
analyzer: "Rules",
|
|
2109
|
+
match: "No .claude/agents/code-reviewer.md",
|
|
2110
|
+
fix: (root) => createReviewerAgent(root)
|
|
2111
|
+
},
|
|
2112
|
+
{
|
|
2113
|
+
analyzer: "Quality",
|
|
2114
|
+
match: "Duplicate ## Memory",
|
|
2115
|
+
fix: (root) => collapseMemoryHeadings(root)
|
|
2116
|
+
},
|
|
2117
|
+
{
|
|
2118
|
+
analyzer: "Rules",
|
|
2119
|
+
match: "No BACKLOG.md",
|
|
2120
|
+
fix: (root) => createBacklogMd(root)
|
|
2121
|
+
},
|
|
2122
|
+
{
|
|
2123
|
+
analyzer: "Rules",
|
|
2124
|
+
match: "No .claudeignore",
|
|
2125
|
+
fix: (root, detected) => createClaudeignore(root, detected)
|
|
2126
|
+
},
|
|
2127
|
+
{
|
|
2128
|
+
analyzer: "Rules",
|
|
2129
|
+
match: "No .claude/rules/workflow.md",
|
|
2130
|
+
fix: (root) => createWorkflowRule(root)
|
|
2131
|
+
},
|
|
2132
|
+
{
|
|
2133
|
+
analyzer: "Rules",
|
|
2134
|
+
match: "No .claude/rules/hooks.md",
|
|
2135
|
+
fix: (root) => createHooksRule(root)
|
|
2136
|
+
},
|
|
2137
|
+
{
|
|
2138
|
+
analyzer: "Rules",
|
|
2139
|
+
match: "No .claude/rules/verification.md",
|
|
2140
|
+
fix: (root) => createVerificationRule(root)
|
|
2141
|
+
},
|
|
2142
|
+
{
|
|
2143
|
+
analyzer: "Rules",
|
|
2144
|
+
match: "No .claude/rules/",
|
|
2145
|
+
fix: (root) => createStarterRules(root)
|
|
2146
|
+
},
|
|
2147
|
+
{
|
|
2148
|
+
analyzer: "Hooks",
|
|
2149
|
+
match: "PostCompact hooks can't inject context",
|
|
2150
|
+
fix: (root) => migratePostCompactHook(root)
|
|
2151
|
+
},
|
|
2152
|
+
{
|
|
2153
|
+
analyzer: "Hooks",
|
|
2154
|
+
match: "compact matcher",
|
|
2155
|
+
fix: (root) => addCompactMatcherHook(root)
|
|
2156
|
+
},
|
|
2157
|
+
{
|
|
2158
|
+
analyzer: "Permissions",
|
|
2159
|
+
match: "force-push",
|
|
2160
|
+
fix: (root) => addForcePushProtection(root)
|
|
2161
|
+
},
|
|
2162
|
+
{
|
|
2163
|
+
analyzer: "Permissions",
|
|
2164
|
+
match: "Credential files not blocked",
|
|
2165
|
+
fix: (root) => addCredentialDenyRules(root)
|
|
2166
|
+
},
|
|
2167
|
+
{
|
|
2168
|
+
analyzer: "Permissions",
|
|
2169
|
+
match: "Bypass permissions mode",
|
|
2170
|
+
fix: (root) => addBypassDisable(root)
|
|
2171
|
+
},
|
|
2172
|
+
{
|
|
2173
|
+
analyzer: "Permissions",
|
|
2174
|
+
match: "Sandbox lacks a write grant",
|
|
2175
|
+
fix: (root) => addSandboxMemoryWriteGrant(root)
|
|
2176
|
+
},
|
|
2177
|
+
{
|
|
2178
|
+
analyzer: "Permissions",
|
|
2179
|
+
match: ".env is protected by hooks but not in .claudeignore",
|
|
2180
|
+
fix: (root) => addEnvToClaudeignore(root)
|
|
2181
|
+
},
|
|
2182
|
+
{
|
|
2183
|
+
analyzer: "Permissions",
|
|
2184
|
+
match: ".worktreeinclude is missing or empty",
|
|
2185
|
+
fix: (root) => createWorktreeInclude(root)
|
|
2186
|
+
},
|
|
2187
|
+
{
|
|
2188
|
+
analyzer: "Hooks",
|
|
2189
|
+
match: "registered on PreToolUse",
|
|
2190
|
+
fix: (root) => migrateSprintOpenHookEvent(root)
|
|
2191
|
+
},
|
|
2192
|
+
{
|
|
2193
|
+
analyzer: "Hooks",
|
|
2194
|
+
match: "nudge uses bare stdout",
|
|
2195
|
+
fix: (root) => upgradeStaleNudge(root)
|
|
2196
|
+
},
|
|
2197
|
+
{
|
|
2198
|
+
analyzer: "Hooks",
|
|
2199
|
+
match: "Outdated hygiene script",
|
|
2200
|
+
fix: (root) => refreshHygieneScripts(root)
|
|
2201
|
+
},
|
|
2202
|
+
{
|
|
2203
|
+
analyzer: "Hooks",
|
|
2204
|
+
match: "sprint-size-check",
|
|
2205
|
+
fix: (root) => addSprintSizeHook(root)
|
|
2206
|
+
},
|
|
2207
|
+
{
|
|
2208
|
+
analyzer: "Hooks",
|
|
2209
|
+
match: "sprint-open-check",
|
|
2210
|
+
fix: (root) => addSprintOpenHook(root)
|
|
2211
|
+
},
|
|
2212
|
+
{
|
|
2213
|
+
analyzer: "Hooks",
|
|
2214
|
+
match: "sprint-complete nudge",
|
|
2215
|
+
fix: (root) => addSprintCompleteNudge(root)
|
|
2216
|
+
},
|
|
2217
|
+
{
|
|
2218
|
+
analyzer: "Hooks",
|
|
2219
|
+
match: "workflow-check.sh",
|
|
2220
|
+
fix: (root) => addWorkflowCheckHook(root)
|
|
2221
|
+
},
|
|
2222
|
+
{
|
|
2223
|
+
analyzer: "Rules",
|
|
2224
|
+
match: "No skill authoring conventions",
|
|
2225
|
+
fix: (root) => addSkillAuthoringConventions(root)
|
|
2226
|
+
},
|
|
2227
|
+
{
|
|
2228
|
+
analyzer: "Rules",
|
|
2229
|
+
match: "No /lp-enhance skill",
|
|
2230
|
+
fix: (root) => createEnhanceSkill(root)
|
|
2231
|
+
},
|
|
2232
|
+
{
|
|
2233
|
+
analyzer: "Rules",
|
|
2234
|
+
match: "lp-enhance skill is outdated",
|
|
2235
|
+
fix: (root) => updateEnhanceSkill(root)
|
|
2236
|
+
},
|
|
2237
|
+
{
|
|
2238
|
+
analyzer: "Settings",
|
|
2239
|
+
match: "Deprecated includeCoAuthoredBy",
|
|
2240
|
+
fix: (root) => migrateAttribution(root)
|
|
2241
|
+
},
|
|
2242
|
+
{
|
|
2243
|
+
analyzer: "Hooks",
|
|
2244
|
+
match: "SessionStart",
|
|
2245
|
+
fix: (root) => addSessionStartHook(root)
|
|
2246
|
+
},
|
|
2247
|
+
{
|
|
2248
|
+
analyzer: "Memory",
|
|
2249
|
+
match: "bare claude-launchpad binary",
|
|
2250
|
+
fix: (root) => upgradeBareMemoryHooks(root)
|
|
2251
|
+
},
|
|
2252
|
+
{
|
|
2253
|
+
analyzer: "Memory",
|
|
2254
|
+
match: "Deprecated Stop hook",
|
|
2255
|
+
fix: (root) => removeStaleStopHook(root)
|
|
2256
|
+
},
|
|
2257
|
+
{
|
|
2258
|
+
analyzer: "Memory",
|
|
2259
|
+
match: "autoMemoryEnabled not disabled",
|
|
2260
|
+
fix: (root, _det, placement) => disableAutoMemory(root, placement)
|
|
2261
|
+
},
|
|
2262
|
+
{
|
|
2263
|
+
analyzer: "Memory",
|
|
2264
|
+
match: "MCP tool permission",
|
|
2265
|
+
fix: (root, _det, placement) => addMemoryToolPermissions(root, placement)
|
|
2266
|
+
},
|
|
2267
|
+
{
|
|
2268
|
+
analyzer: "MCP",
|
|
2269
|
+
match: "no allowedMcpServers",
|
|
2270
|
+
fix: (root, _det, placement) => addAllowedMcpServers(root, placement)
|
|
2271
|
+
},
|
|
2272
|
+
{
|
|
2273
|
+
analyzer: "Memory",
|
|
2274
|
+
match: "allowedMcpServers is set but does not include agentic-memory",
|
|
2275
|
+
fix: (root) => addMemoryToAllowedMcpServers(root)
|
|
2276
|
+
},
|
|
2277
|
+
{
|
|
2278
|
+
analyzer: "Memory",
|
|
2279
|
+
match: "SessionStart hook to auto-pull",
|
|
2280
|
+
fix: (root, _det, placement) => addSessionStartPullHook(root, placement)
|
|
2281
|
+
},
|
|
2282
|
+
{
|
|
2283
|
+
analyzer: "Memory",
|
|
2284
|
+
match: "SessionEnd hook to auto-push",
|
|
2285
|
+
fix: (root, _det, placement) => addSessionEndPushHook(root, placement)
|
|
2286
|
+
},
|
|
2287
|
+
{
|
|
2288
|
+
analyzer: "Memory",
|
|
2289
|
+
match: "SessionEnd push hook is not nohup-wrapped",
|
|
2290
|
+
fix: (root) => upgradeStaleSessionEndPushHook(root)
|
|
2291
|
+
},
|
|
2292
|
+
{
|
|
2293
|
+
analyzer: "Memory",
|
|
2294
|
+
match: "CLAUDE.md missing memory guidance",
|
|
2295
|
+
fix: (root, _det, placement) => {
|
|
2296
|
+
const content = "Use agentic-memory to persist knowledge across sessions:\n- Memories are automatically injected at session start\n- STORE IMMEDIATELY when: a dependency strategy changes, an architecture decision is made, a convention is established, a bug pattern is discovered, or a feature is killed/added\n- Use memory_search before memory_store to check for duplicates\n- NEVER store credentials, API keys, tokens, or secrets in memories";
|
|
2297
|
+
const target = placement === "local" ? join7(root, ".claude", "CLAUDE.md") : void 0;
|
|
2298
|
+
return addClaudeMdSection(root, "## Memory", wrapStub(content), target);
|
|
2299
|
+
}
|
|
2300
|
+
}
|
|
1958
2301
|
];
|
|
1959
2302
|
function hasAutoFix(issue) {
|
|
1960
2303
|
return FIX_TABLE.some(
|
|
@@ -1985,7 +2328,10 @@ async function addCredentialDenyRules(root) {
|
|
|
1985
2328
|
const toAdd = ["Read(~/.ssh/*)", "Read(~/.aws/*)", "Read(~/.npmrc)"];
|
|
1986
2329
|
const missing = toAdd.filter((p) => !deny.includes(p));
|
|
1987
2330
|
if (missing.length === 0) return false;
|
|
1988
|
-
const updated = {
|
|
2331
|
+
const updated = {
|
|
2332
|
+
...settings,
|
|
2333
|
+
permissions: { ...permissions, deny: [...deny, ...missing] }
|
|
2334
|
+
};
|
|
1989
2335
|
await writeSettingsJson(root, updated);
|
|
1990
2336
|
log.success("Added credential deny rules (SSH, AWS, npm)");
|
|
1991
2337
|
return true;
|
|
@@ -2011,11 +2357,16 @@ async function addSandboxMemoryWriteGrant(root) {
|
|
|
2011
2357
|
...settings,
|
|
2012
2358
|
sandbox: {
|
|
2013
2359
|
...sandbox,
|
|
2014
|
-
filesystem: {
|
|
2360
|
+
filesystem: {
|
|
2361
|
+
...filesystem,
|
|
2362
|
+
allowWrite: [...allowWrite, "~/.agentic-memory"]
|
|
2363
|
+
}
|
|
2015
2364
|
}
|
|
2016
2365
|
};
|
|
2017
2366
|
await writeSettingsJson(root, updated);
|
|
2018
|
-
log.success(
|
|
2367
|
+
log.success(
|
|
2368
|
+
"Added ~/.agentic-memory to sandbox.filesystem.allowWrite (sandbox stays enabled)"
|
|
2369
|
+
);
|
|
2019
2370
|
return true;
|
|
2020
2371
|
}
|
|
2021
2372
|
async function addEnvToClaudeignore(root) {
|
|
@@ -2027,7 +2378,8 @@ async function addEnvToClaudeignore(root) {
|
|
|
2027
2378
|
return false;
|
|
2028
2379
|
}
|
|
2029
2380
|
const lines = content.split("\n").map((l) => l.trim());
|
|
2030
|
-
if (lines.some((l) => l === ".env" || l === ".env.*" || l === ".env*"))
|
|
2381
|
+
if (lines.some((l) => l === ".env" || l === ".env.*" || l === ".env*"))
|
|
2382
|
+
return false;
|
|
2031
2383
|
await writeFile4(ignorePath, content.trimEnd() + "\n.env\n.env.*\n");
|
|
2032
2384
|
log.success("Added .env to .claudeignore");
|
|
2033
2385
|
return true;
|
|
@@ -2061,7 +2413,9 @@ async function createBacklogMd(root) {
|
|
|
2061
2413
|
if (await fileExists(backlogPath)) return false;
|
|
2062
2414
|
const name = root.split("/").pop() ?? "Project";
|
|
2063
2415
|
await writeFile4(backlogPath, generateBacklogMd({ name, description: "" }));
|
|
2064
|
-
log.success(
|
|
2416
|
+
log.success(
|
|
2417
|
+
"Generated BACKLOG.md (WP template + P0\u2013P3 sections + changelog)"
|
|
2418
|
+
);
|
|
2065
2419
|
return true;
|
|
2066
2420
|
}
|
|
2067
2421
|
async function createClaudeignore(root, detected) {
|
|
@@ -2103,17 +2457,27 @@ async function addSkillAuthoringConventions(root) {
|
|
|
2103
2457
|
return false;
|
|
2104
2458
|
}
|
|
2105
2459
|
if (/^##\s+Skill\s+Authoring/im.test(content)) return false;
|
|
2106
|
-
await writeFile4(
|
|
2460
|
+
await writeFile4(
|
|
2461
|
+
conventionsPath,
|
|
2462
|
+
content.trimEnd() + "\n" + SKILL_AUTHORING_SECTION
|
|
2463
|
+
);
|
|
2107
2464
|
log.success("Added Skill Authoring section to .claude/rules/conventions.md");
|
|
2108
2465
|
return true;
|
|
2109
2466
|
}
|
|
2110
2467
|
async function createEnhanceSkill(root) {
|
|
2111
2468
|
const skillDir = join7(root, ".claude", "skills", "lp-enhance");
|
|
2112
2469
|
const skillPath = join7(skillDir, "SKILL.md");
|
|
2113
|
-
const globalPath = join7(
|
|
2470
|
+
const globalPath = join7(
|
|
2471
|
+
homedir(),
|
|
2472
|
+
".claude",
|
|
2473
|
+
"skills",
|
|
2474
|
+
"lp-enhance",
|
|
2475
|
+
"SKILL.md"
|
|
2476
|
+
);
|
|
2114
2477
|
const legacyProject = join7(root, ".claude", "commands", "lp-enhance.md");
|
|
2115
2478
|
const legacyGlobal = join7(homedir(), ".claude", "commands", "lp-enhance.md");
|
|
2116
|
-
if (await fileExists(skillPath) || await fileExists(globalPath) || await fileExists(legacyProject) || await fileExists(legacyGlobal))
|
|
2479
|
+
if (await fileExists(skillPath) || await fileExists(globalPath) || await fileExists(legacyProject) || await fileExists(legacyGlobal))
|
|
2480
|
+
return false;
|
|
2117
2481
|
await mkdir3(skillDir, { recursive: true });
|
|
2118
2482
|
await writeFile4(skillPath, generateEnhanceSkill());
|
|
2119
2483
|
log.success("Generated /lp-enhance skill (.claude/skills/lp-enhance/)");
|
|
@@ -2121,7 +2485,13 @@ async function createEnhanceSkill(root) {
|
|
|
2121
2485
|
}
|
|
2122
2486
|
async function updateEnhanceSkill(root) {
|
|
2123
2487
|
const projectPath = join7(root, ".claude", "skills", "lp-enhance", "SKILL.md");
|
|
2124
|
-
const globalPath = join7(
|
|
2488
|
+
const globalPath = join7(
|
|
2489
|
+
homedir(),
|
|
2490
|
+
".claude",
|
|
2491
|
+
"skills",
|
|
2492
|
+
"lp-enhance",
|
|
2493
|
+
"SKILL.md"
|
|
2494
|
+
);
|
|
2125
2495
|
const targetPath = await fileExists(projectPath) ? projectPath : await fileExists(globalPath) ? globalPath : null;
|
|
2126
2496
|
if (!targetPath) return false;
|
|
2127
2497
|
await writeFile4(targetPath, generateEnhanceSkill());
|
|
@@ -2303,6 +2673,8 @@ export {
|
|
|
2303
2673
|
WORKFLOW_RULE_VERSION,
|
|
2304
2674
|
generateWorkflowRule,
|
|
2305
2675
|
generateHooksRule,
|
|
2676
|
+
VERIFICATION_RULE_VERSION,
|
|
2677
|
+
generateVerificationRule,
|
|
2306
2678
|
generateReviewerAgent,
|
|
2307
2679
|
applyFixes,
|
|
2308
2680
|
log,
|
|
@@ -2310,4 +2682,4 @@ export {
|
|
|
2310
2682
|
printScoreCard,
|
|
2311
2683
|
renderDoctorReport
|
|
2312
2684
|
};
|
|
2313
|
-
//# sourceMappingURL=chunk-
|
|
2685
|
+
//# sourceMappingURL=chunk-QEPE3WVF.js.map
|