feat: introduce archify skill for generating architecture diagrams

- Added a new Archify skill, enabling users to create polished architecture, workflow, sequence, data-flow, and lifecycle diagrams.
- Implemented comprehensive functionality including rendering, validation, and delivery of diagrams in various formats.
- Integrated a user-friendly command-line interface for generating and previewing diagrams.
- Developed supporting files including package.json, LICENSE, and SKILL.md for documentation and licensing.
- Added unit tests to ensure reliability and functionality of the new skill.

These changes enhance the application by providing a structured approach to visualizing system architecture and workflows, improving user experience and data representation.
This commit is contained in:
shancheas
2026-08-31 11:31:29 +07:00
parent 050fafd731
commit 166e0d40ac
221 changed files with 191228 additions and 1 deletions
@@ -0,0 +1,127 @@
import fs from 'node:fs';
import path from 'node:path';
const DIAGNOSTIC_MODE = process.env.ARCHIFY_DIAGNOSTIC_FORMAT === 'json';
const recorded = [];
const recordedMessages = new Set();
const boundaryKey = Symbol.for('archify.renderer-diagnostic-boundary');
let recordingSuppressionDepth = 0;
function plainObject(value) {
if (!value || typeof value !== 'object' || Array.isArray(value)) return {};
return Object.fromEntries(Object.entries(value).filter(([, entry]) => entry !== undefined));
}
function normalizedDiagnostic(diagnostic) {
const message = String(diagnostic?.message || 'Archify could not classify this failure.').trim();
return {
code: String(diagnostic?.code || 'internal/unclassified'),
severity: diagnostic?.severity === 'warning' ? 'warning' : 'error',
message,
subject: plainObject(diagnostic?.subject),
evidence: plainObject(diagnostic?.evidence),
supportedFixes: Array.isArray(diagnostic?.supportedFixes)
? [...new Set(diagnostic.supportedFixes.map((fix) => String(fix).trim()).filter(Boolean))]
: [],
...(Array.isArray(diagnostic?.suppresses) ? {
suppresses: [...new Set(diagnostic.suppresses.map((code) => String(code).trim()).filter(Boolean))],
} : {}),
};
}
export function recordDiagnostic(diagnostic) {
if (!DIAGNOSTIC_MODE || recordingSuppressionDepth > 0) return;
const normalized = normalizedDiagnostic(diagnostic);
if (recordedMessages.has(normalized.message)) return;
recordedMessages.add(normalized.message);
recorded.push(normalized);
}
export function withDiagnosticRecordingSuppressed(callback) {
recordingSuppressionDepth += 1;
try {
return callback();
} finally {
recordingSuppressionDepth -= 1;
}
}
export function throwDiagnosticError(message, diagnostics) {
for (const diagnostic of diagnostics || []) recordDiagnostic(diagnostic);
const error = new Error(message);
error.archifyDiagnostics = (diagnostics || []).map(normalizedDiagnostic);
throw error;
}
export function throwDiagnosticProblems(prefix, problems, { code = 'layout/constraint', subject = {} } = {}) {
const messages = (problems || []).map((problem) => String(problem));
const diagnostics = messages.map((message) => normalizedDiagnostic({
code,
severity: 'error',
message,
subject,
evidence: {},
supportedFixes: [],
}));
throwDiagnosticError(`${prefix}:\n- ${messages.join('\n- ')}`, diagnostics);
}
function fallbackDiagnostic(error) {
const input = process.argv[2] ? path.resolve(process.argv[2]) : undefined;
if (error instanceof SyntaxError) {
return normalizedDiagnostic({
code: 'input/json-parse',
severity: 'error',
message: `Input JSON could not be parsed: ${error.message}`,
subject: { input },
evidence: { reason: error.message },
supportedFixes: ['repair the JSON syntax and run validation again'],
});
}
if (error?.code === 'ENOENT' || error?.code === 'EACCES' || error?.code === 'EISDIR') {
return normalizedDiagnostic({
code: 'input/read',
severity: 'error',
message: `Input could not be read: ${error.message}`,
subject: { input },
evidence: { systemCode: error.code, reason: error.message },
supportedFixes: ['provide one readable JSON input file'],
});
}
return normalizedDiagnostic({
code: 'internal/unclassified',
severity: 'error',
message: error?.message || 'Renderer failed without a diagnostic.',
subject: { input },
evidence: { errorName: error?.name || 'Error' },
supportedFixes: [],
});
}
function rendererFailure(error) {
const attached = Array.isArray(error?.archifyDiagnostics)
? error.archifyDiagnostics.map(normalizedDiagnostic)
: [];
const diagnostics = recorded.length ? recorded : (attached.length ? attached : [fallbackDiagnostic(error)]);
return {
schemaVersion: 1,
ok: false,
source: 'renderer',
error: error?.message || 'Renderer failed without a diagnostic.',
diagnostics,
};
}
export function installRendererDiagnosticBoundary() {
if (!DIAGNOSTIC_MODE || globalThis[boundaryKey]) return;
globalThis[boundaryKey] = true;
process.on('uncaughtException', (error) => {
const payload = `${JSON.stringify(rendererFailure(error))}\n`;
try {
fs.writeSync(process.stderr.fd, payload);
} catch {
// The renderer is already failing. Avoid replacing its real error with a
// secondary stream failure; the parent CLI still has the exit status.
}
process.exit(1);
});
}