javi-forge 1.6.0 → 1.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/README.md +45 -1
- package/ci-local/README.md +56 -11
- package/ci-local/ci-local.ps1 +445 -0
- package/ci-local/ci-local.sh +52 -9
- package/ci-local/docker/python.Dockerfile +7 -0
- package/ci-local/hooks/commit-msg +120 -44
- package/ci-local/hooks/commit-msg.test.sh +286 -0
- package/ci-local/hooks/pre-commit +9 -1
- package/ci-local/hooks/pre-push +13 -2
- package/ci-local/install.ps1 +367 -0
- package/ci-local/install.sh +151 -5
- package/ci-local/uninstall.ps1 +85 -0
- package/ci-local/uninstall.sh +95 -0
- package/dist/cli/dispatch/ci.d.ts +12 -0
- package/dist/cli/dispatch/ci.js +38 -0
- package/dist/cli/dispatch/security.d.ts +11 -0
- package/dist/cli/dispatch/security.js +68 -0
- package/dist/cli/dispatch/simple-renderers.d.ts +16 -0
- package/dist/cli/dispatch/simple-renderers.js +65 -0
- package/dist/cli/dispatch/skill-publish.d.ts +15 -0
- package/dist/cli/dispatch/skill-publish.js +44 -0
- package/dist/cli/dispatch/skills-cmd.d.ts +13 -0
- package/dist/cli/dispatch/skills-cmd.js +93 -0
- package/dist/cli/dispatch/tdd.d.ts +11 -0
- package/dist/cli/dispatch/tdd.js +45 -0
- package/dist/cli/dispatch/types.d.ts +29 -0
- package/dist/cli/dispatch/types.js +2 -0
- package/dist/cli/dispatch/workflow.d.ts +11 -0
- package/dist/cli/dispatch/workflow.js +67 -0
- package/dist/cli/help.d.ts +127 -0
- package/dist/cli/help.js +138 -0
- package/dist/cli/runtime.d.ts +16 -0
- package/dist/cli/runtime.js +38 -0
- package/dist/cli/validators.d.ts +17 -0
- package/dist/cli/validators.js +35 -0
- package/dist/commands/analyze.d.ts +1 -1
- package/dist/commands/analyze.js +14 -16
- package/dist/commands/ci.d.ts +50 -3
- package/dist/commands/ci.js +537 -182
- package/dist/commands/doctor.d.ts +2 -2
- package/dist/commands/doctor.js +112 -62
- package/dist/commands/init/report.d.ts +13 -0
- package/dist/commands/init/report.js +13 -0
- package/dist/commands/init/steps/agent-skills.d.ts +13 -0
- package/dist/commands/init/steps/agent-skills.js +45 -0
- package/dist/commands/init/steps/ai-sync.d.ts +15 -0
- package/dist/commands/init/steps/ai-sync.js +62 -0
- package/dist/commands/init/steps/ci.d.ts +24 -0
- package/dist/commands/init/steps/ci.js +74 -0
- package/dist/commands/init/steps/claude-md.d.ts +14 -0
- package/dist/commands/init/steps/claude-md.js +54 -0
- package/dist/commands/init/steps/code-graph.d.ts +16 -0
- package/dist/commands/init/steps/code-graph.js +68 -0
- package/dist/commands/init/steps/context-dir.d.ts +13 -0
- package/dist/commands/init/steps/context-dir.js +47 -0
- package/dist/commands/init/steps/docker-deploy.d.ts +16 -0
- package/dist/commands/init/steps/docker-deploy.js +60 -0
- package/dist/commands/init/steps/ghagga.d.ts +15 -0
- package/dist/commands/init/steps/ghagga.js +58 -0
- package/dist/commands/init/steps/git.d.ts +25 -0
- package/dist/commands/init/steps/git.js +81 -0
- package/dist/commands/init/steps/gitignore.d.ts +13 -0
- package/dist/commands/init/steps/gitignore.js +39 -0
- package/dist/commands/init/steps/local-ai.d.ts +14 -0
- package/dist/commands/init/steps/local-ai.js +53 -0
- package/dist/commands/init/steps/manifest.d.ts +13 -0
- package/dist/commands/init/steps/manifest.js +58 -0
- package/dist/commands/init/steps/memory.d.ts +15 -0
- package/dist/commands/init/steps/memory.js +60 -0
- package/dist/commands/init/steps/mock.d.ts +13 -0
- package/dist/commands/init/steps/mock.js +64 -0
- package/dist/commands/init/steps/sdd.d.ts +12 -0
- package/dist/commands/init/steps/sdd.js +40 -0
- package/dist/commands/init/steps/security.d.ts +28 -0
- package/dist/commands/init/steps/security.js +103 -0
- package/dist/commands/init/types.d.ts +30 -0
- package/dist/commands/init/types.js +2 -0
- package/dist/commands/init.d.ts +5 -4
- package/dist/commands/init.js +42 -387
- package/dist/commands/llmstxt.d.ts +1 -1
- package/dist/commands/llmstxt.js +36 -34
- package/dist/commands/plugin.d.ts +10 -1
- package/dist/commands/plugin.js +92 -47
- package/dist/commands/security.d.ts +11 -5
- package/dist/commands/security.js +236 -77
- package/dist/commands/skills/analysis.d.ts +19 -0
- package/dist/commands/skills/analysis.js +211 -0
- package/dist/commands/skills/benchmark.d.ts +6 -0
- package/dist/commands/skills/benchmark.js +82 -0
- package/dist/commands/skills/constants.d.ts +10 -0
- package/dist/commands/skills/constants.js +27 -0
- package/dist/commands/skills/directives.d.ts +21 -0
- package/dist/commands/skills/directives.js +101 -0
- package/dist/commands/skills/parsing.d.ts +16 -0
- package/dist/commands/skills/parsing.js +108 -0
- package/dist/commands/skills/rules.d.ts +5 -0
- package/dist/commands/skills/rules.js +32 -0
- package/dist/commands/skills/scoring.d.ts +47 -0
- package/dist/commands/skills/scoring.js +306 -0
- package/dist/commands/skills.d.ts +8 -69
- package/dist/commands/skills.js +9 -490
- package/dist/commands/tdd-pipeline.d.ts +17 -0
- package/dist/commands/tdd-pipeline.js +144 -0
- package/dist/commands/tdd.d.ts +1 -1
- package/dist/commands/tdd.js +21 -18
- package/dist/commands/workflow.d.ts +23 -0
- package/dist/commands/workflow.js +116 -0
- package/dist/constants.d.ts +15 -1
- package/dist/constants.js +161 -122
- package/dist/index.js +43 -280
- package/dist/lib/agent-skills.d.ts +36 -1
- package/dist/lib/agent-skills.js +168 -19
- package/dist/lib/atlassian-mcp.d.ts +42 -0
- package/dist/lib/atlassian-mcp.js +98 -0
- package/dist/lib/auto-skill-install.d.ts +37 -0
- package/dist/lib/auto-skill-install.js +91 -0
- package/dist/lib/auto-wire.d.ts +20 -0
- package/dist/lib/auto-wire.js +240 -0
- package/dist/lib/ci-config.d.ts +65 -0
- package/dist/lib/ci-config.js +297 -0
- package/dist/lib/claudemd.d.ts +13 -1
- package/dist/lib/claudemd.js +174 -24
- package/dist/lib/codex-export.d.ts +1 -1
- package/dist/lib/codex-export.js +26 -32
- package/dist/lib/common.d.ts +1 -1
- package/dist/lib/common.js +52 -44
- package/dist/lib/context.d.ts +17 -2
- package/dist/lib/context.js +142 -13
- package/dist/lib/crash-recovery.d.ts +34 -0
- package/dist/lib/crash-recovery.js +123 -0
- package/dist/lib/docker.d.ts +23 -2
- package/dist/lib/docker.js +168 -131
- package/dist/lib/exec.d.ts +10 -0
- package/dist/lib/exec.js +11 -0
- package/dist/lib/frontmatter.d.ts +1 -1
- package/dist/lib/frontmatter.js +29 -15
- package/dist/lib/harness-audit.d.ts +35 -0
- package/dist/lib/harness-audit.js +277 -0
- package/dist/lib/parallel-batch.d.ts +42 -0
- package/dist/lib/parallel-batch.js +88 -0
- package/dist/lib/plugin.d.ts +9 -3
- package/dist/lib/plugin.js +127 -70
- package/dist/lib/secret-scanner.d.ts +30 -0
- package/dist/lib/secret-scanner.js +274 -0
- package/dist/lib/security-analysis.d.ts +74 -0
- package/dist/lib/security-analysis.js +489 -0
- package/dist/lib/skill-publish.d.ts +40 -0
- package/dist/lib/skill-publish.js +164 -0
- package/dist/lib/skill-scanner.d.ts +63 -0
- package/dist/lib/skill-scanner.js +383 -0
- package/dist/lib/stack-detector.d.ts +38 -0
- package/dist/lib/stack-detector.js +207 -0
- package/dist/lib/supply-chain.d.ts +23 -0
- package/dist/lib/supply-chain.js +126 -0
- package/dist/lib/team-presets.d.ts +53 -0
- package/dist/lib/team-presets.js +201 -0
- package/dist/lib/template.d.ts +16 -1
- package/dist/lib/template.js +46 -17
- package/dist/lib/workflow/discovery.d.ts +27 -0
- package/dist/lib/workflow/discovery.js +85 -0
- package/dist/lib/workflow/index.d.ts +5 -0
- package/dist/lib/workflow/index.js +5 -0
- package/dist/lib/workflow/parser.d.ts +16 -0
- package/dist/lib/workflow/parser.js +198 -0
- package/dist/lib/workflow/renderer.d.ts +9 -0
- package/dist/lib/workflow/renderer.js +152 -0
- package/dist/lib/workflow/validator.d.ts +10 -0
- package/dist/lib/workflow/validator.js +189 -0
- package/dist/tasks/index.d.ts +4 -0
- package/dist/tasks/index.js +4 -0
- package/dist/tasks/scaffold-tasks.d.ts +3 -0
- package/dist/tasks/scaffold-tasks.js +14 -0
- package/dist/tasks/task-id.d.ts +30 -0
- package/dist/tasks/task-id.js +59 -0
- package/dist/tasks/task-tracker.d.ts +15 -0
- package/dist/tasks/task-tracker.js +81 -0
- package/dist/types/index.d.ts +134 -6
- package/dist/types/index.js +11 -1
- package/dist/ui/AnalyzeUI.d.ts +1 -1
- package/dist/ui/AnalyzeUI.js +38 -39
- package/dist/ui/App.d.ts +5 -3
- package/dist/ui/App.js +86 -46
- package/dist/ui/AutoSkills.d.ts +9 -0
- package/dist/ui/AutoSkills.js +124 -0
- package/dist/ui/CI.d.ts +2 -2
- package/dist/ui/CI.js +24 -26
- package/dist/ui/CIContext.d.ts +1 -1
- package/dist/ui/CIContext.js +2 -2
- package/dist/ui/CISelector.d.ts +2 -2
- package/dist/ui/CISelector.js +23 -15
- package/dist/ui/Doctor.d.ts +1 -1
- package/dist/ui/Doctor.js +35 -29
- package/dist/ui/Header.d.ts +1 -1
- package/dist/ui/Header.js +14 -14
- package/dist/ui/HookProfileSelector.d.ts +9 -0
- package/dist/ui/HookProfileSelector.js +54 -0
- package/dist/ui/LlmsTxt.d.ts +1 -1
- package/dist/ui/LlmsTxt.js +31 -22
- package/dist/ui/MemorySelector.d.ts +2 -2
- package/dist/ui/MemorySelector.js +28 -16
- package/dist/ui/NameInput.d.ts +1 -1
- package/dist/ui/NameInput.js +21 -21
- package/dist/ui/OptionSelector.d.ts +6 -2
- package/dist/ui/OptionSelector.js +83 -32
- package/dist/ui/Plugin.d.ts +4 -3
- package/dist/ui/Plugin.js +78 -35
- package/dist/ui/Progress.d.ts +3 -3
- package/dist/ui/Progress.js +23 -22
- package/dist/ui/Skills.d.ts +2 -2
- package/dist/ui/Skills.js +61 -32
- package/dist/ui/StackSelector.d.ts +2 -2
- package/dist/ui/StackSelector.js +27 -17
- package/dist/ui/Summary.d.ts +3 -3
- package/dist/ui/Summary.js +60 -50
- package/dist/ui/Welcome.d.ts +1 -1
- package/dist/ui/Welcome.js +15 -16
- package/dist/ui/theme.d.ts +1 -1
- package/dist/ui/theme.js +6 -6
- package/lib/common.psm1 +167 -0
- package/lib/common.sh +30 -0
- package/package.json +46 -24
- package/templates/common/atlassian/mcp-atlassian-snippet.json +16 -0
- package/templates/common/repoforge/mcp-repoforge-snippet.json +11 -0
- package/templates/common/repoforge/repoforge.yaml +34 -0
- package/templates/github/deploy-docker-zero-downtime.yml +140 -0
- package/templates/github/repoforge-graph.yml +45 -0
- package/templates/gitlab/deploy-docker-zero-downtime.yml +57 -0
- package/templates/local-ai/.env.example +17 -0
- package/templates/local-ai/docker-compose.yml +95 -0
- package/templates/security-hooks/claude-settings-security.json +30 -0
- package/templates/security-hooks/commit-msg-signing +29 -0
- package/templates/security-hooks/pre-commit-permissions +74 -0
- package/templates/security-hooks/pre-commit-secrets +74 -0
- package/templates/security-hooks/pre-push-branch-protection +62 -0
- package/templates/security-hooks/pre-push-deps +83 -0
- package/templates/security-hooks/pre-push-signing +67 -0
- package/templates/woodpecker/deploy-docker-zero-downtime.yml +50 -0
- package/templates/workflows/ci-pipeline.dot +15 -0
- package/templates/workflows/feature-flow.dot +21 -0
- package/templates/workflows/release.dot +16 -0
- package/dist/__integration__/helpers.d.ts +0 -20
- package/dist/__integration__/helpers.d.ts.map +0 -1
- package/dist/__integration__/helpers.js +0 -31
- package/dist/__integration__/helpers.js.map +0 -1
- package/dist/commands/analyze.d.ts.map +0 -1
- package/dist/commands/analyze.js.map +0 -1
- package/dist/commands/ci.d.ts.map +0 -1
- package/dist/commands/ci.js.map +0 -1
- package/dist/commands/doctor.d.ts.map +0 -1
- package/dist/commands/doctor.js.map +0 -1
- package/dist/commands/init.d.ts.map +0 -1
- package/dist/commands/init.js.map +0 -1
- package/dist/commands/llmstxt.d.ts.map +0 -1
- package/dist/commands/llmstxt.js.map +0 -1
- package/dist/commands/plugin.d.ts.map +0 -1
- package/dist/commands/plugin.js.map +0 -1
- package/dist/commands/security.d.ts.map +0 -1
- package/dist/commands/security.js.map +0 -1
- package/dist/commands/skills.d.ts.map +0 -1
- package/dist/commands/skills.js.map +0 -1
- package/dist/commands/tdd.d.ts.map +0 -1
- package/dist/commands/tdd.js.map +0 -1
- package/dist/constants.d.ts.map +0 -1
- package/dist/constants.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/lib/agent-skills.d.ts.map +0 -1
- package/dist/lib/agent-skills.js.map +0 -1
- package/dist/lib/claudemd.d.ts.map +0 -1
- package/dist/lib/claudemd.js.map +0 -1
- package/dist/lib/codex-export.d.ts.map +0 -1
- package/dist/lib/codex-export.js.map +0 -1
- package/dist/lib/common.d.ts.map +0 -1
- package/dist/lib/common.js.map +0 -1
- package/dist/lib/context.d.ts.map +0 -1
- package/dist/lib/context.js.map +0 -1
- package/dist/lib/docker.d.ts.map +0 -1
- package/dist/lib/docker.js.map +0 -1
- package/dist/lib/frontmatter.d.ts.map +0 -1
- package/dist/lib/frontmatter.js.map +0 -1
- package/dist/lib/plugin.d.ts.map +0 -1
- package/dist/lib/plugin.js.map +0 -1
- package/dist/lib/template.d.ts.map +0 -1
- package/dist/lib/template.js.map +0 -1
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/index.js.map +0 -1
- package/dist/ui/AnalyzeUI.d.ts.map +0 -1
- package/dist/ui/AnalyzeUI.js.map +0 -1
- package/dist/ui/App.d.ts.map +0 -1
- package/dist/ui/App.js.map +0 -1
- package/dist/ui/CI.d.ts.map +0 -1
- package/dist/ui/CI.js.map +0 -1
- package/dist/ui/CIContext.d.ts.map +0 -1
- package/dist/ui/CIContext.js.map +0 -1
- package/dist/ui/CISelector.d.ts.map +0 -1
- package/dist/ui/CISelector.js.map +0 -1
- package/dist/ui/Doctor.d.ts.map +0 -1
- package/dist/ui/Doctor.js.map +0 -1
- package/dist/ui/Header.d.ts.map +0 -1
- package/dist/ui/Header.js.map +0 -1
- package/dist/ui/LlmsTxt.d.ts.map +0 -1
- package/dist/ui/LlmsTxt.js.map +0 -1
- package/dist/ui/MemorySelector.d.ts.map +0 -1
- package/dist/ui/MemorySelector.js.map +0 -1
- package/dist/ui/NameInput.d.ts.map +0 -1
- package/dist/ui/NameInput.js.map +0 -1
- package/dist/ui/OptionSelector.d.ts.map +0 -1
- package/dist/ui/OptionSelector.js.map +0 -1
- package/dist/ui/Plugin.d.ts.map +0 -1
- package/dist/ui/Plugin.js.map +0 -1
- package/dist/ui/Progress.d.ts.map +0 -1
- package/dist/ui/Progress.js.map +0 -1
- package/dist/ui/Skills.d.ts.map +0 -1
- package/dist/ui/Skills.js.map +0 -1
- package/dist/ui/StackSelector.d.ts.map +0 -1
- package/dist/ui/StackSelector.js.map +0 -1
- package/dist/ui/Summary.d.ts.map +0 -1
- package/dist/ui/Summary.js.map +0 -1
- package/dist/ui/Welcome.d.ts.map +0 -1
- package/dist/ui/Welcome.js.map +0 -1
- package/dist/ui/theme.d.ts.map +0 -1
- package/dist/ui/theme.js.map +0 -1
package/dist/commands/init.js
CHANGED
|
@@ -1,397 +1,52 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
1
|
+
import { ensureDirExists } from "../lib/common.js";
|
|
2
|
+
import { stepAgentSkills } from "./init/steps/agent-skills.js";
|
|
3
|
+
import { stepAISync } from "./init/steps/ai-sync.js";
|
|
4
|
+
import { stepCITemplate, stepDependabot } from "./init/steps/ci.js";
|
|
5
|
+
import { stepClaudeMd } from "./init/steps/claude-md.js";
|
|
6
|
+
import { stepCodeGraph } from "./init/steps/code-graph.js";
|
|
7
|
+
import { stepContextDir } from "./init/steps/context-dir.js";
|
|
8
|
+
import { stepDockerDeploy } from "./init/steps/docker-deploy.js";
|
|
9
|
+
import { stepGhagga } from "./init/steps/ghagga.js";
|
|
10
|
+
import { stepGitHooks, stepGitInit } from "./init/steps/git.js";
|
|
11
|
+
import { stepGitignore } from "./init/steps/gitignore.js";
|
|
12
|
+
import { stepLocalAi } from "./init/steps/local-ai.js";
|
|
13
|
+
import { stepManifest } from "./init/steps/manifest.js";
|
|
14
|
+
import { stepMemory } from "./init/steps/memory.js";
|
|
15
|
+
import { stepMock } from "./init/steps/mock.js";
|
|
16
|
+
import { stepSDD } from "./init/steps/sdd.js";
|
|
17
|
+
import { stepHookProfile, stepSecurityHooks } from "./init/steps/security.js";
|
|
14
18
|
/**
|
|
15
19
|
* Main init orchestrator: bootstraps a project with CI, git hooks,
|
|
16
|
-
* memory module, AI config sync, SDD, and
|
|
20
|
+
* memory module, AI config sync, SDD, ghagga, and friends.
|
|
21
|
+
*
|
|
22
|
+
* Pure dispatch: every step lives in src/commands/init/steps/.
|
|
17
23
|
*/
|
|
18
24
|
export async function initProject(options, onStep) {
|
|
19
|
-
const { projectDir,
|
|
25
|
+
const { projectDir, dryRun } = options;
|
|
20
26
|
// Ensure project directory exists before any steps
|
|
21
27
|
if (!dryRun && projectDir) {
|
|
22
28
|
await ensureDirExists(projectDir);
|
|
23
29
|
}
|
|
24
|
-
//
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
try {
|
|
46
|
-
const ciLocalSrc = CI_LOCAL_DIR;
|
|
47
|
-
const ciLocalDest = path.join(projectDir, 'ci-local');
|
|
48
|
-
if (await fs.pathExists(ciLocalSrc)) {
|
|
49
|
-
if (!dryRun) {
|
|
50
|
-
await fs.copy(ciLocalSrc, ciLocalDest, { overwrite: false, errorOnExist: false });
|
|
51
|
-
// Set core.hooksPath to ci-local/hooks
|
|
52
|
-
const hooksDir = path.join(ciLocalDest, 'hooks');
|
|
53
|
-
if (await fs.pathExists(hooksDir)) {
|
|
54
|
-
// Ensure hooks are executable
|
|
55
|
-
const hookFiles = await fs.readdir(hooksDir);
|
|
56
|
-
for (const hook of hookFiles) {
|
|
57
|
-
await fs.chmod(path.join(hooksDir, hook), 0o755);
|
|
58
|
-
}
|
|
59
|
-
await execFileAsync('git', ['config', 'core.hooksPath', 'ci-local/hooks'], { cwd: projectDir });
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
report(onStep, stepHooks, 'Configure git hooks path', 'done', 'ci-local/hooks');
|
|
63
|
-
}
|
|
64
|
-
else {
|
|
65
|
-
report(onStep, stepHooks, 'Configure git hooks path', 'skipped', 'no ci-local dir');
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
catch (e) {
|
|
69
|
-
report(onStep, stepHooks, 'Configure git hooks path', 'error', String(e));
|
|
70
|
-
}
|
|
71
|
-
// ── Step 3: Copy CI template ──────────────────────────────────────────────
|
|
72
|
-
const stepCI = 'ci-template';
|
|
73
|
-
report(onStep, stepCI, `Copy ${ciProvider} CI workflow`, 'running');
|
|
74
|
-
try {
|
|
75
|
-
const ciContent = await generateCIWorkflow(stack, ciProvider);
|
|
76
|
-
if (ciContent) {
|
|
77
|
-
const dest = path.join(projectDir, getCIDestination(ciProvider));
|
|
78
|
-
if (!dryRun) {
|
|
79
|
-
await backupIfExists(dest);
|
|
80
|
-
await ensureDirExists(path.dirname(dest));
|
|
81
|
-
await fs.writeFile(dest, ciContent, 'utf-8');
|
|
82
|
-
}
|
|
83
|
-
report(onStep, stepCI, `Copy ${ciProvider} CI workflow`, 'done', getCIDestination(ciProvider));
|
|
84
|
-
}
|
|
85
|
-
else {
|
|
86
|
-
report(onStep, stepCI, `Copy ${ciProvider} CI workflow`, 'skipped', `no template for ${stack}`);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
catch (e) {
|
|
90
|
-
report(onStep, stepCI, `Copy ${ciProvider} CI workflow`, 'error', String(e));
|
|
91
|
-
}
|
|
92
|
-
// ── Step 4: Generate .gitignore ───────────────────────────────────────────
|
|
93
|
-
const stepGitignore = 'gitignore';
|
|
94
|
-
report(onStep, stepGitignore, 'Generate .gitignore', 'running');
|
|
95
|
-
try {
|
|
96
|
-
const templatePath = path.join(FORGE_ROOT, '.gitignore.template');
|
|
97
|
-
const dest = path.join(projectDir, '.gitignore');
|
|
98
|
-
if (await fs.pathExists(templatePath) && !await fs.pathExists(dest)) {
|
|
99
|
-
if (!dryRun) {
|
|
100
|
-
await fs.copy(templatePath, dest);
|
|
101
|
-
}
|
|
102
|
-
report(onStep, stepGitignore, 'Generate .gitignore', 'done', 'from template');
|
|
103
|
-
}
|
|
104
|
-
else if (await fs.pathExists(dest)) {
|
|
105
|
-
report(onStep, stepGitignore, 'Generate .gitignore', 'done', 'already exists');
|
|
106
|
-
}
|
|
107
|
-
else {
|
|
108
|
-
report(onStep, stepGitignore, 'Generate .gitignore', 'skipped', 'no template');
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
catch (e) {
|
|
112
|
-
report(onStep, stepGitignore, 'Generate .gitignore', 'error', String(e));
|
|
113
|
-
}
|
|
114
|
-
// ── Step 5: Generate dependabot.yml ───────────────────────────────────────
|
|
115
|
-
const stepDeps = 'dependabot';
|
|
116
|
-
report(onStep, stepDeps, 'Generate dependabot.yml', 'running');
|
|
117
|
-
try {
|
|
118
|
-
if (ciProvider === 'github') {
|
|
119
|
-
const content = await generateDependabotYml([stack], true);
|
|
120
|
-
const dest = path.join(projectDir, '.github', 'dependabot.yml');
|
|
121
|
-
if (!dryRun) {
|
|
122
|
-
await backupIfExists(dest);
|
|
123
|
-
await ensureDirExists(path.dirname(dest));
|
|
124
|
-
await fs.writeFile(dest, content, 'utf-8');
|
|
125
|
-
}
|
|
126
|
-
report(onStep, stepDeps, 'Generate dependabot.yml', 'done');
|
|
127
|
-
}
|
|
128
|
-
else {
|
|
129
|
-
report(onStep, stepDeps, 'Generate dependabot.yml', 'skipped', `not needed for ${ciProvider}`);
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
catch (e) {
|
|
133
|
-
report(onStep, stepDeps, 'Generate dependabot.yml', 'error', String(e));
|
|
134
|
-
}
|
|
135
|
-
// ── Step 6: Install memory module ─────────────────────────────────────────
|
|
136
|
-
const stepMem = 'memory';
|
|
137
|
-
report(onStep, stepMem, `Install memory module: ${memory}`, 'running');
|
|
138
|
-
try {
|
|
139
|
-
if (memory !== 'none') {
|
|
140
|
-
const moduleSrc = path.join(MODULES_DIR, memory);
|
|
141
|
-
if (await fs.pathExists(moduleSrc)) {
|
|
142
|
-
if (!dryRun) {
|
|
143
|
-
// Copy module files to project
|
|
144
|
-
const moduleDest = path.join(projectDir, '.javi-forge', 'modules', memory);
|
|
145
|
-
await ensureDirExists(moduleDest);
|
|
146
|
-
await fs.copy(moduleSrc, moduleDest, { overwrite: false, errorOnExist: false });
|
|
147
|
-
// If engram, copy .mcp-config-snippet.json to project with placeholder replacement
|
|
148
|
-
if (memory === 'engram') {
|
|
149
|
-
const snippetSrc = path.join(moduleSrc, '.mcp-config-snippet.json');
|
|
150
|
-
if (await fs.pathExists(snippetSrc)) {
|
|
151
|
-
const snippetDest = path.join(projectDir, '.mcp-config-snippet.json');
|
|
152
|
-
let content = await fs.readFile(snippetSrc, 'utf-8');
|
|
153
|
-
content = content.replace(/__PROJECT_NAME__/g, projectName);
|
|
154
|
-
await fs.writeFile(snippetDest, content, 'utf-8');
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
report(onStep, stepMem, `Install memory module: ${memory}`, 'done');
|
|
159
|
-
}
|
|
160
|
-
else {
|
|
161
|
-
report(onStep, stepMem, `Install memory module: ${memory}`, 'error', 'module not found');
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
else {
|
|
165
|
-
report(onStep, stepMem, `Install memory module: ${memory}`, 'skipped', 'none selected');
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
catch (e) {
|
|
169
|
-
report(onStep, stepMem, `Install memory module: ${memory}`, 'error', String(e));
|
|
170
|
-
}
|
|
171
|
-
// ── Step 7: AI config sync (delegated to javi-ai) ──────────────────────────
|
|
172
|
-
const stepAI = 'ai-sync';
|
|
173
|
-
report(onStep, stepAI, 'Sync AI config via javi-ai', 'running');
|
|
174
|
-
try {
|
|
175
|
-
if (aiSync) {
|
|
176
|
-
if (!dryRun) {
|
|
177
|
-
try {
|
|
178
|
-
const { stderr } = await execFileAsync('npx', ['javi-ai', 'sync', '--project-dir', projectDir, '--target', 'all'], {
|
|
179
|
-
cwd: projectDir,
|
|
180
|
-
timeout: 120_000,
|
|
181
|
-
});
|
|
182
|
-
// javi-ai may exit 0 but crash (e.g. Ink raw mode error) — detect via stderr
|
|
183
|
-
if (stderr && (stderr.includes('Raw mode is not supported') || stderr.includes('ERROR'))) {
|
|
184
|
-
report(onStep, stepAI, 'Sync AI config via javi-ai', 'error', 'javi-ai crashed. Run manually: npx javi-ai sync --project-dir . --target all');
|
|
185
|
-
}
|
|
186
|
-
else {
|
|
187
|
-
report(onStep, stepAI, 'Sync AI config via javi-ai', 'done', 'javi-ai sync --target all');
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
catch (syncErr) {
|
|
191
|
-
const msg = syncErr instanceof Error ? syncErr.message : String(syncErr);
|
|
192
|
-
if (msg.includes('ENOENT') || msg.includes('not found') || msg.includes('ERR_MODULE_NOT_FOUND')) {
|
|
193
|
-
report(onStep, stepAI, 'Sync AI config via javi-ai', 'error', 'javi-ai not found. Install with: npm install -g javi-ai (or run npx javi-ai sync manually)');
|
|
194
|
-
}
|
|
195
|
-
else {
|
|
196
|
-
report(onStep, stepAI, 'Sync AI config via javi-ai', 'error', msg);
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
else {
|
|
201
|
-
report(onStep, stepAI, 'Sync AI config via javi-ai', 'done', 'dry-run: would run javi-ai sync --target all');
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
else {
|
|
205
|
-
report(onStep, stepAI, 'Sync AI config via javi-ai', 'skipped', 'not selected');
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
catch (e) {
|
|
209
|
-
report(onStep, stepAI, 'Sync AI config via javi-ai', 'error', String(e));
|
|
210
|
-
}
|
|
211
|
-
// ── Step 8: SDD (Spec-Driven Development) ─────────────────────────────────
|
|
212
|
-
const stepSDD = 'sdd';
|
|
213
|
-
report(onStep, stepSDD, 'Set up SDD (openspec/)', 'running');
|
|
214
|
-
try {
|
|
215
|
-
if (sdd) {
|
|
216
|
-
if (!dryRun) {
|
|
217
|
-
const openspecDir = path.join(projectDir, 'openspec');
|
|
218
|
-
await ensureDirExists(openspecDir);
|
|
219
|
-
// Create a README if none exists
|
|
220
|
-
const readmePath = path.join(openspecDir, 'README.md');
|
|
221
|
-
if (!await fs.pathExists(readmePath)) {
|
|
222
|
-
await fs.writeFile(readmePath, `# openspec/\n\nSpec-Driven Development artifacts for ${projectName}.\n\nSee: /sdd:new <name> to start a new change.\n`, 'utf-8');
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
report(onStep, stepSDD, 'Set up SDD (openspec/)', 'done');
|
|
226
|
-
}
|
|
227
|
-
else {
|
|
228
|
-
report(onStep, stepSDD, 'Set up SDD (openspec/)', 'skipped', 'not selected');
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
catch (e) {
|
|
232
|
-
report(onStep, stepSDD, 'Set up SDD (openspec/)', 'error', String(e));
|
|
233
|
-
}
|
|
234
|
-
// ── Step 9: GHAGGA ────────────────────────────────────────────────────────
|
|
235
|
-
const stepGhagga = 'ghagga';
|
|
236
|
-
report(onStep, stepGhagga, 'Install GHAGGA review system', 'running');
|
|
237
|
-
try {
|
|
238
|
-
if (ghagga) {
|
|
239
|
-
const ghaggaSrc = path.join(MODULES_DIR, 'ghagga');
|
|
240
|
-
if (await fs.pathExists(ghaggaSrc)) {
|
|
241
|
-
if (!dryRun) {
|
|
242
|
-
const ghaggaDest = path.join(projectDir, '.javi-forge', 'modules', 'ghagga');
|
|
243
|
-
await ensureDirExists(ghaggaDest);
|
|
244
|
-
await fs.copy(ghaggaSrc, ghaggaDest, { overwrite: false, errorOnExist: false });
|
|
245
|
-
// Copy ghagga caller workflow to CI provider location
|
|
246
|
-
if (ciProvider === 'github') {
|
|
247
|
-
const workflowSrc = path.join(FORGE_ROOT, 'templates', 'github', 'ghagga-review.yml');
|
|
248
|
-
if (await fs.pathExists(workflowSrc)) {
|
|
249
|
-
const workflowDest = path.join(projectDir, '.github', 'workflows', 'ghagga-review.yml');
|
|
250
|
-
await ensureDirExists(path.dirname(workflowDest));
|
|
251
|
-
await fs.copy(workflowSrc, workflowDest, { overwrite: false });
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
report(onStep, stepGhagga, 'Install GHAGGA review system', 'done');
|
|
256
|
-
}
|
|
257
|
-
else {
|
|
258
|
-
report(onStep, stepGhagga, 'Install GHAGGA review system', 'error', 'module not found');
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
else {
|
|
262
|
-
report(onStep, stepGhagga, 'Install GHAGGA review system', 'skipped', 'not selected');
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
catch (e) {
|
|
266
|
-
report(onStep, stepGhagga, 'Install GHAGGA review system', 'error', String(e));
|
|
267
|
-
}
|
|
268
|
-
// ── Step 10: Mock-first mode ───────────────────────────────────────────────
|
|
269
|
-
const stepMock = 'mock';
|
|
270
|
-
if (options.mock) {
|
|
271
|
-
report(onStep, stepMock, 'Configure mock-first mode', 'running');
|
|
272
|
-
try {
|
|
273
|
-
if (!dryRun) {
|
|
274
|
-
// Create .env.example with mock values
|
|
275
|
-
const envExample = `# Mock environment — no real API keys required
|
|
276
|
-
# Copy to .env to use: cp .env.example .env
|
|
277
|
-
|
|
278
|
-
# Database
|
|
279
|
-
DATABASE_URL=postgresql://mock:mock@localhost:5432/mock_db
|
|
280
|
-
|
|
281
|
-
# Auth
|
|
282
|
-
JWT_SECRET=mock-jwt-secret-for-local-development
|
|
283
|
-
SESSION_SECRET=mock-session-secret
|
|
284
|
-
|
|
285
|
-
# External APIs (mock mode — no real calls)
|
|
286
|
-
MOCK_MODE=true
|
|
287
|
-
API_KEY=mock-api-key-not-real
|
|
288
|
-
STRIPE_KEY=sk_test_mock_not_real
|
|
289
|
-
SENDGRID_KEY=SG.mock_not_real
|
|
290
|
-
|
|
291
|
-
# Feature flags
|
|
292
|
-
ENABLE_ANALYTICS=false
|
|
293
|
-
ENABLE_EMAILS=false
|
|
294
|
-
ENABLE_WEBHOOKS=false
|
|
295
|
-
`;
|
|
296
|
-
const envExamplePath = path.join(projectDir, '.env.example');
|
|
297
|
-
if (!await fs.pathExists(envExamplePath)) {
|
|
298
|
-
await fs.writeFile(envExamplePath, envExample, 'utf-8');
|
|
299
|
-
}
|
|
300
|
-
// Create .env from example
|
|
301
|
-
const envPath = path.join(projectDir, '.env');
|
|
302
|
-
if (!await fs.pathExists(envPath)) {
|
|
303
|
-
await fs.writeFile(envPath, envExample, 'utf-8');
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
report(onStep, stepMock, 'Configure mock-first mode', 'done', '.env.example + .env with mock values');
|
|
307
|
-
}
|
|
308
|
-
catch (e) {
|
|
309
|
-
report(onStep, stepMock, 'Configure mock-first mode', 'error', String(e));
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
else {
|
|
313
|
-
report(onStep, stepMock, 'Configure mock-first mode', 'skipped', 'not selected');
|
|
314
|
-
}
|
|
315
|
-
// ── Step 11: Generate .context/ directory ──────────────────────────────────
|
|
316
|
-
const stepContext = 'context-dir';
|
|
317
|
-
report(onStep, stepContext, 'Generate .context/ directory', 'running');
|
|
318
|
-
try {
|
|
319
|
-
if (contextDir) {
|
|
320
|
-
const contextDirPath = path.join(projectDir, '.context');
|
|
321
|
-
if (await fs.pathExists(contextDirPath)) {
|
|
322
|
-
report(onStep, stepContext, 'Generate .context/ directory', 'done', 'already exists');
|
|
323
|
-
}
|
|
324
|
-
else {
|
|
325
|
-
if (!dryRun) {
|
|
326
|
-
const { index, summary } = await generateContextDir(options);
|
|
327
|
-
await ensureDirExists(contextDirPath);
|
|
328
|
-
await fs.writeFile(path.join(contextDirPath, 'INDEX.md'), index, 'utf-8');
|
|
329
|
-
await fs.writeFile(path.join(contextDirPath, 'summary.md'), summary, 'utf-8');
|
|
330
|
-
}
|
|
331
|
-
report(onStep, stepContext, 'Generate .context/ directory', 'done', dryRun ? 'dry-run: would generate .context/' : '.context/INDEX.md + summary.md');
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
else {
|
|
335
|
-
report(onStep, stepContext, 'Generate .context/ directory', 'skipped', 'not selected');
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
catch (e) {
|
|
339
|
-
report(onStep, stepContext, 'Generate .context/ directory', 'error', String(e));
|
|
340
|
-
}
|
|
341
|
-
// ── Step 12: Generate CLAUDE.md ────────────────────────────────────────────
|
|
342
|
-
const stepClaudeMd = 'claude-md';
|
|
343
|
-
report(onStep, stepClaudeMd, 'Generate CLAUDE.md', 'running');
|
|
344
|
-
try {
|
|
345
|
-
if (claudeMd) {
|
|
346
|
-
const claudeMdPath = path.join(projectDir, 'CLAUDE.md');
|
|
347
|
-
if (await fs.pathExists(claudeMdPath)) {
|
|
348
|
-
report(onStep, stepClaudeMd, 'Generate CLAUDE.md', 'done', 'already exists');
|
|
349
|
-
}
|
|
350
|
-
else {
|
|
351
|
-
if (!dryRun) {
|
|
352
|
-
const content = generateClaudeMd(options);
|
|
353
|
-
await fs.writeFile(claudeMdPath, content, 'utf-8');
|
|
354
|
-
}
|
|
355
|
-
report(onStep, stepClaudeMd, 'Generate CLAUDE.md', 'done', dryRun ? 'dry-run: would generate CLAUDE.md' : 'CLAUDE.md');
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
else {
|
|
359
|
-
report(onStep, stepClaudeMd, 'Generate CLAUDE.md', 'skipped', 'not selected');
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
catch (e) {
|
|
363
|
-
report(onStep, stepClaudeMd, 'Generate CLAUDE.md', 'error', String(e));
|
|
364
|
-
}
|
|
365
|
-
// ── Step 13: Write manifest ───────────────────────────────────────────────
|
|
366
|
-
const stepManifest = 'manifest';
|
|
367
|
-
report(onStep, stepManifest, 'Write forge manifest', 'running');
|
|
368
|
-
try {
|
|
369
|
-
if (!dryRun) {
|
|
370
|
-
const manifestDir = path.join(projectDir, '.javi-forge');
|
|
371
|
-
await ensureDirExists(manifestDir);
|
|
372
|
-
const manifest = {
|
|
373
|
-
version: '0.1.0',
|
|
374
|
-
projectName,
|
|
375
|
-
stack,
|
|
376
|
-
ciProvider,
|
|
377
|
-
memory,
|
|
378
|
-
createdAt: new Date().toISOString(),
|
|
379
|
-
updatedAt: new Date().toISOString(),
|
|
380
|
-
modules: [
|
|
381
|
-
...(memory !== 'none' ? [memory] : []),
|
|
382
|
-
...(ghagga ? ['ghagga'] : []),
|
|
383
|
-
...(sdd ? ['sdd'] : []),
|
|
384
|
-
...(aiSync ? ['ai-config'] : []),
|
|
385
|
-
...(contextDir ? ['context'] : []),
|
|
386
|
-
...(claudeMd ? ['claude-md'] : []),
|
|
387
|
-
],
|
|
388
|
-
};
|
|
389
|
-
await fs.writeJson(path.join(manifestDir, 'manifest.json'), manifest, { spaces: 2 });
|
|
390
|
-
}
|
|
391
|
-
report(onStep, stepManifest, 'Write forge manifest', 'done', '.javi-forge/manifest.json');
|
|
392
|
-
}
|
|
393
|
-
catch (e) {
|
|
394
|
-
report(onStep, stepManifest, 'Write forge manifest', 'error', String(e));
|
|
395
|
-
}
|
|
30
|
+
// Shared context passed to every step.
|
|
31
|
+
const ctx = { options, projectDir, dryRun, onStep };
|
|
32
|
+
await stepGitInit(ctx);
|
|
33
|
+
await stepGitHooks(ctx);
|
|
34
|
+
await stepCITemplate(ctx);
|
|
35
|
+
await stepGitignore(ctx);
|
|
36
|
+
await stepDependabot(ctx);
|
|
37
|
+
await stepMemory(ctx);
|
|
38
|
+
await stepAISync(ctx);
|
|
39
|
+
await stepSDD(ctx);
|
|
40
|
+
await stepGhagga(ctx);
|
|
41
|
+
await stepMock(ctx);
|
|
42
|
+
await stepContextDir(ctx);
|
|
43
|
+
await stepClaudeMd(ctx);
|
|
44
|
+
await stepDockerDeploy(ctx);
|
|
45
|
+
await stepSecurityHooks(ctx);
|
|
46
|
+
await stepHookProfile(ctx);
|
|
47
|
+
await stepCodeGraph(ctx);
|
|
48
|
+
await stepLocalAi(ctx);
|
|
49
|
+
await stepAgentSkills(ctx);
|
|
50
|
+
await stepManifest(ctx);
|
|
396
51
|
}
|
|
397
52
|
//# sourceMappingURL=init.js.map
|
package/dist/commands/llmstxt.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import { glob } from
|
|
4
|
-
import { detectStack } from
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import fs from "fs-extra";
|
|
3
|
+
import { glob } from "glob";
|
|
4
|
+
import { detectStack } from "../lib/common.js";
|
|
5
5
|
function report(onStep, id, label, status, detail) {
|
|
6
6
|
onStep({ id, label, status, detail });
|
|
7
7
|
}
|
|
@@ -10,53 +10,55 @@ function report(onStep, id, label, status, detail) {
|
|
|
10
10
|
* Reduces token usage by ~75% compared to full README + docs.
|
|
11
11
|
*/
|
|
12
12
|
export async function generateLlmsTxt(projectDir, dryRun, onStep) {
|
|
13
|
-
report(onStep,
|
|
13
|
+
report(onStep, "scan", "Scan project structure", "running");
|
|
14
14
|
const detection = await detectStack(projectDir);
|
|
15
|
-
const stackLabel = detection?.stackType ??
|
|
15
|
+
const stackLabel = detection?.stackType ?? "unknown";
|
|
16
16
|
// Gather project info
|
|
17
17
|
const name = path.basename(projectDir);
|
|
18
|
-
let description =
|
|
19
|
-
let version =
|
|
18
|
+
let description = "";
|
|
19
|
+
let version = "";
|
|
20
20
|
let entryPoints = [];
|
|
21
21
|
let dependencies = [];
|
|
22
22
|
// Try package.json (Node)
|
|
23
|
-
const pkgPath = path.join(projectDir,
|
|
23
|
+
const pkgPath = path.join(projectDir, "package.json");
|
|
24
24
|
if (await fs.pathExists(pkgPath)) {
|
|
25
25
|
try {
|
|
26
26
|
const pkg = await fs.readJson(pkgPath);
|
|
27
|
-
description = pkg.description ??
|
|
28
|
-
version = pkg.version ??
|
|
27
|
+
description = pkg.description ?? "";
|
|
28
|
+
version = pkg.version ?? "";
|
|
29
29
|
entryPoints = pkg.main ? [pkg.main] : [];
|
|
30
30
|
dependencies = Object.keys(pkg.dependencies ?? {}).slice(0, 15);
|
|
31
31
|
}
|
|
32
|
-
catch {
|
|
32
|
+
catch {
|
|
33
|
+
/* ignore */
|
|
34
|
+
}
|
|
33
35
|
}
|
|
34
36
|
// Scan source files
|
|
35
|
-
const sourceFiles = await glob(
|
|
37
|
+
const sourceFiles = await glob("src/**/*.{ts,tsx,js,jsx,py,go,rs}", {
|
|
36
38
|
cwd: projectDir,
|
|
37
|
-
ignore: [
|
|
39
|
+
ignore: ["**/node_modules/**", "**/dist/**", "**/.git/**"],
|
|
38
40
|
});
|
|
39
41
|
// Scan test files
|
|
40
|
-
const testFiles = await glob(
|
|
42
|
+
const testFiles = await glob("**/*.{test,spec}.{ts,tsx,js,jsx,py}", {
|
|
41
43
|
cwd: projectDir,
|
|
42
|
-
ignore: [
|
|
44
|
+
ignore: ["**/node_modules/**", "**/dist/**"],
|
|
43
45
|
});
|
|
44
|
-
report(onStep,
|
|
46
|
+
report(onStep, "scan", "Scan project structure", "done", `${sourceFiles.length} source, ${testFiles.length} test files`);
|
|
45
47
|
// Build llms.txt content
|
|
46
|
-
report(onStep,
|
|
48
|
+
report(onStep, "generate", "Generate llms.txt", "running");
|
|
47
49
|
const lines = [
|
|
48
50
|
`# ${name}`,
|
|
49
|
-
|
|
50
|
-
`> ${description ||
|
|
51
|
-
|
|
52
|
-
`- stack: ${stackLabel}${detection?.buildTool ? ` (${detection.buildTool})` :
|
|
53
|
-
`- version: ${version ||
|
|
51
|
+
"",
|
|
52
|
+
`> ${description || "No description"}`,
|
|
53
|
+
"",
|
|
54
|
+
`- stack: ${stackLabel}${detection?.buildTool ? ` (${detection.buildTool})` : ""}`,
|
|
55
|
+
`- version: ${version || "unknown"}`,
|
|
54
56
|
`- files: ${sourceFiles.length} source, ${testFiles.length} tests`,
|
|
55
|
-
|
|
57
|
+
"",
|
|
56
58
|
];
|
|
57
59
|
// Structure summary (compact)
|
|
58
60
|
if (sourceFiles.length > 0) {
|
|
59
|
-
lines.push(
|
|
61
|
+
lines.push("## Structure");
|
|
60
62
|
const dirs = new Map();
|
|
61
63
|
for (const f of sourceFiles) {
|
|
62
64
|
const dir = path.dirname(f);
|
|
@@ -65,28 +67,28 @@ export async function generateLlmsTxt(projectDir, dryRun, onStep) {
|
|
|
65
67
|
for (const [dir, count] of [...dirs.entries()].sort().slice(0, 20)) {
|
|
66
68
|
lines.push(`- ${dir}/ (${count})`);
|
|
67
69
|
}
|
|
68
|
-
lines.push(
|
|
70
|
+
lines.push("");
|
|
69
71
|
}
|
|
70
72
|
// Dependencies (compact — name only, no versions)
|
|
71
73
|
if (dependencies.length > 0) {
|
|
72
|
-
lines.push(
|
|
73
|
-
lines.push(dependencies.join(
|
|
74
|
-
lines.push(
|
|
74
|
+
lines.push("## Dependencies");
|
|
75
|
+
lines.push(dependencies.join(", "));
|
|
76
|
+
lines.push("");
|
|
75
77
|
}
|
|
76
78
|
// Entry points
|
|
77
79
|
if (entryPoints.length > 0) {
|
|
78
|
-
lines.push(
|
|
80
|
+
lines.push("## Entry");
|
|
79
81
|
for (const ep of entryPoints) {
|
|
80
82
|
lines.push(`- ${ep}`);
|
|
81
83
|
}
|
|
82
|
-
lines.push(
|
|
84
|
+
lines.push("");
|
|
83
85
|
}
|
|
84
|
-
const content = lines.join(
|
|
86
|
+
const content = lines.join("\n");
|
|
85
87
|
const tokenEstimate = Math.ceil(content.length / 4);
|
|
86
88
|
if (!dryRun) {
|
|
87
|
-
await fs.writeFile(path.join(projectDir,
|
|
89
|
+
await fs.writeFile(path.join(projectDir, "llms.txt"), content, "utf-8");
|
|
88
90
|
}
|
|
89
|
-
report(onStep,
|
|
91
|
+
report(onStep, "generate", "Generate llms.txt", "done", dryRun
|
|
90
92
|
? `dry-run: ~${tokenEstimate} tokens (${content.length} chars)`
|
|
91
93
|
: `written — ~${tokenEstimate} tokens (${content.length} chars)`);
|
|
92
94
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { InitStep } from
|
|
1
|
+
import type { InitStep } from "../types/index.js";
|
|
2
2
|
type StepCallback = (step: InitStep) => void;
|
|
3
3
|
/**
|
|
4
4
|
* Add (install) a plugin from a GitHub source.
|
|
@@ -36,5 +36,14 @@ export declare function runPluginExportCodex(name: string, onStep: StepCallback)
|
|
|
36
36
|
* Import an Agent Skills spec package and convert to javi-forge plugin format.
|
|
37
37
|
*/
|
|
38
38
|
export declare function runPluginImport(sourceDir: string, dryRun: boolean, onStep: StepCallback): Promise<void>;
|
|
39
|
+
/**
|
|
40
|
+
* Generate a project-level skills.json from all installed plugins.
|
|
41
|
+
* Makes the project discoverable by `npx skills add` and 40+ AI agents.
|
|
42
|
+
*/
|
|
43
|
+
export declare function runPluginExportSkillsJson(projectDir: string, dryRun: boolean, onStep: StepCallback): Promise<void>;
|
|
44
|
+
/**
|
|
45
|
+
* Generate a global skills.json from all globally installed plugins.
|
|
46
|
+
*/
|
|
47
|
+
export declare function runPluginExportGlobalSkillsJson(dryRun: boolean, onStep: StepCallback): Promise<void>;
|
|
39
48
|
export {};
|
|
40
49
|
//# sourceMappingURL=plugin.d.ts.map
|