bitacora-cli 1.1.0 → 1.1.1

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 CHANGED
@@ -15,6 +15,7 @@ bitacora --help
15
15
  ```
16
16
 
17
17
  Use `--root <path>` on any command to target a different project directory.
18
+ Command examples are available in `examples/cli-workflows.md`.
18
19
 
19
20
  ## What Each Bitacora File Stores
20
21
 
@@ -50,23 +51,30 @@ Bitacora now supports compacting finished tracks to reduce active context size a
50
51
 
51
52
  If gates fail, command exits with code `1` and no compaction is applied.
52
53
 
54
+ ## New in v1.1.1: Skill-only update
55
+
56
+ Use `bitacora skill` to install/update only `.agents/skills/bitacora/SKILL.md` and `skills-lock.json` without recreating `bitacora/` context files.
57
+
53
58
  ## Typical flow
54
59
 
55
60
  ```bash
56
61
  # 1) bootstrap
57
62
  bitacora init
58
63
 
59
- # 2) create work
64
+ # 2) update skill only (after CLI upgrades)
65
+ bitacora skill
66
+
67
+ # 3) create work
60
68
  bitacora new-track
61
69
 
62
- # 3) append progress
70
+ # 4) append progress
63
71
  bitacora log --track-id TRACK-001 --message "implemented parser"
64
72
  bitacora log --track-id TRACK-001 --message "TEST: npm test -- --run tests/core/parser.test.ts -> pass"
65
73
 
66
- # 4) compact when fully completed
74
+ # 5) compact when fully completed
67
75
  bitacora compact --track-id TRACK-001 --complete
68
76
 
69
- # 5) inspect archive only when needed
77
+ # 6) inspect archive only when needed
70
78
  bitacora history --track-id TRACK-001
71
79
  bitacora history --track-id TRACK-001 --show
72
80
  ```
@@ -80,6 +88,14 @@ Creates the `bitacora/` memory structure in the project root.
80
88
  - `--force`: recreates memory files if they already exist.
81
89
  - `--root <path>`: sets the project root (default: current directory).
82
90
 
91
+ ### `bitacora skill [--root <path>]`
92
+
93
+ Installs or updates only the Bitacora local agent skill and its lock entry.
94
+
95
+ - Updates `.agents/skills/bitacora/SKILL.md`.
96
+ - Updates `skills-lock.json` entry for `bitacora` while preserving other skills.
97
+ - Does not recreate or modify `bitacora/` project memory files.
98
+
83
99
  ### `bitacora new-track [trackId] [--status <status>] [--priority <priority>] [--root <path>]`
84
100
 
85
101
  Creates a new track file. If `trackId` is omitted, Bitacora picks the next sequential ID.
@@ -106,6 +122,13 @@ Compacts tracks by summarizing content and archiving full detail.
106
122
  - `--complete`: mark target tracks as completed (requires completion gates).
107
123
  - `--dry-run`: report estimated byte/token savings without writing files.
108
124
  - `--root <path>`: sets the project root.
125
+ - `--complete` gates:
126
+ - `# Tasks` must not contain unchecked items (`- [ ]`).
127
+ - `# Log` must include at least one `TEST:` line.
128
+ - rewrite/archive model:
129
+ - full source track is archived under `bitacora/history/TRACK-###.md`.
130
+ - active `tracks/TRACK-###/track.md` is rewritten into compact summary form.
131
+ - `tracks/tracks.md` is regenerated and the previous snapshot is archived in `bitacora/history/tracks-*.md`.
109
132
 
110
133
  Examples:
111
134
 
@@ -131,6 +154,15 @@ Reads archived track history.
131
154
  - `--show`: print full archived content (default prints only metadata/path).
132
155
  - `--root <path>`: sets the project root.
133
156
 
157
+ ### `bitacora --help`
158
+
159
+ `bitacora --help` includes full command details for:
160
+ - `init`, `skill`, `new-track`, `validate`, `rebuild-state`, `log`
161
+ - `compact` (flags, completion gates, output/archive model)
162
+ - `history` (metadata mode vs `--show`)
163
+
164
+ For a maintained example output, see `examples/help-output.txt`.
165
+
134
166
  ### `bitacora validate [--json] [--root <path>]`
135
167
 
136
168
  Validates the Bitacora file/folder structure and reports errors.
