thachvd-kit 1.0.32 → 1.0.33

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
@@ -45,7 +45,17 @@ Superpowers is the primary workflow backend:
45
45
 
46
46
  For bugs, use `systematic-debugging`: reproduce, inspect, test hypotheses, add regression protection, fix the root cause, and verify.
47
47
 
48
- For a trivial one-file change with no behavior or contract change, use the client's fast path. State the narrow scope and verification before editing. If the scope grows, return to brainstorming and planning.
48
+ Fast-path eligibility is based on risk and contract surface, not file count. A localized, mechanically obvious, low-risk change with focused verification can use the client fast path; a one-file security, schema, payment, concurrency, or public-contract change should not.
49
+
50
+ ## Engineering Policy
51
+
52
+ The generated context optimizes for the **smallest sufficient change**, not the fewest lines of code.
53
+
54
+ - Preserve required behavior, product and architectural contracts, UX/accessibility, security/data integrity, compatibility/performance, and maintainability before optimizing for simplicity.
55
+ - Reuse an existing project abstraction when it satisfies the contract. Do not bypass it merely because a lower-level primitive is shorter.
56
+ - Avoid speculative abstractions and unrelated refactors.
57
+ - Do not split code solely to satisfy a hard line-count target; prefer cohesive modules and split only for a concrete design or maintenance benefit.
58
+ - Use the cheapest reliable context source. Read known local code directly; use structural tooling for unknown ownership, call paths, architecture, or impact; avoid duplicate retrieval when one source already provides enough evidence.
49
59
 
50
60
  ## Integrations
51
61
 
@@ -55,14 +65,14 @@ Install it separately for each AI client. The official guide contains the curren
55
65
 
56
66
  ### codebase-memory-mcp
57
67
 
58
- Use it for symbol search, call paths, architecture, and impact analysis:
68
+ Use it for structural discovery when symbol ownership, call paths, architecture, or impact are not already obvious:
59
69
 
60
70
  ```bash
61
71
  npm install -g codebase-memory-mcp
62
72
  codebase-memory-mcp cli index_repository --repo-path .
63
73
  ```
64
74
 
65
- The index is local state. Keep it out of git unless the team explicitly chooses to share a snapshot.
75
+ The index is local state. Keep it out of git unless the team explicitly chooses to share a snapshot. If another structural index such as CodeGraph already provides sufficient evidence, avoid querying both for the same question.
66
76
 
67
77
  ### RTK
68
78
 
