novahiz 0.5.2 → 0.7.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 +87 -0
- package/README.md +4 -4
- package/adapters/opencode/commands/novahiz-upgrade.md +13 -0
- package/adapters/opencode/instructions.md +21 -9
- package/adapters/opencode/novahiz-plugin.ts +173 -31
- package/catalog/categories.json +14 -0
- package/catalog/providers.json +25 -0
- package/catalog/rules.json +19 -0
- package/catalog/vault-structure.json +366 -0
- package/dist/cli.js +19 -39
- package/dist/commands/docs.js +55 -0
- package/dist/commands/gate.js +54 -0
- package/dist/commands/second-memory.js +1116 -67
- package/dist/commands/stitch.js +298 -0
- package/dist/commands/upgrade.js +161 -0
- package/dist/gate.js +85 -1
- package/dist/spec.js +28 -1
- package/install/install.mjs +148 -16
- package/install/ui.d.mts +35 -0
- package/install/ui.mjs +246 -0
- package/mcp/novahiz-docs/index.mjs +63 -0
- package/mcp/novahiz-docs/src/query.ts +1 -1
- package/mcp/stitch-template/recommandation.md +14 -0
- package/package.json +1 -1
- package/skills/novahiz-second-memory/SKILL.md +189 -277
- package/skills/novahiz-second-memory/references/arborescence.md +131 -0
- package/skills/novahiz-second-memory/references/templates.md +153 -0
- package/skills/novahiz-stitch-fidelity/SKILL.md +113 -0
- package/skills/novahiz-stitch-fidelity/defaults/verify.config.defaults.json +29 -0
- package/skills/novahiz-stitch-fidelity/references/capture-recipes.md +74 -0
- package/skills/novahiz-stitch-fidelity/references/judgment-grid.md +67 -0
- package/skills/novahiz-stitch-fidelity/scripts/stitch_capture.mjs +598 -0
- package/skills/novahiz-stitch-fidelity/scripts/stitch_composite.mjs +271 -0
- package/skills/stitch-design-fidelity/SKILL.md +140 -0
- package/skills/stitch-design-fidelity/evals.json +23 -0
- package/skills/stitch-design-fidelity/references/anti-ai-patterns.md +115 -0
- package/skills/stitch-design-fidelity/references/design-system.md +192 -0
- package/skills/stitch-design-fidelity/references/prompt-methodology.md +143 -0
- package/skills/stitch-design-fidelity/references/stitch-fidelity.md +65 -0
- package/skills/stitch-design-fidelity/references/stitch-mcp.md +100 -0
- package/skills/stitch-design-fidelity/scripts/validate-frontmatter.py +11 -0
- package/src/cli.ts +18 -39
- package/src/commands/docs.ts +62 -0
- package/src/commands/gate.ts +54 -0
- package/src/commands/second-memory.ts +1164 -66
- package/src/commands/stitch.ts +295 -0
- package/src/commands/upgrade.ts +174 -0
- package/src/gate.ts +77 -1
- package/src/spec.ts +51 -1
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 1,
|
|
3
|
+
"index": "INDEX.md",
|
|
4
|
+
"log": "log.md",
|
|
5
|
+
"structureFile": "STRUCTURE.md",
|
|
6
|
+
"moc": "_MOC.md",
|
|
7
|
+
"indexSection": "Categories",
|
|
8
|
+
"systemFolders": ["Inbox", "Archive", "Templates", "Excalidraw"],
|
|
9
|
+
"systemFiles": ["INDEX.md", "log.md", "STRUCTURE.md"],
|
|
10
|
+
"defaultProject": "general",
|
|
11
|
+
"domains": [
|
|
12
|
+
{
|
|
13
|
+
"id": "code",
|
|
14
|
+
"name": "Code",
|
|
15
|
+
"title": "Code",
|
|
16
|
+
"kind": "domain",
|
|
17
|
+
"keywords": ["code", "coding", "dev", "developer", "programming", "software", "logiciel", "app", "application", "api", "cli", "npm", "git", "repo", "frontend", "backend", "stack", "compilation", "build"],
|
|
18
|
+
"children": [
|
|
19
|
+
{
|
|
20
|
+
"id": "mobile",
|
|
21
|
+
"name": "Mobile",
|
|
22
|
+
"title": "Mobile",
|
|
23
|
+
"kind": "branch",
|
|
24
|
+
"keywords": ["mobile", "flutter", "expo", "react native", "android", "ios", "kotlin", "swift", "xcode", "apk", "ipa", "emulator", "emu", "device", "playstore", "app store"],
|
|
25
|
+
"children": [
|
|
26
|
+
{ "id": "memory", "name": "memory", "title": "Memory", "kind": "memory" },
|
|
27
|
+
{ "id": "docs", "name": "docs", "title": "Docs", "kind": "docs" }
|
|
28
|
+
]
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"id": "web",
|
|
32
|
+
"name": "Web",
|
|
33
|
+
"title": "Web",
|
|
34
|
+
"kind": "branch",
|
|
35
|
+
"keywords": ["web", "nextjs", "next.js", "react", "vue", "angular", "spa", "ssr", "site", "website", "frontend", "html", "css", "tailwind", "browser", "responsive"],
|
|
36
|
+
"children": [
|
|
37
|
+
{ "id": "memory", "name": "memory", "title": "Memory", "kind": "memory" },
|
|
38
|
+
{ "id": "docs", "name": "docs", "title": "Docs", "kind": "docs" }
|
|
39
|
+
]
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"id": "desktop",
|
|
43
|
+
"name": "Desktop",
|
|
44
|
+
"title": "Desktop",
|
|
45
|
+
"kind": "branch",
|
|
46
|
+
"keywords": ["desktop", "windows", "linux", "mac", "macos", "ubuntu", "electron", "tauri", "winui", "winforms", "qt", "bureau", "exe", "appimage", "deb"],
|
|
47
|
+
"children": [
|
|
48
|
+
{ "id": "memory", "name": "memory", "title": "Memory", "kind": "memory" },
|
|
49
|
+
{ "id": "docs", "name": "docs", "title": "Docs", "kind": "docs" }
|
|
50
|
+
]
|
|
51
|
+
}
|
|
52
|
+
]
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"id": "trading",
|
|
56
|
+
"name": "Trading",
|
|
57
|
+
"title": "Trading",
|
|
58
|
+
"kind": "domain",
|
|
59
|
+
"keywords": ["trading", "trader", "finance", "financial", "crypto", "bourse", "forex", "invest", "investment", "investissement", "market", "marche", "marché", "strategy", "strategie", "stratégie", "chart", "indicator", "order", "position", "portfolio"],
|
|
60
|
+
"children": [
|
|
61
|
+
{
|
|
62
|
+
"id": "markets",
|
|
63
|
+
"name": "Markets",
|
|
64
|
+
"title": "Markets",
|
|
65
|
+
"kind": "branch",
|
|
66
|
+
"keywords": ["market", "marche", "marché", "crypto", "forex", "action", "stock", "indice", "index", "volatility", "volatilite", "tendance"],
|
|
67
|
+
"children": [
|
|
68
|
+
{ "id": "memory", "name": "memory", "title": "Memory", "kind": "memory" },
|
|
69
|
+
{ "id": "docs", "name": "docs", "title": "Docs", "kind": "docs" }
|
|
70
|
+
]
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"id": "strategies",
|
|
74
|
+
"name": "Strategies",
|
|
75
|
+
"title": "Strategies",
|
|
76
|
+
"kind": "branch",
|
|
77
|
+
"keywords": ["strategy", "strategie", "stratégie", "setup", "backtest", "signal", "risk", "risque", "money management", "entry", "sortie"],
|
|
78
|
+
"children": [
|
|
79
|
+
{ "id": "memory", "name": "memory", "title": "Memory", "kind": "memory" },
|
|
80
|
+
{ "id": "docs", "name": "docs", "title": "Docs", "kind": "docs" }
|
|
81
|
+
]
|
|
82
|
+
}
|
|
83
|
+
]
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
"id": "ai",
|
|
87
|
+
"name": "AI",
|
|
88
|
+
"title": "AI & Data",
|
|
89
|
+
"kind": "domain",
|
|
90
|
+
"keywords": ["ai", "ia", "artificial intelligence", "intelligence artificielle", "machine learning", "llm", "gpt", "model", "modele", "modèle", "dataset", "data", "donnee", "données", "nlp", "prompt", "neural", "deep learning", "analytics", "statistique", "rag", "embedding"],
|
|
91
|
+
"children": [
|
|
92
|
+
{
|
|
93
|
+
"id": "models",
|
|
94
|
+
"name": "Models",
|
|
95
|
+
"title": "Models",
|
|
96
|
+
"kind": "branch",
|
|
97
|
+
"keywords": ["model", "modele", "modèle", "llm", "gpt", "prompt", "fine-tune", "inference", "agent", "pipeline ia", "embedding", "rag"],
|
|
98
|
+
"children": [
|
|
99
|
+
{ "id": "memory", "name": "memory", "title": "Memory", "kind": "memory" },
|
|
100
|
+
{ "id": "docs", "name": "docs", "title": "Docs", "kind": "docs" }
|
|
101
|
+
]
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
"id": "datasets",
|
|
105
|
+
"name": "Datasets",
|
|
106
|
+
"title": "Datasets",
|
|
107
|
+
"kind": "branch",
|
|
108
|
+
"keywords": ["dataset", "data", "donnee", "données", "csv", "etl", "analytics", "statistique", "dashboard", "mesure", "metric"],
|
|
109
|
+
"children": [
|
|
110
|
+
{ "id": "memory", "name": "memory", "title": "Memory", "kind": "memory" },
|
|
111
|
+
{ "id": "docs", "name": "docs", "title": "Docs", "kind": "docs" }
|
|
112
|
+
]
|
|
113
|
+
}
|
|
114
|
+
]
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
"id": "design",
|
|
118
|
+
"name": "Design",
|
|
119
|
+
"title": "Design",
|
|
120
|
+
"kind": "domain",
|
|
121
|
+
"keywords": ["design", "ui", "ux", "figma", "maquette", "mockup", "wireframe", "couleur", "color", "typographie", "typography", "token", "branding", "logo", "icon", "icône", "interface", "charte", "responsive design"],
|
|
122
|
+
"children": [
|
|
123
|
+
{
|
|
124
|
+
"id": "systems",
|
|
125
|
+
"name": "Systems",
|
|
126
|
+
"title": "Systems",
|
|
127
|
+
"kind": "branch",
|
|
128
|
+
"keywords": ["design system", "token", "palette", "typographie", "typography", "composant", "component", "guideline", "charte", "branding", "logo", "icon", "icône"],
|
|
129
|
+
"children": [
|
|
130
|
+
{ "id": "memory", "name": "memory", "title": "Memory", "kind": "memory" },
|
|
131
|
+
{ "id": "docs", "name": "docs", "title": "Docs", "kind": "docs" }
|
|
132
|
+
]
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
"id": "interface",
|
|
136
|
+
"name": "Interface",
|
|
137
|
+
"title": "Interface",
|
|
138
|
+
"kind": "branch",
|
|
139
|
+
"keywords": ["maquette", "mockup", "wireframe", "figma", "ecran", "écran", "page", "screen", "layout", "navigation", "ux", "parcours"],
|
|
140
|
+
"children": [
|
|
141
|
+
{ "id": "memory", "name": "memory", "title": "Memory", "kind": "memory" },
|
|
142
|
+
{ "id": "docs", "name": "docs", "title": "Docs", "kind": "docs" }
|
|
143
|
+
]
|
|
144
|
+
}
|
|
145
|
+
]
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
"id": "devops",
|
|
149
|
+
"name": "DevOps",
|
|
150
|
+
"title": "DevOps",
|
|
151
|
+
"kind": "domain",
|
|
152
|
+
"keywords": ["devops", "ci", "cd", "docker", "kubernetes", "k8s", "terraform", "cloud", "aws", "azure", "gcp", "deploy", "deploiement", "déploiement", "pipeline", "server", "serveur", "nginx", "vm", "container", "monitoring", "observabilite", "observabilité"],
|
|
153
|
+
"children": [
|
|
154
|
+
{
|
|
155
|
+
"id": "infra",
|
|
156
|
+
"name": "Infra",
|
|
157
|
+
"title": "Infra",
|
|
158
|
+
"kind": "branch",
|
|
159
|
+
"keywords": ["infra", "server", "serveur", "cloud", "aws", "azure", "gcp", "vm", "network", "reseau", "réseau", "dns", "storage", "backup", "kubernetes", "k8s", "docker", "container"],
|
|
160
|
+
"children": [
|
|
161
|
+
{ "id": "memory", "name": "memory", "title": "Memory", "kind": "memory" },
|
|
162
|
+
{ "id": "docs", "name": "docs", "title": "Docs", "kind": "docs" }
|
|
163
|
+
]
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
"id": "pipelines",
|
|
167
|
+
"name": "Pipelines",
|
|
168
|
+
"title": "Pipelines",
|
|
169
|
+
"kind": "branch",
|
|
170
|
+
"keywords": ["ci", "cd", "pipeline", "workflow", "github actions", "gitlab", "build", "release", "deploy", "deploiement", "déploiement", "monitoring", "alerte", "log"],
|
|
171
|
+
"children": [
|
|
172
|
+
{ "id": "memory", "name": "memory", "title": "Memory", "kind": "memory" },
|
|
173
|
+
{ "id": "docs", "name": "docs", "title": "Docs", "kind": "docs" }
|
|
174
|
+
]
|
|
175
|
+
}
|
|
176
|
+
]
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
"id": "security",
|
|
180
|
+
"name": "Security",
|
|
181
|
+
"title": "Security",
|
|
182
|
+
"kind": "domain",
|
|
183
|
+
"keywords": ["security", "securite", "sécurité", "audit", "vulnerability", "vulnérabilité", "cve", "owasp", "pentest", "ransomware", "malware", "auth", "token", "encryption", "chiffrement", "secret", "incident", "hardening"],
|
|
184
|
+
"children": [
|
|
185
|
+
{
|
|
186
|
+
"id": "audits",
|
|
187
|
+
"name": "Audits",
|
|
188
|
+
"title": "Audits",
|
|
189
|
+
"kind": "branch",
|
|
190
|
+
"keywords": ["audit", "review", "scan", "pentest", "checklist", "compliance", "conformite", "conformité", "rapport", "hardening", "review sécurité"],
|
|
191
|
+
"children": [
|
|
192
|
+
{ "id": "memory", "name": "memory", "title": "Memory", "kind": "memory" },
|
|
193
|
+
{ "id": "docs", "name": "docs", "title": "Docs", "kind": "docs" }
|
|
194
|
+
]
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
"id": "threats",
|
|
198
|
+
"name": "Threats",
|
|
199
|
+
"title": "Threats",
|
|
200
|
+
"kind": "branch",
|
|
201
|
+
"keywords": ["threat", "menace", "cve", "vulnerability", "vulnérabilité", "incident", "breach", "malware", "ransomware", "phishing", "exploit"],
|
|
202
|
+
"children": [
|
|
203
|
+
{ "id": "memory", "name": "memory", "title": "Memory", "kind": "memory" },
|
|
204
|
+
{ "id": "docs", "name": "docs", "title": "Docs", "kind": "docs" }
|
|
205
|
+
]
|
|
206
|
+
}
|
|
207
|
+
]
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
"id": "business",
|
|
211
|
+
"name": "Business",
|
|
212
|
+
"title": "Business",
|
|
213
|
+
"kind": "domain",
|
|
214
|
+
"keywords": ["business", "marketing", "startup", "offer", "offre", "sales", "vente", "client", "revenue", "revenu", "growth", "croissance", "seo", "brand", "communaute", "communauté", "pricing", "prix", "funnel", "acquisition"],
|
|
215
|
+
"children": [
|
|
216
|
+
{
|
|
217
|
+
"id": "offers",
|
|
218
|
+
"name": "Offers",
|
|
219
|
+
"title": "Offers",
|
|
220
|
+
"kind": "branch",
|
|
221
|
+
"keywords": ["offer", "offre", "produit", "product", "pricing", "prix", "positionnement", "value proposition", "client", "contrat", "deal"],
|
|
222
|
+
"children": [
|
|
223
|
+
{ "id": "memory", "name": "memory", "title": "Memory", "kind": "memory" },
|
|
224
|
+
{ "id": "docs", "name": "docs", "title": "Docs", "kind": "docs" }
|
|
225
|
+
]
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
"id": "growth",
|
|
229
|
+
"name": "Growth",
|
|
230
|
+
"title": "Growth",
|
|
231
|
+
"kind": "branch",
|
|
232
|
+
"keywords": ["growth", "croissance", "marketing", "seo", "ads", "publicite", "publicité", "funnel", "acquisition", "communaute", "communauté", "audience", "conversion", "retention"],
|
|
233
|
+
"children": [
|
|
234
|
+
{ "id": "memory", "name": "memory", "title": "Memory", "kind": "memory" },
|
|
235
|
+
{ "id": "docs", "name": "docs", "title": "Docs", "kind": "docs" }
|
|
236
|
+
]
|
|
237
|
+
}
|
|
238
|
+
]
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
"id": "learning",
|
|
242
|
+
"name": "Learning",
|
|
243
|
+
"title": "Learning",
|
|
244
|
+
"kind": "domain",
|
|
245
|
+
"keywords": ["learning", "cours", "course", "formation", "tutorial", "tutoriel", "etude", "étude", "study", "ecole", "école", "school", "universite", "université", "livre", "book", "certification", "apprendre", "revision", "révision"],
|
|
246
|
+
"children": [
|
|
247
|
+
{
|
|
248
|
+
"id": "courses",
|
|
249
|
+
"name": "Courses",
|
|
250
|
+
"title": "Courses",
|
|
251
|
+
"kind": "branch",
|
|
252
|
+
"keywords": ["cours", "course", "formation", "tutorial", "tutoriel", "mooc", "certification", "module", "lesson", "leçon", "exercice"],
|
|
253
|
+
"children": [
|
|
254
|
+
{ "id": "memory", "name": "memory", "title": "Memory", "kind": "memory" },
|
|
255
|
+
{ "id": "docs", "name": "docs", "title": "Docs", "kind": "docs" }
|
|
256
|
+
]
|
|
257
|
+
},
|
|
258
|
+
{
|
|
259
|
+
"id": "notes",
|
|
260
|
+
"name": "Study-Notes",
|
|
261
|
+
"title": "Study Notes",
|
|
262
|
+
"kind": "branch",
|
|
263
|
+
"keywords": ["note", "fiche", "synthese", "synthèse", "revision", "révision", "flashcard", "ancret", "mémoire", "dissertation", "resume", "résumé"],
|
|
264
|
+
"children": [
|
|
265
|
+
{ "id": "memory", "name": "memory", "title": "Memory", "kind": "memory" },
|
|
266
|
+
{ "id": "docs", "name": "docs", "title": "Docs", "kind": "docs" }
|
|
267
|
+
]
|
|
268
|
+
}
|
|
269
|
+
]
|
|
270
|
+
},
|
|
271
|
+
{
|
|
272
|
+
"id": "wiki",
|
|
273
|
+
"name": "Wiki",
|
|
274
|
+
"title": "Wiki",
|
|
275
|
+
"kind": "domain",
|
|
276
|
+
"keywords": ["wiki", "doc", "docs", "documentation", "guide", "reference", "référence", "manuel", "howto", "how-to", "faq", "glossary", "glossaire", "spec", "specification", "spécification", "convention", "best practice"],
|
|
277
|
+
"children": [
|
|
278
|
+
{
|
|
279
|
+
"id": "guides",
|
|
280
|
+
"name": "Guides",
|
|
281
|
+
"title": "Guides",
|
|
282
|
+
"kind": "branch",
|
|
283
|
+
"keywords": ["guide", "howto", "how-to", "tutoriel", "recipe", "recette", "procedure", "procédure", "checklist", "bonne pratique", "best practice"],
|
|
284
|
+
"children": [
|
|
285
|
+
{ "id": "memory", "name": "memory", "title": "Memory", "kind": "memory" },
|
|
286
|
+
{ "id": "docs", "name": "docs", "title": "Docs", "kind": "docs" }
|
|
287
|
+
]
|
|
288
|
+
},
|
|
289
|
+
{
|
|
290
|
+
"id": "reference",
|
|
291
|
+
"name": "Reference",
|
|
292
|
+
"title": "Reference",
|
|
293
|
+
"kind": "branch",
|
|
294
|
+
"keywords": ["reference", "référence", "manuel", "faq", "glossary", "glossaire", "spec", "specification", "spécification", "convention", "definition", "définition", "api"],
|
|
295
|
+
"children": [
|
|
296
|
+
{ "id": "memory", "name": "memory", "title": "Memory", "kind": "memory" },
|
|
297
|
+
{ "id": "docs", "name": "docs", "title": "Docs", "kind": "docs" }
|
|
298
|
+
]
|
|
299
|
+
}
|
|
300
|
+
]
|
|
301
|
+
},
|
|
302
|
+
{
|
|
303
|
+
"id": "journal",
|
|
304
|
+
"name": "Journal",
|
|
305
|
+
"title": "Journal",
|
|
306
|
+
"kind": "domain",
|
|
307
|
+
"keywords": ["journal", "daily", "quotidien", "diary", "journal intime", "note rapide", "braindump", "weekly review", "review hebdo", "retour", "reflection", "réflexion"],
|
|
308
|
+
"children": [
|
|
309
|
+
{
|
|
310
|
+
"id": "daily",
|
|
311
|
+
"name": "Daily",
|
|
312
|
+
"title": "Daily",
|
|
313
|
+
"kind": "notes",
|
|
314
|
+
"keywords": ["daily", "quotidien", "jour", "matin", "soir", "aujourd'hui", "date"],
|
|
315
|
+
"children": []
|
|
316
|
+
},
|
|
317
|
+
{
|
|
318
|
+
"id": "weekly",
|
|
319
|
+
"name": "Weekly",
|
|
320
|
+
"title": "Weekly",
|
|
321
|
+
"kind": "notes",
|
|
322
|
+
"keywords": ["weekly", "hebdo", "semaine", "review", "bilan"],
|
|
323
|
+
"children": []
|
|
324
|
+
}
|
|
325
|
+
]
|
|
326
|
+
},
|
|
327
|
+
{
|
|
328
|
+
"id": "projects",
|
|
329
|
+
"name": "Projects",
|
|
330
|
+
"title": "Projects",
|
|
331
|
+
"kind": "domain",
|
|
332
|
+
"keywords": ["project", "projet", "roadmap", "milestone", "jalon", "sprint", "todo", "tache", "tâche", "objective", "objectif", "release", "livraison"],
|
|
333
|
+
"children": [
|
|
334
|
+
{
|
|
335
|
+
"id": "active",
|
|
336
|
+
"name": "Active",
|
|
337
|
+
"title": "Active",
|
|
338
|
+
"kind": "notes",
|
|
339
|
+
"keywords": ["active", "en cours", "encours", "wip", "sprint", "todo", "tache", "tâche"],
|
|
340
|
+
"children": []
|
|
341
|
+
},
|
|
342
|
+
{
|
|
343
|
+
"id": "archived",
|
|
344
|
+
"name": "Archived",
|
|
345
|
+
"title": "Archived",
|
|
346
|
+
"kind": "notes",
|
|
347
|
+
"keywords": ["archived", "archive", "termine", "terminé", "done", "clos", "livre", "shipped"],
|
|
348
|
+
"children": []
|
|
349
|
+
}
|
|
350
|
+
]
|
|
351
|
+
}
|
|
352
|
+
],
|
|
353
|
+
"docsKeywords": ["doc", "docs", "documentation", "guide", "reference", "référence", "manuel", "spec", "specification", "spécification", "readme", "api", "tutorial", "tutoriel", "howto", "how-to", "convention", "architecture", "glossaire", "glossary", "faq"],
|
|
354
|
+
"plugins": [
|
|
355
|
+
{ "id": "dataview", "repo": "blacksmithgu/obsidian-dataview", "required": true },
|
|
356
|
+
{ "id": "templater-obsidian", "repo": "silentvoid13/Templater", "required": true },
|
|
357
|
+
{ "id": "obsidian-linter", "repo": "platers/obsidian-linter", "required": true },
|
|
358
|
+
{ "id": "omnisearch", "repo": "scambier/obsidian-omnisearch", "required": true },
|
|
359
|
+
{ "id": "recent-files-obsidian", "repo": "tgrosinger/recent-files-obsidian", "required": true },
|
|
360
|
+
{ "id": "tag-wrangler", "repo": "pjeby/tag-wrangler", "required": true },
|
|
361
|
+
{ "id": "periodic-notes", "repo": "liamcain/obsidian-periodic-notes", "required": true },
|
|
362
|
+
{ "id": "calendar", "repo": "liamcain/obsidian-calendar-plugin", "required": true },
|
|
363
|
+
{ "id": "obsidian-excalidraw-plugin", "repo": "zsviczian/obsidian-excalidraw-plugin", "required": true },
|
|
364
|
+
{ "id": "obsidian-style-settings", "repo": "obsidian-community/obsidian-style-settings", "required": true }
|
|
365
|
+
]
|
|
366
|
+
}
|
package/dist/cli.js
CHANGED
|
@@ -5,7 +5,7 @@ import { spawnSync } from "node:child_process";
|
|
|
5
5
|
import { parse, print, flagOn } from "./commands/context.js";
|
|
6
6
|
import { expandHome } from "./spec.js";
|
|
7
7
|
import { commandCheck, commandSync, commandClassify, commandSkills, commandCategories, commandRules, commandSessionLoad, commandSessionState, commandCatalog, commandRoadmap, commandStep, commandProviders, commandDeps, commandDispatch } from "./commands/inspect.js";
|
|
8
|
-
import { commandGate } from "./commands/gate.js";
|
|
8
|
+
import { commandGate, commandGateToggle } from "./commands/gate.js";
|
|
9
9
|
import { commandReport } from "./commands/report.js";
|
|
10
10
|
import { commandTask } from "./commands/task.js";
|
|
11
11
|
import { commandClean } from "./commands/clean.js";
|
|
@@ -17,6 +17,9 @@ import { memoryCommand } from "./commands/memory.js";
|
|
|
17
17
|
import { secondMemoryCommand } from "./commands/second-memory.js";
|
|
18
18
|
import { commandInit } from "./commands/init.js";
|
|
19
19
|
import { commandAutodocs } from "./commands/autodocs.js";
|
|
20
|
+
import { commandUpgrade } from "./commands/upgrade.js";
|
|
21
|
+
import { commandStitch } from "./commands/stitch.js";
|
|
22
|
+
import { commandDocs } from "./commands/docs.js";
|
|
20
23
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
21
24
|
// M6: HOME was a module-level const, so `--home` (which sets the env var in
|
|
22
25
|
// main()) was silently ignored by the current execution. Read it lazily.
|
|
@@ -52,8 +55,11 @@ function usage() {
|
|
|
52
55
|
"snap [save|list|show|diff|restore|export|verify|prune|status] Ledger snapshots (ours, no external tool)",
|
|
53
56
|
"graph [build|status|find|all|trace|api|map|fresh|help] Code graph (ours, in-process)",
|
|
54
57
|
"memory [status|clean|prune] Project memory hygiene (dry-run by default, --apply)",
|
|
55
|
-
"second-memory [init|lint|fix|sync|status] Obsidian vault management (dry-run by default, --apply)",
|
|
56
|
-
"upgrade
|
|
58
|
+
"second-memory [init|doctor|lint|fix|sync|status|search] Obsidian vault management (dry-run by default, --apply)",
|
|
59
|
+
"upgrade [--apply] Check for a newer release: npm (global installs) or git pull (source checkouts)",
|
|
60
|
+
"docs [status|ingest <id>|--all] Local docs index: state, or fill it (network)",
|
|
61
|
+
"stitch [--key <k>] Configure the Google Stitch MCP API key (interactive prompt if no --key)",
|
|
62
|
+
"gate on|off Persistently disable/enable the gate (restart OpenCode to apply)",
|
|
57
63
|
"version Show version",
|
|
58
64
|
"",
|
|
59
65
|
"",
|
|
@@ -102,40 +108,6 @@ function runInit() {
|
|
|
102
108
|
runSync();
|
|
103
109
|
process.stdout.write("\nDone! Restart opencode to activate Novahiz.\n");
|
|
104
110
|
}
|
|
105
|
-
function runUpgrade(parsed) {
|
|
106
|
-
const home = homeDir();
|
|
107
|
-
if (!existsSync(join(home, ".git"))) {
|
|
108
|
-
process.stderr.write("Not a git repository. Install from source first.\n");
|
|
109
|
-
process.exitCode = 1;
|
|
110
|
-
return;
|
|
111
|
-
}
|
|
112
|
-
// P2-C (LOW): `git pull` rewrote the running code (hooks included) with no
|
|
113
|
-
// preview. Default to a dry run; `--apply` is required to actually pull.
|
|
114
|
-
if (!flagOn(parsed, "apply")) {
|
|
115
|
-
const dry = spawnSync("git", ["pull", "--dry-run"], { cwd: home, encoding: "utf8" });
|
|
116
|
-
const preview = `${dry.stdout ?? ""}${dry.stderr ?? ""}`.trim();
|
|
117
|
-
if (preview)
|
|
118
|
-
process.stdout.write(preview + "\n");
|
|
119
|
-
if (dry.status !== 0) {
|
|
120
|
-
process.stderr.write("Dry run failed; fix git first.\n");
|
|
121
|
-
process.exitCode = 1;
|
|
122
|
-
return;
|
|
123
|
-
}
|
|
124
|
-
process.stdout.write("Dry run only. Re-run `novahiz upgrade --apply` to pull and rebuild.\n");
|
|
125
|
-
process.exitCode = 1;
|
|
126
|
-
return;
|
|
127
|
-
}
|
|
128
|
-
process.stdout.write("Pulling latest changes...\n");
|
|
129
|
-
const pull = spawnSync("git", ["pull", "--ff-only"], { cwd: home, stdio: "inherit" });
|
|
130
|
-
if (pull.status !== 0) {
|
|
131
|
-
process.stderr.write("Pull failed; nothing rebuilt.\n");
|
|
132
|
-
process.exitCode = 1;
|
|
133
|
-
return;
|
|
134
|
-
}
|
|
135
|
-
process.stdout.write("\nRebuilding skill catalog...\n");
|
|
136
|
-
runSync();
|
|
137
|
-
process.stdout.write("\nUpgraded! Restart opencode to apply changes.\n");
|
|
138
|
-
}
|
|
139
111
|
// Async so `doctor --deep` can await its MCP probes; every other command
|
|
140
112
|
// still returns void, which await handles transparently.
|
|
141
113
|
async function main(argv) {
|
|
@@ -170,7 +142,7 @@ async function main(argv) {
|
|
|
170
142
|
return commandClean(parsed);
|
|
171
143
|
case "upgrade":
|
|
172
144
|
case "update":
|
|
173
|
-
return
|
|
145
|
+
return commandUpgrade(parsed);
|
|
174
146
|
case "version":
|
|
175
147
|
case "-v":
|
|
176
148
|
case "--version":
|
|
@@ -181,8 +153,16 @@ async function main(argv) {
|
|
|
181
153
|
return commandSync();
|
|
182
154
|
case "classify":
|
|
183
155
|
return commandClassify(parsed);
|
|
184
|
-
case "gate":
|
|
156
|
+
case "gate": {
|
|
157
|
+
const gateSub = (parsed.positionals[1] ?? "").toLowerCase();
|
|
158
|
+
if (gateSub === "on" || gateSub === "off")
|
|
159
|
+
return commandGateToggle(parsed);
|
|
185
160
|
return commandGate(parsed);
|
|
161
|
+
}
|
|
162
|
+
case "stitch":
|
|
163
|
+
return commandStitch(parsed);
|
|
164
|
+
case "docs":
|
|
165
|
+
return commandDocs(parsed);
|
|
186
166
|
case "skills":
|
|
187
167
|
return commandSkills(parsed);
|
|
188
168
|
case "categories":
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// `novahiz docs` : etat et remplissage de l'index documentaire local.
|
|
2
|
+
// Le travail reseau vit dans mcp/novahiz-docs (ingest) — ce fichier ne fait
|
|
3
|
+
// que lui passer la main par spawn, mcp/ restant hors du typecheck racine
|
|
4
|
+
// (tsconfig include = src/adapters/tests).
|
|
5
|
+
import { spawnSync } from "node:child_process";
|
|
6
|
+
import { existsSync } from "node:fs";
|
|
7
|
+
import { dirname, join } from "node:path";
|
|
8
|
+
import { fileURLToPath } from "node:url";
|
|
9
|
+
import { flagOn } from "./context.js";
|
|
10
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
11
|
+
function usage() {
|
|
12
|
+
process.stderr.write([
|
|
13
|
+
"usage:",
|
|
14
|
+
" novahiz docs status Index state per library",
|
|
15
|
+
" novahiz docs ingest <id>|--all Fill the local docs index (network)",
|
|
16
|
+
" novahiz docs ingest <id> --dry List the targets, touch nothing",
|
|
17
|
+
""
|
|
18
|
+
].join("\n"));
|
|
19
|
+
}
|
|
20
|
+
export function commandDocs(parsed) {
|
|
21
|
+
const sub = parsed.positionals[1];
|
|
22
|
+
const script = join(__dirname, "..", "..", "mcp", "novahiz-docs", "index.mjs");
|
|
23
|
+
if (!existsSync(script)) {
|
|
24
|
+
process.stderr.write(`novahiz docs: missing ${script}\n`);
|
|
25
|
+
process.exitCode = 1;
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
const run = (argv) => {
|
|
29
|
+
const result = spawnSync(process.execPath, [script, ...argv], { encoding: "utf8", stdio: "inherit" });
|
|
30
|
+
process.exitCode = typeof result.status === "number" ? result.status : 1;
|
|
31
|
+
};
|
|
32
|
+
if (sub === "status" || sub === undefined) {
|
|
33
|
+
run(["--status"]);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
if (sub === "ingest") {
|
|
37
|
+
// parse() absorbe la valeur d'un flag : `ingest --dry react` met react dans
|
|
38
|
+
// flags.dry. On recover la spec depuis les deux emplacements et on echoue
|
|
39
|
+
// TOUJOURS vers le dry-run — jamais de reseau quand --dry est ecrit.
|
|
40
|
+
const rawDry = parsed.flags.dry;
|
|
41
|
+
const dry = rawDry !== undefined;
|
|
42
|
+
const spec = parsed.positionals[2] ??
|
|
43
|
+
(typeof rawDry === "string" && rawDry !== "false" && rawDry !== "true" ? rawDry : undefined) ??
|
|
44
|
+
(flagOn(parsed, "all") ? "--all" : undefined);
|
|
45
|
+
if (!spec) {
|
|
46
|
+
usage();
|
|
47
|
+
process.exitCode = 2;
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
run(dry ? ["--ingest", spec, "--dry"] : ["--ingest", spec]);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
usage();
|
|
54
|
+
process.exitCode = 2;
|
|
55
|
+
}
|
package/dist/commands/gate.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { join } from "node:path";
|
|
2
|
+
import { spawnSync } from "node:child_process";
|
|
3
|
+
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
4
|
+
import { homedir } from "node:os";
|
|
2
5
|
import { asString, dbPathFor, parse, print, readStdin, splitList } from "./context.js";
|
|
3
6
|
import { loadSpec, NovahizHome } from "../spec.js";
|
|
4
7
|
import { openDb } from "../db.js";
|
|
@@ -246,3 +249,54 @@ export function commandGate(parsed) {
|
|
|
246
249
|
if (!allow && gateConfig.mode === "block")
|
|
247
250
|
process.exitCode = 2;
|
|
248
251
|
}
|
|
252
|
+
// --- novahiz gate on|off -----------------------------------------------------
|
|
253
|
+
// Persistance du kill-switch NOVAHIZ_GATE au niveau utilisateur, pour un
|
|
254
|
+
// utilisateur final qui ne touche jamais au code :
|
|
255
|
+
// - Windows : registre HKCU\Environment (lu par tout nouveau process) ;
|
|
256
|
+
// - Linux/macOS : bloc marque dans ~/.profile (OpenCode lance depuis un
|
|
257
|
+
// terminal ; un lanceur GUI doit export la variable lui-meme).
|
|
258
|
+
// Le changement ne prend effet qu'apres restart complet d'OpenCode : le plugin
|
|
259
|
+
// lit la variable une seule fois, a l'import.
|
|
260
|
+
export const GATE_PROFILE_BEGIN = "# >>> novahiz-gate >>>";
|
|
261
|
+
export const GATE_PROFILE_END = "# <<< novahiz-gate <<<";
|
|
262
|
+
/** Fonction pure (testee) : ajoute/remplace ou retire le bloc marque. */
|
|
263
|
+
export function upsertGateProfile(profile, off) {
|
|
264
|
+
const escape = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
265
|
+
const blockRe = new RegExp(`${escape(GATE_PROFILE_BEGIN)}[\\s\\S]*?${escape(GATE_PROFILE_END)}\\n?`);
|
|
266
|
+
const stripped = profile.replace(blockRe, "");
|
|
267
|
+
if (!off)
|
|
268
|
+
return stripped;
|
|
269
|
+
const base = stripped.length > 0 && !stripped.endsWith("\n") ? `${stripped}\n` : stripped;
|
|
270
|
+
return `${base}${GATE_PROFILE_BEGIN}\nexport NOVAHIZ_GATE=off\n${GATE_PROFILE_END}\n`;
|
|
271
|
+
}
|
|
272
|
+
export function commandGateToggle(parsed) {
|
|
273
|
+
const mode = (parsed.positionals[1] ?? "").toLowerCase();
|
|
274
|
+
const off = mode === "off";
|
|
275
|
+
if (process.platform === "win32") {
|
|
276
|
+
const result = off
|
|
277
|
+
? spawnSync("reg", ["add", "HKCU\\Environment", "/v", "NOVAHIZ_GATE", "/t", "REG_SZ", "/d", "off", "/f"], { encoding: "utf8" })
|
|
278
|
+
: spawnSync("reg", ["delete", "HKCU\\Environment", "/v", "NOVAHIZ_GATE", "/f"], { encoding: "utf8" });
|
|
279
|
+
if (result.status !== 0) {
|
|
280
|
+
// `reg delete` echoue aussi quand la valeur n'existe pas : dans ce cas
|
|
281
|
+
// "on" est deja l'etat voulu, ce n'est pas une erreur.
|
|
282
|
+
if (off) {
|
|
283
|
+
process.stderr.write(`novahiz gate: registre inaccessible (${(result.stderr ?? "").trim() || `exit ${result.status}`}).\n`);
|
|
284
|
+
process.exitCode = 1;
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
process.stdout.write("NOVAHIZ_GATE deja absente du registre : le gate est actif.\n");
|
|
288
|
+
}
|
|
289
|
+
else {
|
|
290
|
+
process.stdout.write(off ? "NOVAHIZ_GATE=off ecrite (HKCU\\Environment).\n" : "NOVAHIZ_GATE retiree du registre : gate actif.\n");
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
else {
|
|
294
|
+
const profile = join(homedir(), ".profile");
|
|
295
|
+
const current = existsSync(profile) ? readFileSync(profile, "utf8") : "";
|
|
296
|
+
const next = upsertGateProfile(current, off);
|
|
297
|
+
if (next !== current)
|
|
298
|
+
writeFileSync(profile, next, "utf8");
|
|
299
|
+
process.stdout.write(off ? `NOVAHIZ_GATE=off ecrite dans ${profile}.\n` : `Bloc NOVAHIZ_GATE retire de ${profile}.\n`);
|
|
300
|
+
}
|
|
301
|
+
process.stdout.write("Restart OpenCode completely for the change to take effect.\n");
|
|
302
|
+
}
|