@pedrocivita/tocket 1.0.0 → 1.1.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 CHANGED
@@ -1,38 +1,110 @@
1
+ ![CI](https://github.com/pedrocivita/tocket/actions/workflows/ci.yml/badge.svg)
2
+ [![npm](https://img.shields.io/npm/v/@pedrocivita/tocket)](https://www.npmjs.com/package/@pedrocivita/tocket)
3
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
4
+
1
5
  # Tocket
2
6
 
3
7
  **The Context Engineering Framework for Multi-Agent Workspaces**
4
8
 
5
- Tocket structures how AI agents share context, hand off work, and build on each other's output. It turns ad-hoc prompting into a repeatable engineering workflow.
9
+ When multiple AI agents work on the same codebase, context is lost between sessions and between agents. Each one starts from scratch, re-reads files, and makes decisions that conflict with previous ones.
6
10
 
7
- ## Core Pillars
11
+ Tocket fixes this with two primitives:
8
12
 
9
- - **Triangulation** — Architect + Executor pattern. One agent plans, another implements, with structured handoff payloads between them.
10
- - **Context as Code** — Memory Bank protocol. Project context lives in version-controlled files (`.context/`), not ephemeral chat history.
13
+ - **Memory Bank** — A `.context/` directory with version-controlled markdown files that any AI can read. The project's ground truth lives in files, not in chat history.
14
+ - **Triangulation** — An Architect plans, an Executor implements, and structured XML payloads are the handoff between them.
11
15
 
12
- ## Commands
16
+ ## Who is this for?
17
+
18
+ - Developers using **multi-agent setups** (Gemini + Claude, Cursor + Copilot, etc.)
19
+ - Teams that want **reproducible AI-assisted development** across sessions
20
+ - Anyone tired of re-explaining project context to AI every time they open a chat
21
+
22
+ ## You don't need the CLI to use Tocket
13
23
 
14
- | Command | Description |
15
- |---------|-------------|
16
- | `tocket init` | Scaffold an agentic workspace with Memory Bank and triangulation config |
17
- | `tocket generate` | Build payload XMLs interactively for Architect-Executor handoff |
18
- | `tocket sync` | Update Memory Bank from git history and session artifacts |
24
+ The protocol is just files. You can adopt it manually:
19
25
 
20
- ## Installation
26
+ 1. Create a `.context/` directory with `activeContext.md` and `systemPatterns.md`
27
+ 2. Add a `TOCKET.md` to your repo root (see [the spec](TOCKET.md))
28
+ 3. Tell your AI agents to read `.context/` before acting
29
+
30
+ The CLI just automates the scaffolding.
31
+
32
+ ## Quick Start
21
33
 
22
34
  ```bash
23
- npx @pedrocivita/tocket
35
+ # Scaffold a new workspace (creates .context/, TOCKET.md, CLAUDE.md, GEMINI.md)
36
+ npx @pedrocivita/tocket init
37
+
38
+ # Generate a payload XML for agent handoff
39
+ npx @pedrocivita/tocket generate
40
+
41
+ # Sync session progress into Memory Bank
42
+ npx @pedrocivita/tocket sync
24
43
  ```
25
44
 
26
- ## Development
45
+ ## Commands
27
46
 
28
- ```bash
29
- git clone https://github.com/pedrocivita/tocket.git
30
- cd tocket
31
- npm install
32
- npm run build
33
- node dist/index.js --help
47
+ | Command | What it does |
48
+ | ----------------- | -------------------------------------------------------------- |
49
+ | `tocket init` | Scaffolds `.context/`, `TOCKET.md`, `CLAUDE.md`, `GEMINI.md` |
50
+ | `tocket generate` | Interactive payload XML builder — copies to clipboard |
51
+ | `tocket sync` | Appends session summary + git log to `.context/progress.md` |
52
+ | `tocket validate` | Checks if the current directory has a valid Tocket Memory Bank |
53
+
54
+ ## How Triangulation works
55
+
56
+ ```
57
+ Architect (any planning AI) Executor (any coding AI)
58
+ │ │
59
+ │ 1. Reads .context/ │
60
+ │ 2. Analyzes task │
61
+ │ 3. Generates <payload> XML │
62
+ │──────── structured handoff ──────►│
63
+ │ │ 4. Reads .context/ + payload
64
+ │ │ 5. Implements tasks
65
+ │ │ 6. Updates .context/
66
+ │◄──────── status report ───────────│
34
67
  ```
35
68
 
69
+ The Architect doesn't write code. The Executor doesn't make architecture decisions. The payload is the contract between them.
70
+
71
+ ## Memory Bank files
72
+
73
+ ```
74
+ .context/
75
+ activeContext.md ← Current focus. Read this first.
76
+ systemPatterns.md ← Architecture decisions and conventions.
77
+ techContext.md ← Stack, build tools, critical rules.
78
+ productContext.md ← What the product is and why it exists.
79
+ progress.md ← What's done, what's next.
80
+ ```
81
+
82
+ All files are markdown. All files are committed to git. Any AI that can read files can participate.
83
+
84
+ ## Documentation
85
+
86
+ | Guide | Description |
87
+ | ------------------------------------------- | ----------------------------------------------- |
88
+ | [Getting Started](docs/GETTING_STARTED.md) | Set up your first Tocket workspace in 5 minutes |
89
+ | [Tocket Rules](docs/TOCKET_RULES.md) | Complete reference for all protocol rules |
90
+ | [Developer Guide](docs/DEVELOPERS_GUIDE.md) | Contributing to the Tocket CLI codebase |
91
+ | [Protocol Spec](TOCKET.md) | The agent-agnostic protocol specification |
92
+
93
+ ## How is this different from...
94
+
95
+ | Tool | What it does | How Tocket differs |
96
+ | ---------------- | ------------------------------------ | ------------------------------------------------------------------------------------ |
97
+ | `.cursorrules` | Single-agent instructions for Cursor | Tocket defines _inter-agent_ protocol, not just single-agent rules |
98
+ | `CLAUDE.md` | Instructions for Claude Code | Tocket generates `CLAUDE.md` _as part of_ a broader multi-agent system |
99
+ | `AGENTS.md` | Codex agent instructions | Same idea for one agent; Tocket coordinates multiple agents |
100
+ | Prompt templates | Static prompts for LLMs | Tocket's Memory Bank evolves with the project; payloads are structured, not freeform |
101
+
102
+ ## Contributing
103
+
104
+ We welcome contributions! Please read our [Contributing Guide](CONTRIBUTING.md) to get started.
105
+
106
+ This project follows a [Code of Conduct](CODE_OF_CONDUCT.md).
107
+
36
108
  ## License
37
109
 
38
110
  MIT
@@ -1,43 +1,31 @@
1
- import { input, select, number } from "@inquirer/prompts";
1
+ import { input, select } from "@inquirer/prompts";
2
2
  import clipboard from "clipboardy";
3
- function inferMode(score) {
4
- if (score <= 6)
5
- return "solo";
6
- if (score <= 10)
7
- return "team-small";
8
- return "team-full";
9
- }
10
3
  function buildPayloadXml(opts) {
11
- const mode = inferMode(opts.complexity);
12
- const skillLines = opts.skills
13
- .split(",")
14
- .map((s) => s.trim())
15
- .filter(Boolean)
16
- .map((s) => ` <skill>${s}</skill>`)
17
- .join("\n");
18
- return `<payload version="3.0">
4
+ const skillsAttr = opts.skills.trim()
5
+ ? `\n <skills>${opts.skills.trim()}</skills>`
6
+ : "";
7
+ return `<payload version="2.0">
19
8
  <meta>
20
9
  <intent>${opts.intent}</intent>
21
- <scope>${opts.scope}</scope>
10
+ <scope>${opts.scope}</scope>${skillsAttr}
22
11
  <priority>${opts.priority}</priority>
23
- <complexity score="${opts.complexity}" mode="${mode}" />
24
- <model>${opts.model}</model>
25
12
  </meta>
26
13
 
27
- <skills>
28
- ${skillLines || " <!-- Add skills here -->"}
29
- </skills>
30
-
31
14
  <context>
32
- <!-- Provide relevant context for the Architect -->
15
+ <summary><!-- Background and reasoning --></summary>
33
16
  </context>
34
17
 
35
18
  <tasks>
36
- <!-- The Architect will populate tasks based on the intent -->
19
+ <task id="1" type="create | edit | delete">
20
+ <target><!-- file/path --></target>
21
+ <action><!-- What to do --></action>
22
+ <spec><!-- Detailed specification --></spec>
23
+ <done><!-- Definition of done --></done>
24
+ </task>
37
25
  </tasks>
38
26
 
39
27
  <validate>
40
- <!-- Define acceptance criteria -->
28
+ <check><!-- How to verify success --></check>
41
29
  </validate>
42
30
  </payload>`;
43
31
  }
@@ -57,33 +45,10 @@ export function registerGenerateCommand(program) {
57
45
  ],
58
46
  });