package/bin/entry.js ADDED
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env node
2
+
3
+ const {
4
+ snapshotPolicyFiles,
5
+ applyPolicyUpgrades
6
+ } = require('./policy');
7
+
8
+ function isInitInvocation(args) {
9
+ if (args.includes('--help') || args.includes('-h') || args.includes('--version') || args.includes('-v')) {
10
+ return false;
11
+ }
12
+ const first = args[0];
13
+ return !first || first === 'init' || first.startsWith('-');
14
+ }
15
+
16
+ const args = process.argv.slice(2);
17
+ const shouldUpgradeGeneratedPolicy = isInitInvocation(args);
18
+ const beforeSnapshot = shouldUpgradeGeneratedPolicy ? snapshotPolicyFiles(process.cwd()) : null;
19
+ const force = args.includes('--yes') || args.includes('-y');
20
+
21
+ if (shouldUpgradeGeneratedPolicy) {
22
+ process.once('beforeExit', code => {
23
+ if (code !== 0 || (process.exitCode && process.exitCode !== 0)) return;
24
+ const changed = applyPolicyUpgrades(process.cwd(), beforeSnapshot, { force });
25
+ if (changed.length > 0) {
26
+ console.log(` OK Applied engineering quality policy to ${changed.length} generated context file(s)`);
27
+ }
28
+ });
29
+ }
30
+
31
+ require('./cli');
package/bin/policy.js ADDED
@@ -0,0 +1,196 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
4
+ const POLICY_PATHS = [
5
+ 'AGENTS.md',
6
+ '.cursorrules',
7
+ path.join('.agent', 'docs', 'conventions.md'),
8
+ path.join('.agent', 'docs', 'workflow.md'),
9
+ path.join('.agent', 'docs', 'getting-started.md'),
10
+ path.join('.agent', 'docs', 'tooling.md')
11
+ ];
12
+
13
+ const QUALITY_FLOOR_SECTION = `## Engineering Quality Floor
14
+
15
+ Prefer the smallest sufficient change, not the fewest lines of code.
16
+
17
+ A simpler implementation is acceptable only when it fully preserves:
18
+
19
+ - required behavior and acceptance criteria;
20
+ - existing product and architectural contracts;
21
+ - UX and accessibility behavior;
22
+ - security and data integrity;
23
+ - compatibility and expected performance;
24
+ - maintainability appropriate to the codebase.
25
+
26
+ Do not bypass an existing project abstraction merely because a lower-level primitive requires less code. Existing abstractions may encode product behavior and implicit requirements. Do not introduce speculative abstractions either; add complexity only when concrete requirements or codebase evidence justify it.`;
27
+
28
+ const AGENT_RULES_SECTION = `## Rules
29
+
30
+ - Respond in the user's language; keep code, identifiers, and code comments in English.
31
+ - State assumptions when the request is ambiguous.
32
+ - Prefer established project patterns and abstractions when they satisfy the required contract.
33
+ - Keep changes surgical, but never trade away required behavior, UX, accessibility, security, data integrity, compatibility, or maintainability just to reduce code.
34
+ - Do not split or reorganize code solely to satisfy a line-count target. Prefer cohesive modules with clear responsibilities; split only for a concrete cohesion, ownership, testability, or maintainability benefit.
35
+ - **Context retrieval**: use the cheapest source that can answer the question reliably. Read/search directly for a known local file or obvious local edit; use \`codebase-memory-mcp\` or another configured structural index for unknown ownership, symbol relationships, call paths, architecture, or impact; use \`context7\` for external API/docs uncertainty; use \`playwright\` for browser/UI verification. Avoid duplicate retrieval when one source already provides sufficient evidence.
36
+ - Prefer \`rtk\` by default for verbose shell commands such as git, tests, builds, package managers, Docker, and Kubernetes. Run the underlying command directly when RTK is unavailable or incompatible.
37
+ - Tests or equivalent verification are mandatory before claiming completion.`;
38
+
39
+ const CONVENTIONS_STANDARDS_SECTION = `## Current Standards
40
+
41
+ - Code comments and identifiers should be written in English.
42
+ - Keep changes scoped to the user request and preserve established local conventions.
43
+ - Prefer existing project abstractions when they satisfy the required contract; do not bypass them solely to save lines of code.
44
+ - Do not split or reorganize code solely to satisfy a line-count target. Prefer cohesive modules with clear responsibilities.
45
+ - Add abstractions only when concrete requirements or codebase evidence justify them.
46
+ - TODO: refine naming, formatting, folder, API, state, styling, and testing conventions from the real codebase.`;
47
+
48
+ const FAST_PATH_SECTION = `## Fast Path
49
+
50
+ Fast-path eligibility is based on risk and contract surface, not file count. Use it only when the change is localized, mechanically obvious, has no meaningful public API, schema, security, data-integrity, dependency, CI/release, or architectural risk, and has focused verification available. A two-file change such as code plus its focused test may still be fast-path; a one-file auth, payment, schema, concurrency, or other high-risk change is not.
51
+
52
+ State the narrow scope and verification before editing. If the task becomes ambiguous, introduces new behavior or architectural decisions, or its risk/contract surface grows, switch to brainstorming and planning.`;
53
+
54
+ const GETTING_STARTED_FAST_PATH_SECTION = `## Fast Path
55
+
56
+ Use a fast path when the change is localized, mechanically obvious, low-risk, and has focused verification. File count alone does not determine eligibility: code plus a focused test can still be trivial, while a one-file security, schema, payment, concurrency, or public-contract change requires the full workflow. If scope or risk grows, return to brainstorming and planning.`;
57
+
58
+ const TOOL_ROUTING_SECTION = `## Tool Routing
59
+
60
+ Use the cheapest source that can answer the question reliably and avoid retrieving the same evidence twice.
61
+
62
+ - Known local file or obvious local edit: read/search directly.
63
+ - Unknown ownership, symbol relationships, call paths, architecture, or impact: use \`codebase-memory-mcp\` or another configured structural index such as CodeGraph.
64
+ - External library/API uncertainty: use Context7.
65
+ - Browser/UI behavior: use Playwright.
66
+ - Noisy shell output: prefer RTK.
67
+
68
+ Structural tools are aids, not mandatory ceremony. If direct evidence is already sufficient, do not call extra MCP tools just because they are available.`;
69
+
70
+ function normalizeNewlines(text) {
71
+ return String(text || '').replace(/\r\n/g, '\n');
72
+ }
73
+
74
+ function replaceSection(markdown, heading, replacement) {
75
+ const text = normalizeNewlines(markdown);
76
+ const marker = `${heading}\n`;
77
+ const start = text.indexOf(marker);
78
+ if (start < 0) return text;
79
+
80
+ const searchFrom = start + marker.length;
81
+ const nextHeading = text.indexOf('\n## ', searchFrom);
82
+ const end = nextHeading >= 0 ? nextHeading + 1 : text.length;
83
+ const prefix = text.slice(0, start);
84
+ const suffix = text.slice(end).replace(/^\n+/, '');
85
+ return `${prefix}${replacement.trimEnd()}\n\n${suffix}`.replace(/\n{3,}/g, '\n\n');
86
+ }
87
+
88
+ function insertSectionBefore(markdown, beforeHeading, section) {
89
+ const text = normalizeNewlines(markdown);
90
+ const sectionHeading = section.split('\n', 1)[0];
91
+ if (text.includes(`${sectionHeading}\n`)) return text;
92
+
93
+ const marker = `${beforeHeading}\n`;
94
+ const index = text.indexOf(marker);
95
+ if (index < 0) return `${text.trimEnd()}\n\n${section.trimEnd()}\n`;
96
+ return `${text.slice(0, index)}${section.trimEnd()}\n\n${text.slice(index)}`;
97
+ }
98
+
99
+ function replaceFastPathInline(markdown) {
100
+ return normalizeNewlines(markdown)
101
+ .replace(
102
+ 'Questions and research do not edit product code. A simple fix may use a fast path only when it is one-file, unambiguous, and changes no behavior or contract. State the scope and verification before editing. If the scope grows, switch to the full Superpowers flow.',
103
+ 'Questions and research do not edit product code. A fast path is allowed only when the change is localized, mechanically obvious, low-risk, and has focused verification; file count alone is not a gate. State the scope and verification before editing. If the task becomes ambiguous or its behavior, contract, or risk surface grows, switch to the full Superpowers flow.'
104
+ )
105
+ .replace(
106
+ 'Questions and research do not edit product code. A simple fix may use a fast path only when it is one-file, unambiguous, and changes no behavior or contract. State the narrow scope and verification before editing. If the scope grows, return to brainstorming and planning.',
107
+ 'Questions and research do not edit product code. A fast path is allowed only when the change is localized, mechanically obvious, low-risk, and has focused verification; file count alone is not a gate. State the narrow scope and verification before editing. If scope or risk grows, return to brainstorming and planning.'
108
+ );
109
+ }
110
+
111
+ function upgradeAgentsMarkdown(markdown) {
112
+ let text = replaceFastPathInline(markdown);
113
+ text = insertSectionBefore(text, '## Rules', QUALITY_FLOOR_SECTION);
114
+ text = replaceSection(text, '## Rules', AGENT_RULES_SECTION);
115
+ return text.trimEnd() + '\n';
116
+ }
117
+
118
+ function upgradeConventionsMarkdown(markdown) {
119
+ let text = replaceSection(markdown, '## Current Standards', CONVENTIONS_STANDARDS_SECTION);
120
+ text = insertSectionBefore(text, '## Verification', QUALITY_FLOOR_SECTION);
121
+ return text.trimEnd() + '\n';
122
+ }
123
+
124
+ function upgradeWorkflowMarkdown(markdown) {
125
+ return replaceSection(markdown, '## Fast Path', FAST_PATH_SECTION).trimEnd() + '\n';
126
+ }
127
+
128
+ function upgradeGettingStartedMarkdown(markdown) {
129
+ return replaceSection(markdown, '## Fast Path', GETTING_STARTED_FAST_PATH_SECTION).trimEnd() + '\n';
130
+ }
131
+
132
+ function upgradeToolingMarkdown(markdown) {
133
+ const text = normalizeNewlines(markdown);
134
+ const targetHeading = text.includes('## Codebase Memory MCP\n')
135
+ ? '## Codebase Memory MCP'
136
+ : '## codebase-memory-mcp';
137
+ return insertSectionBefore(text, targetHeading, TOOL_ROUTING_SECTION).trimEnd() + '\n';
138
+ }
139
+
140
+ function upgradeGeneratedContent(relativePath, content) {
141
+ const normalized = relativePath.split(path.sep).join('/');
142
+ if (normalized === 'AGENTS.md' || normalized === '.cursorrules') return upgradeAgentsMarkdown(content);
143
+ if (normalized.endsWith('/conventions.md')) return upgradeConventionsMarkdown(content);
144
+ if (normalized.endsWith('/workflow.md')) return upgradeWorkflowMarkdown(content);
145
+ if (normalized.endsWith('/getting-started.md')) return upgradeGettingStartedMarkdown(content);
146
+ if (normalized.endsWith('/tooling.md')) return upgradeToolingMarkdown(content);
147
+ return normalizeNewlines(content);
148
+ }
149
+
150
+ function snapshotPolicyFiles(rootDir) {
151
+ const snapshot = new Map();
152
+ for (const relativePath of POLICY_PATHS) {
153
+ const fullPath = path.join(rootDir, relativePath);
154
+ snapshot.set(relativePath, fs.existsSync(fullPath) ? fs.readFileSync(fullPath, 'utf8') : null);
155
+ }
156
+ return snapshot;
157
+ }
158
+
159
+ function applyPolicyUpgrades(rootDir, beforeSnapshot, options = {}) {
160
+ const force = options.force === true;
161
+ const changed = [];
162
+
163
+ for (const relativePath of POLICY_PATHS) {
164
+ const fullPath = path.join(rootDir, relativePath);
165
+ if (!fs.existsSync(fullPath)) continue;
166
+
167
+ const current = fs.readFileSync(fullPath, 'utf8');
168
+ const before = beforeSnapshot ? beforeSnapshot.get(relativePath) : null;
169
+ const wasWritten = force || before === null || before !== current;
170
+ if (!wasWritten) continue;
171
+
172
+ const upgraded = upgradeGeneratedContent(relativePath, current);
173
+ if (upgraded !== normalizeNewlines(current)) {
174
+ fs.writeFileSync(fullPath, upgraded, 'utf8');
175
+ changed.push(relativePath);
176
+ }
177
+ }
178
+
179
+ return changed;
180
+ }
181
+
182
+ module.exports = {
183
+ POLICY_PATHS,
184
+ QUALITY_FLOOR_SECTION,
185
+ AGENT_RULES_SECTION,
186
+ FAST_PATH_SECTION,
187
+ TOOL_ROUTING_SECTION,
188
+ upgradeGeneratedContent,
189
+ upgradeAgentsMarkdown,
190
+ upgradeConventionsMarkdown,
191
+ upgradeWorkflowMarkdown,
192
+ upgradeGettingStartedMarkdown,
193
+ upgradeToolingMarkdown,
194
+ snapshotPolicyFiles,
195
+ applyPolicyUpgrades
196
+ };
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "thachvd-kit",
3
- "version": "1.0.32",
3
+ "version": "1.0.33",
4
4
  "description": "Cross-agent project rules bootstrap kit for Codex, Antigravity, and Claude Code",
5
5
  "bin": {
6
- "thachvd-kit": "./bin/cli.js"
6
+ "thachvd-kit": "./bin/entry.js"
7
7
  },
8
8
  "files": [
9
9
  "bin",
@@ -15,8 +15,8 @@
15
15
  "node": ">=16.7"
16
16
  },
17
17
  "scripts": {
18
- "test": "node test/cli.test.js",
19
- "release:verify": "npm test && node --check bin/cli.js && npm pack --dry-run",
18
+ "test": "node test/cli.test.js && node test/policy.test.js",
19
+ "release:verify": "npm test && node --check bin/cli.js && node --check bin/entry.js && node --check bin/policy.js && npm pack --dry-run",
20
20
  "preversion": "npm run release:verify",
21
21
  "release:patch": "npm version patch",
22
22
  "release:dry-run": "npm pack --dry-run",