knowns 0.1.1 → 0.1.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.
- package/CHANGELOG.md +19 -0
- package/dist/index.js +489 -220
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,24 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.1.2] - 2024-12-26
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- New `src/constants/knowns-guidelines.ts` file containing system prompt as TypeScript constant
|
|
12
|
+
- Auto-sync of Knowns guidelines to AI instruction files during `knowns init`
|
|
13
|
+
- Third step in "Next steps" output: "Update AI instructions: knowns agents --update-instructions"
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
- Refactored `agents` command to use bundled constant instead of reading from CLAUDE.md
|
|
17
|
+
- CLAUDE.md is now a target file (not source) - gets updated like other AI instruction files
|
|
18
|
+
- Exported `updateInstructionFile()` and `INSTRUCTION_FILES` from agents.ts for reusability
|
|
19
|
+
- System prompt now bundled into binary, eliminating file I/O during sync
|
|
20
|
+
|
|
21
|
+
### Improved
|
|
22
|
+
- Faster agent instruction updates (no file reads required)
|
|
23
|
+
- More reliable init process - new projects get AI instructions automatically
|
|
24
|
+
- Simplified architecture: single source of truth for guidelines in codebase
|
|
25
|
+
|
|
8
26
|
## [0.1.1] - 2024-12-26
|
|
9
27
|
|
|
10
28
|
### Added
|
|
@@ -51,5 +69,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
51
69
|
- CLAUDE.md with complete guidelines for AI agents
|
|
52
70
|
- Example workflows and patterns
|
|
53
71
|
|
|
72
|
+
[0.1.2]: https://github.com/knowns-dev/knowns/compare/v0.1.1...v0.1.2
|
|
54
73
|
[0.1.1]: https://github.com/knowns-dev/knowns/compare/v0.1.0...v0.1.1
|
|
55
74
|
[0.1.0]: https://github.com/knowns-dev/knowns/releases/tag/v0.1.0
|
package/dist/index.js
CHANGED
|
@@ -5341,8 +5341,8 @@ var require_commander = __commonJS((exports) => {
|
|
|
5341
5341
|
});
|
|
5342
5342
|
|
|
5343
5343
|
// src/commands/init.ts
|
|
5344
|
-
import { existsSync } from "fs";
|
|
5345
|
-
import { join as
|
|
5344
|
+
import { existsSync as existsSync2 } from "fs";
|
|
5345
|
+
import { join as join4 } from "path";
|
|
5346
5346
|
|
|
5347
5347
|
// src/storage/file-store.ts
|
|
5348
5348
|
import { mkdir as mkdir2, readdir } from "fs/promises";
|
|
@@ -6506,12 +6506,381 @@ var {
|
|
|
6506
6506
|
Help
|
|
6507
6507
|
} = import__.default;
|
|
6508
6508
|
|
|
6509
|
+
// src/constants/knowns-guidelines.ts
|
|
6510
|
+
var KNOWNS_GUIDELINES = `<!-- KNOWNS GUIDELINES START -->
|
|
6511
|
+
# Knowns CLI Guidelines
|
|
6512
|
+
|
|
6513
|
+
## Core Principle
|
|
6514
|
+
|
|
6515
|
+
**NEVER edit .md files directly. ALL operations MUST use CLI commands.**
|
|
6516
|
+
|
|
6517
|
+
---
|
|
6518
|
+
|
|
6519
|
+
## Project Structure
|
|
6520
|
+
|
|
6521
|
+
\`\`\`
|
|
6522
|
+
.knowns/
|
|
6523
|
+
\u251C\u2500\u2500 tasks/ # Task files: task-<id> - <title>.md
|
|
6524
|
+
\u251C\u2500\u2500 docs/ # Documentation (supports nested folders)
|
|
6525
|
+
\u2514\u2500\u2500 decisions/ # Architecture decision records
|
|
6526
|
+
\`\`\`
|
|
6527
|
+
|
|
6528
|
+
---
|
|
6529
|
+
|
|
6530
|
+
## Task Management
|
|
6531
|
+
|
|
6532
|
+
### Task Lifecycle
|
|
6533
|
+
|
|
6534
|
+
1. **Create** \u2192 \`knowns task create "Title" -d "Description" --ac "Criterion 1" --ac "Criterion 2"\`
|
|
6535
|
+
2. **Start** \u2192 \`knowns task edit <id> -s "In Progress" -a @yourself\`
|
|
6536
|
+
3. **Work** \u2192 Check acceptance criteria as you complete them
|
|
6537
|
+
4. **Complete** \u2192 Mark status as Done after all criteria met
|
|
6538
|
+
|
|
6539
|
+
### Critical Commands
|
|
6540
|
+
|
|
6541
|
+
\`\`\`bash
|
|
6542
|
+
# View task (always use --plain for AI)
|
|
6543
|
+
knowns task view <id> --plain
|
|
6544
|
+
|
|
6545
|
+
# List tasks
|
|
6546
|
+
knowns task list --plain
|
|
6547
|
+
knowns task list -s "In Progress" --plain
|
|
6548
|
+
|
|
6549
|
+
# Search tasks/docs
|
|
6550
|
+
knowns search "query" --plain
|
|
6551
|
+
knowns search "query" --type task --plain
|
|
6552
|
+
|
|
6553
|
+
# Edit task
|
|
6554
|
+
knowns task edit <id> -s "In Progress" -a @agent
|
|
6555
|
+
knowns task edit <id> -t "New Title"
|
|
6556
|
+
knowns task edit <id> -d "Description"
|
|
6557
|
+
|
|
6558
|
+
# Acceptance criteria
|
|
6559
|
+
knowns task edit <id> --ac "New criterion"
|
|
6560
|
+
knowns task edit <id> --check-ac 1
|
|
6561
|
+
knowns task edit <id> --check-ac 1 --check-ac 2 --check-ac 3
|
|
6562
|
+
knowns task edit <id> --uncheck-ac 2
|
|
6563
|
+
knowns task edit <id> --remove-ac 3
|
|
6564
|
+
|
|
6565
|
+
# Implementation
|
|
6566
|
+
knowns task edit <id> --plan $'1. Step one\\n2. Step two'
|
|
6567
|
+
knowns task edit <id> --notes "Implementation summary"
|
|
6568
|
+
knowns task edit <id> --append-notes $'Additional note\\nAnother line'
|
|
6569
|
+
\`\`\`
|
|
6570
|
+
|
|
6571
|
+
### Multi-line Input (Shell-specific)
|
|
6572
|
+
|
|
6573
|
+
**Bash/Zsh** - Use \`$'...\\n...'\`:
|
|
6574
|
+
\`\`\`bash
|
|
6575
|
+
knowns task edit 42 --desc $'Line 1\\nLine 2\\n\\nLine 3'
|
|
6576
|
+
knowns task edit 42 --plan $'1. First\\n2. Second'
|
|
6577
|
+
knowns task edit 42 --notes $'Done A\\nDoing B'
|
|
6578
|
+
\`\`\`
|
|
6579
|
+
|
|
6580
|
+
**PowerShell** - Use backtick-n:
|
|
6581
|
+
\`\`\`powershell
|
|
6582
|
+
knowns task edit 42 --notes "Line1\`nLine2"
|
|
6583
|
+
\`\`\`
|
|
6584
|
+
|
|
6585
|
+
**Portable** - Use printf:
|
|
6586
|
+
\`\`\`bash
|
|
6587
|
+
knowns task edit 42 --notes "$(printf 'Line1\\nLine2')"
|
|
6588
|
+
\`\`\`
|
|
6589
|
+
|
|
6590
|
+
---
|
|
6591
|
+
|
|
6592
|
+
## Task Workflow
|
|
6593
|
+
|
|
6594
|
+
### Step 1: Take Task
|
|
6595
|
+
\`\`\`bash
|
|
6596
|
+
knowns task edit <id> -s "In Progress" -a @yourself
|
|
6597
|
+
\`\`\`
|
|
6598
|
+
|
|
6599
|
+
### Step 2: Create Plan
|
|
6600
|
+
\`\`\`bash
|
|
6601
|
+
knowns task edit <id> --plan $'1. Research\\n2. Implement\\n3. Test'
|
|
6602
|
+
\`\`\`
|
|
6603
|
+
|
|
6604
|
+
**IMPORTANT**: Share plan with user and wait for approval before coding.
|
|
6605
|
+
|
|
6606
|
+
### Step 3: Implementation
|
|
6607
|
+
Write code, then check acceptance criteria:
|
|
6608
|
+
\`\`\`bash
|
|
6609
|
+
knowns task edit <id> --check-ac 1 --check-ac 2 --check-ac 3
|
|
6610
|
+
\`\`\`
|
|
6611
|
+
|
|
6612
|
+
### Step 4: Add Notes (PR Description)
|
|
6613
|
+
\`\`\`bash
|
|
6614
|
+
knowns task edit <id> --notes $'Implemented using X pattern\\nUpdated tests\\nReady for review'
|
|
6615
|
+
\`\`\`
|
|
6616
|
+
|
|
6617
|
+
Or append progressively:
|
|
6618
|
+
\`\`\`bash
|
|
6619
|
+
knowns task edit <id> --append-notes "Completed feature X"
|
|
6620
|
+
knowns task edit <id> --append-notes "Added tests"
|
|
6621
|
+
\`\`\`
|
|
6622
|
+
|
|
6623
|
+
### Step 5: Complete
|
|
6624
|
+
\`\`\`bash
|
|
6625
|
+
knowns task edit <id> -s Done
|
|
6626
|
+
\`\`\`
|
|
6627
|
+
|
|
6628
|
+
---
|
|
6629
|
+
|
|
6630
|
+
## Definition of Done
|
|
6631
|
+
|
|
6632
|
+
Task is Done ONLY when ALL items are complete:
|
|
6633
|
+
|
|
6634
|
+
**Via CLI:**
|
|
6635
|
+
1. All acceptance criteria checked: \`--check-ac <index>\`
|
|
6636
|
+
2. Implementation notes added: \`--notes "..."\`
|
|
6637
|
+
3. Status set to Done: \`-s Done\`
|
|
6638
|
+
|
|
6639
|
+
**Via Code:**
|
|
6640
|
+
4. Tests pass
|
|
6641
|
+
5. Documentation updated
|
|
6642
|
+
6. Code reviewed
|
|
6643
|
+
7. No regressions
|
|
6644
|
+
|
|
6645
|
+
---
|
|
6646
|
+
|
|
6647
|
+
## Documentation Management
|
|
6648
|
+
|
|
6649
|
+
### Commands
|
|
6650
|
+
|
|
6651
|
+
\`\`\`bash
|
|
6652
|
+
# List all docs (includes nested folders)
|
|
6653
|
+
knowns doc list --plain
|
|
6654
|
+
|
|
6655
|
+
# View document
|
|
6656
|
+
knowns doc view <name> --plain
|
|
6657
|
+
knowns doc view patterns/guards --plain
|
|
6658
|
+
knowns doc view patterns/guards.md --plain
|
|
6659
|
+
|
|
6660
|
+
# Create document
|
|
6661
|
+
knowns doc create "Title" -d "Description" -t "tag1,tag2"
|
|
6662
|
+
|
|
6663
|
+
# Edit metadata
|
|
6664
|
+
knowns doc edit <name> -t "New Title" -d "New Description"
|
|
6665
|
+
\`\`\`
|
|
6666
|
+
|
|
6667
|
+
### Document Links
|
|
6668
|
+
|
|
6669
|
+
In \`--plain\` mode, markdown links are replaced with resolved paths:
|
|
6670
|
+
- \`[guards.md](./patterns/guards.md)\` \u2192 \`@.knowns/docs/patterns/guards.md\`
|
|
6671
|
+
|
|
6672
|
+
---
|
|
6673
|
+
|
|
6674
|
+
## Task Structure
|
|
6675
|
+
|
|
6676
|
+
### Title
|
|
6677
|
+
Brief, clear summary of the task.
|
|
6678
|
+
|
|
6679
|
+
### Description
|
|
6680
|
+
Explains WHY and WHAT (not HOW). Provides context.
|
|
6681
|
+
|
|
6682
|
+
### Acceptance Criteria
|
|
6683
|
+
**Outcome-oriented**, testable, user-focused criteria.
|
|
6684
|
+
|
|
6685
|
+
Good:
|
|
6686
|
+
- "User can login with valid credentials"
|
|
6687
|
+
- "System processes 1000 requests/sec without errors"
|
|
6688
|
+
|
|
6689
|
+
Bad:
|
|
6690
|
+
- "Add function handleLogin() in auth.ts" (implementation detail)
|
|
6691
|
+
|
|
6692
|
+
### Implementation Plan (added during work)
|
|
6693
|
+
**HOW** to solve the task. Added AFTER taking the task, BEFORE coding.
|
|
6694
|
+
|
|
6695
|
+
### Implementation Notes (PR description)
|
|
6696
|
+
Summary of what was done, suitable for PR. Added AFTER completion.
|
|
6697
|
+
|
|
6698
|
+
---
|
|
6699
|
+
|
|
6700
|
+
## Common Mistakes
|
|
6701
|
+
|
|
6702
|
+
| Wrong | Right |
|
|
6703
|
+
|-------|-------|
|
|
6704
|
+
| Edit .md files directly | Use \`knowns task edit\` |
|
|
6705
|
+
| Change \`- [ ]\` to \`- [x]\` in file | Use \`--check-ac <index>\` |
|
|
6706
|
+
| Add plan during creation | Add plan when starting work |
|
|
6707
|
+
| Mark Done without all criteria | Check ALL criteria first |
|
|
6708
|
+
|
|
6709
|
+
---
|
|
6710
|
+
|
|
6711
|
+
## Search
|
|
6712
|
+
|
|
6713
|
+
\`\`\`bash
|
|
6714
|
+
# Search everything
|
|
6715
|
+
knowns search "auth" --plain
|
|
6716
|
+
|
|
6717
|
+
# Search tasks only
|
|
6718
|
+
knowns search "login" --type task --plain
|
|
6719
|
+
|
|
6720
|
+
# Search with filters
|
|
6721
|
+
knowns search "api" --status "In Progress" --plain
|
|
6722
|
+
knowns search "bug" --priority high --plain
|
|
6723
|
+
\`\`\`
|
|
6724
|
+
|
|
6725
|
+
---
|
|
6726
|
+
|
|
6727
|
+
## Required Patterns
|
|
6728
|
+
|
|
6729
|
+
### When Starting Task
|
|
6730
|
+
\`\`\`bash
|
|
6731
|
+
# Step 1: Assign and set in progress
|
|
6732
|
+
knowns task edit <id> -s "In Progress" -a @yourself
|
|
6733
|
+
|
|
6734
|
+
# Step 2: Add implementation plan
|
|
6735
|
+
knowns task edit <id> --plan $'1. Research codebase\\n2. Implement\\n3. Test'
|
|
6736
|
+
|
|
6737
|
+
# Step 3: Share plan with user, WAIT for approval
|
|
6738
|
+
# Step 4: Start coding only after approval
|
|
6739
|
+
\`\`\`
|
|
6740
|
+
|
|
6741
|
+
### When Completing Task
|
|
6742
|
+
\`\`\`bash
|
|
6743
|
+
# Step 1: Check all acceptance criteria
|
|
6744
|
+
knowns task edit <id> --check-ac 1 --check-ac 2 --check-ac 3
|
|
6745
|
+
|
|
6746
|
+
# Step 2: Add implementation notes (PR description)
|
|
6747
|
+
knowns task edit <id> --notes $'Summary of changes\\nTesting approach\\nFollow-up needed'
|
|
6748
|
+
|
|
6749
|
+
# Step 3: Mark as done
|
|
6750
|
+
knowns task edit <id> -s Done
|
|
6751
|
+
\`\`\`
|
|
6752
|
+
|
|
6753
|
+
### Only Implement What's In Acceptance Criteria
|
|
6754
|
+
If you need to do more:
|
|
6755
|
+
1. Update AC first: \`knowns task edit <id> --ac "New requirement"\`
|
|
6756
|
+
2. Or create new task: \`knowns task create "Additional feature"\`
|
|
6757
|
+
|
|
6758
|
+
---
|
|
6759
|
+
|
|
6760
|
+
## Tips
|
|
6761
|
+
|
|
6762
|
+
- Always use \`--plain\` flag for AI-readable output
|
|
6763
|
+
- AC flags accept multiple values: \`--check-ac 1 --check-ac 2\`
|
|
6764
|
+
- Mixed operations work: \`--check-ac 1 --uncheck-ac 2 --remove-ac 3\`
|
|
6765
|
+
- Use \`$'...\\n...'\` for multi-line input in Bash/Zsh
|
|
6766
|
+
- Related docs show as \`@.knowns/docs/path/to/file.md\` in plain mode
|
|
6767
|
+
|
|
6768
|
+
---
|
|
6769
|
+
|
|
6770
|
+
## Full Help
|
|
6771
|
+
|
|
6772
|
+
\`\`\`bash
|
|
6773
|
+
knowns --help
|
|
6774
|
+
knowns task --help
|
|
6775
|
+
knowns doc --help
|
|
6776
|
+
knowns search --help
|
|
6777
|
+
\`\`\`
|
|
6778
|
+
<!-- KNOWNS GUIDELINES END -->
|
|
6779
|
+
`;
|
|
6780
|
+
|
|
6781
|
+
// src/commands/agents.ts
|
|
6782
|
+
import { existsSync } from "fs";
|
|
6783
|
+
import { mkdir as mkdir3, readFile, writeFile } from "fs/promises";
|
|
6784
|
+
import { dirname, join as join3 } from "path";
|
|
6785
|
+
var PROJECT_ROOT = process.cwd();
|
|
6786
|
+
var INSTRUCTION_FILES = [
|
|
6787
|
+
{ path: "CLAUDE.md", name: "Claude Code" },
|
|
6788
|
+
{ path: "AGENTS.md", name: "Agent SDK" },
|
|
6789
|
+
{ path: "GEMINI.md", name: "Gemini" },
|
|
6790
|
+
{ path: ".github/copilot-instructions.md", name: "GitHub Copilot" }
|
|
6791
|
+
];
|
|
6792
|
+
async function updateInstructionFile(filePath, guidelines) {
|
|
6793
|
+
const fullPath = join3(PROJECT_ROOT, filePath);
|
|
6794
|
+
const startMarker = "<!-- KNOWNS GUIDELINES START -->";
|
|
6795
|
+
const endMarker = "<!-- KNOWNS GUIDELINES END -->";
|
|
6796
|
+
const dir = dirname(fullPath);
|
|
6797
|
+
if (!existsSync(dir)) {
|
|
6798
|
+
await mkdir3(dir, { recursive: true });
|
|
6799
|
+
}
|
|
6800
|
+
if (!existsSync(fullPath)) {
|
|
6801
|
+
await writeFile(fullPath, guidelines, "utf-8");
|
|
6802
|
+
return { success: true, action: "created" };
|
|
6803
|
+
}
|
|
6804
|
+
const content = await readFile(fullPath, "utf-8");
|
|
6805
|
+
const startIndex = content.indexOf(startMarker);
|
|
6806
|
+
const endIndex = content.indexOf(endMarker);
|
|
6807
|
+
if (startIndex === -1 || endIndex === -1) {
|
|
6808
|
+
const newContent2 = `${content.trimEnd()}
|
|
6809
|
+
|
|
6810
|
+
${guidelines}
|
|
6811
|
+
`;
|
|
6812
|
+
await writeFile(fullPath, newContent2, "utf-8");
|
|
6813
|
+
return { success: true, action: "appended" };
|
|
6814
|
+
}
|
|
6815
|
+
const before = content.substring(0, startIndex);
|
|
6816
|
+
const after = content.substring(endIndex + endMarker.length);
|
|
6817
|
+
const newContent = before + guidelines + after;
|
|
6818
|
+
await writeFile(fullPath, newContent, "utf-8");
|
|
6819
|
+
return { success: true, action: "updated" };
|
|
6820
|
+
}
|
|
6821
|
+
var updateInstructionsCommand = new Command("agents").description("Manage agent instruction files").option("--update-instructions", "Update agent instruction files").action(async (options2) => {
|
|
6822
|
+
if (!options2.updateInstructions) {
|
|
6823
|
+
console.log(source_default.yellow("No action specified. Use --update-instructions to update files."));
|
|
6824
|
+
console.log(source_default.gray(`
|
|
6825
|
+
Example: knowns agents --update-instructions`));
|
|
6826
|
+
return;
|
|
6827
|
+
}
|
|
6828
|
+
try {
|
|
6829
|
+
console.log(source_default.bold(`
|
|
6830
|
+
Updating agent instruction files...
|
|
6831
|
+
`));
|
|
6832
|
+
let createdCount = 0;
|
|
6833
|
+
let appendedCount = 0;
|
|
6834
|
+
let updatedCount = 0;
|
|
6835
|
+
let errorCount = 0;
|
|
6836
|
+
for (const file of INSTRUCTION_FILES) {
|
|
6837
|
+
try {
|
|
6838
|
+
const result = await updateInstructionFile(file.path, KNOWNS_GUIDELINES);
|
|
6839
|
+
if (result.success) {
|
|
6840
|
+
if (result.action === "created") {
|
|
6841
|
+
createdCount++;
|
|
6842
|
+
console.log(source_default.green(`\u2713 Created ${file.name}: ${file.path}`));
|
|
6843
|
+
} else if (result.action === "appended") {
|
|
6844
|
+
appendedCount++;
|
|
6845
|
+
console.log(source_default.cyan(`\u2713 Appended ${file.name}: ${file.path}`));
|
|
6846
|
+
} else {
|
|
6847
|
+
updatedCount++;
|
|
6848
|
+
console.log(source_default.green(`\u2713 Updated ${file.name}: ${file.path}`));
|
|
6849
|
+
}
|
|
6850
|
+
}
|
|
6851
|
+
} catch (error) {
|
|
6852
|
+
errorCount++;
|
|
6853
|
+
console.error(source_default.red(`\u2717 Failed ${file.name}: ${file.path}`), error instanceof Error ? error.message : String(error));
|
|
6854
|
+
}
|
|
6855
|
+
}
|
|
6856
|
+
console.log(source_default.bold(`
|
|
6857
|
+
Summary:`));
|
|
6858
|
+
if (createdCount > 0) {
|
|
6859
|
+
console.log(source_default.green(` Created: ${createdCount}`));
|
|
6860
|
+
}
|
|
6861
|
+
if (appendedCount > 0) {
|
|
6862
|
+
console.log(source_default.cyan(` Appended: ${appendedCount}`));
|
|
6863
|
+
}
|
|
6864
|
+
if (updatedCount > 0) {
|
|
6865
|
+
console.log(source_default.green(` Updated: ${updatedCount}`));
|
|
6866
|
+
}
|
|
6867
|
+
if (errorCount > 0) {
|
|
6868
|
+
console.log(source_default.red(` Failed: ${errorCount}`));
|
|
6869
|
+
}
|
|
6870
|
+
console.log();
|
|
6871
|
+
} catch (error) {
|
|
6872
|
+
console.error(source_default.red("Error updating instruction files:"), error instanceof Error ? error.message : String(error));
|
|
6873
|
+
process.exit(1);
|
|
6874
|
+
}
|
|
6875
|
+
});
|
|
6876
|
+
var agentsCommand = updateInstructionsCommand;
|
|
6877
|
+
|
|
6509
6878
|
// src/commands/init.ts
|
|
6510
6879
|
var initCommand = new Command("init").description("Initialize .knowns/ folder in current directory").argument("[name]", "Project name", "My Project").action(async (name) => {
|
|
6511
6880
|
try {
|
|
6512
6881
|
const projectRoot = process.cwd();
|
|
6513
|
-
const knownsPath =
|
|
6514
|
-
if (
|
|
6882
|
+
const knownsPath = join4(projectRoot, ".knowns");
|
|
6883
|
+
if (existsSync2(knownsPath)) {
|
|
6515
6884
|
console.log(source_default.yellow("\u26A0\uFE0F Project already initialized"));
|
|
6516
6885
|
console.log(source_default.gray(` Location: ${knownsPath}`));
|
|
6517
6886
|
return;
|
|
@@ -6522,9 +6891,28 @@ var initCommand = new Command("init").description("Initialize .knowns/ folder in
|
|
|
6522
6891
|
console.log(source_default.gray(` Name: ${project.name}`));
|
|
6523
6892
|
console.log(source_default.gray(` Location: ${knownsPath}`));
|
|
6524
6893
|
console.log();
|
|
6894
|
+
console.log(source_default.bold("Updating AI instruction files..."));
|
|
6895
|
+
console.log();
|
|
6896
|
+
let syncedCount = 0;
|
|
6897
|
+
for (const file of INSTRUCTION_FILES) {
|
|
6898
|
+
try {
|
|
6899
|
+
const result = await updateInstructionFile(file.path, KNOWNS_GUIDELINES);
|
|
6900
|
+
if (result.success) {
|
|
6901
|
+
syncedCount++;
|
|
6902
|
+
const action = result.action === "created" ? "Created" : result.action === "appended" ? "Appended" : "Updated";
|
|
6903
|
+
console.log(source_default.green(`\u2713 ${action} ${file.name}: ${file.path}`));
|
|
6904
|
+
}
|
|
6905
|
+
} catch (error) {
|
|
6906
|
+
console.log(source_default.yellow(`\u26A0\uFE0F Skipped ${file.name}: ${file.path}`));
|
|
6907
|
+
}
|
|
6908
|
+
}
|
|
6909
|
+
console.log();
|
|
6910
|
+
console.log(source_default.green(`\u2713 Synced guidelines to ${syncedCount} AI instruction file(s)`));
|
|
6911
|
+
console.log();
|
|
6525
6912
|
console.log(source_default.cyan("Next steps:"));
|
|
6526
6913
|
console.log(source_default.gray(' 1. Create a task: knowns task create "My first task"'));
|
|
6527
6914
|
console.log(source_default.gray(" 2. List tasks: knowns task list"));
|
|
6915
|
+
console.log(source_default.gray(" 3. Update AI instructions: knowns agents --update-instructions"));
|
|
6528
6916
|
} catch (error) {
|
|
6529
6917
|
console.error(source_default.red("\u2717 Failed to initialize project"));
|
|
6530
6918
|
if (error instanceof Error) {
|
|
@@ -6534,12 +6922,12 @@ var initCommand = new Command("init").description("Initialize .knowns/ folder in
|
|
|
6534
6922
|
}
|
|
6535
6923
|
});
|
|
6536
6924
|
// src/commands/task.ts
|
|
6537
|
-
import { mkdir as
|
|
6538
|
-
import { join as
|
|
6925
|
+
import { mkdir as mkdir4, readdir as readdir2, unlink } from "fs/promises";
|
|
6926
|
+
import { join as join7 } from "path";
|
|
6539
6927
|
|
|
6540
6928
|
// src/utils/doc-links.ts
|
|
6541
|
-
import { existsSync as
|
|
6542
|
-
import { join as
|
|
6929
|
+
import { existsSync as existsSync3 } from "fs";
|
|
6930
|
+
import { join as join5 } from "path";
|
|
6543
6931
|
function parseMarkdownLinks(text) {
|
|
6544
6932
|
const linkPattern = /\[([^\]]+)\]\(([^)]+)\)/g;
|
|
6545
6933
|
const links = [];
|
|
@@ -6555,7 +6943,7 @@ function parseMarkdownLinks(text) {
|
|
|
6555
6943
|
function resolveDocReferences(content, projectRoot) {
|
|
6556
6944
|
const links = parseMarkdownLinks(content);
|
|
6557
6945
|
const docReferences = [];
|
|
6558
|
-
const docsDir =
|
|
6946
|
+
const docsDir = join5(projectRoot, ".knowns", "docs");
|
|
6559
6947
|
for (const link of links) {
|
|
6560
6948
|
if (link.target.startsWith("http://") || link.target.startsWith("https://")) {
|
|
6561
6949
|
continue;
|
|
@@ -6568,8 +6956,8 @@ function resolveDocReferences(content, projectRoot) {
|
|
|
6568
6956
|
if (!filename.endsWith(".md")) {
|
|
6569
6957
|
filename = `${filename}.md`;
|
|
6570
6958
|
}
|
|
6571
|
-
const resolvedPath =
|
|
6572
|
-
const exists =
|
|
6959
|
+
const resolvedPath = join5(docsDir, filename);
|
|
6960
|
+
const exists = existsSync3(resolvedPath);
|
|
6573
6961
|
docReferences.push({
|
|
6574
6962
|
text: link.text,
|
|
6575
6963
|
filename: link.target,
|
|
@@ -6599,16 +6987,16 @@ function formatDocReferences(references, options2 = {}) {
|
|
|
6599
6987
|
}
|
|
6600
6988
|
|
|
6601
6989
|
// src/utils/find-project-root.ts
|
|
6602
|
-
import { existsSync as
|
|
6603
|
-
import { dirname, join as
|
|
6990
|
+
import { existsSync as existsSync4 } from "fs";
|
|
6991
|
+
import { dirname as dirname2, join as join6 } from "path";
|
|
6604
6992
|
function findProjectRoot(startPath = process.cwd()) {
|
|
6605
6993
|
let currentPath = startPath;
|
|
6606
6994
|
for (let i = 0;i < 20; i++) {
|
|
6607
|
-
const knownsPath =
|
|
6608
|
-
if (
|
|
6995
|
+
const knownsPath = join6(currentPath, ".knowns");
|
|
6996
|
+
if (existsSync4(knownsPath)) {
|
|
6609
6997
|
return currentPath;
|
|
6610
6998
|
}
|
|
6611
|
-
const parentPath =
|
|
6999
|
+
const parentPath = dirname2(currentPath);
|
|
6612
7000
|
if (parentPath === currentPath) {
|
|
6613
7001
|
return null;
|
|
6614
7002
|
}
|
|
@@ -7223,17 +7611,17 @@ var archiveCommand = new Command("archive").description("Archive a task").argume
|
|
|
7223
7611
|
console.error(source_default.red(`\u2717 Task ${id} not found`));
|
|
7224
7612
|
process.exit(1);
|
|
7225
7613
|
}
|
|
7226
|
-
const archiveDir =
|
|
7227
|
-
await
|
|
7228
|
-
const tasksPath =
|
|
7614
|
+
const archiveDir = join7(projectRoot, ".knowns", "archive");
|
|
7615
|
+
await mkdir4(archiveDir, { recursive: true });
|
|
7616
|
+
const tasksPath = join7(projectRoot, ".knowns", "tasks");
|
|
7229
7617
|
const files = await readdir2(tasksPath);
|
|
7230
7618
|
const taskFile = files.find((f) => f.startsWith(`task-${id} -`));
|
|
7231
7619
|
if (!taskFile) {
|
|
7232
7620
|
console.error(source_default.red(`\u2717 Task file for ${id} not found`));
|
|
7233
7621
|
process.exit(1);
|
|
7234
7622
|
}
|
|
7235
|
-
const oldPath =
|
|
7236
|
-
const newPath =
|
|
7623
|
+
const oldPath = join7(tasksPath, taskFile);
|
|
7624
|
+
const newPath = join7(archiveDir, taskFile);
|
|
7237
7625
|
const content = await Bun.file(oldPath).text();
|
|
7238
7626
|
await Bun.write(newPath, content);
|
|
7239
7627
|
await unlink(oldPath);
|
|
@@ -7254,16 +7642,16 @@ var unarchiveCommand = new Command("unarchive").description("Restore archived ta
|
|
|
7254
7642
|
console.error(source_default.gray(' Run "knowns init" to initialize'));
|
|
7255
7643
|
process.exit(1);
|
|
7256
7644
|
}
|
|
7257
|
-
const archiveDir =
|
|
7258
|
-
const tasksPath =
|
|
7645
|
+
const archiveDir = join7(projectRoot, ".knowns", "archive");
|
|
7646
|
+
const tasksPath = join7(projectRoot, ".knowns", "tasks");
|
|
7259
7647
|
const files = await readdir2(archiveDir);
|
|
7260
7648
|
const taskFile = files.find((f) => f.startsWith(`task-${id} -`));
|
|
7261
7649
|
if (!taskFile) {
|
|
7262
7650
|
console.error(source_default.red(`\u2717 Archived task ${id} not found`));
|
|
7263
7651
|
process.exit(1);
|
|
7264
7652
|
}
|
|
7265
|
-
const archivePath =
|
|
7266
|
-
const tasksFilePath =
|
|
7653
|
+
const archivePath = join7(archiveDir, taskFile);
|
|
7654
|
+
const tasksFilePath = join7(tasksPath, taskFile);
|
|
7267
7655
|
const content = await Bun.file(archivePath).text();
|
|
7268
7656
|
await Bun.write(tasksFilePath, content);
|
|
7269
7657
|
await unlink(archivePath);
|
|
@@ -7854,9 +8242,9 @@ var boardCommand = new Command("board").description("Display Kanban board").opti
|
|
|
7854
8242
|
}
|
|
7855
8243
|
});
|
|
7856
8244
|
// src/commands/search.ts
|
|
7857
|
-
import { existsSync as
|
|
7858
|
-
import { readFile, readdir as readdir3 } from "fs/promises";
|
|
7859
|
-
import { join as
|
|
8245
|
+
import { existsSync as existsSync5 } from "fs";
|
|
8246
|
+
import { readFile as readFile2, readdir as readdir3 } from "fs/promises";
|
|
8247
|
+
import { join as join8 } from "path";
|
|
7860
8248
|
var import_gray_matter2 = __toESM(require_gray_matter(), 1);
|
|
7861
8249
|
function getFileStore3() {
|
|
7862
8250
|
const projectRoot = findProjectRoot();
|
|
@@ -7908,8 +8296,8 @@ function calculateDocScore(doc, query) {
|
|
|
7908
8296
|
return score;
|
|
7909
8297
|
}
|
|
7910
8298
|
async function searchDocs(query, projectRoot) {
|
|
7911
|
-
const docsDir =
|
|
7912
|
-
if (!
|
|
8299
|
+
const docsDir = join8(projectRoot, ".knowns", "docs");
|
|
8300
|
+
if (!existsSync5(docsDir)) {
|
|
7913
8301
|
return [];
|
|
7914
8302
|
}
|
|
7915
8303
|
try {
|
|
@@ -7917,7 +8305,7 @@ async function searchDocs(query, projectRoot) {
|
|
|
7917
8305
|
const mdFiles = files.filter((f) => f.endsWith(".md"));
|
|
7918
8306
|
const results = [];
|
|
7919
8307
|
for (const file of mdFiles) {
|
|
7920
|
-
const content = await
|
|
8308
|
+
const content = await readFile2(join8(docsDir, file), "utf-8");
|
|
7921
8309
|
const { data, content: docContent } = import_gray_matter2.default(content);
|
|
7922
8310
|
const metadata = data;
|
|
7923
8311
|
const doc = {
|
|
@@ -8500,9 +8888,9 @@ timeCommand.addCommand(addCommand);
|
|
|
8500
8888
|
timeCommand.addCommand(reportCommand);
|
|
8501
8889
|
// src/server/index.ts
|
|
8502
8890
|
import { watch } from "fs";
|
|
8503
|
-
import { existsSync as
|
|
8504
|
-
import { mkdir as
|
|
8505
|
-
import { join as
|
|
8891
|
+
import { existsSync as existsSync6 } from "fs";
|
|
8892
|
+
import { mkdir as mkdir5, readFile as readFile3, readdir as readdir4, writeFile as writeFile2 } from "fs/promises";
|
|
8893
|
+
import { join as join9, relative } from "path";
|
|
8506
8894
|
var import_gray_matter3 = __toESM(require_gray_matter(), 1);
|
|
8507
8895
|
var buildVersion = Date.now();
|
|
8508
8896
|
async function startServer(options2) {
|
|
@@ -8515,9 +8903,9 @@ async function startServer(options2) {
|
|
|
8515
8903
|
client.send(msg);
|
|
8516
8904
|
}
|
|
8517
8905
|
};
|
|
8518
|
-
const uiPath =
|
|
8519
|
-
const entrypoint =
|
|
8520
|
-
const buildDir =
|
|
8906
|
+
const uiPath = join9(projectRoot, "src", "ui");
|
|
8907
|
+
const entrypoint = join9(uiPath, "index.html");
|
|
8908
|
+
const buildDir = join9(projectRoot, ".knowns", "ui-build");
|
|
8521
8909
|
const entryFile = Bun.file(entrypoint);
|
|
8522
8910
|
if (!await entryFile.exists()) {
|
|
8523
8911
|
throw new Error(`UI entry point not found: ${entrypoint}`);
|
|
@@ -8526,7 +8914,7 @@ async function startServer(options2) {
|
|
|
8526
8914
|
console.log("Building UI...");
|
|
8527
8915
|
const startTime = Date.now();
|
|
8528
8916
|
const buildResult = await Bun.build({
|
|
8529
|
-
entrypoints: [
|
|
8917
|
+
entrypoints: [join9(uiPath, "main.tsx")],
|
|
8530
8918
|
outdir: buildDir,
|
|
8531
8919
|
target: "browser",
|
|
8532
8920
|
minify: false,
|
|
@@ -8540,7 +8928,7 @@ async function startServer(options2) {
|
|
|
8540
8928
|
return false;
|
|
8541
8929
|
}
|
|
8542
8930
|
const cssResult = await Bun.build({
|
|
8543
|
-
entrypoints: [
|
|
8931
|
+
entrypoints: [join9(uiPath, "index.css")],
|
|
8544
8932
|
outdir: buildDir,
|
|
8545
8933
|
target: "browser",
|
|
8546
8934
|
minify: false
|
|
@@ -8594,7 +8982,7 @@ async function startServer(options2) {
|
|
|
8594
8982
|
return handleAPI(req, url, store, broadcast);
|
|
8595
8983
|
}
|
|
8596
8984
|
if (url.pathname === "/main.js" || url.pathname.startsWith("/main.js?")) {
|
|
8597
|
-
const file = Bun.file(
|
|
8985
|
+
const file = Bun.file(join9(buildDir, "main.js"));
|
|
8598
8986
|
if (await file.exists()) {
|
|
8599
8987
|
return new Response(file, {
|
|
8600
8988
|
headers: {
|
|
@@ -8605,7 +8993,7 @@ async function startServer(options2) {
|
|
|
8605
8993
|
}
|
|
8606
8994
|
}
|
|
8607
8995
|
if (url.pathname === "/index.css" || url.pathname.startsWith("/index.css?")) {
|
|
8608
|
-
const file = Bun.file(
|
|
8996
|
+
const file = Bun.file(join9(buildDir, "index.css"));
|
|
8609
8997
|
if (await file.exists()) {
|
|
8610
8998
|
return new Response(file, {
|
|
8611
8999
|
headers: {
|
|
@@ -8708,7 +9096,7 @@ async function findMarkdownFiles(dir, baseDir) {
|
|
|
8708
9096
|
const files = [];
|
|
8709
9097
|
const entries = await readdir4(dir, { withFileTypes: true });
|
|
8710
9098
|
for (const entry of entries) {
|
|
8711
|
-
const fullPath =
|
|
9099
|
+
const fullPath = join9(dir, entry.name);
|
|
8712
9100
|
if (entry.isDirectory()) {
|
|
8713
9101
|
const subFiles = await findMarkdownFiles(fullPath, baseDir);
|
|
8714
9102
|
files.push(...subFiles);
|
|
@@ -8761,14 +9149,14 @@ async function handleAPI(req, url, store, broadcast) {
|
|
|
8761
9149
|
});
|
|
8762
9150
|
}
|
|
8763
9151
|
if (url.pathname === "/api/docs" && req.method === "GET") {
|
|
8764
|
-
const docsDir =
|
|
8765
|
-
if (!
|
|
9152
|
+
const docsDir = join9(store.projectRoot, ".knowns", "docs");
|
|
9153
|
+
if (!existsSync6(docsDir)) {
|
|
8766
9154
|
return new Response(JSON.stringify({ docs: [] }), { headers });
|
|
8767
9155
|
}
|
|
8768
9156
|
const mdFiles = await findMarkdownFiles(docsDir, docsDir);
|
|
8769
9157
|
const docs = await Promise.all(mdFiles.map(async (relativePath) => {
|
|
8770
|
-
const fullPath =
|
|
8771
|
-
const content = await
|
|
9158
|
+
const fullPath = join9(docsDir, relativePath);
|
|
9159
|
+
const content = await readFile3(fullPath, "utf-8");
|
|
8772
9160
|
const { data, content: docContent } = import_gray_matter3.default(content);
|
|
8773
9161
|
const pathParts = relativePath.split("/");
|
|
8774
9162
|
const filename = pathParts[pathParts.length - 1];
|
|
@@ -8784,9 +9172,9 @@ async function handleAPI(req, url, store, broadcast) {
|
|
|
8784
9172
|
return new Response(JSON.stringify({ docs }), { headers });
|
|
8785
9173
|
}
|
|
8786
9174
|
if (url.pathname === "/api/docs" && req.method === "POST") {
|
|
8787
|
-
const docsDir =
|
|
8788
|
-
if (!
|
|
8789
|
-
await
|
|
9175
|
+
const docsDir = join9(store.projectRoot, ".knowns", "docs");
|
|
9176
|
+
if (!existsSync6(docsDir)) {
|
|
9177
|
+
await mkdir5(docsDir, { recursive: true });
|
|
8790
9178
|
}
|
|
8791
9179
|
const data = await req.json();
|
|
8792
9180
|
const { title, description, tags, content, folder } = data;
|
|
@@ -8801,16 +9189,16 @@ async function handleAPI(req, url, store, broadcast) {
|
|
|
8801
9189
|
let targetDir;
|
|
8802
9190
|
if (folder?.trim()) {
|
|
8803
9191
|
const cleanFolder = folder.trim().replace(/^\/+|\/+$/g, "");
|
|
8804
|
-
targetDir =
|
|
8805
|
-
filepath =
|
|
9192
|
+
targetDir = join9(docsDir, cleanFolder);
|
|
9193
|
+
filepath = join9(targetDir, filename);
|
|
8806
9194
|
} else {
|
|
8807
9195
|
targetDir = docsDir;
|
|
8808
|
-
filepath =
|
|
9196
|
+
filepath = join9(docsDir, filename);
|
|
8809
9197
|
}
|
|
8810
|
-
if (!
|
|
8811
|
-
await
|
|
9198
|
+
if (!existsSync6(targetDir)) {
|
|
9199
|
+
await mkdir5(targetDir, { recursive: true });
|
|
8812
9200
|
}
|
|
8813
|
-
if (
|
|
9201
|
+
if (existsSync6(filepath)) {
|
|
8814
9202
|
return new Response(JSON.stringify({ error: "Document with this title already exists in this folder" }), {
|
|
8815
9203
|
status: 409,
|
|
8816
9204
|
headers
|
|
@@ -8825,7 +9213,7 @@ async function handleAPI(req, url, store, broadcast) {
|
|
|
8825
9213
|
tags: tags || []
|
|
8826
9214
|
};
|
|
8827
9215
|
const markdown = import_gray_matter3.default.stringify(content || "", frontmatter);
|
|
8828
|
-
await
|
|
9216
|
+
await writeFile2(filepath, markdown, "utf-8");
|
|
8829
9217
|
return new Response(JSON.stringify({
|
|
8830
9218
|
success: true,
|
|
8831
9219
|
filename,
|
|
@@ -8835,8 +9223,8 @@ async function handleAPI(req, url, store, broadcast) {
|
|
|
8835
9223
|
}), { status: 201, headers });
|
|
8836
9224
|
}
|
|
8837
9225
|
if (url.pathname === "/api/config" && req.method === "GET") {
|
|
8838
|
-
const configPath =
|
|
8839
|
-
if (!
|
|
9226
|
+
const configPath = join9(store.projectRoot, ".knowns", "config.json");
|
|
9227
|
+
if (!existsSync6(configPath)) {
|
|
8840
9228
|
return new Response(JSON.stringify({
|
|
8841
9229
|
config: {
|
|
8842
9230
|
defaultPriority: "medium",
|
|
@@ -8846,7 +9234,7 @@ async function handleAPI(req, url, store, broadcast) {
|
|
|
8846
9234
|
}
|
|
8847
9235
|
}), { headers });
|
|
8848
9236
|
}
|
|
8849
|
-
const content = await
|
|
9237
|
+
const content = await readFile3(configPath, "utf-8");
|
|
8850
9238
|
const config = JSON.parse(content);
|
|
8851
9239
|
if (!config.visibleColumns) {
|
|
8852
9240
|
config.visibleColumns = ["todo", "in-progress", "done"];
|
|
@@ -8855,8 +9243,8 @@ async function handleAPI(req, url, store, broadcast) {
|
|
|
8855
9243
|
}
|
|
8856
9244
|
if (url.pathname === "/api/config" && req.method === "POST") {
|
|
8857
9245
|
const config = await req.json();
|
|
8858
|
-
const configPath =
|
|
8859
|
-
await
|
|
9246
|
+
const configPath = join9(store.projectRoot, ".knowns", "config.json");
|
|
9247
|
+
await writeFile2(configPath, JSON.stringify(config, null, 2), "utf-8");
|
|
8860
9248
|
return new Response(JSON.stringify({ success: true }), { headers });
|
|
8861
9249
|
}
|
|
8862
9250
|
if (url.pathname === "/api/search" && req.method === "GET") {
|
|
@@ -8878,13 +9266,13 @@ async function handleAPI(req, url, store, broadcast) {
|
|
|
8878
9266
|
].join(" ").toLowerCase();
|
|
8879
9267
|
return searchText.includes(q);
|
|
8880
9268
|
});
|
|
8881
|
-
const docsDir =
|
|
9269
|
+
const docsDir = join9(store.projectRoot, ".knowns", "docs");
|
|
8882
9270
|
const docResults = [];
|
|
8883
|
-
if (
|
|
9271
|
+
if (existsSync6(docsDir)) {
|
|
8884
9272
|
const files = await readdir4(docsDir);
|
|
8885
9273
|
const mdFiles = files.filter((f) => f.endsWith(".md"));
|
|
8886
9274
|
for (const file of mdFiles) {
|
|
8887
|
-
const content = await
|
|
9275
|
+
const content = await readFile3(join9(docsDir, file), "utf-8");
|
|
8888
9276
|
const { data, content: docContent } = import_gray_matter3.default(content);
|
|
8889
9277
|
const searchText = `${data.title || ""} ${data.description || ""} ${data.tags?.join(" ") || ""} ${docContent}`.toLowerCase();
|
|
8890
9278
|
if (searchText.includes(q)) {
|
|
@@ -8936,17 +9324,17 @@ var browserCommand = new Command("browser").description("Open web UI for task ma
|
|
|
8936
9324
|
}
|
|
8937
9325
|
});
|
|
8938
9326
|
// src/commands/doc.ts
|
|
8939
|
-
import { existsSync as
|
|
8940
|
-
import { mkdir as
|
|
8941
|
-
import { join as
|
|
9327
|
+
import { existsSync as existsSync7 } from "fs";
|
|
9328
|
+
import { mkdir as mkdir6, readFile as readFile4, readdir as readdir5, writeFile as writeFile3 } from "fs/promises";
|
|
9329
|
+
import { join as join10 } from "path";
|
|
8942
9330
|
var import_gray_matter4 = __toESM(require_gray_matter(), 1);
|
|
8943
|
-
var DOCS_DIR =
|
|
9331
|
+
var DOCS_DIR = join10(process.cwd(), ".knowns", "docs");
|
|
8944
9332
|
async function getAllMdFiles(dir, basePath = "") {
|
|
8945
9333
|
const files = [];
|
|
8946
9334
|
const entries = await readdir5(dir, { withFileTypes: true });
|
|
8947
9335
|
for (const entry of entries) {
|
|
8948
|
-
const fullPath =
|
|
8949
|
-
const relativePath = basePath ?
|
|
9336
|
+
const fullPath = join10(dir, entry.name);
|
|
9337
|
+
const relativePath = basePath ? join10(basePath, entry.name) : entry.name;
|
|
8950
9338
|
if (entry.isDirectory()) {
|
|
8951
9339
|
const subFiles = await getAllMdFiles(fullPath, relativePath);
|
|
8952
9340
|
files.push(...subFiles);
|
|
@@ -8957,8 +9345,8 @@ async function getAllMdFiles(dir, basePath = "") {
|
|
|
8957
9345
|
return files;
|
|
8958
9346
|
}
|
|
8959
9347
|
async function ensureDocsDir() {
|
|
8960
|
-
if (!
|
|
8961
|
-
await
|
|
9348
|
+
if (!existsSync7(DOCS_DIR)) {
|
|
9349
|
+
await mkdir6(DOCS_DIR, { recursive: true });
|
|
8962
9350
|
}
|
|
8963
9351
|
}
|
|
8964
9352
|
function titleToFilename(title) {
|
|
@@ -8968,8 +9356,8 @@ var createCommand3 = new Command("create").description("Create a new documentati
|
|
|
8968
9356
|
try {
|
|
8969
9357
|
await ensureDocsDir();
|
|
8970
9358
|
const filename = `${titleToFilename(title)}.md`;
|
|
8971
|
-
const filepath =
|
|
8972
|
-
if (
|
|
9359
|
+
const filepath = join10(DOCS_DIR, filename);
|
|
9360
|
+
if (existsSync7(filepath)) {
|
|
8973
9361
|
console.error(source_default.red(`\u2717 Document already exists: ${filename}`));
|
|
8974
9362
|
process.exit(1);
|
|
8975
9363
|
}
|
|
@@ -8989,7 +9377,7 @@ var createCommand3 = new Command("create").description("Create a new documentati
|
|
|
8989
9377
|
|
|
8990
9378
|
Write your documentation here.
|
|
8991
9379
|
`, metadata);
|
|
8992
|
-
await
|
|
9380
|
+
await writeFile3(filepath, content, "utf-8");
|
|
8993
9381
|
if (options2.plain) {
|
|
8994
9382
|
console.log(`Created: ${filename}`);
|
|
8995
9383
|
} else {
|
|
@@ -9016,7 +9404,7 @@ var listCommand2 = new Command("list").description("List all documentation files
|
|
|
9016
9404
|
}
|
|
9017
9405
|
const docs = [];
|
|
9018
9406
|
for (const file of mdFiles) {
|
|
9019
|
-
const content = await
|
|
9407
|
+
const content = await readFile4(join10(DOCS_DIR, file), "utf-8");
|
|
9020
9408
|
const { data } = import_gray_matter4.default(content);
|
|
9021
9409
|
docs.push({
|
|
9022
9410
|
filename: file,
|
|
@@ -9075,12 +9463,12 @@ var viewCommand2 = new Command("view").description("View a documentation file").
|
|
|
9075
9463
|
try {
|
|
9076
9464
|
await ensureDocsDir();
|
|
9077
9465
|
let filename = name.endsWith(".md") ? name : `${name}.md`;
|
|
9078
|
-
let filepath =
|
|
9079
|
-
if (!
|
|
9466
|
+
let filepath = join10(DOCS_DIR, filename);
|
|
9467
|
+
if (!existsSync7(filepath)) {
|
|
9080
9468
|
filename = `${titleToFilename(name)}.md`;
|
|
9081
|
-
filepath =
|
|
9469
|
+
filepath = join10(DOCS_DIR, filename);
|
|
9082
9470
|
}
|
|
9083
|
-
if (!
|
|
9471
|
+
if (!existsSync7(filepath)) {
|
|
9084
9472
|
const allFiles = await getAllMdFiles(DOCS_DIR);
|
|
9085
9473
|
const searchName = name.toLowerCase().replace(/\.md$/, "");
|
|
9086
9474
|
const matchingFile = allFiles.find((file) => {
|
|
@@ -9090,14 +9478,14 @@ var viewCommand2 = new Command("view").description("View a documentation file").
|
|
|
9090
9478
|
});
|
|
9091
9479
|
if (matchingFile) {
|
|
9092
9480
|
filename = matchingFile;
|
|
9093
|
-
filepath =
|
|
9481
|
+
filepath = join10(DOCS_DIR, matchingFile);
|
|
9094
9482
|
}
|
|
9095
9483
|
}
|
|
9096
|
-
if (!
|
|
9484
|
+
if (!existsSync7(filepath)) {
|
|
9097
9485
|
console.error(source_default.red(`\u2717 Documentation not found: ${name}`));
|
|
9098
9486
|
process.exit(1);
|
|
9099
9487
|
}
|
|
9100
|
-
const fileContent = await
|
|
9488
|
+
const fileContent = await readFile4(filepath, "utf-8");
|
|
9101
9489
|
const { data, content } = import_gray_matter4.default(fileContent);
|
|
9102
9490
|
const metadata = data;
|
|
9103
9491
|
if (options2.plain) {
|
|
@@ -9176,16 +9564,16 @@ var editCommand2 = new Command("edit").description("Edit a documentation file me
|
|
|
9176
9564
|
try {
|
|
9177
9565
|
await ensureDocsDir();
|
|
9178
9566
|
let filename = name.endsWith(".md") ? name : `${name}.md`;
|
|
9179
|
-
let filepath =
|
|
9180
|
-
if (!
|
|
9567
|
+
let filepath = join10(DOCS_DIR, filename);
|
|
9568
|
+
if (!existsSync7(filepath)) {
|
|
9181
9569
|
filename = `${titleToFilename(name)}.md`;
|
|
9182
|
-
filepath =
|
|
9570
|
+
filepath = join10(DOCS_DIR, filename);
|
|
9183
9571
|
}
|
|
9184
|
-
if (!
|
|
9572
|
+
if (!existsSync7(filepath)) {
|
|
9185
9573
|
console.error(source_default.red(`\u2717 Documentation not found: ${name}`));
|
|
9186
9574
|
process.exit(1);
|
|
9187
9575
|
}
|
|
9188
|
-
const fileContent = await
|
|
9576
|
+
const fileContent = await readFile4(filepath, "utf-8");
|
|
9189
9577
|
const { data, content } = import_gray_matter4.default(fileContent);
|
|
9190
9578
|
const metadata = data;
|
|
9191
9579
|
if (options2.title)
|
|
@@ -9196,7 +9584,7 @@ var editCommand2 = new Command("edit").description("Edit a documentation file me
|
|
|
9196
9584
|
metadata.tags = options2.tags.split(",").map((t) => t.trim());
|
|
9197
9585
|
metadata.updatedAt = new Date().toISOString();
|
|
9198
9586
|
const newContent = import_gray_matter4.default.stringify(content, metadata);
|
|
9199
|
-
await
|
|
9587
|
+
await writeFile3(filepath, newContent, "utf-8");
|
|
9200
9588
|
console.log(source_default.green(`\u2713 Updated documentation: ${source_default.bold(filename)}`));
|
|
9201
9589
|
} catch (error) {
|
|
9202
9590
|
console.error(source_default.red("Error editing documentation:"), error instanceof Error ? error.message : String(error));
|
|
@@ -9205,9 +9593,9 @@ var editCommand2 = new Command("edit").description("Edit a documentation file me
|
|
|
9205
9593
|
});
|
|
9206
9594
|
var docCommand = new Command("doc").description("Manage documentation").addCommand(createCommand3).addCommand(listCommand2).addCommand(viewCommand2).addCommand(editCommand2);
|
|
9207
9595
|
// src/commands/config.ts
|
|
9208
|
-
import { existsSync as
|
|
9209
|
-
import { mkdir as
|
|
9210
|
-
import { join as
|
|
9596
|
+
import { existsSync as existsSync8 } from "fs";
|
|
9597
|
+
import { mkdir as mkdir7, readFile as readFile5, writeFile as writeFile4 } from "fs/promises";
|
|
9598
|
+
import { join as join11 } from "path";
|
|
9211
9599
|
|
|
9212
9600
|
// node_modules/zod/v4/classic/external.js
|
|
9213
9601
|
var exports_external = {};
|
|
@@ -22647,12 +23035,12 @@ function getProjectRoot2() {
|
|
|
22647
23035
|
return projectRoot;
|
|
22648
23036
|
}
|
|
22649
23037
|
async function loadConfig(projectRoot) {
|
|
22650
|
-
const configPath =
|
|
22651
|
-
if (!
|
|
23038
|
+
const configPath = join11(projectRoot, CONFIG_FILE);
|
|
23039
|
+
if (!existsSync8(configPath)) {
|
|
22652
23040
|
return { ...DEFAULT_CONFIG };
|
|
22653
23041
|
}
|
|
22654
23042
|
try {
|
|
22655
|
-
const content = await
|
|
23043
|
+
const content = await readFile5(configPath, "utf-8");
|
|
22656
23044
|
const data = JSON.parse(content);
|
|
22657
23045
|
const validated = ConfigSchema.parse(data);
|
|
22658
23046
|
return { ...DEFAULT_CONFIG, ...validated };
|
|
@@ -22665,13 +23053,13 @@ async function loadConfig(projectRoot) {
|
|
|
22665
23053
|
}
|
|
22666
23054
|
}
|
|
22667
23055
|
async function saveConfig(projectRoot, config2) {
|
|
22668
|
-
const configPath =
|
|
22669
|
-
const knownsDir =
|
|
22670
|
-
if (!
|
|
22671
|
-
await
|
|
23056
|
+
const configPath = join11(projectRoot, CONFIG_FILE);
|
|
23057
|
+
const knownsDir = join11(projectRoot, ".knowns");
|
|
23058
|
+
if (!existsSync8(knownsDir)) {
|
|
23059
|
+
await mkdir7(knownsDir, { recursive: true });
|
|
22672
23060
|
}
|
|
22673
23061
|
try {
|
|
22674
|
-
await
|
|
23062
|
+
await writeFile4(configPath, JSON.stringify(config2, null, 2), "utf-8");
|
|
22675
23063
|
} catch (error46) {
|
|
22676
23064
|
console.error(source_default.red("\u2717 Failed to save config"));
|
|
22677
23065
|
if (error46 instanceof Error) {
|
|
@@ -22813,128 +23201,9 @@ var resetCommand = new Command("reset").description("Reset configuration to defa
|
|
|
22813
23201
|
}
|
|
22814
23202
|
});
|
|
22815
23203
|
var configCommand = new Command("config").description("Manage configuration settings").addCommand(listCommand3).addCommand(getCommand).addCommand(setCommand).addCommand(resetCommand);
|
|
22816
|
-
// src/commands/agents.ts
|
|
22817
|
-
import { existsSync as existsSync8 } from "fs";
|
|
22818
|
-
import { mkdir as mkdir7, readFile as readFile5, writeFile as writeFile4 } from "fs/promises";
|
|
22819
|
-
import { dirname as dirname2, join as join11 } from "path";
|
|
22820
|
-
var PROJECT_ROOT = process.cwd();
|
|
22821
|
-
var CLAUDE_MD = join11(PROJECT_ROOT, "CLAUDE.md");
|
|
22822
|
-
var INSTRUCTION_FILES = [
|
|
22823
|
-
{ path: "CLAUDE.md", name: "Claude Code" },
|
|
22824
|
-
{ path: "AGENTS.md", name: "Agent SDK" },
|
|
22825
|
-
{ path: "GEMINI.md", name: "Gemini" },
|
|
22826
|
-
{ path: ".github/copilot-instructions.md", name: "GitHub Copilot" }
|
|
22827
|
-
];
|
|
22828
|
-
function extractGuidelines(content) {
|
|
22829
|
-
const startMarker = "<!-- KNOWNS GUIDELINES START -->";
|
|
22830
|
-
const endMarker = "<!-- KNOWNS GUIDELINES END -->";
|
|
22831
|
-
const startIndex = content.indexOf(startMarker);
|
|
22832
|
-
const endIndex = content.indexOf(endMarker);
|
|
22833
|
-
if (startIndex === -1 || endIndex === -1) {
|
|
22834
|
-
return null;
|
|
22835
|
-
}
|
|
22836
|
-
return content.substring(startIndex, endIndex + endMarker.length);
|
|
22837
|
-
}
|
|
22838
|
-
async function updateInstructionFile(filePath, guidelines) {
|
|
22839
|
-
const fullPath = join11(PROJECT_ROOT, filePath);
|
|
22840
|
-
const startMarker = "<!-- KNOWNS GUIDELINES START -->";
|
|
22841
|
-
const endMarker = "<!-- KNOWNS GUIDELINES END -->";
|
|
22842
|
-
const dir = dirname2(fullPath);
|
|
22843
|
-
if (!existsSync8(dir)) {
|
|
22844
|
-
await mkdir7(dir, { recursive: true });
|
|
22845
|
-
}
|
|
22846
|
-
if (!existsSync8(fullPath)) {
|
|
22847
|
-
await writeFile4(fullPath, guidelines, "utf-8");
|
|
22848
|
-
return { success: true, action: "created" };
|
|
22849
|
-
}
|
|
22850
|
-
const content = await readFile5(fullPath, "utf-8");
|
|
22851
|
-
const startIndex = content.indexOf(startMarker);
|
|
22852
|
-
const endIndex = content.indexOf(endMarker);
|
|
22853
|
-
if (startIndex === -1 || endIndex === -1) {
|
|
22854
|
-
const newContent2 = `${content.trimEnd()}
|
|
22855
|
-
|
|
22856
|
-
${guidelines}
|
|
22857
|
-
`;
|
|
22858
|
-
await writeFile4(fullPath, newContent2, "utf-8");
|
|
22859
|
-
return { success: true, action: "appended" };
|
|
22860
|
-
}
|
|
22861
|
-
const before = content.substring(0, startIndex);
|
|
22862
|
-
const after = content.substring(endIndex + endMarker.length);
|
|
22863
|
-
const newContent = before + guidelines + after;
|
|
22864
|
-
await writeFile4(fullPath, newContent, "utf-8");
|
|
22865
|
-
return { success: true, action: "updated" };
|
|
22866
|
-
}
|
|
22867
|
-
var updateInstructionsCommand = new Command("agents").description("Manage agent instruction files").option("--update-instructions", "Update agent instruction files").action(async (options2) => {
|
|
22868
|
-
if (!options2.updateInstructions) {
|
|
22869
|
-
console.log(source_default.yellow("No action specified. Use --update-instructions to update files."));
|
|
22870
|
-
console.log(source_default.gray(`
|
|
22871
|
-
Example: knowns agents --update-instructions`));
|
|
22872
|
-
return;
|
|
22873
|
-
}
|
|
22874
|
-
try {
|
|
22875
|
-
if (!existsSync8(CLAUDE_MD)) {
|
|
22876
|
-
console.error(source_default.red("Error: CLAUDE.md not found in project root"));
|
|
22877
|
-
console.error(source_default.gray("The source file must exist with <!-- KNOWNS GUIDELINES START --> markers"));
|
|
22878
|
-
process.exit(1);
|
|
22879
|
-
}
|
|
22880
|
-
const claudeContent = await readFile5(CLAUDE_MD, "utf-8");
|
|
22881
|
-
const guidelines = extractGuidelines(claudeContent);
|
|
22882
|
-
if (!guidelines) {
|
|
22883
|
-
console.error(source_default.red("Error: No guidelines found in CLAUDE.md"));
|
|
22884
|
-
console.error(source_default.gray("Ensure CLAUDE.md contains <!-- KNOWNS GUIDELINES START --> and <!-- KNOWNS GUIDELINES END --> markers"));
|
|
22885
|
-
process.exit(1);
|
|
22886
|
-
}
|
|
22887
|
-
console.log(source_default.bold(`
|
|
22888
|
-
Updating agent instruction files...
|
|
22889
|
-
`));
|
|
22890
|
-
let createdCount = 0;
|
|
22891
|
-
let appendedCount = 0;
|
|
22892
|
-
let updatedCount = 0;
|
|
22893
|
-
let errorCount = 0;
|
|
22894
|
-
for (const file2 of INSTRUCTION_FILES) {
|
|
22895
|
-
try {
|
|
22896
|
-
const result = await updateInstructionFile(file2.path, guidelines);
|
|
22897
|
-
if (result.success) {
|
|
22898
|
-
if (result.action === "created") {
|
|
22899
|
-
createdCount++;
|
|
22900
|
-
console.log(source_default.green(`\u2713 Created ${file2.name}: ${file2.path}`));
|
|
22901
|
-
} else if (result.action === "appended") {
|
|
22902
|
-
appendedCount++;
|
|
22903
|
-
console.log(source_default.cyan(`\u2713 Appended ${file2.name}: ${file2.path}`));
|
|
22904
|
-
} else {
|
|
22905
|
-
updatedCount++;
|
|
22906
|
-
console.log(source_default.green(`\u2713 Updated ${file2.name}: ${file2.path}`));
|
|
22907
|
-
}
|
|
22908
|
-
}
|
|
22909
|
-
} catch (error46) {
|
|
22910
|
-
errorCount++;
|
|
22911
|
-
console.error(source_default.red(`\u2717 Failed ${file2.name}: ${file2.path}`), error46 instanceof Error ? error46.message : String(error46));
|
|
22912
|
-
}
|
|
22913
|
-
}
|
|
22914
|
-
console.log(source_default.bold(`
|
|
22915
|
-
Summary:`));
|
|
22916
|
-
if (createdCount > 0) {
|
|
22917
|
-
console.log(source_default.green(` Created: ${createdCount}`));
|
|
22918
|
-
}
|
|
22919
|
-
if (appendedCount > 0) {
|
|
22920
|
-
console.log(source_default.cyan(` Appended: ${appendedCount}`));
|
|
22921
|
-
}
|
|
22922
|
-
if (updatedCount > 0) {
|
|
22923
|
-
console.log(source_default.green(` Updated: ${updatedCount}`));
|
|
22924
|
-
}
|
|
22925
|
-
if (errorCount > 0) {
|
|
22926
|
-
console.log(source_default.red(` Failed: ${errorCount}`));
|
|
22927
|
-
}
|
|
22928
|
-
console.log();
|
|
22929
|
-
} catch (error46) {
|
|
22930
|
-
console.error(source_default.red("Error updating instruction files:"), error46 instanceof Error ? error46.message : String(error46));
|
|
22931
|
-
process.exit(1);
|
|
22932
|
-
}
|
|
22933
|
-
});
|
|
22934
|
-
var agentsCommand = updateInstructionsCommand;
|
|
22935
23204
|
// src/index.ts
|
|
22936
23205
|
var program2 = new Command;
|
|
22937
|
-
program2.name("knowns").description("CLI tool for dev teams to manage tasks, track time, and sync").version("0.1.
|
|
23206
|
+
program2.name("knowns").description("CLI tool for dev teams to manage tasks, track time, and sync").version("0.1.2");
|
|
22938
23207
|
program2.addCommand(initCommand);
|
|
22939
23208
|
program2.addCommand(taskCommand);
|
|
22940
23209
|
program2.addCommand(boardCommand);
|