package/dist/src/cli.js CHANGED
@@ -10,6 +10,7 @@ const history_1 = require("./commands/history");
10
10
  const log_1 = require("./commands/log");
11
11
  const new_track_1 = require("./commands/new-track");
12
12
  const rebuild_state_1 = require("./commands/rebuild-state");
13
+ const skill_1 = require("./commands/skill");
13
14
  const validate_1 = require("./commands/validate");
14
15
  const COMMAND_HELP_OVERVIEW = `
15
16
  Command details:
@@ -19,6 +20,11 @@ Command details:
19
20
  --force Recreate bitacora memory if it already exists.
20
21
  --root <path> Project root path (default: current directory).
21
22
 
23
+ skill
24
+ Installs or updates only the bitacora agent skill and skills lock entry.
25
+ Options:
26
+ --root <path> Project root path (default: current directory).
27
+
22
28
  new-track [trackId]
23
29
  Creates a new track file, automatically picking the next track id when omitted.
24
30
  Options:
@@ -52,6 +58,13 @@ Command details:
52
58
  --complete Mark target tracks as completed (requires completion gates).
53
59
  --dry-run Show savings without modifying files.
54
60
  --root <path> Project root path (default: current directory).
61
+ Completion gates (--complete):
62
+ - # Tasks has no unchecked item (- [ ]).
63
+ - # Log includes at least one line containing TEST:.
64
+ Output model:
65
+ - Full source moves to bitacora/history/TRACK-###.md.
66
+ - Active track.md is rewritten into compact summary form.
67
+ - tracks/tracks.md is regenerated; previous snapshot is archived in history/.
55
68
 
56
69
  history
57
70
  Reads archived history for a compacted track.
@@ -59,6 +72,9 @@ Command details:
59
72
  --track-id <trackId> Track identifier.
60
73
  --show Print full archived content.
61
74
  --root <path> Project root path (default: current directory).
75
+ Notes:
76
+ - Without --show, prints metadata/path only.
77
+ - Use --show only when compact summary is insufficient.
62
78
  `;
63
79
  function writeLine(writer, message) {
64
80
  writer(message.endsWith("\n") ? message : `${message}\n`);
@@ -91,6 +107,18 @@ function createCliProgram(runtime = {}, onCommandExitCode) {
91
107
  });
92
108
  onCommandExitCode?.(exitCode);
93
109
  });
110
+ program
111
+ .command("skill")
112
+ .description("Install or update only the bitacora agent skill.")
113
+ .option("--root <path>", "project root path")
114
+ .action((options) => {
115
+ const exitCode = (0, skill_1.runSkillCommand)({
116
+ rootDir: options.root ?? cwd()
117
+ }, {
118
+ onError: (message) => writeLine(stderr, message)
119
+ });
120
+ onCommandExitCode?.(exitCode);
121
+ });
94
122
  program
95
123
  .command("new-track [trackId]")
96
124
  .description("Create a new track with optional id, status, and priority.")
@@ -217,6 +245,9 @@ async function runCli(argv, runtime = {}) {
217
245
  }