59
47
  const skills = await input({
60
- message: "Skills/plugins (comma-separated):",
61
- });
62
- const model = await select({
63
- message: "Architect model:",
64
- choices: [
65
- {
66
- value: "gemini-3.1-pro-preview-customtools",
67
- name: "gemini-3.1-pro-preview-customtools (default)",
68
- },
69
- { value: "gemini-2.5-pro", name: "gemini-2.5-pro" },
70
- ],
71
- });
72
- const complexity = await number({
73
- message: "Complexity score (0-15):",
74
- min: 0,
75
- max: 15,
76
- required: true,
77
- });
78
- const xml = buildPayloadXml({
79
- intent,
80
- scope,
81
- priority,
82
- skills,
83
- model,
84
- complexity: complexity ?? 0,
48
+ message: "Skills/plugins (comma-separated, optional):",
85
49
  });
50
+ const xml = buildPayloadXml({ intent, scope, priority, skills });
86
51
  clipboard.writeSync(xml);
87
- console.log("\n\x1b[32m✓\x1b[0m Payload XML (v3.0) copied to clipboard! Paste it into your Architect to continue.");
52
+ console.log("\n\x1b[32m\u2713\x1b[0m Payload XML (v2.0) copied to clipboard! Paste it into your Architect to continue.");
88
53
  });
