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
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import fs from "fs-extra";
|
|
3
|
+
// ── Stack-to-Skills Mapping ────────────────────────────────────────────────
|
|
4
|
+
/**
|
|
5
|
+
* Maps detected project signals to recommended AI skills.
|
|
6
|
+
* Each key is a detection signal (file/dependency/pattern),
|
|
7
|
+
* and the value is the list of skills it implies.
|
|
8
|
+
*/
|
|
9
|
+
export const SIGNAL_SKILL_MAP = {
|
|
10
|
+
// Frameworks
|
|
11
|
+
react: ["react-19"],
|
|
12
|
+
next: ["nextjs-15", "react-19"],
|
|
13
|
+
angular: [],
|
|
14
|
+
vue: [],
|
|
15
|
+
django: ["django-drf", "pytest"],
|
|
16
|
+
flask: ["pytest"],
|
|
17
|
+
fastapi: ["pytest"],
|
|
18
|
+
// Languages / runtimes
|
|
19
|
+
typescript: ["typescript"],
|
|
20
|
+
python: ["pytest"],
|
|
21
|
+
go: [],
|
|
22
|
+
rust: [],
|
|
23
|
+
elixir: [],
|
|
24
|
+
// Styling
|
|
25
|
+
tailwindcss: ["tailwind-4"],
|
|
26
|
+
// State management
|
|
27
|
+
zustand: ["zustand-5"],
|
|
28
|
+
// Validation
|
|
29
|
+
zod: ["zod-4"],
|
|
30
|
+
// AI SDKs
|
|
31
|
+
ai: ["ai-sdk-5"],
|
|
32
|
+
"@ai-sdk": ["ai-sdk-5"],
|
|
33
|
+
// Testing
|
|
34
|
+
vitest: [],
|
|
35
|
+
jest: [],
|
|
36
|
+
pytest: ["pytest"],
|
|
37
|
+
playwright: ["playwright"],
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Additional file-based signals that don't come from package.json dependencies.
|
|
41
|
+
*/
|
|
42
|
+
const FILE_SIGNALS = [
|
|
43
|
+
{
|
|
44
|
+
files: ["tailwind.config.js", "tailwind.config.ts", "tailwind.config.mjs"],
|
|
45
|
+
skills: ["tailwind-4"],
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
files: ["playwright.config.ts", "playwright.config.js"],
|
|
49
|
+
skills: ["playwright"],
|
|
50
|
+
},
|
|
51
|
+
{ files: ["tsconfig.json"], skills: ["typescript"] },
|
|
52
|
+
{
|
|
53
|
+
files: ["pyproject.toml", "setup.py", "requirements.txt"],
|
|
54
|
+
skills: ["pytest"],
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
files: ["next.config.js", "next.config.mjs", "next.config.ts"],
|
|
58
|
+
skills: ["nextjs-15", "react-19"],
|
|
59
|
+
},
|
|
60
|
+
];
|
|
61
|
+
/**
|
|
62
|
+
* Docker-related files that indicate a containerized project.
|
|
63
|
+
* Used by the init command to suggest Docker zero-downtime deploy scaffolding.
|
|
64
|
+
*/
|
|
65
|
+
export const DOCKER_FILES = [
|
|
66
|
+
"Dockerfile",
|
|
67
|
+
"docker-compose.yml",
|
|
68
|
+
"docker-compose.yaml",
|
|
69
|
+
"compose.yml",
|
|
70
|
+
"compose.yaml",
|
|
71
|
+
];
|
|
72
|
+
/**
|
|
73
|
+
* Detect whether the project uses Docker (Dockerfile or compose file present).
|
|
74
|
+
*/
|
|
75
|
+
export async function detectDockerPresence(projectDir) {
|
|
76
|
+
for (const file of DOCKER_FILES) {
|
|
77
|
+
if (await fs.pathExists(path.join(projectDir, file))) {
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
// ── Core Detection ─────────────────────────────────────────────────────────
|
|
84
|
+
/**
|
|
85
|
+
* Scan a project directory and detect its tech stack + recommended skills.
|
|
86
|
+
* Reads package.json deps, pyproject.toml, and well-known config files.
|
|
87
|
+
*/
|
|
88
|
+
export async function detectProjectStack(projectDir) {
|
|
89
|
+
const signals = [];
|
|
90
|
+
let stack = null;
|
|
91
|
+
// 1. Check Node.js (package.json)
|
|
92
|
+
const pkgPath = path.join(projectDir, "package.json");
|
|
93
|
+
if (await fs.pathExists(pkgPath)) {
|
|
94
|
+
stack = "node";
|
|
95
|
+
try {
|
|
96
|
+
const pkg = (await fs.readJson(pkgPath));
|
|
97
|
+
const allDeps = {
|
|
98
|
+
...(pkg.dependencies ?? {}),
|
|
99
|
+
...(pkg.devDependencies ?? {}),
|
|
100
|
+
};
|
|
101
|
+
for (const depName of Object.keys(allDeps)) {
|
|
102
|
+
const normalizedDep = depName.replace(/^@/, "").split("/")[0];
|
|
103
|
+
for (const [signal, skills] of Object.entries(SIGNAL_SKILL_MAP)) {
|
|
104
|
+
if (normalizedDep === signal ||
|
|
105
|
+
depName === signal ||
|
|
106
|
+
depName.startsWith(`@${signal}/`)) {
|
|
107
|
+
if (skills.length > 0) {
|
|
108
|
+
signals.push({ signal: depName, source: "package.json", skills });
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
/* corrupt package.json — skip deps detection */
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
// 2. Check Python
|
|
119
|
+
const pythonFiles = ["pyproject.toml", "requirements.txt", "setup.py"];
|
|
120
|
+
for (const pyFile of pythonFiles) {
|
|
121
|
+
if (await fs.pathExists(path.join(projectDir, pyFile))) {
|
|
122
|
+
if (!stack)
|
|
123
|
+
stack = "python";
|
|
124
|
+
signals.push({
|
|
125
|
+
signal: pyFile,
|
|
126
|
+
source: "file exists",
|
|
127
|
+
skills: ["pytest"],
|
|
128
|
+
});
|
|
129
|
+
break;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
// 3. Check Python deps from pyproject.toml
|
|
133
|
+
const pyprojectPath = path.join(projectDir, "pyproject.toml");
|
|
134
|
+
if (await fs.pathExists(pyprojectPath)) {
|
|
135
|
+
try {
|
|
136
|
+
const content = await fs.readFile(pyprojectPath, "utf-8");
|
|
137
|
+
if (/django/i.test(content)) {
|
|
138
|
+
signals.push({
|
|
139
|
+
signal: "django",
|
|
140
|
+
source: "pyproject.toml",
|
|
141
|
+
skills: ["django-drf", "pytest"],
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
if (/fastapi/i.test(content)) {
|
|
145
|
+
signals.push({
|
|
146
|
+
signal: "fastapi",
|
|
147
|
+
source: "pyproject.toml",
|
|
148
|
+
skills: ["pytest"],
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
if (/playwright/i.test(content)) {
|
|
152
|
+
signals.push({
|
|
153
|
+
signal: "playwright",
|
|
154
|
+
source: "pyproject.toml",
|
|
155
|
+
skills: ["playwright"],
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
catch {
|
|
160
|
+
/* skip */
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
// 4. Check Go
|
|
164
|
+
if (await fs.pathExists(path.join(projectDir, "go.mod"))) {
|
|
165
|
+
if (!stack)
|
|
166
|
+
stack = "go";
|
|
167
|
+
}
|
|
168
|
+
// 5. Check Rust
|
|
169
|
+
if (await fs.pathExists(path.join(projectDir, "Cargo.toml"))) {
|
|
170
|
+
if (!stack)
|
|
171
|
+
stack = "rust";
|
|
172
|
+
}
|
|
173
|
+
// 6. Check Elixir
|
|
174
|
+
if (await fs.pathExists(path.join(projectDir, "mix.exs"))) {
|
|
175
|
+
if (!stack)
|
|
176
|
+
stack = "elixir";
|
|
177
|
+
}
|
|
178
|
+
// 7. Check Java
|
|
179
|
+
if ((await fs.pathExists(path.join(projectDir, "build.gradle"))) ||
|
|
180
|
+
(await fs.pathExists(path.join(projectDir, "build.gradle.kts")))) {
|
|
181
|
+
if (!stack)
|
|
182
|
+
stack = "java-gradle";
|
|
183
|
+
}
|
|
184
|
+
if (await fs.pathExists(path.join(projectDir, "pom.xml"))) {
|
|
185
|
+
if (!stack)
|
|
186
|
+
stack = "java-maven";
|
|
187
|
+
}
|
|
188
|
+
// 8. File-based signals
|
|
189
|
+
for (const { files, skills } of FILE_SIGNALS) {
|
|
190
|
+
for (const file of files) {
|
|
191
|
+
if (await fs.pathExists(path.join(projectDir, file))) {
|
|
192
|
+
signals.push({ signal: file, source: "file exists", skills });
|
|
193
|
+
break; // Only need one file per signal group
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
// De-duplicate recommended skills
|
|
198
|
+
const skillSet = new Set();
|
|
199
|
+
for (const s of signals) {
|
|
200
|
+
for (const skill of s.skills) {
|
|
201
|
+
skillSet.add(skill);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
const recommendedSkills = [...skillSet].sort();
|
|
205
|
+
return { stack, signals, recommendedSkills };
|
|
206
|
+
}
|
|
207
|
+
//# sourceMappingURL=stack-detector.js.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Supply chain protection — configures Socket Firewall and enforces
|
|
3
|
+
* minimum package release age to protect against typosquatting,
|
|
4
|
+
* dependency confusion, and malicious package takeovers.
|
|
5
|
+
*/
|
|
6
|
+
import type { Stack } from "../types/index.js";
|
|
7
|
+
export type PackageManager = "npm" | "pnpm" | "yarn" | "pip" | "cargo" | "go";
|
|
8
|
+
export interface SupplyChainConfig {
|
|
9
|
+
packageManager: PackageManager;
|
|
10
|
+
minReleaseAgeHours: number;
|
|
11
|
+
socketEnabled: boolean;
|
|
12
|
+
enforceLockfile: boolean;
|
|
13
|
+
}
|
|
14
|
+
export interface SupplyChainResult {
|
|
15
|
+
configWritten: string[];
|
|
16
|
+
warnings: string[];
|
|
17
|
+
}
|
|
18
|
+
export declare function detectPackageManager(projectDir: string): PackageManager;
|
|
19
|
+
export declare function stackForPM(pm: PackageManager): Stack;
|
|
20
|
+
export declare function buildSocketConfig(pm: PackageManager): Record<string, unknown>;
|
|
21
|
+
export declare function buildNpmrcLines(minAgeHours: number): string[];
|
|
22
|
+
export declare function configureSupplyChain(projectDir: string, options?: Partial<SupplyChainConfig>): Promise<SupplyChainResult>;
|
|
23
|
+
//# sourceMappingURL=supply-chain.d.ts.map
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Supply chain protection — configures Socket Firewall and enforces
|
|
3
|
+
* minimum package release age to protect against typosquatting,
|
|
4
|
+
* dependency confusion, and malicious package takeovers.
|
|
5
|
+
*/
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
import fs from "fs-extra";
|
|
8
|
+
// ── Detection ──
|
|
9
|
+
export function detectPackageManager(projectDir) {
|
|
10
|
+
if (fs.existsSync(path.join(projectDir, "pnpm-lock.yaml")))
|
|
11
|
+
return "pnpm";
|
|
12
|
+
if (fs.existsSync(path.join(projectDir, "yarn.lock")))
|
|
13
|
+
return "yarn";
|
|
14
|
+
if (fs.existsSync(path.join(projectDir, "package-lock.json")))
|
|
15
|
+
return "npm";
|
|
16
|
+
if (fs.existsSync(path.join(projectDir, "Pipfile.lock")))
|
|
17
|
+
return "pip";
|
|
18
|
+
if (fs.existsSync(path.join(projectDir, "Cargo.lock")))
|
|
19
|
+
return "cargo";
|
|
20
|
+
if (fs.existsSync(path.join(projectDir, "go.sum")))
|
|
21
|
+
return "go";
|
|
22
|
+
if (fs.existsSync(path.join(projectDir, "package.json")))
|
|
23
|
+
return "npm";
|
|
24
|
+
return "npm";
|
|
25
|
+
}
|
|
26
|
+
export function stackForPM(pm) {
|
|
27
|
+
switch (pm) {
|
|
28
|
+
case "npm":
|
|
29
|
+
case "pnpm":
|
|
30
|
+
case "yarn":
|
|
31
|
+
return "node";
|
|
32
|
+
case "pip":
|
|
33
|
+
return "python";
|
|
34
|
+
case "cargo":
|
|
35
|
+
return "rust";
|
|
36
|
+
case "go":
|
|
37
|
+
return "go";
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
// ── Socket Firewall config ──
|
|
41
|
+
export function buildSocketConfig(pm) {
|
|
42
|
+
return {
|
|
43
|
+
version: 2,
|
|
44
|
+
projectType: stackForPM(pm),
|
|
45
|
+
issueRules: {
|
|
46
|
+
"pkg:npm/*": {
|
|
47
|
+
installScripts: "error",
|
|
48
|
+
telemetry: "warn",
|
|
49
|
+
troll: "error",
|
|
50
|
+
unpublished: "error",
|
|
51
|
+
deprecated: "warn",
|
|
52
|
+
unmaintained: "warn",
|
|
53
|
+
"new-author": "warn",
|
|
54
|
+
shellAccess: "error",
|
|
55
|
+
filesystemAccess: "warn",
|
|
56
|
+
networkAccess: "warn",
|
|
57
|
+
envAccess: "warn",
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
// ── npmrc / lockfile enforcement ──
|
|
63
|
+
export function buildNpmrcLines(minAgeHours) {
|
|
64
|
+
const lines = [
|
|
65
|
+
"# Supply chain protection — generated by javi-forge",
|
|
66
|
+
"engine-strict=true",
|
|
67
|
+
"save-exact=true",
|
|
68
|
+
];
|
|
69
|
+
if (minAgeHours > 0) {
|
|
70
|
+
lines.push(`# Minimum package age: ${minAgeHours}h (enforced via CI/pre-install hook)`);
|
|
71
|
+
}
|
|
72
|
+
return lines;
|
|
73
|
+
}
|
|
74
|
+
// ── Orchestrator ──
|
|
75
|
+
export async function configureSupplyChain(projectDir, options = {}) {
|
|
76
|
+
const pm = options.packageManager ?? detectPackageManager(projectDir);
|
|
77
|
+
const minAge = options.minReleaseAgeHours ?? 48;
|
|
78
|
+
const socketEnabled = options.socketEnabled ?? true;
|
|
79
|
+
const enforceLockfile = options.enforceLockfile ?? true;
|
|
80
|
+
const configWritten = [];
|
|
81
|
+
const warnings = [];
|
|
82
|
+
// 1. Socket Firewall config
|
|
83
|
+
if (socketEnabled) {
|
|
84
|
+
const socketPath = path.join(projectDir, ".socketrc");
|
|
85
|
+
await fs.writeJson(socketPath, buildSocketConfig(pm), { spaces: 2 });
|
|
86
|
+
configWritten.push(".socketrc");
|
|
87
|
+
}
|
|
88
|
+
// 2. npmrc for node projects
|
|
89
|
+
if (stackForPM(pm) === "node") {
|
|
90
|
+
const npmrcPath = path.join(projectDir, ".npmrc");
|
|
91
|
+
const lines = buildNpmrcLines(minAge);
|
|
92
|
+
if (enforceLockfile) {
|
|
93
|
+
if (pm === "pnpm") {
|
|
94
|
+
lines.push("frozen-lockfile=true");
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
lines.push("package-lock=true");
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
// Append to existing .npmrc if present
|
|
101
|
+
const existing = (await fs.pathExists(npmrcPath))
|
|
102
|
+
? await fs.readFile(npmrcPath, "utf-8")
|
|
103
|
+
: "";
|
|
104
|
+
const newContent = existing
|
|
105
|
+
? `${existing.trimEnd()}\n\n${lines.join("\n")}\n`
|
|
106
|
+
: `${lines.join("\n")}\n`;
|
|
107
|
+
await fs.writeFile(npmrcPath, newContent);
|
|
108
|
+
configWritten.push(".npmrc");
|
|
109
|
+
}
|
|
110
|
+
// 3. Supply chain metadata in baseline dir
|
|
111
|
+
const metaPath = path.join(projectDir, ".javi-forge", "supply-chain.json");
|
|
112
|
+
await fs.ensureDir(path.dirname(metaPath));
|
|
113
|
+
await fs.writeJson(metaPath, {
|
|
114
|
+
packageManager: pm,
|
|
115
|
+
minReleaseAgeHours: minAge,
|
|
116
|
+
socketEnabled,
|
|
117
|
+
enforceLockfile,
|
|
118
|
+
configuredAt: new Date().toISOString(),
|
|
119
|
+
}, { spaces: 2 });
|
|
120
|
+
configWritten.push(".javi-forge/supply-chain.json");
|
|
121
|
+
if (!socketEnabled) {
|
|
122
|
+
warnings.push("Socket Firewall disabled. Consider enabling it for supply chain protection.");
|
|
123
|
+
}
|
|
124
|
+
return { configWritten, warnings };
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=supply-chain.js.map
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Teams parallel dispatch presets — predefined team configurations
|
|
3
|
+
* for common workflows like review, debug, and security scanning.
|
|
4
|
+
*
|
|
5
|
+
* Each preset defines which sub-agents to spawn in parallel, their roles,
|
|
6
|
+
* and how to aggregate results.
|
|
7
|
+
*/
|
|
8
|
+
export interface AgentRole {
|
|
9
|
+
id: string;
|
|
10
|
+
name: string;
|
|
11
|
+
skill: string;
|
|
12
|
+
perspective: string;
|
|
13
|
+
priority: "critical" | "high" | "medium" | "low";
|
|
14
|
+
}
|
|
15
|
+
export interface TeamPreset {
|
|
16
|
+
name: string;
|
|
17
|
+
description: string;
|
|
18
|
+
roles: AgentRole[];
|
|
19
|
+
aggregation: "all-must-pass" | "majority" | "any-pass";
|
|
20
|
+
maxParallel: number;
|
|
21
|
+
}
|
|
22
|
+
export interface TeamDispatch {
|
|
23
|
+
preset: string;
|
|
24
|
+
roles: AgentRole[];
|
|
25
|
+
targetFiles: string[];
|
|
26
|
+
context: Record<string, string>;
|
|
27
|
+
}
|
|
28
|
+
export interface AgentResult {
|
|
29
|
+
roleId: string;
|
|
30
|
+
roleName: string;
|
|
31
|
+
passed: boolean;
|
|
32
|
+
findings: string[];
|
|
33
|
+
severity: "critical" | "high" | "medium" | "low" | "info";
|
|
34
|
+
durationMs: number;
|
|
35
|
+
}
|
|
36
|
+
export interface TeamResult {
|
|
37
|
+
preset: string;
|
|
38
|
+
passed: boolean;
|
|
39
|
+
agents: AgentResult[];
|
|
40
|
+
totalDurationMs: number;
|
|
41
|
+
summary: string;
|
|
42
|
+
}
|
|
43
|
+
export declare const TEAM_PRESETS: Record<string, TeamPreset>;
|
|
44
|
+
export declare function getPreset(name: string): TeamPreset | null;
|
|
45
|
+
export declare function listPresets(): Array<{
|
|
46
|
+
name: string;
|
|
47
|
+
description: string;
|
|
48
|
+
roleCount: number;
|
|
49
|
+
}>;
|
|
50
|
+
export declare function createDispatch(presetName: string, targetFiles: string[], context?: Record<string, string>): TeamDispatch | null;
|
|
51
|
+
export declare function aggregateResults(preset: TeamPreset, results: AgentResult[]): TeamResult;
|
|
52
|
+
export declare function formatTeamResult(result: TeamResult): string;
|
|
53
|
+
//# sourceMappingURL=team-presets.d.ts.map
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Teams parallel dispatch presets — predefined team configurations
|
|
3
|
+
* for common workflows like review, debug, and security scanning.
|
|
4
|
+
*
|
|
5
|
+
* Each preset defines which sub-agents to spawn in parallel, their roles,
|
|
6
|
+
* and how to aggregate results.
|
|
7
|
+
*/
|
|
8
|
+
// ── Built-in presets ──
|
|
9
|
+
export const TEAM_PRESETS = {
|
|
10
|
+
review: {
|
|
11
|
+
name: "review",
|
|
12
|
+
description: "Multi-perspective code review team",
|
|
13
|
+
roles: [
|
|
14
|
+
{
|
|
15
|
+
id: "quality",
|
|
16
|
+
name: "Quality Reviewer",
|
|
17
|
+
skill: "adversarial-review",
|
|
18
|
+
perspective: "code quality, readability, maintainability",
|
|
19
|
+
priority: "high",
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
id: "security",
|
|
23
|
+
name: "Security Auditor",
|
|
24
|
+
skill: "adversarial-review",
|
|
25
|
+
perspective: "security vulnerabilities, injection, auth",
|
|
26
|
+
priority: "critical",
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
id: "testing",
|
|
30
|
+
name: "Test Reviewer",
|
|
31
|
+
skill: "testing:test-coverage",
|
|
32
|
+
perspective: "test coverage, edge cases, test quality",
|
|
33
|
+
priority: "medium",
|
|
34
|
+
},
|
|
35
|
+
],
|
|
36
|
+
aggregation: "all-must-pass",
|
|
37
|
+
maxParallel: 3,
|
|
38
|
+
},
|
|
39
|
+
debug: {
|
|
40
|
+
name: "debug",
|
|
41
|
+
description: "Parallel debugging team",
|
|
42
|
+
roles: [
|
|
43
|
+
{
|
|
44
|
+
id: "hypothesis",
|
|
45
|
+
name: "Hypothesis Generator",
|
|
46
|
+
skill: "debug-mode",
|
|
47
|
+
perspective: "generate and rank failure hypotheses",
|
|
48
|
+
priority: "high",
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
id: "logs",
|
|
52
|
+
name: "Log Analyzer",
|
|
53
|
+
skill: "debug-mode",
|
|
54
|
+
perspective: "parse logs, stack traces, error patterns",
|
|
55
|
+
priority: "high",
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
id: "repro",
|
|
59
|
+
name: "Reproducer",
|
|
60
|
+
skill: "testing:e2e",
|
|
61
|
+
perspective: "create minimal reproduction steps",
|
|
62
|
+
priority: "medium",
|
|
63
|
+
},
|
|
64
|
+
],
|
|
65
|
+
aggregation: "any-pass",
|
|
66
|
+
maxParallel: 3,
|
|
67
|
+
},
|
|
68
|
+
security: {
|
|
69
|
+
name: "security",
|
|
70
|
+
description: "Security scanning team",
|
|
71
|
+
roles: [
|
|
72
|
+
{
|
|
73
|
+
id: "sast",
|
|
74
|
+
name: "SAST Scanner",
|
|
75
|
+
skill: "adversarial-review",
|
|
76
|
+
perspective: "static analysis, code patterns, OWASP",
|
|
77
|
+
priority: "critical",
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
id: "deps",
|
|
81
|
+
name: "Dependency Auditor",
|
|
82
|
+
skill: "adversarial-review",
|
|
83
|
+
perspective: "supply chain, outdated deps, known CVEs",
|
|
84
|
+
priority: "critical",
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
id: "secrets",
|
|
88
|
+
name: "Secret Scanner",
|
|
89
|
+
skill: "adversarial-review",
|
|
90
|
+
perspective: "hardcoded secrets, API keys, credentials",
|
|
91
|
+
priority: "critical",
|
|
92
|
+
},
|
|
93
|
+
],
|
|
94
|
+
aggregation: "all-must-pass",
|
|
95
|
+
maxParallel: 3,
|
|
96
|
+
},
|
|
97
|
+
"tdd-cycle": {
|
|
98
|
+
name: "tdd-cycle",
|
|
99
|
+
description: "TDD pipeline team",
|
|
100
|
+
roles: [
|
|
101
|
+
{
|
|
102
|
+
id: "test-writer",
|
|
103
|
+
name: "Test Writer",
|
|
104
|
+
skill: "testing:tdd",
|
|
105
|
+
perspective: "write failing tests first",
|
|
106
|
+
priority: "high",
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
id: "implementer",
|
|
110
|
+
name: "Implementer",
|
|
111
|
+
skill: "sdd-apply",
|
|
112
|
+
perspective: "make tests pass with minimal code",
|
|
113
|
+
priority: "high",
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
id: "refactorer",
|
|
117
|
+
name: "Refactorer",
|
|
118
|
+
skill: "refactoring:cleanup",
|
|
119
|
+
perspective: "clean up without breaking tests",
|
|
120
|
+
priority: "medium",
|
|
121
|
+
},
|
|
122
|
+
],
|
|
123
|
+
aggregation: "all-must-pass",
|
|
124
|
+
maxParallel: 1, // sequential for TDD
|
|
125
|
+
},
|
|
126
|
+
};
|
|
127
|
+
// ── Preset management ──
|
|
128
|
+
export function getPreset(name) {
|
|
129
|
+
return TEAM_PRESETS[name] ?? null;
|
|
130
|
+
}
|
|
131
|
+
export function listPresets() {
|
|
132
|
+
return Object.values(TEAM_PRESETS).map((p) => ({
|
|
133
|
+
name: p.name,
|
|
134
|
+
description: p.description,
|
|
135
|
+
roleCount: p.roles.length,
|
|
136
|
+
}));
|
|
137
|
+
}
|
|
138
|
+
// ── Dispatch creation ──
|
|
139
|
+
export function createDispatch(presetName, targetFiles, context = {}) {
|
|
140
|
+
const preset = getPreset(presetName);
|
|
141
|
+
if (!preset)
|
|
142
|
+
return null;
|
|
143
|
+
return {
|
|
144
|
+
preset: presetName,
|
|
145
|
+
roles: preset.roles,
|
|
146
|
+
targetFiles,
|
|
147
|
+
context,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
// ── Result aggregation ──
|
|
151
|
+
export function aggregateResults(preset, results) {
|
|
152
|
+
const totalDurationMs = Math.max(...results.map((r) => r.durationMs), 0);
|
|
153
|
+
let passed;
|
|
154
|
+
switch (preset.aggregation) {
|
|
155
|
+
case "all-must-pass":
|
|
156
|
+
passed = results.every((r) => r.passed);
|
|
157
|
+
break;
|
|
158
|
+
case "majority":
|
|
159
|
+
passed = results.filter((r) => r.passed).length > results.length / 2;
|
|
160
|
+
break;
|
|
161
|
+
case "any-pass":
|
|
162
|
+
passed = results.some((r) => r.passed);
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
165
|
+
const criticalFindings = results
|
|
166
|
+
.filter((r) => r.severity === "critical" && !r.passed)
|
|
167
|
+
.flatMap((r) => r.findings);
|
|
168
|
+
const summary = passed
|
|
169
|
+
? `All ${results.length} agents passed.`
|
|
170
|
+
: `${results.filter((r) => !r.passed).length}/${results.length} agents reported issues.${criticalFindings.length > 0 ? ` ${criticalFindings.length} critical findings.` : ""}`;
|
|
171
|
+
return {
|
|
172
|
+
preset: preset.name,
|
|
173
|
+
passed,
|
|
174
|
+
agents: results,
|
|
175
|
+
totalDurationMs,
|
|
176
|
+
summary,
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
// ── Formatting ──
|
|
180
|
+
export function formatTeamResult(result) {
|
|
181
|
+
const icon = result.passed ? "✅" : "❌";
|
|
182
|
+
const lines = [
|
|
183
|
+
`${icon} Team: ${result.preset} — ${result.summary}`,
|
|
184
|
+
"",
|
|
185
|
+
];
|
|
186
|
+
for (const agent of result.agents) {
|
|
187
|
+
const aIcon = agent.passed ? "✓" : "✗";
|
|
188
|
+
const dur = `${(agent.durationMs / 1000).toFixed(1)}s`;
|
|
189
|
+
lines.push(` ${aIcon} ${agent.roleName} [${agent.severity}] ${dur}`);
|
|
190
|
+
if (agent.findings.length > 0) {
|
|
191
|
+
for (const f of agent.findings.slice(0, 3)) {
|
|
192
|
+
lines.push(` - ${f}`);
|
|
193
|
+
}
|
|
194
|
+
if (agent.findings.length > 3) {
|
|
195
|
+
lines.push(` ... +${agent.findings.length - 3} more`);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
return lines.join("\n");
|
|
200
|
+
}
|
|
201
|
+
//# sourceMappingURL=team-presets.js.map
|
package/dist/lib/template.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { CIProvider, Stack } from "../types/index.js";
|
|
2
2
|
/**
|
|
3
3
|
* Read a template file and replace __VAR_NAME__ placeholders.
|
|
4
4
|
*/
|
|
@@ -21,4 +21,19 @@ export declare function generateCIWorkflow(stack: Stack, provider: CIProvider):
|
|
|
21
21
|
* Get the destination path for a CI workflow file within a project.
|
|
22
22
|
*/
|
|
23
23
|
export declare function getCIDestination(provider: CIProvider): string;
|
|
24
|
+
/**
|
|
25
|
+
* Get the template path for the zero-downtime Docker deploy workflow.
|
|
26
|
+
* Returns null if no template exists for the given provider.
|
|
27
|
+
*/
|
|
28
|
+
export declare function getDeployTemplatePath(provider: CIProvider): string | null;
|
|
29
|
+
/**
|
|
30
|
+
* Get the destination path for the deploy workflow file within a project.
|
|
31
|
+
* Returns null if no mapping exists for the given provider.
|
|
32
|
+
*/
|
|
33
|
+
export declare function getDeployDestination(provider: CIProvider): string | null;
|
|
34
|
+
/**
|
|
35
|
+
* Generate the zero-downtime Docker deploy workflow content.
|
|
36
|
+
* Replaces __SERVICE_NAME__ with the provided service name.
|
|
37
|
+
*/
|
|
38
|
+
export declare function generateDeployWorkflow(provider: CIProvider, serviceName: string): Promise<string | null>;
|
|
24
39
|
//# sourceMappingURL=template.d.ts.map
|