218
246
  catch (error) {
219
247
  if (error instanceof commander_1.CommanderError) {
248
+ if (error.code === "commander.helpDisplayed") {
249
+ return 0;
250
+ }
220
251
  return commandExitCode !== 0 ? commandExitCode : 1;
221
252
  }
222
253
  throw error;
@@ -6,63 +6,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.runInitCommand = runInitCommand;
7
7
  const node_fs_1 = __importDefault(require("node:fs"));
8
8
  const node_path_1 = __importDefault(require("node:path"));
9
- const node_crypto_1 = require("node:crypto");
10
9
  const templates_1 = require("../core/templates");
11
- function computeHash(content) {
12
- return (0, node_crypto_1.createHash)("sha256").update(content).digest("hex");
13
- }
14
- function readSkillsLockFile(filePath) {
15
- if (!node_fs_1.default.existsSync(filePath)) {
16
- return {
17
- version: 1,
18
- skills: {}
19
- };
20
- }
21
- try {
22
- const parsed = JSON.parse(node_fs_1.default.readFileSync(filePath, "utf8"));
23
- if (typeof parsed !== "object" || parsed === null) {
24
- return { version: 1, skills: {} };
25
- }
26
- const versionRaw = parsed.version;
27
- const skillsRaw = parsed.skills;
28
- const normalized = {};
29
- if (typeof skillsRaw === "object" && skillsRaw !== null) {
30
- for (const [name, value] of Object.entries(skillsRaw)) {
31
- if (typeof value !== "object" || value === null) {
32
- continue;
33
- }
34
- const source = value.source;
35
- const sourceType = value.sourceType;
36
- const computedHash = value.computedHash;
37
- if (typeof source === "string" &&
38
- typeof sourceType === "string" &&
39
- typeof computedHash === "string") {
40
- normalized[name] = { source, sourceType, computedHash };
41
- }
42
- }
43
- }
44
- return {
45
- version: typeof versionRaw === "number" ? versionRaw : 1,
46
- skills: normalized
47
- };
48
- }
49
- catch {
50
- return {
51
- version: 1,
52
- skills: {}
53
- };
54
- }
55
- }
56
- function writeSkillsLockFile(rootDir, skillContent) {
57
- const lockPath = node_path_1.default.join(rootDir, "skills-lock.json");
58
- const lock = readSkillsLockFile(lockPath);
59
- lock.skills.bitacora = {
60
- source: ".agents/skills/bitacora/SKILL.md",
61
- sourceType: "local",
62
- computedHash: computeHash(skillContent)
63
- };
64
- node_fs_1.default.writeFileSync(lockPath, `${JSON.stringify(lock, null, 2)}\n`, "utf8");
65
- }
10
+ const skill_installer_1 = require("../core/skill-installer");
66
11
  function runInitCommand(options, dependencies = {}) {
67
12
  const now = dependencies.now ?? (() => new Date().toISOString());
68
13
  const onError = dependencies.onError ?? (() => { });
@@ -79,15 +24,12 @@ function runInitCommand(options, dependencies = {}) {
79
24
  const trackId = "TRACK-001";
80
25
  node_fs_1.default.mkdirSync(node_path_1.default.join(memoryRoot, "tracks", trackId), { recursive: true });
81
26
  node_fs_1.default.mkdirSync(node_path_1.default.join(memoryRoot, "history"), { recursive: true });
82
- node_fs_1.default.mkdirSync(node_path_1.default.join(options.rootDir, ".agents", "skills", "bitacora"), { recursive: true });
83
27
  node_fs_1.default.writeFileSync(node_path_1.default.join(memoryRoot, "product.md"), (0, templates_1.createProductTemplate)(), "utf8");
84
28
  node_fs_1.default.writeFileSync(node_path_1.default.join(memoryRoot, "tech-stack.md"), (0, templates_1.createTechStackTemplate)(), "utf8");
85
29
  node_fs_1.default.writeFileSync(node_path_1.default.join(memoryRoot, "workflow.md"), (0, templates_1.createWorkflowTemplate)(), "utf8");
86
30
  node_fs_1.default.writeFileSync(node_path_1.default.join(memoryRoot, "ux-style-guide.md"), (0, templates_1.createUxStyleGuideTemplate)(), "utf8");
87
31
  node_fs_1.default.writeFileSync(node_path_1.default.join(memoryRoot, "index.md"), (0, templates_1.createIndexTemplate)(), "utf8");
88
- const skillContent = (0, templates_1.createAgentSkillTemplate)();
89
- node_fs_1.default.writeFileSync(node_path_1.default.join(options.rootDir, ".agents", "skills", "bitacora", "SKILL.md"), skillContent, "utf8");
90
- writeSkillsLockFile(options.rootDir, skillContent);
32
+ (0, skill_installer_1.installBitacoraSkill)(options.rootDir);
91
33
  node_fs_1.default.writeFileSync(node_path_1.default.join(memoryRoot, "tracks", "tracks.md"), (0, templates_1.createTracksRegistryTemplate)(createdOnDate), "utf8");
92
34
  node_fs_1.default.writeFileSync(node_path_1.default.join(memoryRoot, "tracks", "tracks-template.md"), (0, templates_1.createTracksTemplate)(), "utf8");
93
35
  node_fs_1.default.writeFileSync(node_path_1.default.join(memoryRoot, "tracks", trackId, "track.md"), (0, templates_1.createTrackTemplate)(trackId, "active", "medium", createdAt), "utf8");
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runSkillCommand = runSkillCommand;
4
+ const skill_installer_1 = require("../core/skill-installer");
5
+ function runSkillCommand(options, dependencies = {}) {
6
+ const onError = dependencies.onError ?? (() => { });
7
+ try {
8
+ (0, skill_installer_1.installBitacoraSkill)(options.rootDir);
9
+ return 0;
10
+ }
11
+ catch (error) {
12
+ const message = error instanceof Error ? error.message : String(error);
13
+ onError(message);
14
+ return 1;
15
+ }
16
+ }
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.installBitacoraSkill = installBitacoraSkill;
7
+ const node_fs_1 = __importDefault(require("node:fs"));
8
+ const node_path_1 = __importDefault(require("node:path"));
9
+ const node_crypto_1 = require("node:crypto");
10
+ const templates_1 = require("./templates");
11
+ function computeHash(content) {
12
+ return (0, node_crypto_1.createHash)("sha256").update(content).digest("hex");
13
+ }
14
+ function readSkillsLockFile(filePath) {
15
+ if (!node_fs_1.default.existsSync(filePath)) {
16
+ return {
17
+ version: 1,
18
+ skills: {}
19
+ };
20
+ }
21
+ try {
22
+ const parsed = JSON.parse(node_fs_1.default.readFileSync(filePath, "utf8"));
23
+ if (typeof parsed !== "object" || parsed === null) {
24
+ return { version: 1, skills: {} };
25
+ }
26
+ const versionRaw = parsed.version;
27
+ const skillsRaw = parsed.skills;
28
+ const normalized = {};
29
+ if (typeof skillsRaw === "object" && skillsRaw !== null) {
30
+ for (const [name, value] of Object.entries(skillsRaw)) {
31
+ if (typeof value !== "object" || value === null) {
32
+ continue;
33
+ }
34
+ const source = value.source;
35
+ const sourceType = value.sourceType;
36
+ const computedHash = value.computedHash;
37
+ if (typeof source === "string" &&
38
+ typeof sourceType === "string" &&
39
+ typeof computedHash === "string") {
40
+ normalized[name] = { source, sourceType, computedHash };
41
+ }
42
+ }
43
+ }
44
+ return {
45
+ version: typeof versionRaw === "number" ? versionRaw : 1,
46
+ skills: normalized
47
+ };
48
+ }
49
+ catch {
50
+ return {
51
+ version: 1,
52
+ skills: {}
53
+ };
54
+ }
55
+ }
56
+ function writeSkillsLockFile(rootDir, skillContent) {
57
+ const lockPath = node_path_1.default.join(rootDir, "skills-lock.json");
58
+ const lock = readSkillsLockFile(lockPath);
59
+ lock.skills.bitacora = {
60
+ source: ".agents/skills/bitacora/SKILL.md",
61
+ sourceType: "local",
62
+ computedHash: computeHash(skillContent)
63
+ };
64
+ node_fs_1.default.writeFileSync(lockPath, `${JSON.stringify(lock, null, 2)}\n`, "utf8");
65
+ }
66
+ function installBitacoraSkill(rootDir) {
67
+ const skillDir = node_path_1.default.join(rootDir, ".agents", "skills", "bitacora");
68
+ node_fs_1.default.mkdirSync(skillDir, { recursive: true });
69
+ const skillContent = (0, templates_1.createAgentSkillTemplate)();
70
+ node_fs_1.default.writeFileSync(node_path_1.default.join(skillDir, "SKILL.md"), skillContent, "utf8");
71
+ writeSkillsLockFile(rootDir, skillContent);
72
+ }
@@ -169,7 +169,7 @@ function createAgentSkillTemplate() {
169
169
  return `---
170
170
  name: bitacora
171
171
  description: Keep deterministic project memory in bitacora/ and update it continuously during implementation sessions.
172
- version: 1.0.0
172
+ version: 1.1.1
173
173
  type: local
174
174
  source: .agents/skills/bitacora/SKILL.md
175
175
  ---
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bitacora-cli",
3
- "version": "1.1.0",
3
+ "version": "1.1.1",
4
4
  "description": "Deterministic agent-oriented project memory system. Provides structured Markdown-based long-term memory, strict validation, state reconstruction, and an enforcement CLI with agent skill integration to guide and limit agent behavior.",
5
5
  "repository": {
6
6
  "type": "git",