toga-ai 1.0.4 → 1.0.5
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/package.json +1 -1
- package/scripts/install.js +27 -29
package/package.json
CHANGED
package/scripts/install.js
CHANGED
|
@@ -462,17 +462,17 @@ function main() {
|
|
|
462
462
|
console.log('toga-ai — TOGA Technology Claude harness');
|
|
463
463
|
console.log('═════════════════════════════════════════════');
|
|
464
464
|
|
|
465
|
-
//
|
|
466
|
-
|
|
467
|
-
|
|
465
|
+
// Harness components (skills/agents/rules/hooks) ALWAYS come from the npm bundle.
|
|
466
|
+
// The git repo is ONLY used to pull newer knowledge docs on top — it never
|
|
467
|
+
// replaces harness components, so a stale local clone can't break the install.
|
|
468
|
+
const harnessDir = PACKAGE_ROOT;
|
|
469
|
+
let knowledgeDir = PACKAGE_ROOT; // overridden below if git repo found
|
|
468
470
|
let gitUpdateLine = null;
|
|
469
471
|
|
|
470
|
-
// Step 2: find or try to clone git repo for updates
|
|
471
472
|
if (repoFlag) {
|
|
472
473
|
const resolved = path.resolve(repoFlag);
|
|
473
474
|
if (isValidClone(resolved)) {
|
|
474
|
-
|
|
475
|
-
sourceLabel = 'git repo (--repo flag)';
|
|
475
|
+
knowledgeDir = resolved;
|
|
476
476
|
} else {
|
|
477
477
|
console.error(' ERROR: --repo path is not a valid clone: ' + resolved);
|
|
478
478
|
process.exit(1);
|
|
@@ -481,40 +481,37 @@ function main() {
|
|
|
481
481
|
let repoDir = findExistingClone();
|
|
482
482
|
|
|
483
483
|
if (!repoDir && !isPostInstall) {
|
|
484
|
-
// Try to clone silently — no error if it fails
|
|
485
484
|
repoDir = tryCloneRepo(path.join(os.homedir(), 'toga-tech'));
|
|
486
485
|
}
|
|
487
486
|
|
|
488
487
|
if (repoDir) {
|
|
489
|
-
// Pull latest — silent on failure, just use bundle
|
|
490
488
|
const pullResult = tryGitPull(repoDir);
|
|
491
489
|
saveRepoPathCache(repoDir);
|
|
492
490
|
|
|
493
491
|
if (pullResult.pulled) {
|
|
494
|
-
|
|
495
|
-
sourceLabel = 'npm bundle v' + bundleVersion;
|
|
492
|
+
knowledgeDir = repoDir;
|
|
496
493
|
if (pullResult.newDocs > 0) {
|
|
497
494
|
gitUpdateLine = 'git update: pulled ' + pullResult.newDocs + ' new knowledge doc' + (pullResult.newDocs !== 1 ? 's' : '') + ' from TOGATechnology/claude';
|
|
498
|
-
} else {
|
|
495
|
+
} else if (pullResult.message !== 'already up to date') {
|
|
499
496
|
gitUpdateLine = 'git update: ' + pullResult.message;
|
|
500
497
|
}
|
|
501
498
|
} else if (isValidClone(repoDir)) {
|
|
502
|
-
// Pull failed but repo exists —
|
|
503
|
-
|
|
504
|
-
sourceLabel = 'git repo (offline, using cached)';
|
|
499
|
+
// Pull failed but repo exists — use cached knowledge only
|
|
500
|
+
knowledgeDir = repoDir;
|
|
505
501
|
}
|
|
506
|
-
// else: pull failed and can't use repo — silently stick with bundle
|
|
507
502
|
}
|
|
508
|
-
// No git access at all — silently use bundle
|
|
509
503
|
}
|
|
510
504
|
|
|
511
|
-
console.log('
|
|
512
|
-
if (
|
|
505
|
+
console.log(' Harness: npm bundle v' + bundleVersion);
|
|
506
|
+
if (knowledgeDir !== PACKAGE_ROOT) {
|
|
507
|
+
console.log(' Knowledge: git repo' + (gitUpdateLine ? ' (' + gitUpdateLine.replace('git update: ', '') + ')' : ' (cached)'));
|
|
508
|
+
}
|
|
509
|
+
if (gitUpdateLine && knowledgeDir === PACKAGE_ROOT) {
|
|
513
510
|
console.log(' ↳ ' + gitUpdateLine);
|
|
514
511
|
}
|
|
515
512
|
console.log('');
|
|
516
513
|
|
|
517
|
-
if (isPostInstall &&
|
|
514
|
+
if (isPostInstall && !repoFlag) {
|
|
518
515
|
console.log(' First-time setup: run `toga-ai` from your project to');
|
|
519
516
|
console.log(' install the harness into your .claude/ directory.');
|
|
520
517
|
console.log('');
|
|
@@ -535,7 +532,7 @@ function main() {
|
|
|
535
532
|
const errors = [];
|
|
536
533
|
|
|
537
534
|
// Skills
|
|
538
|
-
const skillsSrc = path.join(
|
|
535
|
+
const skillsSrc = path.join(harnessDir, 'skills');
|
|
539
536
|
const skillsDest = path.join(claudeDir, 'skills');
|
|
540
537
|
fs.mkdirSync(skillsDest, { recursive: true });
|
|
541
538
|
const skillNames = fs.existsSync(skillsSrc)
|
|
@@ -552,7 +549,7 @@ function main() {
|
|
|
552
549
|
console.log(' ✓ Skills (' + skillNames.length + '): ' + fmtStats(skillStats));
|
|
553
550
|
|
|
554
551
|
// Rules — update if content changed (team standards should always be current)
|
|
555
|
-
const rulesSrc = path.join(
|
|
552
|
+
const rulesSrc = path.join(harnessDir, 'rules');
|
|
556
553
|
const rulesDest = path.join(claudeDir, 'rules', 'toga');
|
|
557
554
|
let rulesStats = { added: 0, updated: 0, unchanged: 0 };
|
|
558
555
|
if (fs.existsSync(rulesSrc)) {
|
|
@@ -562,7 +559,7 @@ function main() {
|
|
|
562
559
|
console.log(' ✓ Rules (' + countMd(rulesDest) + '): ' + fmtStats(rulesStats));
|
|
563
560
|
|
|
564
561
|
// Agents — update if content changed
|
|
565
|
-
const agentsSrc = path.join(
|
|
562
|
+
const agentsSrc = path.join(harnessDir, 'agents');
|
|
566
563
|
const agentsDest = path.join(claudeDir, 'agents', 'toga');
|
|
567
564
|
let agentsStats = { added: 0, updated: 0, unchanged: 0 };
|
|
568
565
|
if (fs.existsSync(agentsSrc)) {
|
|
@@ -573,7 +570,7 @@ function main() {
|
|
|
573
570
|
console.log(' ✓ Agents (' + agentsCount + '): ' + fmtStats(agentsStats));
|
|
574
571
|
|
|
575
572
|
// Hook scripts — always overwrite so paths stay up to date
|
|
576
|
-
const hooksSrc = path.join(
|
|
573
|
+
const hooksSrc = path.join(harnessDir, 'scripts', 'hooks');
|
|
577
574
|
const hooksDest = path.join(claudeDir, 'hooks', 'toga');
|
|
578
575
|
let hooksCount = 0;
|
|
579
576
|
if (fs.existsSync(hooksSrc)) {
|
|
@@ -584,18 +581,18 @@ function main() {
|
|
|
584
581
|
}
|
|
585
582
|
|
|
586
583
|
// knowledge.js CLI — always overwrite so it stays current
|
|
587
|
-
const knowledgeJsSrc = path.join(
|
|
584
|
+
const knowledgeJsSrc = path.join(harnessDir, 'knowledge.js');
|
|
588
585
|
if (fs.existsSync(knowledgeJsSrc)) {
|
|
589
586
|
try { fs.copyFileSync(knowledgeJsSrc, path.join(claudeDir, 'knowledge.js')); }
|
|
590
587
|
catch (e) { errors.push('knowledge.js: ' + e.message); }
|
|
591
588
|
}
|
|
592
589
|
|
|
593
590
|
// Settings — merge (additive only, never removes existing hooks or permissions)
|
|
594
|
-
const ok = mergeSettings(claudeDir,
|
|
591
|
+
const ok = mergeSettings(claudeDir, harnessDir);
|
|
595
592
|
console.log(' ' + (ok ? '✓' : '✗') + ' Hooks (' + hooksCount + ' scripts in .claude/hooks/toga/, settings.json merged)');
|
|
596
593
|
|
|
597
594
|
// MCP example — skip if already present
|
|
598
|
-
const mcpSrc = path.join(
|
|
595
|
+
const mcpSrc = path.join(harnessDir, 'mcp-configs', 'mcp-servers.json');
|
|
599
596
|
const mcpDest = path.join(claudeDir, 'mcp-servers.example.json');
|
|
600
597
|
if (fs.existsSync(mcpSrc) && !fs.existsSync(mcpDest)) {
|
|
601
598
|
try { fs.copyFileSync(mcpSrc, mcpDest); }
|
|
@@ -603,8 +600,9 @@ function main() {
|
|
|
603
600
|
console.log(' ✓ MCP (.claude/mcp-servers.example.json — merge into .mcp.json to enable)');
|
|
604
601
|
}
|
|
605
602
|
|
|
606
|
-
// Knowledge —
|
|
607
|
-
|
|
603
|
+
// Knowledge — git repo if available (has team-captured docs), else npm bundle
|
|
604
|
+
// skipExisting: user-grown docs are never overwritten
|
|
605
|
+
const knowledgeSrc = path.join(knowledgeDir, 'knowledge');
|
|
608
606
|
const knowledgeDest = path.join(claudeDir, 'knowledge');
|
|
609
607
|
let knowledgeStats = { added: 0, updated: 0, unchanged: 0 };
|
|
610
608
|
if (fs.existsSync(knowledgeSrc)) {
|
|
@@ -614,7 +612,7 @@ function main() {
|
|
|
614
612
|
console.log(' ✓ Knowledge (' + countMd(knowledgeDest) + ' docs): ' + fmtStats(knowledgeStats));
|
|
615
613
|
|
|
616
614
|
// CLAUDE.md
|
|
617
|
-
const action = updateClaudeMd(projectRoot, skillNames,
|
|
615
|
+
const action = updateClaudeMd(projectRoot, skillNames, harnessDir, 'npm bundle v' + bundleVersion);
|
|
618
616
|
console.log(' ✓ CLAUDE.md ' + action);
|
|
619
617
|
|
|
620
618
|
// ECC global integration — detect and report
|