@guiho/mirror 3.2.1 → 3.3.0-alpha.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/CHANGELOG.md +15 -0
- package/DOCS.md +35 -74
- package/README.md +15 -41
- package/jsr.json +4 -2
- package/package.json +11 -20
- package/scripts/install-package.ts +70 -0
- package/scripts/mirror-bin.ts +20 -0
- package/skills/guiho-as-mirror/SKILL.md +2 -29
- package/library/adapters.d.ts +0 -32
- package/library/adapters.d.ts.map +0 -1
- package/library/adapters.js +0 -210
- package/library/agents.d.ts +0 -29
- package/library/agents.d.ts.map +0 -1
- package/library/agents.js +0 -212
- package/library/cli.d.ts +0 -29
- package/library/cli.d.ts.map +0 -1
- package/library/cli.js +0 -416
- package/library/config.d.ts +0 -18
- package/library/config.d.ts.map +0 -1
- package/library/config.js +0 -280
- package/library/errors.d.ts +0 -9
- package/library/errors.d.ts.map +0 -1
- package/library/errors.js +0 -15
- package/library/executor.d.ts +0 -7
- package/library/executor.d.ts.map +0 -1
- package/library/executor.js +0 -48
- package/library/flags.d.ts +0 -6
- package/library/flags.d.ts.map +0 -1
- package/library/flags.js +0 -80
- package/library/guiho-mirror-bin.d.ts +0 -6
- package/library/guiho-mirror-bin.d.ts.map +0 -1
- package/library/guiho-mirror-bin.js +0 -6
- package/library/guiho-mirror.d.ts +0 -18
- package/library/guiho-mirror.d.ts.map +0 -1
- package/library/guiho-mirror.js +0 -16
- package/library/hooks.d.ts +0 -14
- package/library/hooks.d.ts.map +0 -1
- package/library/hooks.js +0 -122
- package/library/init.d.ts +0 -12
- package/library/init.d.ts.map +0 -1
- package/library/init.js +0 -100
- package/library/plan.d.ts +0 -10
- package/library/plan.d.ts.map +0 -1
- package/library/plan.js +0 -85
- package/library/reporter.d.ts +0 -15
- package/library/reporter.d.ts.map +0 -1
- package/library/reporter.js +0 -182
- package/library/schema.d.ts +0 -164
- package/library/schema.d.ts.map +0 -1
- package/library/schema.js +0 -152
- package/library/types.d.ts +0 -205
- package/library/types.d.ts.map +0 -1
- package/library/types.js +0 -4
- package/library/version.d.ts +0 -10
- package/library/version.d.ts.map +0 -1
- package/library/version.js +0 -31
package/library/adapters.js
DELETED
|
@@ -1,210 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @copyright Copyright (c) 2026 GUIHO Technologies as represented by Cristóvão GUIHO. All Rights Reserved.
|
|
3
|
-
*/
|
|
4
|
-
import { execFile } from 'node:child_process';
|
|
5
|
-
import { existsSync } from 'node:fs';
|
|
6
|
-
import { readFile, writeFile } from 'node:fs/promises';
|
|
7
|
-
import { promisify } from 'node:util';
|
|
8
|
-
import { MirrorError } from './errors.js';
|
|
9
|
-
import { assertValidSemver, sortSemverDescending } from './version.js';
|
|
10
|
-
import { resolveMirrorPath } from './config.js';
|
|
11
|
-
const execFileAsync = promisify(execFile);
|
|
12
|
-
let gitChecked = false;
|
|
13
|
-
let gitExists = false;
|
|
14
|
-
const checkGitAvailable = async () => {
|
|
15
|
-
if (gitChecked)
|
|
16
|
-
return gitExists;
|
|
17
|
-
gitChecked = true;
|
|
18
|
-
try {
|
|
19
|
-
await execFileAsync('git', ['--version']);
|
|
20
|
-
gitExists = true;
|
|
21
|
-
}
|
|
22
|
-
catch {
|
|
23
|
-
gitExists = false;
|
|
24
|
-
}
|
|
25
|
-
return gitExists;
|
|
26
|
-
};
|
|
27
|
-
export const ensureGitAvailable = async () => {
|
|
28
|
-
if (!(await checkGitAvailable())) {
|
|
29
|
-
throw new MirrorError('Git executable not found. Git is required when using git as a source or output.');
|
|
30
|
-
}
|
|
31
|
-
};
|
|
32
|
-
const gitNotFoundMessage = 'Git executable not found. Git is required when using git as a source or output.';
|
|
33
|
-
const runGit = async (cwd, args) => {
|
|
34
|
-
if (!(await checkGitAvailable())) {
|
|
35
|
-
throw new MirrorError(gitNotFoundMessage);
|
|
36
|
-
}
|
|
37
|
-
try {
|
|
38
|
-
const { stdout } = await execFileAsync('git', args, { cwd });
|
|
39
|
-
return stdout;
|
|
40
|
-
}
|
|
41
|
-
catch (error) {
|
|
42
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
43
|
-
throw new MirrorError(`Git command failed: git ${args.join(' ')}\n${message}`);
|
|
44
|
-
}
|
|
45
|
-
};
|
|
46
|
-
export const supportedGitTagTemplates = ['v{version}', '{name}@{version}', '{name}/v{version}'];
|
|
47
|
-
export const readPackageJson = async (path) => readJsonObject(path, 'package.json');
|
|
48
|
-
export const readJsrJson = async (path) => readJsonObject(path, 'jsr.json');
|
|
49
|
-
export const writeJsonObject = async (path, object) => {
|
|
50
|
-
await writeFile(path, `${JSON.stringify(object, null, 2)}\n`, 'utf8');
|
|
51
|
-
};
|
|
52
|
-
export const readPackageVersion = async (config) => readVersionField(resolveMirrorPath(config.cwd, config.package.path), 'package.json');
|
|
53
|
-
export const readJsrVersion = async (config) => readVersionField(resolveMirrorPath(config.cwd, config.jsr.path), 'jsr.json');
|
|
54
|
-
export const readPackageVersionFile = async (path) => readVersionField(path, 'package.json');
|
|
55
|
-
export const readJsrVersionFile = async (path) => readVersionField(path, 'jsr.json');
|
|
56
|
-
export const readPackageName = async (config) => readNameField(resolveMirrorPath(config.cwd, config.package.path), 'package.json');
|
|
57
|
-
export const readJsrName = async (config) => readNameField(resolveMirrorPath(config.cwd, config.jsr.path), 'jsr.json');
|
|
58
|
-
export const writePackageVersion = async (config, nextVersion) => writeVersionField(resolveMirrorPath(config.cwd, config.package.path), 'package.json', nextVersion);
|
|
59
|
-
export const writeJsrVersion = async (config, nextVersion) => writeVersionField(resolveMirrorPath(config.cwd, config.jsr.path), 'jsr.json', nextVersion);
|
|
60
|
-
export const writePackageVersionFile = async (path, nextVersion) => writeVersionField(path, 'package.json', nextVersion);
|
|
61
|
-
export const writeJsrVersionFile = async (path, nextVersion) => writeVersionField(path, 'jsr.json', nextVersion);
|
|
62
|
-
export const ensureAdapterFiles = async (config) => {
|
|
63
|
-
if (usesAdapter(config, 'package.json')) {
|
|
64
|
-
ensureFile(resolveMirrorPath(config.cwd, config.package.path), 'package.json');
|
|
65
|
-
for (const path of config.package.auxiliaryPaths)
|
|
66
|
-
ensureFile(resolveMirrorPath(config.cwd, path), 'package.json');
|
|
67
|
-
}
|
|
68
|
-
if (usesAdapter(config, 'jsr.json'))
|
|
69
|
-
ensureFile(resolveMirrorPath(config.cwd, config.jsr.path), 'jsr.json');
|
|
70
|
-
if (usesAdapter(config, 'git'))
|
|
71
|
-
await ensureGitRepository(config.cwd);
|
|
72
|
-
};
|
|
73
|
-
export const resolveProjectName = async (config) => {
|
|
74
|
-
if (config.project.name)
|
|
75
|
-
return config.project.name;
|
|
76
|
-
if (config.project.nameSource === 'package.json')
|
|
77
|
-
return readPackageName(config);
|
|
78
|
-
if (config.project.nameSource === 'jsr.json')
|
|
79
|
-
return readJsrName(config);
|
|
80
|
-
return undefined;
|
|
81
|
-
};
|
|
82
|
-
export const readCurrentVersion = async (config, projectName) => {
|
|
83
|
-
if (config.version.source === 'package.json')
|
|
84
|
-
return readPackageVersion(config);
|
|
85
|
-
if (config.version.source === 'jsr.json')
|
|
86
|
-
return readJsrVersion(config);
|
|
87
|
-
return readGitVersion(config, projectName);
|
|
88
|
-
};
|
|
89
|
-
export const readGitVersion = async (config, projectName) => {
|
|
90
|
-
await ensureGitAvailable();
|
|
91
|
-
await ensureGitRepository(config.cwd);
|
|
92
|
-
const tagsOutput = await runGit(config.cwd, ['-C', config.cwd, 'tag', '--list']);
|
|
93
|
-
const versions = tagsOutput
|
|
94
|
-
.split(/\r?\n/)
|
|
95
|
-
.map((line) => line.trim())
|
|
96
|
-
.filter(Boolean)
|
|
97
|
-
.map((tag) => versionFromTag(config.git.tagTemplate, tag, projectName))
|
|
98
|
-
.filter((version) => Boolean(version));
|
|
99
|
-
if (versions.length === 0)
|
|
100
|
-
throw new MirrorError(`No Git tags match template: ${config.git.tagTemplate}`);
|
|
101
|
-
return sortSemverDescending(versions)[0] ?? '';
|
|
102
|
-
};
|
|
103
|
-
export const renderGitTag = (template, version, projectName) => {
|
|
104
|
-
assertSupportedGitTagTemplate(template);
|
|
105
|
-
assertValidSemver(version, 'Git tag version');
|
|
106
|
-
if (template.includes('{name}') && !projectName)
|
|
107
|
-
throw new MirrorError(`Tag template requires a project name: ${template}`);
|
|
108
|
-
return template.replaceAll('{version}', version).replaceAll('{name}', projectName ?? '');
|
|
109
|
-
};
|
|
110
|
-
export const versionFromTag = (template, tag, projectName) => {
|
|
111
|
-
assertSupportedGitTagTemplate(template);
|
|
112
|
-
if (template.includes('{name}') && !projectName)
|
|
113
|
-
throw new MirrorError(`Tag template requires a project name: ${template}`);
|
|
114
|
-
const escapedTemplate = escapeRegex(template)
|
|
115
|
-
.replaceAll('\\{version\\}', '(?<version>.+)')
|
|
116
|
-
.replaceAll('\\{name\\}', escapeRegex(projectName ?? ''));
|
|
117
|
-
const match = new RegExp(`^${escapedTemplate}$`).exec(tag);
|
|
118
|
-
const version = match?.groups?.['version'];
|
|
119
|
-
if (!version)
|
|
120
|
-
return undefined;
|
|
121
|
-
try {
|
|
122
|
-
assertValidSemver(version, 'Git tag version');
|
|
123
|
-
return version;
|
|
124
|
-
}
|
|
125
|
-
catch {
|
|
126
|
-
return undefined;
|
|
127
|
-
}
|
|
128
|
-
};
|
|
129
|
-
export const assertSupportedGitTagTemplate = (template) => {
|
|
130
|
-
if (!supportedGitTagTemplates.includes(template)) {
|
|
131
|
-
throw new MirrorError(`Unsupported Git tag template: ${template}. Expected v{version}, {name}@{version}, or {name}/v{version}.`);
|
|
132
|
-
}
|
|
133
|
-
};
|
|
134
|
-
export const isGitRepository = async (cwd) => {
|
|
135
|
-
if (!(await checkGitAvailable()))
|
|
136
|
-
return false;
|
|
137
|
-
try {
|
|
138
|
-
await execFileAsync('git', ['-C', cwd, 'rev-parse', '--is-inside-work-tree']);
|
|
139
|
-
return true;
|
|
140
|
-
}
|
|
141
|
-
catch {
|
|
142
|
-
return false;
|
|
143
|
-
}
|
|
144
|
-
};
|
|
145
|
-
export const isGitDirty = async (cwd) => {
|
|
146
|
-
const output = await runGit(cwd, ['-C', cwd, 'status', '--porcelain']);
|
|
147
|
-
return output.trim().length > 0;
|
|
148
|
-
};
|
|
149
|
-
export const createGitCommit = async (cwd, paths, message) => {
|
|
150
|
-
await ensureGitAvailable();
|
|
151
|
-
for (const path of paths)
|
|
152
|
-
await runGit(cwd, ['-C', cwd, 'add', path]);
|
|
153
|
-
await runGit(cwd, ['-C', cwd, 'commit', '-m', message]);
|
|
154
|
-
};
|
|
155
|
-
export const createGitTag = async (cwd, tag) => {
|
|
156
|
-
await ensureGitAvailable();
|
|
157
|
-
await runGit(cwd, ['-C', cwd, 'tag', tag, '-m', `Release ${tag}`]);
|
|
158
|
-
};
|
|
159
|
-
export const pushGitRefs = async (cwd, includeCommit, includeTags) => {
|
|
160
|
-
await ensureGitAvailable();
|
|
161
|
-
if (includeCommit)
|
|
162
|
-
await runGit(cwd, ['-C', cwd, 'push']);
|
|
163
|
-
if (includeTags)
|
|
164
|
-
await runGit(cwd, ['-C', cwd, 'push', '--tags']);
|
|
165
|
-
};
|
|
166
|
-
const readJsonObject = async (path, label) => {
|
|
167
|
-
ensureFile(path, label);
|
|
168
|
-
const content = await readFile(path, 'utf8');
|
|
169
|
-
let json;
|
|
170
|
-
try {
|
|
171
|
-
json = JSON.parse(content);
|
|
172
|
-
}
|
|
173
|
-
catch {
|
|
174
|
-
throw new MirrorError(`${label} must contain valid JSON: ${path}`);
|
|
175
|
-
}
|
|
176
|
-
if (typeof json !== 'object' || json === null || Array.isArray(json))
|
|
177
|
-
throw new MirrorError(`${label} must contain a JSON object: ${path}`);
|
|
178
|
-
return json;
|
|
179
|
-
};
|
|
180
|
-
const readVersionField = async (path, label) => {
|
|
181
|
-
const json = await readJsonObject(path, label);
|
|
182
|
-
const version = json['version'];
|
|
183
|
-
if (typeof version !== 'string')
|
|
184
|
-
throw new MirrorError(`${label} must contain a string version field: ${path}`);
|
|
185
|
-
assertValidSemver(version, `${label} version`);
|
|
186
|
-
return version;
|
|
187
|
-
};
|
|
188
|
-
const readNameField = async (path, label) => {
|
|
189
|
-
const json = await readJsonObject(path, label);
|
|
190
|
-
const name = json['name'];
|
|
191
|
-
if (typeof name !== 'string' || name.length === 0)
|
|
192
|
-
throw new MirrorError(`${label} must contain a string name field: ${path}`);
|
|
193
|
-
return name;
|
|
194
|
-
};
|
|
195
|
-
const writeVersionField = async (path, label, nextVersion) => {
|
|
196
|
-
const json = await readJsonObject(path, label);
|
|
197
|
-
json['version'] = nextVersion;
|
|
198
|
-
await writeJsonObject(path, json);
|
|
199
|
-
};
|
|
200
|
-
const ensureFile = (path, label) => {
|
|
201
|
-
if (!existsSync(path))
|
|
202
|
-
throw new MirrorError(`${label} file not found: ${path}`);
|
|
203
|
-
};
|
|
204
|
-
const ensureGitRepository = async (cwd) => {
|
|
205
|
-
await ensureGitAvailable();
|
|
206
|
-
if (!(await isGitRepository(cwd)))
|
|
207
|
-
throw new MirrorError(`Not a Git repository: ${cwd}`);
|
|
208
|
-
};
|
|
209
|
-
const usesAdapter = (config, adapter) => config.version.source === adapter || config.version.output.includes(adapter);
|
|
210
|
-
const escapeRegex = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
package/library/agents.d.ts
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @copyright Copyright (c) 2026 GUIHO Technologies as represented by Cristóvão GUIHO. All Rights Reserved.
|
|
3
|
-
*/
|
|
4
|
-
import type { MirrorAgentAutomationResult, MirrorAgentSettings, MirrorAgentsInstructionsResult, MirrorCliOptions, MirrorSkillInstallResult, MirrorSkillInstallScope } from './types.js';
|
|
5
|
-
export declare const mirrorSkillName = "guiho-as-mirror";
|
|
6
|
-
export declare const mirrorAgentsSectionStartMarker = "<!-- BEGIN GUIHO MIRROR - DO NOT EDIT THIS SECTION -->";
|
|
7
|
-
export declare const mirrorAgentsSectionEndMarker = "<!-- END GUIHO MIRROR -->";
|
|
8
|
-
export declare const mirrorAgentsSectionHeading = "## Semantic Project Versioning -- GUIHO Mirror";
|
|
9
|
-
export declare const defaultMirrorAgentSettings: MirrorAgentSettings;
|
|
10
|
-
export declare const mirrorAgentsSection: string;
|
|
11
|
-
type MirrorSkillPathOptions = {
|
|
12
|
-
cwd?: string;
|
|
13
|
-
homeDirectory?: string;
|
|
14
|
-
};
|
|
15
|
-
type MirrorSkillInstallOptions = MirrorSkillPathOptions & {
|
|
16
|
-
overwrite?: boolean;
|
|
17
|
-
};
|
|
18
|
-
type MirrorAgentAutomationOptions = MirrorCliOptions & {
|
|
19
|
-
homeDirectory?: string;
|
|
20
|
-
};
|
|
21
|
-
export declare const resolveMirrorSkillPath: (scope: MirrorSkillInstallScope, options?: MirrorSkillPathOptions) => string;
|
|
22
|
-
export declare const isMirrorSkillInstalled: (scope: MirrorSkillInstallScope, options?: MirrorSkillPathOptions) => boolean;
|
|
23
|
-
export declare const installMirrorSkill: (scope: MirrorSkillInstallScope, options?: MirrorSkillInstallOptions) => Promise<MirrorSkillInstallResult>;
|
|
24
|
-
export declare const ensureMirrorAgentsInstructions: (cwd: string, create?: boolean) => Promise<MirrorAgentsInstructionsResult>;
|
|
25
|
-
export declare const findAgentsFile: (cwd: string) => string | undefined;
|
|
26
|
-
export declare const resolveMirrorAgentSettings: (options?: MirrorCliOptions) => Promise<MirrorAgentSettings>;
|
|
27
|
-
export declare const runMirrorAgentAutomation: (options?: MirrorAgentAutomationOptions, notify?: (message: string) => void) => Promise<MirrorAgentAutomationResult>;
|
|
28
|
-
export {};
|
|
29
|
-
//# sourceMappingURL=agents.d.ts.map
|
package/library/agents.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../source/agents.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,OAAO,KAAK,EACV,2BAA2B,EAC3B,mBAAmB,EACnB,8BAA8B,EAC9B,gBAAgB,EAChB,wBAAwB,EACxB,uBAAuB,EACxB,MAAM,YAAY,CAAA;AAInB,eAAO,MAAM,eAAe,oBAAoB,CAAA;AAChD,eAAO,MAAM,8BAA8B,2DAA2D,CAAA;AACtG,eAAO,MAAM,4BAA4B,8BAA8B,CAAA;AACvE,eAAO,MAAM,0BAA0B,mDAAmD,CAAA;AAE1F,eAAO,MAAM,0BAA0B,EAAE,mBAKxC,CAAA;AAWD,eAAO,MAAM,mBAAmB,QAEA,CAAA;AAEhC,KAAK,sBAAsB,GAAG;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB,CAAA;AAED,KAAK,yBAAyB,GAAG,sBAAsB,GAAG;IACxD,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB,CAAA;AAED,KAAK,4BAA4B,GAAG,gBAAgB,GAAG;IACrD,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB,CAAA;AAED,eAAO,MAAM,sBAAsB,GAAI,OAAO,uBAAuB,EAAE,UAAS,sBAA2B,WAI1G,CAAA;AAED,eAAO,MAAM,sBAAsB,GAAI,OAAO,uBAAuB,EAAE,UAAS,sBAA2B,YACvD,CAAA;AAEpD,eAAO,MAAM,kBAAkB,GAC7B,OAAO,uBAAuB,EAC9B,UAAS,yBAA8B,KACtC,OAAO,CAAC,wBAAwB,CAelC,CAAA;AAED,eAAO,MAAM,8BAA8B,GAAU,KAAK,MAAM,EAAE,gBAAc,KAAG,OAAO,CAAC,8BAA8B,CAkBxH,CAAA;AAED,eAAO,MAAM,cAAc,GAAI,KAAK,MAAM,KAAG,MAAM,GAAG,SAWrD,CAAA;AAED,eAAO,MAAM,0BAA0B,GAAU,UAAS,gBAAqB,KAAG,OAAO,CAAC,mBAAmB,CAa5G,CAAA;AAED,eAAO,MAAM,wBAAwB,GACnC,UAAS,4BAAiC,EAC1C,SAAQ,CAAC,OAAO,EAAE,MAAM,KAAK,IAAe,KAC3C,OAAO,CAAC,2BAA2B,CAkBrC,CAAA"}
|
package/library/agents.js
DELETED
|
@@ -1,212 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @copyright Copyright (c) 2026 GUIHO Technologies as represented by Cristóvão GUIHO. All Rights Reserved.
|
|
3
|
-
*/
|
|
4
|
-
import { existsSync } from 'node:fs';
|
|
5
|
-
import { mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
6
|
-
import { homedir } from 'node:os';
|
|
7
|
-
import { dirname, resolve } from 'node:path';
|
|
8
|
-
import { MirrorError } from './errors.js';
|
|
9
|
-
import { discoverMirrorConfig, resolveMirrorPath } from './config.js';
|
|
10
|
-
export const mirrorSkillName = 'guiho-as-mirror';
|
|
11
|
-
export const mirrorAgentsSectionStartMarker = '<!-- BEGIN GUIHO MIRROR - DO NOT EDIT THIS SECTION -->';
|
|
12
|
-
export const mirrorAgentsSectionEndMarker = '<!-- END GUIHO MIRROR -->';
|
|
13
|
-
export const mirrorAgentsSectionHeading = '## Semantic Project Versioning -- GUIHO Mirror';
|
|
14
|
-
export const defaultMirrorAgentSettings = {
|
|
15
|
-
writeChangelog: true,
|
|
16
|
-
changelogPath: 'CHANGELOG.md',
|
|
17
|
-
autoAgentsMd: true,
|
|
18
|
-
autoSkillInstall: true,
|
|
19
|
-
};
|
|
20
|
-
const mirrorAgentsSectionBody = `${mirrorAgentsSectionHeading}
|
|
21
|
-
|
|
22
|
-
Invoke the guiho-as-mirror agent skill every time the user wants to bump, tag, release, plan, initialize, configure, or troubleshoot semantic project versioning with GUIHO Mirror.
|
|
23
|
-
|
|
24
|
-
Before editing release docs or changelogs, inspect mirror.config.toml. If [agents].write_changelog is false, skip changelog edits. If it is missing or true, changelog edits are allowed when the project has a changelog.
|
|
25
|
-
|
|
26
|
-
Use [agents].changelog_path as the changelog file path. If it is missing, use CHANGELOG.md in the project root.
|
|
27
|
-
`;
|
|
28
|
-
export const mirrorAgentsSection = `${mirrorAgentsSectionStartMarker}
|
|
29
|
-
${mirrorAgentsSectionBody.trimEnd()}
|
|
30
|
-
${mirrorAgentsSectionEndMarker}`;
|
|
31
|
-
export const resolveMirrorSkillPath = (scope, options = {}) => {
|
|
32
|
-
if (scope === 'local')
|
|
33
|
-
return resolve(options.cwd ?? process.cwd(), '.agents', 'skills', mirrorSkillName, 'SKILL.md');
|
|
34
|
-
return resolve(resolveMirrorAgentHome(options.homeDirectory), '.agents', 'skills', mirrorSkillName, 'SKILL.md');
|
|
35
|
-
};
|
|
36
|
-
export const isMirrorSkillInstalled = (scope, options = {}) => existsSync(resolveMirrorSkillPath(scope, options));
|
|
37
|
-
export const installMirrorSkill = async (scope, options = {}) => {
|
|
38
|
-
const path = resolveMirrorSkillPath(scope, options);
|
|
39
|
-
const exists = existsSync(path);
|
|
40
|
-
if (exists && options.overwrite === false)
|
|
41
|
-
return { scope, path, installed: false, updated: false };
|
|
42
|
-
const content = await readBundledMirrorSkill();
|
|
43
|
-
const current = exists ? await readFile(path, 'utf8') : undefined;
|
|
44
|
-
if (current === content)
|
|
45
|
-
return { scope, path, installed: false, updated: false };
|
|
46
|
-
await mkdir(dirname(path), { recursive: true });
|
|
47
|
-
await writeFile(path, content, 'utf8');
|
|
48
|
-
return { scope, path, installed: !exists, updated: exists };
|
|
49
|
-
};
|
|
50
|
-
export const ensureMirrorAgentsInstructions = async (cwd, create = false) => {
|
|
51
|
-
const path = findAgentsFile(cwd) ?? resolve(cwd, 'AGENTS.md');
|
|
52
|
-
const exists = existsSync(path);
|
|
53
|
-
if (!exists && !create)
|
|
54
|
-
return { path, exists: false, changed: false };
|
|
55
|
-
if (!exists) {
|
|
56
|
-
await writeFile(path, `# Project Agents\n\n${mirrorAgentsSection}\n`, 'utf8');
|
|
57
|
-
return { path, exists: true, changed: true };
|
|
58
|
-
}
|
|
59
|
-
const content = await readFile(path, 'utf8');
|
|
60
|
-
if (hasMirrorAgentsSection(content))
|
|
61
|
-
return { path, exists: true, changed: false };
|
|
62
|
-
const nextContent = `${content.trimEnd()}\n\n${mirrorAgentsSection}\n`;
|
|
63
|
-
await writeFile(path, nextContent, 'utf8');
|
|
64
|
-
return { path, exists: true, changed: true };
|
|
65
|
-
};
|
|
66
|
-
export const findAgentsFile = (cwd) => {
|
|
67
|
-
let current = resolve(cwd);
|
|
68
|
-
while (true) {
|
|
69
|
-
const path = resolve(current, 'AGENTS.md');
|
|
70
|
-
if (existsSync(path))
|
|
71
|
-
return path;
|
|
72
|
-
const parent = dirname(current);
|
|
73
|
-
if (parent === current)
|
|
74
|
-
return undefined;
|
|
75
|
-
current = parent;
|
|
76
|
-
}
|
|
77
|
-
};
|
|
78
|
-
export const resolveMirrorAgentSettings = async (options = {}) => {
|
|
79
|
-
const cwd = resolve(options.cwd ?? process.cwd());
|
|
80
|
-
const discovered = await discoverMirrorConfig(cwd, options.config);
|
|
81
|
-
if (!discovered.raw)
|
|
82
|
-
return { ...defaultMirrorAgentSettings };
|
|
83
|
-
if (discovered.raw.schema !== 1)
|
|
84
|
-
throw new MirrorError('Unsupported or missing configuration schema. Expected `schema = 1`.');
|
|
85
|
-
return {
|
|
86
|
-
writeChangelog: optionalBoolean(discovered.raw.agents?.write_changelog, 'agents.write_changelog') !== false,
|
|
87
|
-
changelogPath: optionalString(discovered.raw.agents?.changelog_path, 'agents.changelog_path') ?? 'CHANGELOG.md',
|
|
88
|
-
autoAgentsMd: optionalBoolean(discovered.raw.agents?.auto_agents_md, 'agents.auto_agents_md') !== false,
|
|
89
|
-
autoSkillInstall: optionalBoolean(discovered.raw.agents?.auto_skill_install, 'agents.auto_skill_install') !== false,
|
|
90
|
-
};
|
|
91
|
-
};
|
|
92
|
-
export const runMirrorAgentAutomation = async (options = {}, notify = () => { }) => {
|
|
93
|
-
const cwd = resolve(options.cwd ?? process.cwd());
|
|
94
|
-
const settings = await resolveMirrorAgentSettings(options);
|
|
95
|
-
const result = { settings };
|
|
96
|
-
if (settings.autoAgentsMd)
|
|
97
|
-
result.agentsMd = await ensureMirrorAgentsInstructions(cwd, false);
|
|
98
|
-
if (settings.autoSkillInstall) {
|
|
99
|
-
const scope = 'global';
|
|
100
|
-
if (!isMirrorSkillInstalled(scope, { cwd, homeDirectory: options.homeDirectory })) {
|
|
101
|
-
const path = resolveMirrorSkillPath(scope, { cwd, homeDirectory: options.homeDirectory });
|
|
102
|
-
notify(`notice: ${mirrorSkillName} skill not found ${scope}; Mirror is installing it at ${path}`);
|
|
103
|
-
result.globalSkill = await installMirrorSkill(scope, { cwd, homeDirectory: options.homeDirectory, overwrite: false });
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
return result;
|
|
107
|
-
};
|
|
108
|
-
const readBundledMirrorSkill = async () => {
|
|
109
|
-
try {
|
|
110
|
-
return await readFile(new URL('../skills/guiho-as-mirror/SKILL.md', import.meta.url), 'utf8');
|
|
111
|
-
}
|
|
112
|
-
catch {
|
|
113
|
-
return embeddedMirrorSkillContent;
|
|
114
|
-
}
|
|
115
|
-
};
|
|
116
|
-
const resolveMirrorAgentHome = (homeDirectory) => {
|
|
117
|
-
const value = homeDirectory ?? process.env['MIRROR_AGENT_HOME'] ?? homedir();
|
|
118
|
-
return resolveMirrorPath(process.cwd(), value);
|
|
119
|
-
};
|
|
120
|
-
const optionalBoolean = (value, key) => {
|
|
121
|
-
if (value === undefined)
|
|
122
|
-
return undefined;
|
|
123
|
-
if (typeof value !== 'boolean')
|
|
124
|
-
throw new MirrorError(`Invalid ${key}. Expected true or false.`);
|
|
125
|
-
return value;
|
|
126
|
-
};
|
|
127
|
-
const optionalString = (value, key) => {
|
|
128
|
-
if (value === undefined)
|
|
129
|
-
return undefined;
|
|
130
|
-
if (typeof value !== 'string')
|
|
131
|
-
throw new MirrorError(`Invalid ${key}. Expected a string.`);
|
|
132
|
-
return value;
|
|
133
|
-
};
|
|
134
|
-
const hasMirrorAgentsSection = (content) => {
|
|
135
|
-
const normalizedContent = normalizeMirrorAgentsSection(content);
|
|
136
|
-
return [mirrorAgentsSection, mirrorAgentsSectionBody].some((section) => {
|
|
137
|
-
return normalizedContent.includes(normalizeMirrorAgentsSection(section));
|
|
138
|
-
});
|
|
139
|
-
};
|
|
140
|
-
const normalizeMirrorAgentsSection = (content) => content.replace(/\s+/g, ' ').trim();
|
|
141
|
-
const embeddedMirrorSkillContent = [
|
|
142
|
-
'---',
|
|
143
|
-
'name: guiho-as-mirror',
|
|
144
|
-
'description: Use this skill whenever the user asks to version, bump, release, tag, initialize, configure, or troubleshoot a project with GUIHO Mirror. This includes Bun, npm, JSR, package.json, jsr.json, Git tag, semantic versioning, changelog, release-plan, prerelease, and what version comes next workflows.',
|
|
145
|
-
'---',
|
|
146
|
-
'',
|
|
147
|
-
'# GUIHO Mirror',
|
|
148
|
-
'',
|
|
149
|
-
'GUIHO Mirror is a deterministic CLI and TypeScript library for semantic project versioning. Use it instead of ad hoc version edits, manual package-manager version commands, or manual release tags.',
|
|
150
|
-
'',
|
|
151
|
-
'## Command Selection',
|
|
152
|
-
'',
|
|
153
|
-
'1. Use `bun @guiho/mirror` when the package is installed locally and Bun is available.',
|
|
154
|
-
'2. Use `mirror` when a global binary is available.',
|
|
155
|
-
'3. Use `bunx @guiho/mirror` when running without installation.',
|
|
156
|
-
'',
|
|
157
|
-
'Run `mirror --help` or `mirror <command> --help` for command-specific details when needed.',
|
|
158
|
-
'',
|
|
159
|
-
'## Release Workflow',
|
|
160
|
-
'',
|
|
161
|
-
'When the user asks to bump, release, tag, or version a project, follow this sequence:',
|
|
162
|
-
'',
|
|
163
|
-
'1. Confirm the target and project root. Supported targets are `major`, `premajor`, `minor`, `preminor`, `patch`, `prepatch`, `prerelease`, or an exact semver like `2.0.0`.',
|
|
164
|
-
'2. Run `<mirror> config show` and read `[git].allow_dirty`, `[agents].write_changelog`, and `[agents].changelog_path`.',
|
|
165
|
-
'3. If `allow_dirty = false` or absent, check `git status --short` and stop if the worktree is dirty.',
|
|
166
|
-
'4. Run the project type checker, commonly `bun run typecheck`.',
|
|
167
|
-
'5. Run the project test suite, commonly `bun test`.',
|
|
168
|
-
'6. Run `<mirror> version plan <target>` and use the planned next version as the source of truth.',
|
|
169
|
-
'7. Update release documentation only when it is part of the project release process.',
|
|
170
|
-
'8. If `[agents].write_changelog = false`, skip changelog edits. Otherwise update `[agents].changelog_path`, defaulting to `CHANGELOG.md` in the project root, and summarize only real changes.',
|
|
171
|
-
'9. Commit release-preparation changes before applying the version bump.',
|
|
172
|
-
'10. Run `<mirror> version apply <target> --yes`. Include `--commit` when file outputs and Git tag output are combined unless config already enables commits or push.',
|
|
173
|
-
'',
|
|
174
|
-
'## Safety Rules',
|
|
175
|
-
'',
|
|
176
|
-
'- Never skip `version plan`.',
|
|
177
|
-
'- Never hand-edit `package.json` or `jsr.json` version fields as a Mirror substitute.',
|
|
178
|
-
'- Never create Git tags manually for a Mirror-managed release unless recovering intentionally.',
|
|
179
|
-
'- Do not apply a version bump after failed typecheck or tests.',
|
|
180
|
-
'- Do not push release refs unless explicitly requested or configured.',
|
|
181
|
-
'- When plan output is surprising, stop and explain the mismatch.',
|
|
182
|
-
'',
|
|
183
|
-
'## Initialization Workflow',
|
|
184
|
-
'',
|
|
185
|
-
'Use `mirror init package.json`, `mirror init jsr.json`, or `mirror init git`, then validate with `mirror config check`, inspect with `mirror config show`, and test with `mirror version current` plus `mirror version plan patch`.',
|
|
186
|
-
'',
|
|
187
|
-
'## Configuration Reference',
|
|
188
|
-
'',
|
|
189
|
-
'Mirror searches for configuration via `--config <path>`, `./mirror.config.toml`, or `./config/mirror.config.toml`.',
|
|
190
|
-
'',
|
|
191
|
-
'Common configuration keys: `[version].source`, `[version].output`, `[version].prerelease_id`, `[git].tag_template`, `[git].commit`, `[git].push`, `[git].allow_dirty`, `[agents].write_changelog`, `[agents].changelog_path`, `[agents].auto_agents_md`, and `[agents].auto_skill_install`.',
|
|
192
|
-
'',
|
|
193
|
-
'Agent automation options default to true. Set `write_changelog = false` to tell agents to skip changelog edits, `changelog_path = "docs/CHANGELOG.md"` to specify the changelog file, `auto_agents_md = false` to stop Mirror from inserting its AGENTS.md section, and `auto_skill_install = false` to stop Mirror from installing `guiho-as-mirror` globally when missing.',
|
|
194
|
-
'',
|
|
195
|
-
'## CLI Reference',
|
|
196
|
-
'',
|
|
197
|
-
'- `mirror config show`',
|
|
198
|
-
'- `mirror config check`',
|
|
199
|
-
'- `mirror config schema`',
|
|
200
|
-
'- `mirror agents install local`',
|
|
201
|
-
'- `mirror agents install global`',
|
|
202
|
-
'- `mirror agents instructions`',
|
|
203
|
-
'- `mirror version current`',
|
|
204
|
-
'- `mirror version next <target>`',
|
|
205
|
-
'- `mirror version plan <target>`',
|
|
206
|
-
'- `mirror version apply <target> --yes`',
|
|
207
|
-
'',
|
|
208
|
-
'## Response Style',
|
|
209
|
-
'',
|
|
210
|
-
'When reporting a Mirror release result, include the target, current version, planned next version, typecheck/test status, docs or changelog files changed, final apply command, and whether commits, tags, or pushes were created.',
|
|
211
|
-
'',
|
|
212
|
-
].join('\n');
|
package/library/cli.d.ts
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @copyright Copyright (c) 2026 GUIHO Technologies as represented by Cristóvão GUIHO. All Rights Reserved.
|
|
3
|
-
*/
|
|
4
|
-
export declare const createMirrorCommand: () => import("citty").CommandDef<{
|
|
5
|
-
config: {
|
|
6
|
-
type: "string";
|
|
7
|
-
description: string;
|
|
8
|
-
};
|
|
9
|
-
cwd: {
|
|
10
|
-
type: "string";
|
|
11
|
-
description: string;
|
|
12
|
-
};
|
|
13
|
-
format: {
|
|
14
|
-
type: "enum";
|
|
15
|
-
options: string[];
|
|
16
|
-
default: string;
|
|
17
|
-
description: string;
|
|
18
|
-
};
|
|
19
|
-
'no-color': {
|
|
20
|
-
type: "boolean";
|
|
21
|
-
description: string;
|
|
22
|
-
};
|
|
23
|
-
verbose: {
|
|
24
|
-
type: "boolean";
|
|
25
|
-
description: string;
|
|
26
|
-
};
|
|
27
|
-
}>;
|
|
28
|
-
export declare const runMirrorCli: (rawArgs?: string[]) => Promise<void>;
|
|
29
|
-
//# sourceMappingURL=cli.d.ts.map
|
package/library/cli.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../source/cli.ts"],"names":[],"mappings":"AAAA;;GAEG;AA6DH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;EAc5B,CAAA;AAEJ,eAAO,MAAM,YAAY,GAAU,kBAA+B,kBAwEjE,CAAA"}
|