89
54
  }
@@ -1,7 +1,7 @@
1
1
  import { input } from "@inquirer/prompts";
2
2
  import { mkdir, writeFile } from "node:fs/promises";
3
3
  import { join } from "node:path";
4
- import { claudeMd, geminiMd, activeContextMd, systemPatternsMd, } from "../templates/memory-bank.js";
4
+ import { claudeMd, geminiMd, tocketMd, activeContextMd, systemPatternsMd, productContextMd, techContextMd, progressMd, } from "../templates/memory-bank.js";
5
5
  export function registerInitCommand(program) {
6
6
  program
7
7
  .command("init")
@@ -12,10 +12,14 @@ export function registerInitCommand(program) {
12
12
  const contextDir = join(process.cwd(), ".context");
13
13
  await mkdir(contextDir, { recursive: true });
14
14
  const files = [
15
+ ["TOCKET.md", tocketMd(projectName)],
15
16
  ["CLAUDE.md", claudeMd(projectName, description)],
16
17
  ["GEMINI.md", geminiMd(projectName, description)],
17
18
  [join(".context", "activeContext.md"), activeContextMd(projectName)],
18
19
  [join(".context", "systemPatterns.md"), systemPatternsMd(projectName)],
20
+ [join(".context", "productContext.md"), productContextMd(projectName, description)],
21
+ [join(".context", "techContext.md"), techContextMd(projectName)],
22
+ [join(".context", "progress.md"), progressMd(projectName)],
19
23
  ];
20
24
  for (const [filePath, content] of files) {
21
25
  const fullPath = join(process.cwd(), filePath);
@@ -0,0 +1,2 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerValidateCommand(program: Command): void;
@@ -0,0 +1,90 @@
1
+ import { existsSync, statSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ const PASS = "\x1b[32m\u2713\x1b[0m";
4
+ const WARN = "\x1b[33m\u26A0\x1b[0m";
5
+ const FAIL = "\x1b[31m\u2717\x1b[0m";
6
+ function checkFile(basePath, relativePath, required) {
7
+ const fullPath = join(basePath, relativePath);
8
+ if (existsSync(fullPath)) {
9
+ return { icon: PASS, message: `${relativePath} found` };
10
+ }
11
+ if (required) {
12
+ return { icon: FAIL, message: `${relativePath} missing (required)` };
13
+ }
14
+ return { icon: WARN, message: `${relativePath} missing (optional)` };
15
+ }
16
+ function checkStale(basePath, relativePath) {
17
+ const fullPath = join(basePath, relativePath);
18
+ if (!existsSync(fullPath))
19
+ return null;
20
+ const stats = statSync(fullPath);
21
+ const daysSinceModified = Math.floor((Date.now() - stats.mtimeMs) / (1000 * 60 * 60 * 24));
22
+ if (daysSinceModified > 7) {
23
+ return {
24
+ icon: WARN,
25
+ message: `${relativePath} last modified ${daysSinceModified} days ago (may be stale)`,
26
+ };
27
+ }
28
+ return null;
29
+ }
30
+ function checkAgentFile(basePath) {
31
+ const agentFiles = [
32
+ "CLAUDE.md",
33
+ "GEMINI.md",
34
+ "EXECUTOR.md",
35
+ "ARCHITECT.md",
36
+ ".cursorrules",
37
+ ];
38
+ const found = agentFiles.filter((f) => existsSync(join(basePath, f)));
39
+ if (found.length > 0) {
40
+ return {
41
+ icon: PASS,
42
+ message: `Agent config found: ${found.join(", ")}`,
43
+ };
44
+ }
45
+ return {
46
+ icon: WARN,
47
+ message: "No agent config file found (CLAUDE.md, GEMINI.md, etc.)",
48
+ };
49
+ }
50
+ export function registerValidateCommand(program) {
51
+ program
52
+ .command("validate")
53
+ .description("Check the health of a Tocket workspace")
54
+ .action(() => {
55
+ const cwd = process.cwd();
56
+ const results = [];
57
+ let hasFailure = false;
58
+ console.log("\nValidating Tocket workspace...\n");
59
+ // Required files
60
+ results.push(checkFile(cwd, join(".context"), true));
61
+ results.push(checkFile(cwd, join(".context", "activeContext.md"), true));
62
+ results.push(checkFile(cwd, join(".context", "systemPatterns.md"), true));
63
+ results.push(checkFile(cwd, "TOCKET.md", true));
64
+ // Optional files
65
+ results.push(checkFile(cwd, join(".context", "techContext.md"), false));
66
+ results.push(checkFile(cwd, join(".context", "productContext.md"), false));
67
+ results.push(checkFile(cwd, join(".context", "progress.md"), false));
68
+ // Agent config
69
+ results.push(checkAgentFile(cwd));
70
+ // Staleness check
71
+ const staleCheck = checkStale(cwd, join(".context", "activeContext.md"));
72
+ if (staleCheck) {
73
+ results.push(staleCheck);
74
+ }
75
+ // Print results
76
+ for (const r of results) {
77
+ console.log(` ${r.icon} ${r.message}`);
78
+ if (r.icon === FAIL)
79
+ hasFailure = true;
80
+ }
81
+ console.log("");
82
+ if (hasFailure) {
83
+ console.log("\x1b[31mWorkspace has issues.\x1b[0m Run \x1b[1mtocket init\x1b[0m to scaffold missing files.");
84
+ process.exitCode = 1;
85
+ }
86
+ else {
87
+ console.log("\x1b[32mWorkspace is healthy.\x1b[0m");
88
+ }
89
+ });
90
+ }
package/dist/index.js CHANGED
@@ -3,12 +3,14 @@ import { Command } from "commander";
3
3
  import { registerInitCommand } from "./commands/init.cmd.js";
4
4
  import { registerGenerateCommand } from "./commands/generate.cmd.js";
5
5
  import { registerSyncCommand } from "./commands/sync.cmd.js";
6
+ import { registerValidateCommand } from "./commands/validate.cmd.js";
6
7
  const program = new Command();
7
8
  program
8
9
  .name("tocket")
9
10
  .description("The Context Engineering Framework for Multi-Agent Workspaces")
10
- .version("1.0.0");
11
+ .version("1.1.0");
11
12
  registerInitCommand(program);
12
13
  registerGenerateCommand(program);
13
14
  registerSyncCommand(program);
15
+ registerValidateCommand(program);
14
16
  program.parse();
@@ -2,3 +2,7 @@ export declare const claudeMd: (projectName: string, description: string) => str
2
2
  export declare const geminiMd: (projectName: string, description: string) => string;
3
3
  export declare const activeContextMd: (projectName: string) => string;
4
4
  export declare const systemPatternsMd: (projectName: string) => string;
5
+ export declare const productContextMd: (projectName: string, description: string) => string;
6
+ export declare const techContextMd: (projectName: string) => string;
7
+ export declare const progressMd: (projectName: string) => string;
8
+ export declare const tocketMd: (projectName: string) => string;
@@ -53,7 +53,7 @@ Your job is to **analyze, plan, and decide**. You do not write code directly —
53
53
  ## Rules
54
54
 
55
55
  1. **Read \`.context/\` first** — Understand current state before planning.
56
- 2. **Produce mission briefs** — Use \`<mission-brief>\` XML format for handoff to the Executor.
56
+ 2. **Produce payloads** — Use \`<payload version="2.0">\` XML format for handoff to the Executor.
57
57
  3. **Never write code inline** — Provide specs, not implementations. The Executor handles code.
58
58
  4. **Update systemPatterns.md** — When you make architectural decisions, record them.
59
59
  5. **Think in constraints** — Define what the system should and should not do.
@@ -70,12 +70,12 @@ Your job is to **analyze, plan, and decide**. You do not write code directly —
70
70
 
71
71
  ---
72
72
 
73
- ## Mission Brief Format
73
+ ## Payload Format
74
74
 
75
75
  \`\`\`xml
76
- <mission-brief version="1.0">
76
+ <payload version="2.0">
77
77
  <meta>
78
- <goal>What needs to happen</goal>
78
+ <intent>What needs to happen</intent>
79
79
  <scope>Which files/modules are affected</scope>
80
80
  <priority>high | medium | low</priority>
81
81
  </meta>
@@ -94,7 +94,7 @@ Your job is to **analyze, plan, and decide**. You do not write code directly —
94
94
  <validate>
95
95
  <check>Verification step</check>
96
96
  </validate>
97
- </mission-brief>
97
+ </payload>
98
98
  \`\`\`
99
99
  `;
100
100
  export const activeContextMd = (projectName) => `# Active Context - ${projectName}
@@ -139,3 +139,168 @@ _To be defined._
139
139
  |----------|-----------|------|
140
140
  | Adopted Tocket triangulation | Structured multi-agent workflow | ${new Date().toISOString().split("T")[0]} |
141
141
  `;
142
+ export const productContextMd = (projectName, description) => `# Product Context - ${projectName}
143
+
144
+ <!-- What the product is, who it's for, and why it exists. Updated by the Architect. -->
145
+
146
+ ## What is ${projectName}?
147
+
148
+ ${description || "_Describe your product here._"}
149
+
150
+ ## Problem
151
+
152
+ _What problem does this project solve?_
153
+
154
+ ## Solution
155
+
156
+ _How does it solve it?_
157
+
158
+ ## Target Users
159
+
160
+ _Who is this for?_
161
+
162
+ ## Design Principles
163
+
164
+ - _List the guiding principles for this project_
165
+ `;
166
+ export const techContextMd = (projectName) => `# Tech Context - ${projectName}
167
+
168
+ <!-- Stack, build tools, and critical rules. Updated by the Architect. -->
169
+
170
+ ## Stack
171
+
172
+ | Layer | Technology | Notes |
173
+ |-------|-----------|-------|
174
+ | Language | | |
175
+ | Runtime | | |
176
+ | Build | | |
177
+ | Framework | | |
178
+
179
+ ## Critical Rules
180
+
181
+ _Document any rules that agents must follow (e.g., import conventions, naming patterns)._
182
+
183
+ ## Project Structure
184
+
185
+ \`\`\`
186
+ ${projectName}/
187
+ src/ # Source code
188
+ .context/ # Memory Bank
189
+ \`\`\`
190
+ `;
191
+ export const progressMd = (projectName) => `# Progress Log - ${projectName}
192
+
193
+ <!-- Appended by tocket sync and manual updates -->
194
+
195
+ ## Milestone: Project Initialization
196
+
197
+ **Status**: Complete
198
+
199
+ - [x] Agentic workspace scaffolded with Tocket CLI
200
+ - [x] Memory Bank initialized (\`.context/\`)
201
+
202
+ ## Next Up
203
+
204
+ - [ ] _Define your first milestone here_
205
+ `;
206
+ export const tocketMd = (projectName) => `# Tocket Protocol Specification
207
+
208
+ > How any AI agent should operate in **${projectName}**.
209
+
210
+ This file is **agent-agnostic**. Whether you are Claude, Gemini, GPT, Cursor, Cline, Copilot, or any future AI — if you see this file, follow these rules.
211
+
212
+ ---
213
+
214
+ ## 1. Memory Bank
215
+
216
+ Project context lives in \`.context/\`, not in chat history. **Read it before doing anything.**
217
+
218
+ \`\`\`
219
+ .context/
220
+ activeContext.md <- Start here. Current focus, recent changes, open decisions.
221
+ systemPatterns.md <- Architecture patterns, conventions, key decisions.
222
+ techContext.md <- Tech stack, build tools, critical rules.
223
+ productContext.md <- What the product is, who it's for, why it exists.
224
+ progress.md <- What's done, what's next.
225
+ \`\`\`
226
+
227
+ ### Rules
228
+
229
+ - **Read before acting** — Always read \`activeContext.md\` and \`systemPatterns.md\` before your first action in a session.
230
+ - **Write before leaving** — Update \`activeContext.md\` with what changed after completing significant work.
231
+ - **Trust the files** — If \`.context/\` says the project uses ESM, it uses ESM. Don't second-guess documented decisions.
232
+ - **Don't duplicate** — Context belongs in \`.context/\`, not scattered in code comments or chat summaries.
233
+
234
+ ---
235
+
236
+ ## 2. Triangulation
237
+
238
+ Tocket separates **planning** from **implementation** across two agent roles:
239
+
240
+ \`\`\`
241
+ ┌─────────────────┐ ┌─────────────────┐
242
+ │ ARCHITECT │ │ EXECUTOR │
243
+ │ (Planner) │ payload │ (Implementer) │
244
+ │ │─────────>│ │
245
+ │ Analyzes task │ │ Receives plan │
246
+ │ Designs approach│ │ Writes code │
247
+ │ Generates XML │ │ Runs tests │
248
+ │ Updates patterns│ │ Updates context │
249
+ └─────────────────┘ └─────────────────┘
250
+ \`\`\`
251
+
252
+ ### Architect
253
+
254
+ - Reads \`.context/\` to understand current state
255
+ - Produces structured payloads (see Section 3) with clear tasks
256
+ - Makes architectural decisions and records them in \`systemPatterns.md\`
257
+ - **Does not write code** — only specs and constraints
258
+
259
+ ### Executor
260
+
261
+ - Reads \`.context/\` and the Architect's payload
262
+ - Implements tasks exactly as specified
263
+ - Asks when the plan is unclear — does not improvise architecture
264
+ - Updates \`activeContext.md\` and \`progress.md\` after completing work
265
+
266
+ ### Solo Mode
267
+
268
+ Not every task needs triangulation. For simple, well-defined changes, a single agent can act as both Architect and Executor. The Memory Bank rules still apply.
269
+
270
+ ---
271
+
272
+ ## 3. Payloads
273
+
274
+ A payload is the structured handoff from Architect to Executor.
275
+
276
+ ### Minimal Example
277
+
278
+ \`\`\`xml
279
+ <payload version="2.0">
280
+ <meta>
281
+ <intent>Goal in one line</intent>
282
+ <scope>Files affected</scope>
283
+ <priority>high | medium | low</priority>
284
+ </meta>
285
+ <tasks>
286
+ <task id="1" type="create | edit | delete">
287
+ <target>file/path</target>
288
+ <action>What to do</action>
289
+ <done>Definition of done</done>
290
+ </task>
291
+ </tasks>
292
+ <validate>
293
+ <check>How to verify success</check>
294
+ </validate>
295
+ </payload>
296
+ \`\`\`
297
+
298
+ ---
299
+
300
+ ## Quick Start
301
+
302
+ 1. Read this file (\`TOCKET.md\`)
303
+ 2. Read \`.context/activeContext.md\` for current state
304
+ 3. Read your role-specific config (\`CLAUDE.md\` or \`GEMINI.md\`)
305
+ 4. Proceed with your task, following the Memory Bank rules above
306
+ `;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,132 @@
1
+ import { describe, it } from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { claudeMd, geminiMd, tocketMd, activeContextMd, systemPatternsMd, productContextMd, techContextMd, progressMd, } from "../templates/memory-bank.js";
4
+ describe("claudeMd", () => {
5
+ const output = claudeMd("TestProject", "A test project");
6
+ it("includes the project name in the title", () => {
7
+ assert.ok(output.includes("# CLAUDE.md - TestProject"));
8
+ });
9
+ it("includes the description as a blockquote", () => {
10
+ assert.ok(output.includes("> A test project"));
11
+ });
12
+ it("defines the Executor role", () => {
13
+ assert.ok(output.includes("**Executor**"));
14
+ });
15
+ it("references the Memory Bank files", () => {
16
+ assert.ok(output.includes(".context/activeContext.md"));
17
+ assert.ok(output.includes(".context/systemPatterns.md"));
18
+ });
19
+ it("handles empty description gracefully", () => {
20
+ const noDesc = claudeMd("Foo", "");
21
+ assert.ok(noDesc.includes("# CLAUDE.md - Foo"));
22
+ assert.ok(!noDesc.includes("> \n"));
23
+ });
24
+ });
25
+ describe("geminiMd", () => {
26
+ const output = geminiMd("TestProject", "A test project");
27
+ it("includes the project name in the title", () => {
28
+ assert.ok(output.includes("# GEMINI.md - TestProject"));
29
+ });
30
+ it("defines the Architect role", () => {
31
+ assert.ok(output.includes("**Architect**"));
32
+ });
33
+ it("references payload v2.0 format", () => {
34
+ assert.ok(output.includes('<payload version="2.0">'));
35
+ });
36
+ it("does not reference the deprecated mission-brief format", () => {
37
+ assert.ok(!output.includes("<mission-brief"));
38
+ });
39
+ });
40
+ describe("tocketMd", () => {
41
+ const output = tocketMd("TestProject");
42
+ it("includes the protocol title", () => {
43
+ assert.ok(output.includes("# Tocket Protocol Specification"));
44
+ });
45
+ it("includes the project name", () => {
46
+ assert.ok(output.includes("**TestProject**"));
47
+ });
48
+ it("declares agent-agnostic stance", () => {
49
+ assert.ok(output.includes("agent-agnostic"));
50
+ });
51
+ it("documents all 5 Memory Bank files", () => {
52
+ assert.ok(output.includes("activeContext.md"));
53
+ assert.ok(output.includes("systemPatterns.md"));
54
+ assert.ok(output.includes("techContext.md"));
55
+ assert.ok(output.includes("productContext.md"));
56
+ assert.ok(output.includes("progress.md"));
57
+ });
58
+ it("documents the Triangulation pattern", () => {
59
+ assert.ok(output.includes("ARCHITECT"));
60
+ assert.ok(output.includes("EXECUTOR"));
61
+ });
62
+ it("includes a payload example with v2.0", () => {
63
+ assert.ok(output.includes('<payload version="2.0">'));
64
+ });
65
+ });
66
+ describe("activeContextMd", () => {
67
+ const output = activeContextMd("TestProject");
68
+ it("includes the project name", () => {
69
+ assert.ok(output.includes("# Active Context - TestProject"));
70
+ });
71
+ it("has the required sections", () => {
72
+ assert.ok(output.includes("## Current Focus"));
73
+ assert.ok(output.includes("## Recent Changes"));
74
+ assert.ok(output.includes("## Open Decisions"));
75
+ });
76
+ it("includes a date in the recent changes table", () => {
77
+ assert.match(output, /\d{4}-\d{2}-\d{2}/);
78
+ });
79
+ });
80
+ describe("systemPatternsMd", () => {
81
+ const output = systemPatternsMd("TestProject");
82
+ it("includes the project name", () => {
83
+ assert.ok(output.includes("# System Patterns - TestProject"));
84
+ });
85
+ it("has the required sections", () => {
86
+ assert.ok(output.includes("## Tech Stack"));
87
+ assert.ok(output.includes("## Conventions"));
88
+ assert.ok(output.includes("## Key Decisions"));
89
+ });
90
+ });
91
+ describe("productContextMd", () => {
92
+ it("includes the project name and description", () => {
93
+ const output = productContextMd("TestProject", "A cool tool");
94
+ assert.ok(output.includes("# Product Context - TestProject"));
95
+ assert.ok(output.includes("A cool tool"));
96
+ });
97
+ it("shows placeholder when description is empty", () => {
98
+ const output = productContextMd("TestProject", "");
99
+ assert.ok(output.includes("_Describe your product here._"));
100
+ });
101
+ it("has the required sections", () => {
102
+ const output = productContextMd("TestProject", "desc");
103
+ assert.ok(output.includes("## Problem"));
104
+ assert.ok(output.includes("## Solution"));
105
+ assert.ok(output.includes("## Target Users"));
106
+ });
107
+ });
108
+ describe("techContextMd", () => {
109
+ const output = techContextMd("TestProject");
110
+ it("includes the project name", () => {
111
+ assert.ok(output.includes("# Tech Context - TestProject"));
112
+ });
113
+ it("has a stack table", () => {
114
+ assert.ok(output.includes("| Language |"));
115
+ assert.ok(output.includes("| Runtime |"));
116
+ });
117
+ it("includes project structure with project name", () => {
118
+ assert.ok(output.includes("TestProject/"));
119
+ });
120
+ });
121
+ describe("progressMd", () => {
122
+ const output = progressMd("TestProject");
123
+ it("includes the project name", () => {
124
+ assert.ok(output.includes("# Progress Log - TestProject"));
125
+ });
126
+ it("has an initialization milestone marked complete", () => {
127
+ assert.ok(output.includes("**Status**: Complete"));
128
+ });
129
+ it("has a Next Up section", () => {
130
+ assert.ok(output.includes("## Next Up"));
131
+ });
132
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pedrocivita/tocket",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "The Context Engineering Framework for Multi-Agent Workspaces",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -14,7 +14,7 @@
14
14
  "build": "tsc",
15
15
  "start": "node dist/index.js",
16
16
  "prepublishOnly": "npm run build",
17
- "test": "echo \"Error: no test specified\" && exit 1"
17
+ "test": "npm run build && node --test dist/tests/*.test.js"
18
18
  },
19
19
  "repository": {
20
20
  "type": "git",