@tekmidian/pai 0.3.1 → 0.3.2

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.
@@ -4263,6 +4263,15 @@ function getStatuslineScript() {
4263
4263
  for (const c of candidates) if (existsSync(c)) return c;
4264
4264
  return null;
4265
4265
  }
4266
+ function getTabColorScript() {
4267
+ const candidates = [
4268
+ join(process.cwd(), "tab-color-command.sh"),
4269
+ join(homedir(), "dev", "ai", "PAI", "tab-color-command.sh"),
4270
+ join("/", "usr", "local", "lib", "node_modules", "@tekmidian", "pai", "tab-color-command.sh")
4271
+ ];
4272
+ for (const c of candidates) if (existsSync(c)) return c;
4273
+ return null;
4274
+ }
4266
4275
  async function startDocker(rl) {
4267
4276
  const dockerDir = getDockerDir();
4268
4277
  if (!existsSync(join(dockerDir, "docker-compose.yml"))) {
@@ -4583,10 +4592,57 @@ async function stepPaiSkill(rl) {
4583
4592
  return true;
4584
4593
  }
4585
4594
  /**
4586
- * Step 6: Hook scripts (pre-compact, session-stop, statusline)
4595
+ * Step 6: AI Steering Rules installation (~/.claude/skills/PAI/AI-STEERING-RULES.md)
4596
+ */
4597
+ async function stepAiSteeringRules(rl) {
4598
+ section("Step 6: AI Steering Rules");
4599
+ line$1();
4600
+ line$1(" PAI ships a set of universal behavioral rules for AI assistants:");
4601
+ line$1(" surgical fixes, verification before assertion, root cause analysis,");
4602
+ line$1(" and honest failure modes. These rules load at startup as a skill.");
4603
+ line$1();
4604
+ const templatePath = join(getTemplatesDir$1(), "ai-steering-rules.template.md");
4605
+ if (!existsSync(templatePath)) {
4606
+ console.log(c.warn("AI steering rules template not found: " + templatePath));
4607
+ console.log(c.dim(" Skipping AI steering rules installation."));
4608
+ return false;
4609
+ }
4610
+ const skillDir = join(homedir(), ".claude", "skills", "PAI");
4611
+ const skillFile = join(skillDir, "AI-STEERING-RULES.md");
4612
+ if (existsSync(skillFile)) {
4613
+ const content = readFileSync(skillFile, "utf-8");
4614
+ const isGenerated = content.includes("Generated by PAI Setup");
4615
+ if (isGenerated) console.log(c.dim(" Found existing PAI-generated AI-STEERING-RULES.md."));
4616
+ else {
4617
+ console.log(c.yellow(" Found existing AI-STEERING-RULES.md (not PAI-generated)."));
4618
+ console.log(c.dim(" A backup will be created before overwriting."));
4619
+ }
4620
+ line$1();
4621
+ if (!await promptYesNo(rl, "Update ~/.claude/skills/PAI/AI-STEERING-RULES.md with the latest rules?", isGenerated)) {
4622
+ console.log(c.dim(" Keeping existing AI-STEERING-RULES.md unchanged."));
4623
+ return false;
4624
+ }
4625
+ if (!isGenerated) {
4626
+ const backupPath = skillFile + ".backup";
4627
+ writeFileSync(backupPath, content, "utf-8");
4628
+ console.log(c.ok(`Backed up existing AI-STEERING-RULES.md to ${backupPath}`));
4629
+ }
4630
+ } else if (!await promptYesNo(rl, "Install AI steering rules to ~/.claude/skills/PAI/AI-STEERING-RULES.md?", true)) {
4631
+ console.log(c.dim(" Skipping AI steering rules installation."));
4632
+ return false;
4633
+ }
4634
+ const template = readFileSync(templatePath, "utf-8");
4635
+ if (!existsSync(skillDir)) mkdirSync(skillDir, { recursive: true });
4636
+ writeFileSync(skillFile, template, "utf-8");
4637
+ line$1();
4638
+ console.log(c.ok("Installed ~/.claude/skills/PAI/AI-STEERING-RULES.md"));
4639
+ return true;
4640
+ }
4641
+ /**
4642
+ * Step 7: Hook scripts (pre-compact, session-stop, statusline)
4587
4643
  */
4588
4644
  async function stepHooks(rl) {
4589
- section("Step 6: Lifecycle Hooks");
4645
+ section("Step 7: Lifecycle Hooks");
4590
4646
  line$1();
4591
4647
  line$1(" PAI hooks fire on session stop and context compaction to save state,");
4592
4648
  line$1(" update notes, and display live statusline information.");
@@ -4597,6 +4653,7 @@ async function stepHooks(rl) {
4597
4653
  }
4598
4654
  const hooksDir = getHooksDir();
4599
4655
  const statuslineSrc = getStatuslineScript();
4656
+ const tabColorSrc = getTabColorScript();
4600
4657
  const claudeDir = join(homedir(), ".claude");
4601
4658
  const hooksTarget = join(claudeDir, "Hooks");
4602
4659
  if (!existsSync(hooksTarget)) mkdirSync(hooksTarget, { recursive: true });
@@ -4623,13 +4680,15 @@ async function stepHooks(rl) {
4623
4680
  installFile(join(hooksDir, "session-stop.sh"), join(hooksTarget, "pai-session-stop.sh"), "pai-session-stop.sh");
4624
4681
  if (statuslineSrc) installFile(statuslineSrc, join(claudeDir, "statusline-command.sh"), "statusline-command.sh");
4625
4682
  else console.log(c.warn(" statusline-command.sh not found — skipping statusline."));
4683
+ if (tabColorSrc) installFile(tabColorSrc, join(claudeDir, "tab-color-command.sh"), "tab-color-command.sh");
4684
+ else console.log(c.warn(" tab-color-command.sh not found — skipping tab color."));
4626
4685
  return anyInstalled;
4627
4686
  }
4628
4687
  /**
4629
- * Step 7: Patch ~/.claude/settings.json with PAI hooks, env vars, and statusline
4688
+ * Step 8: Patch ~/.claude/settings.json with PAI hooks, env vars, and statusline
4630
4689
  */
4631
4690
  async function stepSettings(rl) {
4632
- section("Step 7: Settings Patch");
4691
+ section("Step 8: Settings Patch");
4633
4692
  line$1();
4634
4693
  line$1(" PAI will add env vars, hook registrations, and the statusline command");
4635
4694
  line$1(" to ~/.claude/settings.json. Existing values are never overwritten.");
@@ -4662,10 +4721,10 @@ async function stepSettings(rl) {
4662
4721
  return result.changed;
4663
4722
  }
4664
4723
  /**
4665
- * Step 8: Daemon install (launchd plist)
4724
+ * Step 9: Daemon install (launchd plist)
4666
4725
  */
4667
4726
  async function stepDaemon(rl) {
4668
- section("Step 8: Daemon Install");
4727
+ section("Step 9: Daemon Install");
4669
4728
  line$1();
4670
4729
  line$1(" The PAI daemon indexes your projects every 5 minutes in the background.");
4671
4730
  line$1();
@@ -4689,10 +4748,10 @@ async function stepDaemon(rl) {
4689
4748
  return true;
4690
4749
  }
4691
4750
  /**
4692
- * Step 9: MCP registration in ~/.claude.json
4751
+ * Step 10: MCP registration in ~/.claude.json
4693
4752
  */
4694
4753
  async function stepMcp(rl) {
4695
- section("Step 9: MCP Registration");
4754
+ section("Step 10: MCP Registration");
4696
4755
  line$1();
4697
4756
  line$1(" Registering the PAI MCP server lets Claude Code call PAI tools directly.");
4698
4757
  line$1();
@@ -4719,10 +4778,10 @@ async function stepMcp(rl) {
4719
4778
  return true;
4720
4779
  }
4721
4780
  /**
4722
- * Step 10: Directory scanning configuration
4781
+ * Step 11: Directory scanning configuration
4723
4782
  */
4724
4783
  async function stepDirectories(rl) {
4725
- section("Step 10: Directories to Index");
4784
+ section("Step 11: Directories to Index");
4726
4785
  line$1();
4727
4786
  line$1(" PAI indexes files in your registered projects. You can register projects");
4728
4787
  line$1(" individually with `pai project add <path>`, or let the registry scanner");
@@ -4749,10 +4808,10 @@ async function stepDirectories(rl) {
4749
4808
  stepDirectories._runScan = runScan;
4750
4809
  }
4751
4810
  /**
4752
- * Step 11: Initial index
4811
+ * Step 12: Initial index
4753
4812
  */
4754
4813
  async function stepInitialIndex(rl) {
4755
- section("Step 11: Initial Index");
4814
+ section("Step 12: Initial Index");
4756
4815
  line$1();
4757
4816
  line$1(" Indexing scans your registered projects and builds the search index.");
4758
4817
  line$1(" The daemon runs indexing automatically every 5 minutes once started.");
@@ -4794,9 +4853,9 @@ async function stepInitialIndex(rl) {
4794
4853
  }
4795
4854
  }
4796
4855
  /**
4797
- * Step 12: Summary and next steps
4856
+ * Step 13: Summary and next steps
4798
4857
  */
4799
- function stepSummary(configUpdates, claudeMdGenerated, paiSkillInstalled, hooksInstalled, settingsPatched, daemonInstalled, mcpRegistered) {
4858
+ function stepSummary(configUpdates, claudeMdGenerated, paiSkillInstalled, aiSteeringRulesInstalled, hooksInstalled, settingsPatched, daemonInstalled, mcpRegistered) {
4800
4859
  section("Setup Complete");
4801
4860
  line$1();
4802
4861
  console.log(c.ok("PAI Knowledge OS is configured!"));
@@ -4809,6 +4868,7 @@ function stepSummary(configUpdates, claudeMdGenerated, paiSkillInstalled, hooksI
4809
4868
  console.log(chalk.dim(" Embedding model: ") + chalk.cyan(model && model !== "none" ? model : "(none — keyword search only)"));
4810
4869
  console.log(chalk.dim(" CLAUDE.md: ") + chalk.cyan(claudeMdGenerated ? "~/.claude/CLAUDE.md (generated)" : "(unchanged)"));
4811
4870
  console.log(chalk.dim(" PAI skill: ") + chalk.cyan(paiSkillInstalled ? "~/.claude/skills/PAI/SKILL.md (installed)" : "(unchanged)"));
4871
+ console.log(chalk.dim(" Steering rules: ") + chalk.cyan(aiSteeringRulesInstalled ? "~/.claude/skills/PAI/AI-STEERING-RULES.md (installed)" : "(unchanged)"));
4812
4872
  console.log(chalk.dim(" Hooks: ") + chalk.cyan(hooksInstalled ? "pai-pre-compact.sh, pai-session-stop.sh (installed)" : "(unchanged)"));
4813
4873
  console.log(chalk.dim(" Settings: ") + chalk.cyan(settingsPatched ? "env vars, hooks, statusline (patched)" : "(unchanged)"));
4814
4874
  console.log(chalk.dim(" Daemon: ") + chalk.cyan(daemonInstalled ? "com.pai.pai-daemon (installed)" : "(unchanged)"));
@@ -4866,6 +4926,7 @@ async function runSetup() {
4866
4926
  const embeddingConfig = await stepEmbedding(rl);
4867
4927
  const claudeMdGenerated = await stepClaudeMd(rl);
4868
4928
  const paiSkillInstalled = await stepPaiSkill(rl);
4929
+ const aiSteeringRulesInstalled = await stepAiSteeringRules(rl);
4869
4930
  const hooksInstalled = await stepHooks(rl);
4870
4931
  const settingsPatched = await stepSettings(rl);
4871
4932
  const daemonInstalled = await stepDaemon(rl);
@@ -4879,7 +4940,7 @@ async function runSetup() {
4879
4940
  line$1();
4880
4941
  console.log(c.ok("Configuration saved."));
4881
4942
  await stepInitialIndex(rl);
4882
- stepSummary(allUpdates, claudeMdGenerated, paiSkillInstalled, hooksInstalled, settingsPatched, daemonInstalled, mcpRegistered);
4943
+ stepSummary(allUpdates, claudeMdGenerated, paiSkillInstalled, aiSteeringRulesInstalled, hooksInstalled, settingsPatched, daemonInstalled, mcpRegistered);
4883
4944
  } finally {
4884
4945
  rl.close();
4885
4946
  }