invos 2.0.3 → 2.0.5
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/bin/invos.js +1 -1
- package/kit/CHANGELOG.md +45 -0
- package/kit/INVOS.json +1 -1
- package/package.json +3 -2
- package/src/commands/doctor.js +17 -4
- package/src/commands/install.js +9 -10
- package/src/symlinks.js +31 -3
- package/src/utils.js +1 -1
package/bin/invos.js
CHANGED
package/kit/CHANGELOG.md
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
Todas as mudanças notáveis no INVOS. Formato baseado em [Keep a Changelog](https://keepachangelog.com/).
|
|
4
|
+
|
|
5
|
+
## [2.0.4] - 2026-07-29
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
- Symlinks Windows: fallback para copyFileSync quando symlinkSync falha (EPERM)
|
|
9
|
+
- Symlinks stale: limpeza automática de symlinks quebrados em `.claude/skills/`
|
|
10
|
+
- Dead code removido no `install.js` — loop simplificado
|
|
11
|
+
- `.env` não vaza mais em subpastas do bundle (SKIP recursivo)
|
|
12
|
+
- `.env.example` não é mais sobrescrito em updates
|
|
13
|
+
- Doctor: threshold reduzido de 5 para 1 (só erro se zero skills)
|
|
14
|
+
- Doctor `--fix` só roda quando há issues reais
|
|
15
|
+
- Stack traces completas em erros CLI
|
|
16
|
+
- Comparação de paths normalizada com `path.resolve()`
|
|
17
|
+
- Race condition (TOCTOU) no install tratada com try/catch
|
|
18
|
+
|
|
19
|
+
## [2.0.3] - 2026-07-29
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
- Templates de memória (`empresa.md`, `estrategia.md`) limpos — dados preenchidos incorretamente removidos
|
|
23
|
+
|
|
24
|
+
## [2.0.2] - 2026-07-28
|
|
25
|
+
|
|
26
|
+
### Fixed
|
|
27
|
+
- 8 findings de segurança corrigidos
|
|
28
|
+
- README atualizado
|
|
29
|
+
- Manifesto open-source
|
|
30
|
+
|
|
31
|
+
## [2.0.1] - 2026-07-27
|
|
32
|
+
|
|
33
|
+
### Added
|
|
34
|
+
- Kit INVOS v2 sincronizado do monorepo
|
|
35
|
+
- ASCII art logo
|
|
36
|
+
- Reenquadramento como AI co-founder
|
|
37
|
+
|
|
38
|
+
## [2.0.0] - 2026-07-26
|
|
39
|
+
|
|
40
|
+
### Added
|
|
41
|
+
- INVOS v2: novo kit, novo README, MIT license
|
|
42
|
+
- CLI: bundle kit para npm publish (`npx invos` de qualquer máquina)
|
|
43
|
+
- Skills: carrossel, humanizer, SEO, ads, notion, youtube-summarizer
|
|
44
|
+
- Squads: advisory-board, brand, hormozi-squad
|
|
45
|
+
- Comandos: init, install, update, doctor
|
package/kit/INVOS.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "invos",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.5",
|
|
4
4
|
"description": "INVOS — OS do negócio em arquivos. Open-source. CLI: init, install, update, doctor.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -11,7 +11,8 @@
|
|
|
11
11
|
},
|
|
12
12
|
"scripts": {
|
|
13
13
|
"bundle-kit": "node scripts/bundle-kit.mjs",
|
|
14
|
-
"prepublishOnly": "node scripts/bundle-kit.mjs"
|
|
14
|
+
"prepublishOnly": "node scripts/bundle-kit.mjs",
|
|
15
|
+
"test": "node tests/smoke-test.mjs"
|
|
15
16
|
},
|
|
16
17
|
"files": [
|
|
17
18
|
"bin/",
|
package/src/commands/doctor.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { existsSync, readdirSync } from 'node:fs';
|
|
2
2
|
import { resolve } from 'node:path';
|
|
3
|
+
import { execSync } from 'node:child_process';
|
|
3
4
|
import { loadManifest } from '../manifest.js';
|
|
4
5
|
import { readLock } from '../lock.js';
|
|
5
6
|
import { checkClaudeSymlinks, syncClaudeSymlinks } from '../symlinks.js';
|
|
@@ -45,7 +46,7 @@ export async function doctor(kit, kitRoot, targetDir, args) {
|
|
|
45
46
|
existsSync(resolve(skillsDir, e, 'SKILL.md')),
|
|
46
47
|
).length;
|
|
47
48
|
r.push(` ✓ skills: ${n}`);
|
|
48
|
-
if (n <
|
|
49
|
+
if (n < 1) ok = false;
|
|
49
50
|
} else {
|
|
50
51
|
r.push(' ✗ .agents/skills');
|
|
51
52
|
ok = false;
|
|
@@ -58,7 +59,7 @@ export async function doctor(kit, kitRoot, targetDir, args) {
|
|
|
58
59
|
ok = false;
|
|
59
60
|
}
|
|
60
61
|
|
|
61
|
-
if (fix) {
|
|
62
|
+
if (fix && !ok) {
|
|
62
63
|
const confirmed = await askFix(!ok);
|
|
63
64
|
if (!confirmed) {
|
|
64
65
|
r.push(' --fix: skipped (not confirmed)');
|
|
@@ -76,8 +77,20 @@ export async function doctor(kit, kitRoot, targetDir, args) {
|
|
|
76
77
|
}
|
|
77
78
|
|
|
78
79
|
const man = loadManifest(resolve(targetDir, 'INVOS.json'));
|
|
79
|
-
|
|
80
|
-
r.push(
|
|
80
|
+
const currentVersion = man?.version || kit?.version || '?';
|
|
81
|
+
r.push(` kit v${currentVersion}`);
|
|
82
|
+
|
|
83
|
+
try {
|
|
84
|
+
const latest = execSync('npm view invos version --no-optional 2>/dev/null', { encoding: 'utf8', timeout: 5000 }).trim();
|
|
85
|
+
if (latest && latest !== currentVersion) {
|
|
86
|
+
r.push(` → nova versão disponível: v${latest}`);
|
|
87
|
+
r.push(' update: npx invos@latest update');
|
|
88
|
+
} else {
|
|
89
|
+
r.push(' ✓ versão atualizada');
|
|
90
|
+
}
|
|
91
|
+
} catch {
|
|
92
|
+
r.push(' update: npx invos@latest update');
|
|
93
|
+
}
|
|
81
94
|
|
|
82
95
|
console.log(r.join('\n'));
|
|
83
96
|
if (!ok) {
|
package/src/commands/install.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync } from 'node:fs';
|
|
2
2
|
import { resolve } from 'node:path';
|
|
3
3
|
import {
|
|
4
|
-
collectFiles, copyFileWithDirs,
|
|
4
|
+
collectFiles, copyFileWithDirs, isDevPath,
|
|
5
5
|
} from '../utils.js';
|
|
6
6
|
import { buildLock, readLock, writeLock } from '../lock.js';
|
|
7
7
|
import { syncClaudeSymlinks } from '../symlinks.js';
|
|
@@ -13,16 +13,15 @@ export async function install(kit, kitRoot, targetDir) {
|
|
|
13
13
|
|
|
14
14
|
for (const f of files) {
|
|
15
15
|
const dest = resolve(targetDir, f.relPath);
|
|
16
|
-
if (
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
16
|
+
if (!existsSync(dest)) {
|
|
17
|
+
try {
|
|
18
|
+
copyFileWithDirs(f.fullPath, dest);
|
|
19
|
+
copied++;
|
|
20
|
+
} catch (err) {
|
|
21
|
+
console.error('install: failed to copy', f.relPath, err.message);
|
|
22
|
+
}
|
|
23
23
|
} else {
|
|
24
|
-
|
|
25
|
-
copied++;
|
|
24
|
+
skipped++;
|
|
26
25
|
}
|
|
27
26
|
}
|
|
28
27
|
|
package/src/symlinks.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
existsSync, mkdirSync, symlinkSync, unlinkSync, readlinkSync,
|
|
3
|
-
readdirSync, statSync,
|
|
3
|
+
readdirSync, statSync, copyFileSync, cpSync,
|
|
4
4
|
} from 'node:fs';
|
|
5
5
|
import { resolve, dirname } from 'node:path';
|
|
6
6
|
|
|
@@ -27,15 +27,43 @@ export function syncClaudeSymlinks(_kitRoot, targetRoot) {
|
|
|
27
27
|
|
|
28
28
|
for (const skill of listSkills(agentsDir)) {
|
|
29
29
|
const linkPath = resolve(claudeDir, skill);
|
|
30
|
+
const expectedTarget = resolve(agentsDir, skill);
|
|
30
31
|
if (existsSync(linkPath)) {
|
|
31
32
|
try {
|
|
32
|
-
|
|
33
|
+
const currentTarget = resolve(dirname(linkPath), readlinkSync(linkPath));
|
|
34
|
+
if (resolve(currentTarget) === resolve(expectedTarget)) continue;
|
|
33
35
|
unlinkSync(linkPath);
|
|
34
36
|
} catch (err) {
|
|
35
37
|
console.error('syncClaudeSymlinks: failed to update', skill, err.message);
|
|
36
38
|
}
|
|
37
39
|
}
|
|
38
|
-
|
|
40
|
+
try {
|
|
41
|
+
symlinkSync(`${REL}/${skill}`, linkPath);
|
|
42
|
+
} catch (err) {
|
|
43
|
+
if (err.code === 'EPERM') {
|
|
44
|
+
console.warn('syncClaudeSymlinks: symlink failed for', skill, '(EPERM), falling back to copy');
|
|
45
|
+
cpSync(resolve(agentsDir, skill), linkPath, { recursive: true });
|
|
46
|
+
} else {
|
|
47
|
+
throw err;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (existsSync(claudeDir)) {
|
|
53
|
+
for (const entry of readdirSync(claudeDir)) {
|
|
54
|
+
const linkPath = resolve(claudeDir, entry);
|
|
55
|
+
try {
|
|
56
|
+
const stat = statSync(linkPath);
|
|
57
|
+
if (stat.isSymbolicLink()) {
|
|
58
|
+
const target = resolve(dirname(linkPath), readlinkSync(linkPath));
|
|
59
|
+
if (!existsSync(target)) {
|
|
60
|
+
unlinkSync(linkPath);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
} catch {
|
|
64
|
+
// ignore read errors
|
|
65
|
+
}
|
|
66
|
+
}
|
|
39
67
|
}
|
|
40
68
|
}
|
|
41
69
|
|
package/src/utils.js
CHANGED
|
@@ -16,7 +16,7 @@ function skipDot(name) {
|
|
|
16
16
|
export function isDenylisted(relPath) {
|
|
17
17
|
const p = relPath.split('/');
|
|
18
18
|
if (p[0] === '.git' || p[0] === 'node_modules' || p[0] === 'packages') return true;
|
|
19
|
-
if (p[0] === 'INVOS-LOCK.json' || p[0] === '.env' || p[0] === '.claude') return true;
|
|
19
|
+
if (p[0] === 'INVOS-LOCK.json' || p[0] === '.env' || p[0] === '.env.example' || p[0] === '.claude') return true;
|
|
20
20
|
if (p[0] === '_memoria' || p[0] === 'memoria') return true;
|
|
21
21
|
if (p[0] === 'clientes') return true;
|
|
22
22
|
if (p[0] === 'conteudo') return true;
|