minimal-vibe-coding-kit 0.5.0 → 0.5.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/.agents/skills/tutien/SKILL.md +36 -13
- package/.agents/skills/tutien/references/adaptive-response.md +68 -0
- package/.agents/skills/tutien/references/lore-sources.md +28 -0
- package/.agents/skills/tutien/references/privacy.md +13 -1
- package/.agents/skills/tutien/references/schema.md +32 -1
- package/.agents/skills/tutien/references/story-system.md +176 -0
- package/.agents/skills/tutien/references/vi-style-guide.md +89 -0
- package/.agents/skills/tutien/references/voice-and-mode.md +23 -8
- package/.agents/skills/tutien/scripts/catalog.mjs +17 -17
- package/.agents/skills/tutien/scripts/classify.mjs +64 -37
- package/.agents/skills/tutien/scripts/command.mjs +40 -21
- package/.agents/skills/tutien/scripts/project-profile.mjs +202 -0
- package/.agents/skills/tutien/scripts/render-report.mjs +128 -72
- package/.agents/skills/tutien/scripts/response-brief.mjs +103 -0
- package/.agents/skills/tutien/scripts/run-tutien.mjs +141 -63
- package/.agents/skills/tutien/scripts/story-ledger.mjs +241 -0
- package/.agents/skills/tutien/scripts/villains.mjs +14 -14
- package/.claude/skills/tutien/SKILL.md +36 -13
- package/.claude/skills/tutien/references/adaptive-response.md +68 -0
- package/.claude/skills/tutien/references/lore-sources.md +28 -0
- package/.claude/skills/tutien/references/privacy.md +13 -1
- package/.claude/skills/tutien/references/schema.md +32 -1
- package/.claude/skills/tutien/references/story-system.md +176 -0
- package/.claude/skills/tutien/references/vi-style-guide.md +89 -0
- package/.claude/skills/tutien/references/voice-and-mode.md +23 -8
- package/.claude/skills/tutien/scripts/catalog.mjs +17 -17
- package/.claude/skills/tutien/scripts/classify.mjs +64 -37
- package/.claude/skills/tutien/scripts/command.mjs +40 -21
- package/.claude/skills/tutien/scripts/project-profile.mjs +202 -0
- package/.claude/skills/tutien/scripts/render-report.mjs +128 -72
- package/.claude/skills/tutien/scripts/response-brief.mjs +103 -0
- package/.claude/skills/tutien/scripts/run-tutien.mjs +141 -63
- package/.claude/skills/tutien/scripts/story-ledger.mjs +241 -0
- package/.claude/skills/tutien/scripts/villains.mjs +14 -14
- package/.codex-plugin/plugin.json +1 -1
- package/.cursor/skills/tutien/SKILL.md +36 -13
- package/.cursor/skills/tutien/references/adaptive-response.md +68 -0
- package/.cursor/skills/tutien/references/lore-sources.md +28 -0
- package/.cursor/skills/tutien/references/privacy.md +13 -1
- package/.cursor/skills/tutien/references/schema.md +32 -1
- package/.cursor/skills/tutien/references/story-system.md +176 -0
- package/.cursor/skills/tutien/references/vi-style-guide.md +89 -0
- package/.cursor/skills/tutien/references/voice-and-mode.md +23 -8
- package/.cursor/skills/tutien/scripts/catalog.mjs +17 -17
- package/.cursor/skills/tutien/scripts/classify.mjs +64 -37
- package/.cursor/skills/tutien/scripts/command.mjs +40 -21
- package/.cursor/skills/tutien/scripts/project-profile.mjs +202 -0
- package/.cursor/skills/tutien/scripts/render-report.mjs +128 -72
- package/.cursor/skills/tutien/scripts/response-brief.mjs +103 -0
- package/.cursor/skills/tutien/scripts/run-tutien.mjs +141 -63
- package/.cursor/skills/tutien/scripts/story-ledger.mjs +241 -0
- package/.cursor/skills/tutien/scripts/villains.mjs +14 -14
- package/.grok/skills/tutien/SKILL.md +36 -13
- package/.grok/skills/tutien/references/adaptive-response.md +68 -0
- package/.grok/skills/tutien/references/lore-sources.md +28 -0
- package/.grok/skills/tutien/references/privacy.md +13 -1
- package/.grok/skills/tutien/references/schema.md +32 -1
- package/.grok/skills/tutien/references/story-system.md +176 -0
- package/.grok/skills/tutien/references/vi-style-guide.md +89 -0
- package/.grok/skills/tutien/references/voice-and-mode.md +23 -8
- package/.grok/skills/tutien/scripts/catalog.mjs +17 -17
- package/.grok/skills/tutien/scripts/classify.mjs +64 -37
- package/.grok/skills/tutien/scripts/command.mjs +40 -21
- package/.grok/skills/tutien/scripts/project-profile.mjs +202 -0
- package/.grok/skills/tutien/scripts/render-report.mjs +128 -72
- package/.grok/skills/tutien/scripts/response-brief.mjs +103 -0
- package/.grok/skills/tutien/scripts/run-tutien.mjs +141 -63
- package/.grok/skills/tutien/scripts/story-ledger.mjs +241 -0
- package/.grok/skills/tutien/scripts/villains.mjs +14 -14
- package/.vibekit/skills/tutien/SKILL.md +36 -13
- package/.vibekit/skills/tutien/references/adaptive-response.md +68 -0
- package/.vibekit/skills/tutien/references/lore-sources.md +28 -0
- package/.vibekit/skills/tutien/references/privacy.md +13 -1
- package/.vibekit/skills/tutien/references/schema.md +32 -1
- package/.vibekit/skills/tutien/references/story-system.md +176 -0
- package/.vibekit/skills/tutien/references/vi-style-guide.md +89 -0
- package/.vibekit/skills/tutien/references/voice-and-mode.md +23 -8
- package/.vibekit/skills/tutien/scripts/catalog.mjs +17 -17
- package/.vibekit/skills/tutien/scripts/classify.mjs +64 -37
- package/.vibekit/skills/tutien/scripts/command.mjs +40 -21
- package/.vibekit/skills/tutien/scripts/project-profile.mjs +202 -0
- package/.vibekit/skills/tutien/scripts/render-report.mjs +128 -72
- package/.vibekit/skills/tutien/scripts/response-brief.mjs +103 -0
- package/.vibekit/skills/tutien/scripts/run-tutien.mjs +141 -63
- package/.vibekit/skills/tutien/scripts/story-ledger.mjs +241 -0
- package/.vibekit/skills/tutien/scripts/villains.mjs +14 -14
- package/CHANGELOG.md +22 -1
- package/README.md +5 -3
- package/docs/README.vi.md +5 -3
- package/docs/README.zh-CN.md +5 -3
- package/package.json +2 -2
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Deterministic storage helpers for the agent-authored living chronicle.
|
|
3
|
+
// This module never generates story prose. It only builds an aggregate-only
|
|
4
|
+
// evidence packet and validates the plot/chapter ledger written by the agent.
|
|
5
|
+
|
|
6
|
+
import crypto from 'node:crypto';
|
|
7
|
+
import fs from 'node:fs';
|
|
8
|
+
import path from 'node:path';
|
|
9
|
+
import process from 'node:process';
|
|
10
|
+
import { fileURLToPath } from 'node:url';
|
|
11
|
+
|
|
12
|
+
export const STORY_SCHEMA = 1;
|
|
13
|
+
export const STORY_CONTEXT_SCHEMA = 'tutien-story-context-v1';
|
|
14
|
+
export const STORY_STATE_SCHEMA = 'tutien-story-state-v1';
|
|
15
|
+
export const STORY_CHAPTER_SCHEMA = 'tutien-story-chapter-v1';
|
|
16
|
+
|
|
17
|
+
const sha16 = (value) => crypto.createHash('sha256').update(String(value)).digest('hex').slice(0, 16);
|
|
18
|
+
|
|
19
|
+
export function storyPaths(root = process.cwd()) {
|
|
20
|
+
const base = path.join(path.resolve(root), '.vibekit', 'reports', 'tutien', 'story');
|
|
21
|
+
return {
|
|
22
|
+
base,
|
|
23
|
+
plot: path.join(base, 'plot.md'),
|
|
24
|
+
state: path.join(base, 'story-state.json'),
|
|
25
|
+
context: path.join(base, 'latest-context.json'),
|
|
26
|
+
chapters: path.join(base, 'chapters')
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Preserve letters from every language, including Han characters. Latin
|
|
31
|
+
// scripts are normalized so Vietnamese titles remain readable in filenames.
|
|
32
|
+
export function slugifyChapterTitle(title) {
|
|
33
|
+
const raw = String(title ?? '').trim();
|
|
34
|
+
if (!raw) throw new Error('chapter title is required');
|
|
35
|
+
const slug = raw
|
|
36
|
+
.normalize('NFD')
|
|
37
|
+
.replace(/\p{M}+/gu, '')
|
|
38
|
+
.toLocaleLowerCase('und')
|
|
39
|
+
.replace(/[^\p{L}\p{N}]+/gu, '-')
|
|
40
|
+
.replace(/^-+|-+$/g, '')
|
|
41
|
+
.slice(0, 80)
|
|
42
|
+
.replace(/-+$/g, '');
|
|
43
|
+
if (!slug || slug === '.' || slug === '..') throw new Error('chapter title does not produce a safe filename');
|
|
44
|
+
return slug;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function chapterFilename(number, title) {
|
|
48
|
+
if (!Number.isInteger(number) || number < 1 || number > 9999) {
|
|
49
|
+
throw new Error('chapter number must be an integer from 1 to 9999');
|
|
50
|
+
}
|
|
51
|
+
return `${String(number).padStart(4, '0')}-${slugifyChapterTitle(title)}.md`;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function listChapters(root = process.cwd()) {
|
|
55
|
+
const dir = storyPaths(root).chapters;
|
|
56
|
+
if (!fs.existsSync(dir)) return [];
|
|
57
|
+
return fs.readdirSync(dir)
|
|
58
|
+
.filter((file) => /^\d{4}-[\p{L}\p{N}][\p{L}\p{N}-]*\.md$/u.test(file))
|
|
59
|
+
.map((file) => ({ file, number: Number(file.slice(0, 4)), path: path.join(dir, file) }))
|
|
60
|
+
.sort((a, b) => a.number - b.number || a.file.localeCompare(b.file));
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function nextChapterNumber(root = process.cwd()) {
|
|
64
|
+
const chapters = listChapters(root);
|
|
65
|
+
return chapters.length ? chapters[chapters.length - 1].number + 1 : 1;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function resolveStoryLanguage(requested = 'auto', invocationText = '', fallback = 'en') {
|
|
69
|
+
const explicit = String(requested).toLowerCase();
|
|
70
|
+
if (['vi', 'en', 'zh'].includes(explicit)) return explicit;
|
|
71
|
+
if (/\p{Script=Han}/u.test(invocationText)) return 'zh';
|
|
72
|
+
if (/[À-ỹĐđ]/u.test(invocationText) || /\b(hãy|giúp|của|và|không|chương|tu tiên)\b/iu.test(invocationText)) return 'vi';
|
|
73
|
+
return ['vi', 'en', 'zh'].includes(fallback) ? fallback : 'en';
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function safeSlug(value, fallback = null) {
|
|
77
|
+
const text = String(value ?? '');
|
|
78
|
+
return /^[a-z0-9][a-z0-9_-]{0,63}$/i.test(text) ? text : fallback;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function safeValidationCommand(value) {
|
|
82
|
+
const text = String(value ?? '');
|
|
83
|
+
return /^(?:npm run|yarn|pnpm|bun run) [A-Za-z0-9][A-Za-z0-9:_-]{0,63}$/.test(text) ? text : null;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function storyFacts(model, profile = {}) {
|
|
87
|
+
const cultivation = model.cultivation ?? null;
|
|
88
|
+
const progression = cultivation?.progression ?? null;
|
|
89
|
+
return {
|
|
90
|
+
project: {
|
|
91
|
+
id: safeSlug(profile.projectId, 'repo'),
|
|
92
|
+
type: safeSlug(profile.projectType),
|
|
93
|
+
primaryLanguage: safeSlug(profile.primaryLanguage),
|
|
94
|
+
domains: (profile.domains ?? []).map((v) => safeSlug(v)).filter(Boolean).slice(0, 12),
|
|
95
|
+
stack: (profile.stack ?? []).map((v) => safeSlug(v)).filter(Boolean).slice(0, 12),
|
|
96
|
+
validationCommands: (profile.validationCommands ?? []).map((v) => safeValidationCommand(v)).filter(Boolean).slice(0, 3),
|
|
97
|
+
metadataSources: (profile.metadataSources ?? []).map((v) => safeSlug(String(v).replace(/\.[^.]+$/, ''))).filter(Boolean).slice(0, 12),
|
|
98
|
+
authorsCount: Number.isInteger(profile.authorsCount) && profile.authorsCount >= 0 ? profile.authorsCount : null
|
|
99
|
+
},
|
|
100
|
+
evidence: {
|
|
101
|
+
window: model.coverage?.window ?? { start: null, end: null },
|
|
102
|
+
sessions: model.coverage?.sessions ?? 0,
|
|
103
|
+
prompts: model.coverage?.userPrompts ?? 0,
|
|
104
|
+
commits: model.coverage?.commits ?? 0,
|
|
105
|
+
confidence: model.coverage?.confidence ?? 'low',
|
|
106
|
+
tokens: {
|
|
107
|
+
reported: model.tokens?.reportedTotal ?? 0,
|
|
108
|
+
estimated: model.tokens?.estimatedTotal ?? 0,
|
|
109
|
+
unknownTurns: model.tokens?.unknownTurns ?? 0
|
|
110
|
+
},
|
|
111
|
+
realm: model.realm ? { name: model.realm.name, score: model.score } : null,
|
|
112
|
+
problems: (model.problems ?? []).map((p) => ({
|
|
113
|
+
type: p.problemType,
|
|
114
|
+
confidence: p.confidence,
|
|
115
|
+
priority: p.priority
|
|
116
|
+
})),
|
|
117
|
+
classification: cultivation ? {
|
|
118
|
+
faction: cultivation.classification?.faction?.id ?? null,
|
|
119
|
+
affiliation: cultivation.classification?.affiliation?.id ?? null,
|
|
120
|
+
paths: (cultivation.classification?.paths ?? []).map((p) => p.id)
|
|
121
|
+
} : null,
|
|
122
|
+
progression: progression ? {
|
|
123
|
+
tuVi: progression.tuVi?.window ?? 0,
|
|
124
|
+
congDuc: progression.congDuc?.window ?? 0,
|
|
125
|
+
nghiepLuc: progression.nghiepLuc?.window ?? 0,
|
|
126
|
+
daoHanhWindows: progression.daoHanh?.windows ?? 0,
|
|
127
|
+
overlap: progression.overlap ?? 0
|
|
128
|
+
} : null
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export function buildStoryContext(model, options = {}) {
|
|
134
|
+
const facts = storyFacts(model, options.profile ?? {});
|
|
135
|
+
const evidenceKey = sha16(JSON.stringify({
|
|
136
|
+
storySchema: STORY_SCHEMA,
|
|
137
|
+
project: facts.project.id,
|
|
138
|
+
range: options.range ?? 'all',
|
|
139
|
+
evidence: facts.evidence
|
|
140
|
+
}));
|
|
141
|
+
return {
|
|
142
|
+
schema: STORY_CONTEXT_SCHEMA,
|
|
143
|
+
storySchema: STORY_SCHEMA,
|
|
144
|
+
evidenceKey,
|
|
145
|
+
language: resolveStoryLanguage(options.language, options.invocationText, options.conversationLanguage),
|
|
146
|
+
style: safeSlug(options.style, 'auto'),
|
|
147
|
+
focus: safeSlug(options.focus, 'balanced'),
|
|
148
|
+
policyState: model.policyState ?? 'clear',
|
|
149
|
+
canWriteChapter: model.suppressGamification !== true,
|
|
150
|
+
...facts
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export function writeStoryContext(root, context) {
|
|
155
|
+
if (context?.schema !== STORY_CONTEXT_SCHEMA) throw new Error(`story context must use ${STORY_CONTEXT_SCHEMA}`);
|
|
156
|
+
const paths = storyPaths(root);
|
|
157
|
+
fs.mkdirSync(paths.base, { recursive: true });
|
|
158
|
+
fs.writeFileSync(paths.context, `${JSON.stringify(context, null, 2)}\n`);
|
|
159
|
+
return paths.context;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function chapterFrontmatter(text) {
|
|
163
|
+
const match = String(text).match(/^---\n([\s\S]*?)\n---\n/);
|
|
164
|
+
if (!match) return null;
|
|
165
|
+
const get = (key) => match[1].match(new RegExp(`^${key}:\\s*(.+)$`, 'm'))?.[1]?.trim().replace(/^['"]|['"]$/g, '') ?? null;
|
|
166
|
+
return {
|
|
167
|
+
schema: get('schema'),
|
|
168
|
+
chapter: Number(get('chapter')),
|
|
169
|
+
title: get('title'),
|
|
170
|
+
evidenceKey: get('evidence_key')
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export function validateStoryTree(root = process.cwd()) {
|
|
175
|
+
const paths = storyPaths(root);
|
|
176
|
+
const chapters = listChapters(root);
|
|
177
|
+
const errors = [];
|
|
178
|
+
if (chapters.length && !fs.existsSync(paths.plot)) errors.push('plot.md is required when chapters exist');
|
|
179
|
+
|
|
180
|
+
let state = null;
|
|
181
|
+
if (fs.existsSync(paths.state)) {
|
|
182
|
+
try {
|
|
183
|
+
state = JSON.parse(fs.readFileSync(paths.state, 'utf8'));
|
|
184
|
+
if (state.schema !== STORY_STATE_SCHEMA) errors.push(`story-state.json must use ${STORY_STATE_SCHEMA}`);
|
|
185
|
+
} catch {
|
|
186
|
+
errors.push('story-state.json must contain valid JSON');
|
|
187
|
+
}
|
|
188
|
+
} else if (chapters.length) {
|
|
189
|
+
errors.push('story-state.json is required when chapters exist');
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const evidenceKeys = new Set();
|
|
193
|
+
for (let i = 0; i < chapters.length; i += 1) {
|
|
194
|
+
const expected = i + 1;
|
|
195
|
+
const item = chapters[i];
|
|
196
|
+
if (item.number !== expected) errors.push(`chapter sequence must be contiguous: expected ${expected}, found ${item.number}`);
|
|
197
|
+
const fm = chapterFrontmatter(fs.readFileSync(item.path, 'utf8'));
|
|
198
|
+
if (!fm) {
|
|
199
|
+
errors.push(`${item.file} is missing YAML frontmatter`);
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
if (fm.schema !== STORY_CHAPTER_SCHEMA) errors.push(`${item.file} must use ${STORY_CHAPTER_SCHEMA}`);
|
|
203
|
+
if (fm.chapter !== item.number) errors.push(`${item.file} frontmatter chapter must equal ${item.number}`);
|
|
204
|
+
if (!fm.title) errors.push(`${item.file} requires a title`);
|
|
205
|
+
if (!fm.evidenceKey || !/^[0-9a-f]{16}$/.test(fm.evidenceKey)) errors.push(`${item.file} requires a 16-hex evidence_key`);
|
|
206
|
+
else if (evidenceKeys.has(fm.evidenceKey)) errors.push(`${item.file} repeats evidence_key ${fm.evidenceKey}`);
|
|
207
|
+
else evidenceKeys.add(fm.evidenceKey);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
if (state) {
|
|
211
|
+
if (state.lastChapter !== chapters.length) errors.push(`story-state.json lastChapter must equal ${chapters.length}`);
|
|
212
|
+
const consumed = state.consumedEvidenceKeys ?? [];
|
|
213
|
+
if (!Array.isArray(consumed) || consumed.some((key) => !/^[0-9a-f]{16}$/.test(key))) {
|
|
214
|
+
errors.push('story-state.json consumedEvidenceKeys must be an array of 16-hex keys');
|
|
215
|
+
}
|
|
216
|
+
for (const key of evidenceKeys) {
|
|
217
|
+
if (!consumed.includes(key)) errors.push(`story-state.json is missing consumed evidence key ${key}`);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
return {
|
|
222
|
+
ok: errors.length === 0,
|
|
223
|
+
errors,
|
|
224
|
+
chapters: chapters.length,
|
|
225
|
+
nextChapter: chapters.length + 1,
|
|
226
|
+
paths: Object.fromEntries(Object.entries(paths).map(([key, value]) => [key, path.relative(path.resolve(root), value)]))
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const isMain = process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url);
|
|
231
|
+
if (isMain) {
|
|
232
|
+
const command = process.argv[2] ?? 'status';
|
|
233
|
+
const root = path.resolve(process.argv[3] ?? process.cwd());
|
|
234
|
+
if (!['status', 'validate'].includes(command)) {
|
|
235
|
+
console.error('usage: story-ledger.mjs [status|validate] [repo-root]');
|
|
236
|
+
process.exit(2);
|
|
237
|
+
}
|
|
238
|
+
const result = validateStoryTree(root);
|
|
239
|
+
console.log(JSON.stringify(result, null, 2));
|
|
240
|
+
if (command === 'validate' && !result.ok) process.exit(1);
|
|
241
|
+
}
|
|
@@ -60,22 +60,22 @@ export function sanitizeContext(ctx = {}) {
|
|
|
60
60
|
const LINES = {
|
|
61
61
|
'repeated-failure': {
|
|
62
62
|
serene: [
|
|
63
|
-
{ vi: 'Giữa làn sương mỏng, Luân Hồi
|
|
64
|
-
{ vi: 'Một lần thử giống hệt khẽ lay chuông, gọi Luân Hồi
|
|
63
|
+
{ vi: 'Giữa làn sương mỏng, Luân Hồi Ma Ảnh hiện bóng khi lỗi cũ quay thêm một vòng.', en: 'In the thin mountain mist, the Error-Cycle Wraith appears as the old error completes another circle.' },
|
|
64
|
+
{ vi: 'Một lần thử giống hệt khẽ lay chuông, gọi Luân Hồi Ma Ảnh trở lại đạo lộ.', en: 'One unchanged retry stirs the bell that calls the Error-Cycle Wraith back to the path.' }
|
|
65
65
|
],
|
|
66
66
|
spirited: [
|
|
67
|
-
{ vi: 'Luân Hồi
|
|
68
|
-
{ vi: 'Vòng lặp cũ vừa khép, Luân Hồi
|
|
67
|
+
{ vi: 'Luân Hồi Ma Ảnh lại gõ chuông: “Không đổi giả thuyết, sao đổi được kết cục?”', en: 'The Error-Cycle Wraith rings its bell again: “Without a new hypothesis, what new ending could appear?”' },
|
|
68
|
+
{ vi: 'Vòng lặp cũ vừa khép, Luân Hồi Ma Ảnh đã bày sẵn bàn trà chờ vòng kế tiếp.', en: 'The old loop has barely closed, and the Error-Cycle Wraith has already set tea for the next.' }
|
|
69
69
|
]
|
|
70
70
|
},
|
|
71
71
|
'too-many-prompts': {
|
|
72
72
|
serene: [
|
|
73
|
-
{ vi: 'Cửu Hoàn Tâm Ma dệt một
|
|
74
|
-
{ vi: 'Nơi ranh giới
|
|
73
|
+
{ vi: 'Cửu Hoàn Tâm Ma dệt một nhiệm vụ thành nhiều vòng sương khi cột mốc chưa hiện rõ.', en: 'The Ninefold Loop Heart-Shadow weaves one task into rings of mist when its checkpoints remain unclear.' },
|
|
74
|
+
{ vi: 'Nơi ranh giới nhiệm vụ nhạt dần, Cửu Hoàn Tâm Ma lặng lẽ nối thêm một vòng.', en: 'Where a task boundary fades, the Ninefold Loop Heart-Shadow quietly adds another circle.' }
|
|
75
75
|
],
|
|
76
76
|
spirited: [
|
|
77
|
-
{ vi: 'Cửu Hoàn Tâm Ma đếm
|
|
78
|
-
{ vi: '
|
|
77
|
+
{ vi: 'Cửu Hoàn Tâm Ma đếm lượt yêu cầu thay cột mốc; đã đến lúc đổi chiếc vòng kế tiếp thành một tiêu chí hoàn thành.', en: 'The Ninefold Loop Heart-Shadow is counting prompts instead of checkpoints; turn the next circle into a done-criterion.' },
|
|
78
|
+
{ vi: 'Lượt yêu cầu càng tản như lá thu, Cửu Hoàn Tâm Ma càng dễ giấu mất lối ra.', en: 'The more prompts scatter like autumn leaves, the easier the Ninefold Loop Heart-Shadow hides the exit.' }
|
|
79
79
|
]
|
|
80
80
|
},
|
|
81
81
|
'conflicting-instructions': {
|
|
@@ -90,21 +90,21 @@ const LINES = {
|
|
|
90
90
|
},
|
|
91
91
|
'unrecovered-failure': {
|
|
92
92
|
serene: [
|
|
93
|
-
{ vi: 'Vô
|
|
94
|
-
{ vi: 'Một lỗi bị bỏ lại làm bóng Vô
|
|
93
|
+
{ vi: 'Vô Nghiệm Ảnh Quân ẩn sau một thất bại chưa được soi lại bằng lần kiểm chứng mới.', en: 'The Unverified Trial Wraith rests behind a failure that has not yet met a fresh validation.' },
|
|
94
|
+
{ vi: 'Một lỗi bị bỏ lại làm bóng Vô Nghiệm Ảnh Quân dài thêm trên bậc đá.', en: 'A failure left behind lengthens the Unverified Trial Wraith’s shadow across the stone steps.' }
|
|
95
95
|
],
|
|
96
96
|
spirited: [
|
|
97
|
-
{ vi: 'Vô
|
|
98
|
-
{ vi: 'Chưa có lần chạy lại, Vô
|
|
97
|
+
{ vi: 'Vô Nghiệm Ảnh Quân phủi bụi trên ghế đá: một lần kiểm chứng thành công là đủ để mời nó rời đi.', en: 'The Unverified Trial Wraith dusts its stone seat; one passing validation is enough to send it on its way.' },
|
|
98
|
+
{ vi: 'Chưa có lần chạy lại, Vô Nghiệm Ảnh Quân vẫn ung dung giữ chỗ bên cổng hoàn thành.', en: 'Without a rerun, the Unverified Trial Wraith calmly keeps its seat beside the completion gate.' }
|
|
99
99
|
]
|
|
100
100
|
},
|
|
101
101
|
'work-without-proof': {
|
|
102
102
|
serene: [
|
|
103
103
|
{ vi: 'Vô Chứng Đan Ảnh lảng vảng bên lò luyện khi lời tuyên bố hoàn thành chưa có bằng chứng đi cùng.', en: 'The Proofless Elixir Shade lingers by the furnace when a claim of completion carries no evidence.' },
|
|
104
|
-
{ vi: 'Một
|
|
104
|
+
{ vi: 'Một bản ghi Git thiếu kết quả kiểm chứng để lại làn khói mỏng cho Vô Chứng Đan Ảnh nương thân.', en: 'A commit without validation leaves a thread of smoke where the Proofless Elixir Shade can dwell.' }
|
|
105
105
|
],
|
|
106
106
|
spirited: [
|
|
107
|
-
{ vi: 'Vô Chứng Đan Ảnh nâng chén trà bên viên đan chưa thử; một dòng
|
|
107
|
+
{ vi: 'Vô Chứng Đan Ảnh nâng chén trà bên viên đan chưa thử; một dòng kiểm chứng sẽ làm màn khói tan ngay.', en: 'The Proofless Elixir Shade raises tea beside an untested pill; one validation line will clear the smoke.' },
|
|
108
108
|
{ vi: 'Không có biên nhận kiểm chứng, Vô Chứng Đan Ảnh cứ ngỡ lò luyện thuộc về mình.', en: 'Without a validation receipt, the Proofless Elixir Shade starts to think the furnace is its own.' }
|
|
109
109
|
]
|
|
110
110
|
}
|
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,27 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## 0.5.1 — 2026-07-22
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- Added a `/tutien` living chronicle that turns each repository's approved aggregate Git, token, classification, and progression evidence into an open-ended agent-authored xianxia serial. Each project keeps a local `plot.md`, continuity state, aggregate-only context, and one ordered chapter file per distinct evidence window under the git-ignored `.vibekit/reports/tutien/story/` directory.
|
|
8
|
+
- Added equal chronicle support for Vietnamese, English, and Simplified Chinese, including language-native xianxia naming, honorifics, dialogue cadence, humor, chapter titles, and safely sarcastic antagonists whose malice targets workflow weaknesses rather than people.
|
|
9
|
+
- Added `story-ledger.mjs` and deterministic tests for multilingual filenames, aggregate-only context, contiguous chapters, duplicate evidence rejection, and story transaction validation.
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
|
|
13
|
+
- Reframed `/tutien` story writing as an evidence-plus-agent hybrid: deterministic scripts preserve facts and privacy, while agents create project-specific plots, characters, sects, realms, techniques, and dialogue without relying on fixed story sentences.
|
|
14
|
+
- Replaced the fixed report-shaped default response with an aggregate-only `latest-brief.json` handoff. It detects safe project anchors from known manifests, recommends real repository validation commands, and leaves structure, pacing, scene, dialogue, and closing imagery to the agent; `output=ledger` preserves the deterministic audit view.
|
|
15
|
+
- Expanded the cultural reference notes into a verified, genre-level writing palette covering path/learning metaphors, classical journey traditions, modern web-serial progression, daily-life cultivation, clan/sect epics, and cultivation-game procedural structure without imitating named living authors.
|
|
16
|
+
|
|
17
|
+
### Security and privacy
|
|
18
|
+
|
|
19
|
+
- Living-chronicle context persists only project slugs and aggregate metrics. Raw prompts, event IDs, commit subjects, contributor identities, URLs, secrets, and source-file contents remain excluded from context, state, plot, and chapters.
|
|
20
|
+
|
|
21
|
+
### Validation
|
|
22
|
+
|
|
23
|
+
- Expanded `/tutien` coverage to **158 deterministic, offline checks**, including project-profile privacy, response-brief composition, living-chronicle, preference sanitization, manifest-bound approval, optional ledger output, and on/off suppression.
|
|
24
|
+
- Synchronized the release version to `0.5.1` in `package.json`, `.codex-plugin/plugin.json`, and all three README badges.
|
|
4
25
|
|
|
5
26
|
## 0.5.0 — 2026-07-20
|
|
6
27
|
|
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
[](LICENSE)
|
|
8
8
|
[](https://www.npmjs.com/package/minimal-vibe-coding-kit)
|
|
9
|
-
[](CHANGELOG.md)
|
|
10
10
|

|
|
11
11
|

|
|
12
12
|

|
|
@@ -146,7 +146,7 @@ You (prompt) ──▶ Claude Code / Cursor / Codex / Grok
|
|
|
146
146
|
2. **Big or vague task?** Start with the `clearthought` or `sequential-thinking` skill to get a plan first.
|
|
147
147
|
3. **Complex task but only a rough prompt?** `/prompt-sharpener <rough prompt>` sharpens it into a precise prompt and executes it in the same turn.
|
|
148
148
|
4. **Found a skill, rule, or tool you want to bring in?** `/claim <request + links>` validates the sources against official docs, checks fit with your repo, asks when unclear, then integrates and documents it.
|
|
149
|
-
5. **Want a quiet reset while reviewing progress?** `/tutien` is a private
|
|
149
|
+
5. **Want a quiet reset while reviewing progress?** `/tutien` is a private xianxia coding-reflection mode over Git history + supplied AI-chat exports. Alongside exact classification, its living chronicle grows an original project-specific world, cast, sects, cultivation system, and ordered chapters in Vietnamese, English, or Simplified Chinese; `/tutien off` restores the kit's normal writing style.
|
|
150
150
|
6. **Repo-wide question or big review?** Use `parallel-analysis` — it fans out read-only analysis lanes and verifies the merged result.
|
|
151
151
|
7. **Changed `.claude/`, skills, hooks, or installer scripts?** Run `/security-scan` before merging.
|
|
152
152
|
8. **Want measurable improvements?** Run `/autoresearch-coding` with a metric and budget.
|
|
@@ -184,7 +184,9 @@ All 15 skills live canonically in `.vibekit/skills/`. Claude, Codex, and Grok mi
|
|
|
184
184
|
| `coding-level` | Setting how detailed explanations should be (0 = ELI5 … 5 = expert). | "/coding-level 2" |
|
|
185
185
|
| `prompt-sharpener` | A complex task but only a rough prompt: sharpen it, then execute it in the same turn. | "/prompt-sharpener make the settings page load faster" |
|
|
186
186
|
| `claim` | Bringing something new into the repo (skill, rule, convention, tool): vet sources against official docs, fit-check, confirm, integrate, document. | "/claim add the conventional-commits rule from https://www.npmjs.com/package/minimal-vibe-coding-kit" |
|
|
187
|
-
| `tutien` | A private
|
|
187
|
+
| `tutien` | A private xianxia coding-reflection mode with exact Git/chat evidence and an open-ended, repository-specific living chronicle. It keeps a plot bible and one ordered chapter per new approved evidence window; user-invoked, and `/tutien off` restores normal prose. | "/tutien preview sources=git story-language=vi story-style=web-serial" |
|
|
188
|
+
|
|
189
|
+
With `story=on` (default), approved analysis prepares `.vibekit/reports/tutien/story/`: `plot.md` is the evolving world/plot bible, `story-state.json` preserves continuity, and `chapters/NNNN-<xianxia-title>.md` stores one chapter per save. Story prose is agent-authored from aggregate evidence rather than a fixed sentence bank; character names and dialogue follow `story-language=vi|en|zh` naturally.
|
|
188
190
|
|
|
189
191
|
## Advanced
|
|
190
192
|
|
package/docs/README.vi.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
[](../LICENSE)
|
|
8
8
|
[](https://www.npmjs.com/package/minimal-vibe-coding-kit)
|
|
9
|
-
[](../CHANGELOG.md)
|
|
10
10
|

|
|
11
11
|

|
|
12
12
|

|
|
@@ -146,7 +146,7 @@ Bạn (prompt) ──▶ Claude Code / Cursor / Codex / Grok
|
|
|
146
146
|
2. **Task lớn hoặc mơ hồ?** Bắt đầu với skill `clearthought` hoặc `sequential-thinking` để có kế hoạch trước.
|
|
147
147
|
3. **Task phức tạp nhưng prompt mù mờ?** `/prompt-sharpener <prompt mù mờ>` cải thiện prompt thành bản rõ ràng rồi thực thi ngay trong cùng lượt.
|
|
148
148
|
4. **Muốn đưa skill, rule, hoặc tool mới vào repo?** `/claim <yêu cầu + link>` kiểm chứng nguồn với tài liệu chính thức, kiểm tra độ khớp với repo, hỏi lại khi chưa rõ, rồi tích hợp và ghi tài liệu.
|
|
149
|
-
5. **Muốn thả lỏng một chút khi nhìn lại tiến độ?** `/tutien` là
|
|
149
|
+
5. **Muốn thả lỏng một chút khi nhìn lại tiến độ?** `/tutien` là chế độ tu tiên riêng tư dựa trên lịch sử Git + file export chat AI. Ngoài phân loại theo bằng chứng thật, trường thiên ký sự sẽ phát triển một thế giới, nhân vật, tông môn, hệ thống cảnh giới và các chương truyện riêng cho từng dự án bằng tiếng Việt, tiếng Anh hoặc tiếng Trung giản thể; `/tutien off` khôi phục văn phong bình thường của kit.
|
|
150
150
|
6. **Câu hỏi toàn repo hoặc review lớn?** Dùng `parallel-analysis` — chia các lane phân tích chỉ-đọc chạy song song rồi xác minh kết quả gộp.
|
|
151
151
|
7. **Đã sửa `.claude/`, skills, hooks, hoặc script installer?** Chạy `/security-scan` trước khi merge.
|
|
152
152
|
8. **Muốn cải tiến đo được?** Chạy `/autoresearch-coding` với metric và budget.
|
|
@@ -184,7 +184,9 @@ Cả 15 skill nằm canonical trong `.vibekit/skills/`. Claude, Codex và Grok m
|
|
|
184
184
|
| `coding-level` | Chỉnh độ chi tiết khi giải thích (0 = ELI5 … 5 = chuyên gia). | "/coding-level 2" |
|
|
185
185
|
| `prompt-sharpener` | Task phức tạp nhưng prompt mù mờ: cải thiện prompt rồi thực thi ngay trong cùng lượt. | "/prompt-sharpener make the settings page load faster" |
|
|
186
186
|
| `claim` | Đưa thứ mới vào repo (skill, rule, quy ước, tool): kiểm chứng nguồn chính thức, kiểm tra độ khớp, xác nhận, tích hợp, ghi tài liệu. | "/claim add the conventional-commits rule from https://www.conventionalcommits.org" |
|
|
187
|
-
| `tutien` |
|
|
187
|
+
| `tutien` | Chế độ tu tiên riêng tư với bằng chứng Git/chat chính xác và trường thiên ký sự mở theo từng repo. Có tổng cương cốt truyện và một chương tuần tự cho mỗi kỳ bằng chứng mới đã duyệt; chỉ chạy khi user gọi, `/tutien off` khôi phục văn phong thường. | "/tutien preview sources=git story-language=vi story-style=web-serial" |
|
|
188
|
+
|
|
189
|
+
Với `story=on` (mặc định), sau khi phân tích được duyệt, chế độ chuẩn bị `.vibekit/reports/tutien/story/`: `plot.md` lưu tổng cương và thế giới quan đang phát triển, `story-state.json` giữ mạch truyện, còn `chapters/NNNN-<tên-chương-tu-tiên>.md` lưu mỗi lần đúng một chương. Văn truyện do agent sáng tác từ dữ liệu tổng hợp thay vì ghép câu cố định; tên nhân vật, xưng hô và đối thoại tự nhiên theo `story-language=vi|en|zh`.
|
|
188
190
|
|
|
189
191
|
## Nâng cao
|
|
190
192
|
|
package/docs/README.zh-CN.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
[](../LICENSE)
|
|
8
8
|
[](https://www.npmjs.com/package/minimal-vibe-coding-kit)
|
|
9
|
-
[](../CHANGELOG.md)
|
|
10
10
|

|
|
11
11
|

|
|
12
12
|

|
|
@@ -146,7 +146,7 @@ your-project/
|
|
|
146
146
|
2. **任务很大或不够明确?** 先使用 `clearthought` 或 `sequential-thinking` 技能生成计划。
|
|
147
147
|
3. **任务复杂,但只有一个粗略提示词?** `/prompt-sharpener <rough prompt>` 会将它变得清晰准确,并在同一轮中执行。
|
|
148
148
|
4. **想把新技能、规则或工具带入仓库?** `/claim <request + links>` 会根据官方文档验证来源、检查是否适合当前仓库、在不明确时询问,然后完成集成和文档记录。
|
|
149
|
-
5. **想在回顾进度时安静地放松一下?** `/tutien`
|
|
149
|
+
5. **想在回顾进度时安静地放松一下?** `/tutien` 是基于 Git 历史和你明确提供的 AI 聊天导出的私密修仙模式。除了严格依据证据进行分类,它还会为每个项目逐步发展独有的世界、人物、宗门、境界体系与连续章节,支持越南语、英语和简体中文;`/tutien off` 会恢复工具包的正常文风。
|
|
150
150
|
6. **需要回答全仓库问题或进行大型审查?** 使用 `parallel-analysis`,它会并行执行多个只读分析通道,并验证合并后的结论。
|
|
151
151
|
7. **修改了 `.claude/`、技能、hook 或安装脚本?** 合并前运行 `/security-scan`。
|
|
152
152
|
8. **想进行可衡量的改进?** 使用带有 metric 和预算的 `/autoresearch-coding`。
|
|
@@ -184,7 +184,9 @@ your-project/
|
|
|
184
184
|
| `coding-level` | 设置解释详细程度(0 = ELI5,5 = 专家同行)。 | "/coding-level 2" |
|
|
185
185
|
| `prompt-sharpener` | 复杂任务只有粗略提示词时:优化提示词并在同一轮执行。 | "/prompt-sharpener make the settings page load faster" |
|
|
186
186
|
| `claim` | 将新技能、规则、约定或工具带入仓库:验证官方来源、检查适配性、确认、集成并记录文档。 | "/claim add the conventional-commits rule from https://www.conventionalcommits.org" |
|
|
187
|
-
| `tutien` |
|
|
187
|
+
| `tutien` | 基于准确 Git/聊天证据的私密修仙模式,并为每个仓库维护开放式连载故事。每个新的已批准证据窗口对应一个有序章节;仅由用户调用,`/tutien off` 恢复正常文风。 | "/tutien preview sources=git story-language=zh story-style=web-serial" |
|
|
188
|
+
|
|
189
|
+
`story=on`(默认)时,获批分析会准备 `.vibekit/reports/tutien/story/`:`plot.md` 保存持续演化的总纲与世界设定,`story-state.json` 保存连续性,`chapters/NNNN-<修仙章名>.md` 每次只保存一个章节。故事由 Agent 根据聚合证据原创,而不是拼接固定句子;人物姓名、称谓和对白会自然遵循 `story-language=vi|en|zh`。
|
|
188
190
|
|
|
189
191
|
## 高级用法
|
|
190
192
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "minimal-vibe-coding-kit",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"description": "Project-agnostic AI coding workflow kit for Claude Code, Cursor, Codex, and Grok with AgentShield security review.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"pack:dry-run": "node .vibekit/scripts/pack-dry-run.mjs",
|
|
22
22
|
"validate:all": "npm test && npm run security:probe && npm run pack:dry-run",
|
|
23
23
|
"pack:repo": "node .vibekit/scripts/validate-kit.mjs . && npm pack",
|
|
24
|
-
"test:tutien": "node test/tutien/scripts/test-analyzer.mjs && node test/tutien/scripts/test-render.mjs && node test/tutien/scripts/test-villains.mjs && node test/tutien/scripts/test-snapshot.mjs && node test/tutien/scripts/test-classify.mjs && node test/tutien/scripts/test-adversarial.mjs && node test/tutien/scripts/test-e2e.mjs"
|
|
24
|
+
"test:tutien": "node test/tutien/scripts/test-analyzer.mjs && node test/tutien/scripts/test-profile.mjs && node test/tutien/scripts/test-render.mjs && node test/tutien/scripts/test-villains.mjs && node test/tutien/scripts/test-snapshot.mjs && node test/tutien/scripts/test-classify.mjs && node test/tutien/scripts/test-story.mjs && node test/tutien/scripts/test-adversarial.mjs && node test/tutien/scripts/test-e2e.mjs"
|
|
25
25
|
},
|
|
26
26
|
"keywords": [
|
|
27
27
|
"vibe-coding",
|