@marvinribeiro_/ignity 0.0.0-stage → 2.0.0-alpha.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/CHANGELOG.md +28 -0
- package/LICENSE +21 -0
- package/README.md +43 -2
- package/bin/ignity.js +13 -0
- package/content/adapters/AGENTS.md +11 -0
- package/content/adapters/CLAUDE.md +11 -0
- package/content/framework/FRAMEWORK.md +150 -0
- package/content/skills/elementor/CHANGELOG.md +16 -0
- package/content/skills/elementor/SKILL.md +92 -0
- package/content/skills/elementor/references/operacao.md +35 -0
- package/content/skills/web-assets/SKILL.md +25 -0
- package/content/skills/web-figma-spec/SKILL.md +27 -0
- package/content/skills/web-motion/SKILL.md +32 -0
- package/content/skills/web-orchestrator/SKILL.md +49 -0
- package/content/skills/web-qa/SKILL.md +34 -0
- package/content/skills/web-release/SKILL.md +22 -0
- package/content/skills/web-seo/SKILL.md +28 -0
- package/content/skills/web-setup/SKILL.md +51 -0
- package/content/templates/ASSETS.csv +1 -0
- package/content/templates/BRIEF.md +75 -0
- package/content/templates/COPY.md +8 -0
- package/content/templates/DECISIONS.md +12 -0
- package/content/templates/IGNITY-FEEDBACK.md +34 -0
- package/content/templates/INICIAR.md +11 -0
- package/content/templates/QA.md +35 -0
- package/content/templates/RETOMAR.md +9 -0
- package/content/templates/SECTIONS.md +12 -0
- package/content/templates/STATE.md +52 -0
- package/package.json +24 -4
- package/src/cli.js +124 -0
- package/src/commands/doctor.js +214 -0
- package/src/commands/init.js +36 -0
- package/src/commands/status.js +67 -0
- package/src/commands/uninstall.js +74 -0
- package/src/commands/update.js +13 -0
- package/src/data/v1-hashes.json +44 -0
- package/src/lib/backup.js +52 -0
- package/src/lib/client-detect.js +19 -0
- package/src/lib/files.js +86 -0
- package/src/lib/log.js +44 -0
- package/src/lib/manifest.js +71 -0
- package/src/lib/mcp-config.js +69 -0
- package/src/lib/merger.js +95 -0
- package/src/lib/node-check.js +28 -0
- package/src/lib/paths.js +91 -0
- package/src/lib/prompt.js +30 -0
- package/src/lib/sanitize-url.js +14 -0
- package/src/lib/sync.js +251 -0
- package/src/lib/v1-detect.js +46 -0
- package/src/lib/writer.js +81 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/** AC 13 and AC 13a: detects a v1 installation (instalar.py) without `.ignity/manifest.json`. */
|
|
4
|
+
|
|
5
|
+
const fs = require('node:fs');
|
|
6
|
+
const path = require('node:path');
|
|
7
|
+
const { V1_FRAMEWORK_PATH } = require('./paths');
|
|
8
|
+
|
|
9
|
+
const V1_DATA = require('../data/v1-hashes.json');
|
|
10
|
+
const V1_SKILL_SIGNALS = ['.claude/skills/web-orchestrator/SKILL.md', '.agents/skills/web-orchestrator/SKILL.md'];
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @param {string} root
|
|
14
|
+
* @returns {{detected: boolean, skillSignals: string[], frameworkSignal: boolean, describe: () => string[]}}
|
|
15
|
+
*/
|
|
16
|
+
function detectV1(root) {
|
|
17
|
+
const skillSignals = V1_SKILL_SIGNALS.filter((rel) => fs.existsSync(path.join(root, ...rel.split('/'))));
|
|
18
|
+
const frameworkSignal = fs.existsSync(path.join(root, ...V1_FRAMEWORK_PATH.split('/')));
|
|
19
|
+
return {
|
|
20
|
+
detected: skillSignals.length > 0 || frameworkSignal,
|
|
21
|
+
skillSignals,
|
|
22
|
+
frameworkSignal,
|
|
23
|
+
describe() {
|
|
24
|
+
const lines = [];
|
|
25
|
+
lines.push(
|
|
26
|
+
skillSignals.length
|
|
27
|
+
? `sinal encontrado: ${skillSignals.join(', ')}`
|
|
28
|
+
: 'sinal ausente: {.claude|.agents}/skills/web-orchestrator/SKILL.md',
|
|
29
|
+
);
|
|
30
|
+
lines.push(frameworkSignal ? `sinal encontrado: ${V1_FRAMEWORK_PATH}` : `sinal ausente: ${V1_FRAMEWORK_PATH}`);
|
|
31
|
+
return lines;
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** SHA-256 of each file the v1 installer wrote, by installed path. */
|
|
37
|
+
function v1Hashes() {
|
|
38
|
+
return new Map(Object.entries(V1_DATA.files));
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Original v1 adapter text (`CLAUDE.md` / `AGENTS.md`). */
|
|
42
|
+
function v1AdapterText(name) {
|
|
43
|
+
return V1_DATA.adapters[name] ? V1_DATA.adapters[name].text : null;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
module.exports = { detectV1, v1Hashes, v1AdapterText, V1_SKILL_SIGNALS, V1_DATA };
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Single choke point for every write/remove the CLI makes (AC 2, AC 11).
|
|
5
|
+
* - `--dry-run`: prints PREVER CRIAR / ATUALIZAR / REMOVER and touches nothing.
|
|
6
|
+
* - project/ guard: only `init` may create a missing file there; nothing else, ever.
|
|
7
|
+
* - every path is resolved inside the target dir (path traversal / symlink guard).
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const fs = require('node:fs');
|
|
11
|
+
const path = require('node:path');
|
|
12
|
+
const { resolveInside, isProjectPath, resolvesToProject } = require('./paths');
|
|
13
|
+
const { atomicWriteFile } = require('./files');
|
|
14
|
+
|
|
15
|
+
const LABELS = {
|
|
16
|
+
create: ['PREVER CRIAR', 'CRIADO'],
|
|
17
|
+
update: ['PREVER ATUALIZAR', 'ATUALIZADO'],
|
|
18
|
+
remove: ['PREVER REMOVER', 'REMOVIDO'],
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @param {{root: string, dryRun: boolean, out: object, allowProjectCreate?: boolean}} options
|
|
23
|
+
*/
|
|
24
|
+
function createWriter({ root, dryRun, out, allowProjectCreate = false }) {
|
|
25
|
+
let changes = 0;
|
|
26
|
+
|
|
27
|
+
function guard(op, rel) {
|
|
28
|
+
const abs = resolveInside(root, rel);
|
|
29
|
+
if (isProjectPath(rel) || resolvesToProject(root, abs)) {
|
|
30
|
+
const allowed = isProjectPath(rel) && op === 'create' && allowProjectCreate && !fs.existsSync(abs);
|
|
31
|
+
if (!allowed) throw new Error(`Operação recusada: o Ignity não altera nem remove nada em project/ (${rel}).`);
|
|
32
|
+
}
|
|
33
|
+
return abs;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function report(op, rel, note) {
|
|
37
|
+
const label = LABELS[op][dryRun ? 0 : 1];
|
|
38
|
+
out.line(`${label} ${rel}${note ? ` (${note})` : ''}`);
|
|
39
|
+
changes++;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return {
|
|
43
|
+
get changes() {
|
|
44
|
+
return changes;
|
|
45
|
+
},
|
|
46
|
+
create(rel, data, note) {
|
|
47
|
+
const abs = guard('create', rel);
|
|
48
|
+
if (!dryRun) atomicWriteFile(abs, data);
|
|
49
|
+
report('create', rel, note);
|
|
50
|
+
},
|
|
51
|
+
update(rel, data, note) {
|
|
52
|
+
const abs = guard('update', rel);
|
|
53
|
+
if (!dryRun) atomicWriteFile(abs, data);
|
|
54
|
+
report('update', rel, note);
|
|
55
|
+
},
|
|
56
|
+
remove(rel, note) {
|
|
57
|
+
const abs = guard('remove', rel);
|
|
58
|
+
if (!dryRun) {
|
|
59
|
+
fs.rmSync(abs, { force: true });
|
|
60
|
+
pruneEmptyDirs(root, path.dirname(abs));
|
|
61
|
+
}
|
|
62
|
+
report('remove', rel, note);
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** Removes empty parent dirs, stopping below the first level (`.claude/`, `.agents/`, `.ignity/` stay). */
|
|
68
|
+
function pruneEmptyDirs(root, dir) {
|
|
69
|
+
let current = dir;
|
|
70
|
+
while (current !== root && path.dirname(current) !== root) {
|
|
71
|
+
try {
|
|
72
|
+
if (fs.readdirSync(current).length > 0) return;
|
|
73
|
+
fs.rmdirSync(current);
|
|
74
|
+
} catch {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
current = path.dirname(current);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
module.exports = { createWriter, pruneEmptyDirs };
|