javi-forge 1.6.0 → 1.6.1
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/dist/commands/analyze.d.ts +1 -1
- package/dist/commands/analyze.js +15 -15
- package/dist/commands/atlassian-mcp.d.ts +42 -0
- package/dist/commands/atlassian-mcp.js +98 -0
- package/dist/commands/ci.d.ts +3 -3
- package/dist/commands/ci.js +185 -147
- package/dist/commands/crash-recovery.d.ts +34 -0
- package/dist/commands/crash-recovery.js +123 -0
- package/dist/commands/doctor.d.ts +2 -2
- package/dist/commands/doctor.js +113 -61
- package/dist/commands/harness-audit.d.ts +35 -0
- package/dist/commands/harness-audit.js +277 -0
- package/dist/commands/init.d.ts +1 -1
- package/dist/commands/init.js +384 -141
- package/dist/commands/llmstxt.d.ts +1 -1
- package/dist/commands/llmstxt.js +36 -34
- package/dist/commands/parallel-batch.d.ts +42 -0
- package/dist/commands/parallel-batch.js +90 -0
- package/dist/commands/plugin.d.ts +10 -1
- package/dist/commands/plugin.js +92 -47
- package/dist/commands/secret-scanner.d.ts +30 -0
- package/dist/commands/secret-scanner.js +272 -0
- package/dist/commands/security-analysis.d.ts +74 -0
- package/dist/commands/security-analysis.js +487 -0
- package/dist/commands/security.d.ts +11 -5
- package/dist/commands/security.js +216 -76
- package/dist/commands/skill-scanner.d.ts +63 -0
- package/dist/commands/skill-scanner.js +383 -0
- package/dist/commands/skills.d.ts +62 -5
- package/dist/commands/skills.js +439 -54
- package/dist/commands/supply-chain.d.ts +23 -0
- package/dist/commands/supply-chain.js +126 -0
- 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/team-presets.d.ts +53 -0
- package/dist/commands/team-presets.js +201 -0
- package/dist/commands/workflow.d.ts +23 -0
- package/dist/commands/workflow.js +114 -0
- package/dist/constants.d.ts +15 -1
- package/dist/constants.js +161 -122
- package/dist/index.js +308 -98
- package/dist/lib/agent-skills.d.ts +36 -1
- package/dist/lib/agent-skills.js +168 -19
- package/dist/lib/auto-skill-install.d.ts +37 -0
- package/dist/lib/auto-skill-install.js +92 -0
- package/dist/lib/auto-wire.d.ts +20 -0
- package/dist/lib/auto-wire.js +240 -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 +29 -31
- 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/docker.d.ts +1 -1
- package/dist/lib/docker.js +141 -112
- package/dist/lib/frontmatter.d.ts +1 -1
- package/dist/lib/frontmatter.js +29 -15
- package/dist/lib/plugin.d.ts +9 -3
- package/dist/lib/plugin.js +128 -69
- package/dist/lib/skill-publish.d.ts +40 -0
- package/dist/lib/skill-publish.js +146 -0
- package/dist/lib/stack-detector.d.ts +38 -0
- package/dist/lib/stack-detector.js +207 -0
- package/dist/lib/template.d.ts +16 -1
- package/dist/lib/template.js +46 -17
- package/dist/lib/workflow/discovery.d.ts +19 -0
- package/dist/lib/workflow/discovery.js +68 -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 +55 -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 +3 -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 +26 -16
- 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/package.json +9 -6
- 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/ui/Skills.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import { runSkillsDoctor } from
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import {
|
|
1
|
+
import { Box, Text, useApp, useInput } from "ink";
|
|
2
|
+
import Spinner from "ink-spinner";
|
|
3
|
+
import React, { useCallback, useEffect, useState } from "react";
|
|
4
|
+
import { runSkillsDoctor } from "../commands/skills.js";
|
|
5
|
+
import { useCIMode } from "./CIContext.js";
|
|
6
|
+
import Header from "./Header.js";
|
|
7
|
+
import { theme } from "./theme.js";
|
|
8
8
|
export default function Skills({ mode, budget, deep, skillsDir }) {
|
|
9
9
|
const { exit } = useApp();
|
|
10
10
|
const isCI = useCIMode();
|
|
@@ -16,10 +16,18 @@ export default function Skills({ mode, budget, deep, skillsDir }) {
|
|
|
16
16
|
setResult(null);
|
|
17
17
|
setError(null);
|
|
18
18
|
runSkillsDoctor({ mode, budget, deep, skillsDir })
|
|
19
|
-
.then(r => {
|
|
20
|
-
|
|
19
|
+
.then((r) => {
|
|
20
|
+
setResult(r);
|
|
21
|
+
setLoading(false);
|
|
22
|
+
})
|
|
23
|
+
.catch((e) => {
|
|
24
|
+
setError(String(e));
|
|
25
|
+
setLoading(false);
|
|
26
|
+
});
|
|
21
27
|
}, [mode, budget, deep, skillsDir]);
|
|
22
|
-
useEffect(() => {
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
runCheck();
|
|
30
|
+
}, [runCheck]);
|
|
23
31
|
// Auto-exit in CI mode once loading finishes
|
|
24
32
|
useEffect(() => {
|
|
25
33
|
if (isCI && !loading) {
|
|
@@ -29,75 +37,96 @@ export default function Skills({ mode, budget, deep, skillsDir }) {
|
|
|
29
37
|
return undefined;
|
|
30
38
|
}, [isCI, loading, exit]);
|
|
31
39
|
useInput((input, key) => {
|
|
32
|
-
if (input.toLowerCase() ===
|
|
40
|
+
if (input.toLowerCase() === "r")
|
|
33
41
|
runCheck();
|
|
34
|
-
if (input.toLowerCase() ===
|
|
42
|
+
if (input.toLowerCase() === "q" || key.return || key.escape)
|
|
35
43
|
exit();
|
|
36
44
|
}, { isActive: !isCI });
|
|
37
|
-
const subtitle = mode ===
|
|
45
|
+
const subtitle = mode === "budget" ? "skills budget" : "skills doctor";
|
|
38
46
|
return (React.createElement(Box, { flexDirection: "column", padding: 1 },
|
|
39
47
|
React.createElement(Header, { subtitle: subtitle }),
|
|
40
48
|
loading && (React.createElement(Text, { color: theme.warning },
|
|
41
49
|
React.createElement(Spinner, { type: "dots" }),
|
|
42
|
-
|
|
50
|
+
" Running skills analysis...")),
|
|
43
51
|
error && (React.createElement(Text, { color: theme.error },
|
|
44
|
-
|
|
52
|
+
"\u2717",
|
|
45
53
|
" Error: ",
|
|
46
54
|
error)),
|
|
47
55
|
result && (React.createElement(Box, { flexDirection: "column" },
|
|
48
56
|
React.createElement(Box, { flexDirection: "column", marginBottom: 1 },
|
|
49
57
|
React.createElement(Text, { bold: true, color: result.budget.overBudget ? theme.warning : theme.success },
|
|
50
|
-
|
|
58
|
+
" ",
|
|
51
59
|
"Context Budget"),
|
|
52
60
|
React.createElement(Box, { marginLeft: 2 },
|
|
53
61
|
React.createElement(Text, { color: result.budget.overBudget ? theme.warning : theme.success },
|
|
54
|
-
result.budget.overBudget ?
|
|
55
|
-
|
|
62
|
+
result.budget.overBudget ? "\u2717" : "\u2713",
|
|
63
|
+
" ",
|
|
56
64
|
result.budget.totalTokens,
|
|
57
65
|
" / ",
|
|
58
66
|
result.budget.budget,
|
|
59
67
|
" tokens",
|
|
60
|
-
result.budget.overBudget ?
|
|
61
|
-
result.budget.entries.map(entry => (React.createElement(Box, { key: entry.skillName, marginLeft: 4 },
|
|
68
|
+
result.budget.overBudget ? " (OVER BUDGET)" : "")),
|
|
69
|
+
result.budget.entries.map((entry) => (React.createElement(Box, { key: entry.skillName, marginLeft: 4 },
|
|
62
70
|
React.createElement(Text, { color: theme.muted }, entry.skillName),
|
|
63
71
|
React.createElement(Text, { color: theme.muted, dimColor: true },
|
|
64
|
-
|
|
72
|
+
" ",
|
|
65
73
|
"~",
|
|
66
74
|
entry.tokens,
|
|
67
75
|
" tokens")))),
|
|
68
76
|
result.budget.suggestions.map((s, i) => (React.createElement(Box, { key: `suggestion-${i}`, marginLeft: 4 },
|
|
69
77
|
React.createElement(Text, { color: theme.warning },
|
|
70
|
-
|
|
78
|
+
"! ",
|
|
71
79
|
s))))),
|
|
80
|
+
result.budget.optimizations.length > 0 && (React.createElement(Box, { flexDirection: "column", marginBottom: 1 },
|
|
81
|
+
React.createElement(Text, { bold: true, color: theme.warning },
|
|
82
|
+
" ",
|
|
83
|
+
"Optimization Suggestions"),
|
|
84
|
+
result.budget.optimizations.map((opt, i) => (React.createElement(Box, { key: `opt-${i}`, flexDirection: "column", marginLeft: 4 },
|
|
85
|
+
React.createElement(Text, { color: opt.meetsbudget ? theme.success : theme.warning },
|
|
86
|
+
opt.meetsbudget ? "\u2713" : "~",
|
|
87
|
+
" Disable [",
|
|
88
|
+
opt.disableSkills.join(", "),
|
|
89
|
+
"] ",
|
|
90
|
+
"\u2192",
|
|
91
|
+
" save ~",
|
|
92
|
+
opt.tokensSaved,
|
|
93
|
+
" tokens (",
|
|
94
|
+
opt.remainingTokens,
|
|
95
|
+
" remaining)")))))),
|
|
72
96
|
result.conflicts.length > 0 && (React.createElement(Box, { flexDirection: "column", marginBottom: 1 },
|
|
73
97
|
React.createElement(Text, { bold: true, color: theme.error },
|
|
74
|
-
|
|
98
|
+
" ",
|
|
75
99
|
"Conflicts (",
|
|
76
100
|
result.conflicts.length,
|
|
77
101
|
")"),
|
|
78
102
|
result.conflicts.map((c, i) => (React.createElement(Box, { key: `conflict-${i}`, flexDirection: "column", marginLeft: 4 },
|
|
79
103
|
React.createElement(Text, { color: theme.error },
|
|
80
|
-
|
|
104
|
+
"\u2717",
|
|
81
105
|
" ",
|
|
82
106
|
c.ruleA.skillName,
|
|
83
107
|
" vs ",
|
|
84
|
-
c.ruleB.skillName
|
|
108
|
+
c.ruleB.skillName,
|
|
109
|
+
React.createElement(Text, { color: theme.muted, dimColor: true },
|
|
110
|
+
" ",
|
|
111
|
+
"[",
|
|
112
|
+
c.kind,
|
|
113
|
+
"]")),
|
|
85
114
|
React.createElement(Text, { color: theme.muted, dimColor: true },
|
|
86
|
-
|
|
115
|
+
" ",
|
|
87
116
|
c.reason)))))),
|
|
88
117
|
deep && result.conflicts.length === 0 && (React.createElement(Box, { marginLeft: 2, marginBottom: 1 },
|
|
89
118
|
React.createElement(Text, { color: theme.success },
|
|
90
|
-
|
|
119
|
+
"\u2713",
|
|
91
120
|
" No rule conflicts detected"))),
|
|
92
121
|
result.duplicates.length > 0 && (React.createElement(Box, { flexDirection: "column", marginBottom: 1 },
|
|
93
122
|
React.createElement(Text, { bold: true, color: theme.warning },
|
|
94
|
-
|
|
123
|
+
" ",
|
|
95
124
|
"Potential Duplicates (",
|
|
96
125
|
result.duplicates.length,
|
|
97
126
|
")"),
|
|
98
127
|
result.duplicates.map((d, i) => (React.createElement(Box, { key: `dup-${i}`, flexDirection: "column", marginLeft: 4 },
|
|
99
128
|
React.createElement(Text, { color: theme.warning },
|
|
100
|
-
|
|
129
|
+
"~",
|
|
101
130
|
" ",
|
|
102
131
|
d.skillA,
|
|
103
132
|
" + ",
|
|
@@ -106,12 +135,12 @@ export default function Skills({ mode, budget, deep, skillsDir }) {
|
|
|
106
135
|
d.similarity,
|
|
107
136
|
"% overlap)"),
|
|
108
137
|
React.createElement(Text, { color: theme.muted, dimColor: true },
|
|
109
|
-
|
|
138
|
+
" ",
|
|
110
139
|
"shared: ",
|
|
111
|
-
d.sharedTriggers.slice(0, 3).join(
|
|
140
|
+
d.sharedTriggers.slice(0, 3).join(", "))))))),
|
|
112
141
|
deep && result.duplicates.length === 0 && (React.createElement(Box, { marginLeft: 2, marginBottom: 1 },
|
|
113
142
|
React.createElement(Text, { color: theme.success },
|
|
114
|
-
|
|
143
|
+
"\u2713",
|
|
115
144
|
" No duplicate skills detected"))))),
|
|
116
145
|
!loading && (React.createElement(Box, { marginTop: 1 },
|
|
117
146
|
React.createElement(Text, { color: theme.muted, dimColor: true }, "Press r to refresh, q to quit")))));
|
package/dist/ui/StackSelector.js
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import { detectStack, STACK_LABELS } from
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
const ALL_STACKS = [
|
|
1
|
+
import { Box, Text, useInput } from "ink";
|
|
2
|
+
import React, { useEffect, useRef, useState } from "react";
|
|
3
|
+
import { detectStack, STACK_LABELS } from "../lib/common.js";
|
|
4
|
+
import { useCIMode } from "./CIContext.js";
|
|
5
|
+
import { theme } from "./theme.js";
|
|
6
|
+
const ALL_STACKS = [
|
|
7
|
+
"node",
|
|
8
|
+
"python",
|
|
9
|
+
"go",
|
|
10
|
+
"rust",
|
|
11
|
+
"java-gradle",
|
|
12
|
+
"java-maven",
|
|
13
|
+
"elixir",
|
|
14
|
+
];
|
|
7
15
|
export default function StackSelector({ projectDir, onConfirm }) {
|
|
8
16
|
const isCI = useCIMode();
|
|
9
17
|
const autoConfirmed = useRef(false);
|
|
@@ -11,7 +19,7 @@ export default function StackSelector({ projectDir, onConfirm }) {
|
|
|
11
19
|
const [detectedStack, setDetectedStack] = useState(null);
|
|
12
20
|
const [detecting, setDetecting] = useState(true);
|
|
13
21
|
useEffect(() => {
|
|
14
|
-
detectStack(projectDir).then(result => {
|
|
22
|
+
detectStack(projectDir).then((result) => {
|
|
15
23
|
if (result) {
|
|
16
24
|
setDetectedStack(result.stackType);
|
|
17
25
|
const idx = ALL_STACKS.indexOf(result.stackType);
|
|
@@ -32,9 +40,9 @@ export default function StackSelector({ projectDir, onConfirm }) {
|
|
|
32
40
|
if (detecting)
|
|
33
41
|
return;
|
|
34
42
|
if (key.upArrow)
|
|
35
|
-
setCursor(c => Math.max(0, c - 1));
|
|
43
|
+
setCursor((c) => Math.max(0, c - 1));
|
|
36
44
|
if (key.downArrow)
|
|
37
|
-
setCursor(c => Math.min(ALL_STACKS.length - 1, c + 1));
|
|
45
|
+
setCursor((c) => Math.min(ALL_STACKS.length - 1, c + 1));
|
|
38
46
|
if (key.return) {
|
|
39
47
|
onConfirm(ALL_STACKS[cursor]);
|
|
40
48
|
}
|
|
@@ -46,20 +54,22 @@ export default function StackSelector({ projectDir, onConfirm }) {
|
|
|
46
54
|
return (React.createElement(Box, { flexDirection: "column" },
|
|
47
55
|
React.createElement(Text, { bold: true }, "Select project stack:"),
|
|
48
56
|
detectedStack && (React.createElement(Text, { color: theme.success },
|
|
49
|
-
|
|
57
|
+
" ",
|
|
50
58
|
"Auto-detected: ",
|
|
51
59
|
STACK_LABELS[detectedStack])),
|
|
52
60
|
React.createElement(Box, { marginTop: 1, flexDirection: "column", borderStyle: "single", borderLeft: true, borderRight: false, borderTop: false, borderBottom: false, borderColor: theme.muted, paddingLeft: 1 }, ALL_STACKS.map((stack, i) => (React.createElement(Box, { key: stack },
|
|
53
|
-
React.createElement(Text, { color: i === cursor ? theme.primary :
|
|
54
|
-
i === cursor ?
|
|
55
|
-
stack === detectedStack ?
|
|
61
|
+
React.createElement(Text, { color: i === cursor ? theme.primary : "white" },
|
|
62
|
+
i === cursor ? "\u25b6 " : " ",
|
|
63
|
+
stack === detectedStack ? "\u25c9" : "\u25cb",
|
|
56
64
|
" ",
|
|
57
65
|
STACK_LABELS[stack],
|
|
58
|
-
stack === detectedStack && (React.createElement(Text, { color: theme.success, dimColor: true },
|
|
66
|
+
stack === detectedStack && (React.createElement(Text, { color: theme.success, dimColor: true },
|
|
67
|
+
" ",
|
|
68
|
+
"(detected)"))))))),
|
|
59
69
|
React.createElement(Box, { marginTop: 1, gap: 2 },
|
|
60
70
|
React.createElement(Text, { color: theme.primary }, STACK_LABELS[ALL_STACKS[cursor]]),
|
|
61
71
|
React.createElement(Text, { color: theme.muted, dimColor: true },
|
|
62
|
-
|
|
63
|
-
" navigate
|
|
72
|
+
"\u2191\u2193",
|
|
73
|
+
" navigate Enter confirm"))));
|
|
64
74
|
}
|
|
65
75
|
//# sourceMappingURL=StackSelector.js.map
|
package/dist/ui/Summary.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import React from
|
|
2
|
-
import type { InitStep } from
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { InitStep } from "../types/index.js";
|
|
3
3
|
interface Props {
|
|
4
4
|
steps: InitStep[];
|
|
5
5
|
dryRun: boolean;
|
|
@@ -7,6 +7,6 @@ interface Props {
|
|
|
7
7
|
stack?: string;
|
|
8
8
|
elapsedMs?: number;
|
|
9
9
|
}
|
|
10
|
-
export default function Summary({ steps, dryRun, projectName, stack, elapsedMs }: Props): React.JSX.Element;
|
|
10
|
+
export default function Summary({ steps, dryRun, projectName, stack, elapsedMs, }: Props): React.JSX.Element;
|
|
11
11
|
export {};
|
|
12
12
|
//# sourceMappingURL=Summary.d.ts.map
|
package/dist/ui/Summary.js
CHANGED
|
@@ -1,29 +1,35 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { Box, Text, useApp, useInput } from "ink";
|
|
2
|
+
import React, { useEffect } from "react";
|
|
3
|
+
import { useCIMode } from "./CIContext.js";
|
|
4
|
+
import { theme } from "./theme.js";
|
|
5
5
|
/** Map stack to the install command hint */
|
|
6
6
|
function getInstallHint(stack) {
|
|
7
7
|
switch (stack) {
|
|
8
|
-
case
|
|
9
|
-
|
|
10
|
-
case
|
|
11
|
-
|
|
12
|
-
case
|
|
13
|
-
|
|
14
|
-
case
|
|
15
|
-
|
|
8
|
+
case "node":
|
|
9
|
+
return "pnpm install";
|
|
10
|
+
case "python":
|
|
11
|
+
return "pip install -r requirements.txt";
|
|
12
|
+
case "go":
|
|
13
|
+
return "go mod tidy";
|
|
14
|
+
case "rust":
|
|
15
|
+
return "cargo build";
|
|
16
|
+
case "java-gradle":
|
|
17
|
+
return "./gradlew build";
|
|
18
|
+
case "java-maven":
|
|
19
|
+
return "mvn install";
|
|
20
|
+
case "elixir":
|
|
21
|
+
return "mix deps.get";
|
|
22
|
+
default:
|
|
23
|
+
return null;
|
|
16
24
|
}
|
|
17
25
|
}
|
|
18
|
-
export default function Summary({ steps, dryRun, projectName, stack, elapsedMs }) {
|
|
26
|
+
export default function Summary({ steps, dryRun, projectName, stack, elapsedMs, }) {
|
|
19
27
|
const { exit } = useApp();
|
|
20
28
|
const isCI = useCIMode();
|
|
21
|
-
const done = steps.filter(s => s.status ===
|
|
22
|
-
const skipped = steps.filter(s => s.status ===
|
|
23
|
-
const errors = steps.filter(s => s.status ===
|
|
24
|
-
const elapsed = elapsedMs != null
|
|
25
|
-
? `${(elapsedMs / 1000).toFixed(1)}s`
|
|
26
|
-
: null;
|
|
29
|
+
const done = steps.filter((s) => s.status === "done").length;
|
|
30
|
+
const skipped = steps.filter((s) => s.status === "skipped").length;
|
|
31
|
+
const errors = steps.filter((s) => s.status === "error");
|
|
32
|
+
const elapsed = elapsedMs != null ? `${(elapsedMs / 1000).toFixed(1)}s` : null;
|
|
27
33
|
// Auto-exit in CI mode
|
|
28
34
|
useEffect(() => {
|
|
29
35
|
if (isCI) {
|
|
@@ -39,75 +45,79 @@ export default function Summary({ steps, dryRun, projectName, stack, elapsedMs }
|
|
|
39
45
|
const installHint = getInstallHint(stack);
|
|
40
46
|
return (React.createElement(Box, { flexDirection: "column" },
|
|
41
47
|
React.createElement(Text, { bold: true, color: errors.length > 0 ? theme.warning : theme.success },
|
|
42
|
-
dryRun ?
|
|
48
|
+
dryRun ? "\u25cb Dry run complete" : "\u2713 Project scaffolded",
|
|
43
49
|
elapsed && React.createElement(Text, { color: theme.muted },
|
|
44
|
-
"
|
|
50
|
+
" Completed in ",
|
|
45
51
|
elapsed)),
|
|
46
52
|
React.createElement(Box, { marginTop: 1 },
|
|
47
|
-
React.createElement(Text, { color: theme.muted }, "
|
|
53
|
+
React.createElement(Text, { color: theme.muted }, " Project: "),
|
|
48
54
|
React.createElement(Text, { color: theme.primary, bold: true }, projectName),
|
|
49
55
|
stack && React.createElement(Text, { color: theme.muted },
|
|
50
|
-
"
|
|
56
|
+
" (",
|
|
51
57
|
stack,
|
|
52
58
|
")")),
|
|
53
59
|
dryRun && (React.createElement(Box, { marginTop: 1 },
|
|
54
|
-
React.createElement(Text, { color: theme.warning, bold: true },
|
|
55
|
-
|
|
56
|
-
|
|
60
|
+
React.createElement(Text, { color: theme.warning, bold: true },
|
|
61
|
+
" ",
|
|
62
|
+
"No changes were made (dry run)"))),
|
|
63
|
+
React.createElement(Box, { marginTop: 1, flexDirection: "column" }, steps.map((step) => (React.createElement(Box, { key: step.id, marginLeft: 2 }, step.status === "done" ? (React.createElement(Text, { color: theme.success },
|
|
64
|
+
"\u2713",
|
|
57
65
|
" ",
|
|
58
66
|
step.label,
|
|
59
|
-
step.detail ? React.createElement(Text, { color: theme.muted, dimColor: true },
|
|
60
|
-
"
|
|
61
|
-
step.detail) : null)) : step.status ===
|
|
62
|
-
|
|
67
|
+
step.detail ? (React.createElement(Text, { color: theme.muted, dimColor: true },
|
|
68
|
+
" ",
|
|
69
|
+
step.detail)) : null)) : step.status === "skipped" ? (React.createElement(Text, { color: theme.muted },
|
|
70
|
+
"\u2013",
|
|
63
71
|
" ",
|
|
64
72
|
step.label,
|
|
65
73
|
step.detail ? React.createElement(Text, { dimColor: true },
|
|
66
|
-
"
|
|
67
|
-
step.detail) : null)) : step.status ===
|
|
68
|
-
|
|
74
|
+
" ",
|
|
75
|
+
step.detail) : null)) : step.status === "error" ? (React.createElement(Text, { color: theme.error },
|
|
76
|
+
"\u2717",
|
|
69
77
|
" ",
|
|
70
78
|
step.label,
|
|
71
|
-
step.detail ? React.createElement(Text, { color: theme.muted, dimColor: true },
|
|
72
|
-
"
|
|
73
|
-
step.detail) : null)) : null)))),
|
|
79
|
+
step.detail ? (React.createElement(Text, { color: theme.muted, dimColor: true },
|
|
80
|
+
" ",
|
|
81
|
+
step.detail)) : null)) : null)))),
|
|
74
82
|
React.createElement(Box, { marginTop: 1, flexDirection: "column" },
|
|
75
83
|
React.createElement(Text, { color: theme.success },
|
|
76
|
-
"
|
|
77
|
-
|
|
84
|
+
" ",
|
|
85
|
+
"\u2713",
|
|
78
86
|
" ",
|
|
79
87
|
done,
|
|
80
88
|
" steps completed"),
|
|
81
89
|
skipped > 0 && (React.createElement(Text, { color: theme.muted },
|
|
82
|
-
"
|
|
83
|
-
|
|
90
|
+
" ",
|
|
91
|
+
"\u2013",
|
|
84
92
|
" ",
|
|
85
93
|
skipped,
|
|
86
94
|
" steps skipped")),
|
|
87
95
|
errors.length > 0 && (React.createElement(Box, { flexDirection: "column" },
|
|
88
96
|
React.createElement(Text, { color: theme.error },
|
|
89
|
-
"
|
|
90
|
-
|
|
97
|
+
" ",
|
|
98
|
+
"\u2717",
|
|
91
99
|
" ",
|
|
92
100
|
errors.length,
|
|
93
101
|
" errors:"),
|
|
94
|
-
errors.map(e => (React.createElement(Text, { key: `err-${e.id}`, color: theme.error },
|
|
95
|
-
"
|
|
96
|
-
|
|
102
|
+
errors.map((e) => (React.createElement(Text, { key: `err-${e.id}`, color: theme.error },
|
|
103
|
+
" ",
|
|
104
|
+
"\u2022",
|
|
97
105
|
" ",
|
|
98
106
|
e.label,
|
|
99
107
|
": ",
|
|
100
108
|
e.detail)))))),
|
|
101
109
|
!dryRun && errors.length === 0 && (React.createElement(Box, { marginTop: 1, flexDirection: "column" },
|
|
102
|
-
React.createElement(Text, { color: theme.muted, bold: true },
|
|
110
|
+
React.createElement(Text, { color: theme.muted, bold: true },
|
|
111
|
+
" ",
|
|
112
|
+
"Next steps:"),
|
|
103
113
|
React.createElement(Text, { color: theme.primary },
|
|
104
|
-
"
|
|
114
|
+
" cd ",
|
|
105
115
|
projectName),
|
|
106
116
|
installHint && React.createElement(Text, { color: theme.primary },
|
|
107
|
-
"
|
|
117
|
+
" ",
|
|
108
118
|
installHint),
|
|
109
|
-
React.createElement(Text, { color: theme.primary }, "
|
|
110
|
-
React.createElement(Text, { color: theme.primary }, "
|
|
119
|
+
React.createElement(Text, { color: theme.primary }, " npx javi-ai sync"),
|
|
120
|
+
React.createElement(Text, { color: theme.primary }, " javi-forge doctor"))),
|
|
111
121
|
React.createElement(Box, { marginTop: 1 },
|
|
112
122
|
React.createElement(Text, { color: theme.muted, dimColor: true }, "Press Enter to exit"))));
|
|
113
123
|
}
|
package/dist/ui/Welcome.d.ts
CHANGED
package/dist/ui/Welcome.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import {
|
|
1
|
+
import { Box, Text } from "ink";
|
|
2
|
+
import Spinner from "ink-spinner";
|
|
3
|
+
import React, { useEffect } from "react";
|
|
4
|
+
import { useCIMode } from "./CIContext.js";
|
|
5
|
+
import Header from "./Header.js";
|
|
6
|
+
import { theme } from "./theme.js";
|
|
7
7
|
export default function Welcome({ onDone }) {
|
|
8
8
|
const isCI = useCIMode();
|
|
9
9
|
useEffect(() => {
|
|
@@ -18,28 +18,27 @@ export default function Welcome({ onDone }) {
|
|
|
18
18
|
React.createElement(Box, { marginTop: 1, flexDirection: "column" },
|
|
19
19
|
React.createElement(Text, null,
|
|
20
20
|
React.createElement(Text, { color: theme.primary },
|
|
21
|
-
|
|
22
|
-
" Templates
|
|
21
|
+
"\u25c6",
|
|
22
|
+
" Templates "),
|
|
23
23
|
React.createElement(Text, { color: theme.muted }, " Go, Java, Node, Python, Rust CI")),
|
|
24
24
|
React.createElement(Text, null,
|
|
25
25
|
React.createElement(Text, { color: theme.success },
|
|
26
|
-
|
|
27
|
-
" Memory
|
|
26
|
+
"\u25c6",
|
|
27
|
+
" Memory "),
|
|
28
28
|
React.createElement(Text, { color: theme.muted }, " Engram, Obsidian Brain")),
|
|
29
29
|
React.createElement(Text, null,
|
|
30
30
|
React.createElement(Text, { color: theme.accent },
|
|
31
|
-
|
|
32
|
-
" SDD
|
|
31
|
+
"\u25c6",
|
|
32
|
+
" SDD "),
|
|
33
33
|
React.createElement(Text, { color: theme.muted }, " Spec-Driven Development")),
|
|
34
34
|
React.createElement(Text, null,
|
|
35
35
|
React.createElement(Text, { color: theme.warning },
|
|
36
|
-
|
|
37
|
-
" Review
|
|
36
|
+
"\u25c6",
|
|
37
|
+
" Review "),
|
|
38
38
|
React.createElement(Text, { color: theme.muted }, " GHAGGA code review"))),
|
|
39
39
|
React.createElement(Box, { marginTop: 1 },
|
|
40
40
|
React.createElement(Text, { color: theme.muted },
|
|
41
41
|
React.createElement(Spinner, { type: "dots" }),
|
|
42
|
-
|
|
43
|
-
"Detecting your environment...")))));
|
|
42
|
+
" Detecting your environment...")))));
|
|
44
43
|
}
|
|
45
44
|
//# sourceMappingURL=Welcome.js.map
|
package/dist/ui/theme.d.ts
CHANGED
package/dist/ui/theme.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
export const theme = {
|
|
2
|
-
primary:
|
|
3
|
-
success:
|
|
4
|
-
warning:
|
|
5
|
-
error:
|
|
6
|
-
muted:
|
|
7
|
-
accent:
|
|
2
|
+
primary: "#f97316", // orange
|
|
3
|
+
success: "green",
|
|
4
|
+
warning: "yellow",
|
|
5
|
+
error: "red",
|
|
6
|
+
muted: "gray",
|
|
7
|
+
accent: "magenta",
|
|
8
8
|
};
|
|
9
9
|
//# sourceMappingURL=theme.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "javi-forge",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.1",
|
|
4
4
|
"description": "Project scaffolding and AI-ready CI bootstrap",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -14,19 +14,21 @@
|
|
|
14
14
|
"test": "vitest run",
|
|
15
15
|
"test:watch": "vitest",
|
|
16
16
|
"test:coverage": "vitest run --coverage",
|
|
17
|
-
"test:mutation": "stryker run"
|
|
17
|
+
"test:mutation": "stryker run",
|
|
18
|
+
"package:check": "npm pack --dry-run --json --cache /tmp/javi-forge-npm-pack-cache > /tmp/javi-forge-pack.json && node scripts/verify-package-contents.mjs /tmp/javi-forge-pack.json"
|
|
18
19
|
},
|
|
19
20
|
"files": [
|
|
20
|
-
"dist
|
|
21
|
+
"dist/**/*.js",
|
|
22
|
+
"dist/**/*.d.ts",
|
|
23
|
+
"!dist/__integration__/**",
|
|
24
|
+
"!dist/e2e/**",
|
|
21
25
|
"ci-local/",
|
|
22
26
|
"modules/",
|
|
23
27
|
"templates/",
|
|
24
28
|
"workflows/",
|
|
25
29
|
"lib/",
|
|
26
|
-
"!dist/**/*.test.*",
|
|
27
|
-
"!dist/**/__snapshots__",
|
|
28
|
-
"package.json",
|
|
29
30
|
"README.md",
|
|
31
|
+
"LICENSE*",
|
|
30
32
|
".gitignore.template"
|
|
31
33
|
],
|
|
32
34
|
"author": "JNZader",
|
|
@@ -64,6 +66,7 @@
|
|
|
64
66
|
"@types/update-notifier": "^6.0.8",
|
|
65
67
|
"@vitest/coverage-v8": "^4.1.0",
|
|
66
68
|
"conventional-changelog-conventionalcommits": "^9.3.0",
|
|
69
|
+
"ink-testing-library": "^4.0.0",
|
|
67
70
|
"semantic-release": "^25.0.3",
|
|
68
71
|
"tsx": "^4.21.0",
|
|
69
72
|
"typescript": "^5.9.3",
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"mcpServers": {
|
|
3
|
+
"atlassian": {
|
|
4
|
+
"command": "uvx",
|
|
5
|
+
"args": ["mcp-atlassian"],
|
|
6
|
+
"env": {
|
|
7
|
+
"CONFLUENCE_URL": "__CONFLUENCE_URL__",
|
|
8
|
+
"CONFLUENCE_USERNAME": "__CONFLUENCE_USERNAME__",
|
|
9
|
+
"CONFLUENCE_API_TOKEN": "__CONFLUENCE_API_TOKEN__",
|
|
10
|
+
"JIRA_URL": "__JIRA_URL__",
|
|
11
|
+
"JIRA_USERNAME": "__JIRA_USERNAME__",
|
|
12
|
+
"JIRA_API_TOKEN": "__JIRA_API_TOKEN__"
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# ===========================================
|
|
2
|
+
# RepoForge Graph Configuration
|
|
3
|
+
# ===========================================
|
|
4
|
+
# Docs: https://github.com/JNZader/repoforge
|
|
5
|
+
# ===========================================
|
|
6
|
+
|
|
7
|
+
graph:
|
|
8
|
+
# Graph type: calls | imports | dependencies
|
|
9
|
+
type: calls
|
|
10
|
+
|
|
11
|
+
# Output format: json | dot | mermaid
|
|
12
|
+
output: json
|
|
13
|
+
|
|
14
|
+
# Where to store the generated graph artifact
|
|
15
|
+
artifact: .repoforge/call-graph.json
|
|
16
|
+
|
|
17
|
+
# Directories to include (globs supported)
|
|
18
|
+
include:
|
|
19
|
+
- src/**
|
|
20
|
+
|
|
21
|
+
# Directories to exclude
|
|
22
|
+
exclude:
|
|
23
|
+
- node_modules/**
|
|
24
|
+
- dist/**
|
|
25
|
+
- coverage/**
|
|
26
|
+
- '**/*.test.*'
|
|
27
|
+
- '**/*.spec.*'
|
|
28
|
+
|
|
29
|
+
query:
|
|
30
|
+
# Enable MCP-based code intelligence queries
|
|
31
|
+
mcp: true
|
|
32
|
+
|
|
33
|
+
# Max depth for transitive dependency lookups
|
|
34
|
+
max_depth: 5
|