deuk-agent-flow 4.2.7 → 5.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.ko.md +277 -0
- package/CHANGELOG.md +794 -124
- package/LICENSE +0 -0
- package/README.ko.md +97 -17
- package/README.md +108 -25
- package/bin/deuk-agent-flow.js +11 -13
- package/bin/deuk-agent-rule.js +1 -1
- package/bundled/README.md +3 -0
- package/bundled/deuk-agent-flow.vsix +0 -0
- package/core-rules/AGENTS.md +30 -120
- package/docs/architecture.ko.md +155 -2
- package/docs/architecture.md +155 -2
- package/docs/assets/agentflow-panel-skills.png +0 -0
- package/docs/assets/agentflow-panel.png +0 -0
- package/docs/how-it-works.ko.md +109 -52
- package/docs/how-it-works.md +128 -71
- package/docs/principles.ko.md +68 -68
- package/docs/principles.md +68 -68
- package/docs/usage-guide.ko.md +251 -212
- package/package.json +60 -45
- package/scripts/bundle-vscode-vsix.ts +67 -0
- package/scripts/{cli-args.mjs → cli-args.ts} +49 -12
- package/scripts/cli-context-commands.ts +35 -0
- package/scripts/cli-init-claude.ts +179 -0
- package/scripts/cli-init-commands.ts +99 -0
- package/scripts/cli-init-core.ts +89 -0
- package/scripts/cli-init-instructions.ts +489 -0
- package/scripts/cli-init-logic.ts +46 -0
- package/scripts/cli-init-migrate.ts +504 -0
- package/scripts/cli-init-workspace.ts +63 -0
- package/scripts/cli-locales.ts +85 -0
- package/scripts/{cli-prompts.mjs → cli-prompts.ts} +19 -34
- package/scripts/{cli-rule-compiler.mjs → cli-rule-compiler.ts} +128 -112
- package/scripts/cli-skill-commands.ts +709 -0
- package/scripts/{cli-telemetry-commands.mjs → cli-telemetry-commands.ts} +25 -22
- package/scripts/cli-ticket-command-shared.ts +4 -0
- package/scripts/cli-ticket-commands.ts +3781 -0
- package/scripts/cli-ticket-docmeta.ts +103 -0
- package/scripts/cli-ticket-document.ts +153 -0
- package/scripts/cli-ticket-evidence.ts +312 -0
- package/scripts/cli-ticket-home.ts +449 -0
- package/scripts/cli-ticket-index.ts +283 -0
- package/scripts/{cli-ticket-migration.mjs → cli-ticket-migration.ts} +44 -68
- package/scripts/cli-ticket-parser.ts +100 -0
- package/scripts/cli-ticket-scan.ts +102 -0
- package/scripts/cli-ticket-surface.ts +56 -0
- package/scripts/{cli-usage-commands.mjs → cli-usage-commands.ts} +325 -326
- package/scripts/cli-utils.ts +1560 -0
- package/scripts/cli.ts +695 -0
- package/scripts/{lint-md.mjs → lint-md.ts} +32 -42
- package/scripts/lint-rules.ts +203 -0
- package/scripts/{merge-logic.mjs → merge-logic.ts} +44 -44
- package/scripts/oss-prepack.js +32 -0
- package/scripts/out/scripts/bundle-vscode-vsix.js +68 -0
- package/scripts/out/scripts/bundle-vscode-vsix.js.map +1 -0
- package/scripts/out/scripts/cli-args.js +374 -0
- package/scripts/out/scripts/cli-args.js.map +1 -0
- package/scripts/out/scripts/cli-context-commands.js +31 -0
- package/scripts/out/scripts/cli-context-commands.js.map +1 -0
- package/scripts/out/scripts/cli-init-claude.js +176 -0
- package/scripts/out/scripts/cli-init-claude.js.map +1 -0
- package/scripts/out/scripts/cli-init-commands.js +87 -0
- package/scripts/out/scripts/cli-init-commands.js.map +1 -0
- package/scripts/out/scripts/cli-init-core.js +89 -0
- package/scripts/out/scripts/cli-init-core.js.map +1 -0
- package/scripts/out/scripts/cli-init-instructions.js +460 -0
- package/scripts/out/scripts/cli-init-instructions.js.map +1 -0
- package/scripts/out/scripts/cli-init-logic.js +41 -0
- package/scripts/out/scripts/cli-init-logic.js.map +1 -0
- package/scripts/out/scripts/cli-init-migrate.js +497 -0
- package/scripts/out/scripts/cli-init-migrate.js.map +1 -0
- package/scripts/out/scripts/cli-init-workspace.js +57 -0
- package/scripts/out/scripts/cli-init-workspace.js.map +1 -0
- package/scripts/out/scripts/cli-locales.js +83 -0
- package/scripts/out/scripts/cli-locales.js.map +1 -0
- package/scripts/out/scripts/cli-prompts.js +101 -0
- package/scripts/out/scripts/cli-prompts.js.map +1 -0
- package/scripts/out/scripts/cli-rule-compiler.js +121 -0
- package/scripts/out/scripts/cli-rule-compiler.js.map +1 -0
- package/scripts/out/scripts/cli-skill-commands.js +708 -0
- package/scripts/out/scripts/cli-skill-commands.js.map +1 -0
- package/scripts/out/scripts/cli-telemetry-commands.js +604 -0
- package/scripts/out/scripts/cli-telemetry-commands.js.map +1 -0
- package/scripts/out/scripts/cli-ticket-command-shared.js +2 -0
- package/scripts/out/scripts/cli-ticket-command-shared.js.map +1 -0
- package/scripts/out/scripts/cli-ticket-commands.js +3530 -0
- package/scripts/out/scripts/cli-ticket-commands.js.map +1 -0
- package/scripts/out/scripts/cli-ticket-docmeta.js +90 -0
- package/scripts/out/scripts/cli-ticket-docmeta.js.map +1 -0
- package/scripts/out/scripts/cli-ticket-document.js +121 -0
- package/scripts/out/scripts/cli-ticket-document.js.map +1 -0
- package/scripts/out/scripts/cli-ticket-evidence.js +286 -0
- package/scripts/out/scripts/cli-ticket-evidence.js.map +1 -0
- package/scripts/out/scripts/cli-ticket-home.js +440 -0
- package/scripts/out/scripts/cli-ticket-home.js.map +1 -0
- package/scripts/out/scripts/cli-ticket-index.js +272 -0
- package/scripts/out/scripts/cli-ticket-index.js.map +1 -0
- package/scripts/out/scripts/cli-ticket-migration.js +261 -0
- package/scripts/out/scripts/cli-ticket-migration.js.map +1 -0
- package/scripts/out/scripts/cli-ticket-parser.js +90 -0
- package/scripts/out/scripts/cli-ticket-parser.js.map +1 -0
- package/scripts/out/scripts/cli-ticket-scan.js +93 -0
- package/scripts/out/scripts/cli-ticket-scan.js.map +1 -0
- package/scripts/out/scripts/cli-ticket-surface.js +53 -0
- package/scripts/out/scripts/cli-ticket-surface.js.map +1 -0
- package/scripts/out/scripts/cli-usage-commands.js +310 -0
- package/scripts/out/scripts/cli-usage-commands.js.map +1 -0
- package/scripts/out/scripts/cli-utils.js +1544 -0
- package/scripts/out/scripts/cli-utils.js.map +1 -0
- package/scripts/out/scripts/cli.js +696 -0
- package/scripts/out/scripts/cli.js.map +1 -0
- package/scripts/out/scripts/lint-md.js +238 -0
- package/scripts/out/scripts/lint-md.js.map +1 -0
- package/scripts/out/scripts/lint-rules.js +193 -0
- package/scripts/out/scripts/lint-rules.js.map +1 -0
- package/scripts/out/scripts/merge-logic.js +38 -0
- package/scripts/out/scripts/merge-logic.js.map +1 -0
- package/scripts/out/scripts/plan-parser.js +52 -0
- package/scripts/out/scripts/plan-parser.js.map +1 -0
- package/scripts/out/scripts/ticket-machine.js +94 -0
- package/scripts/out/scripts/ticket-machine.js.map +1 -0
- package/scripts/out/scripts/ticket-workflow.js +498 -0
- package/scripts/out/scripts/ticket-workflow.js.map +1 -0
- package/scripts/{plan-parser.mjs → plan-parser.ts} +53 -53
- package/scripts/ticket-machine.ts +99 -0
- package/scripts/ticket-workflow.ts +544 -0
- package/templates/MODULE_RULE_TEMPLATE.md +11 -11
- package/templates/PROJECT_RULE.md +46 -47
- package/templates/TICKET_TEMPLATE.ko.md +48 -44
- package/templates/TICKET_TEMPLATE.md +48 -44
- package/templates/project-memory.md +19 -0
- package/templates/project-pilot/CONFORMANCE_GATE_TEMPLATE.md +25 -25
- package/templates/project-pilot/DRIFT_CHECKLIST.md +27 -27
- package/templates/project-pilot/FLOW_CONTRACT_TEMPLATE.md +26 -26
- package/templates/project-pilot/IMPLEMENTATION_MATRIX_TEMPLATE.md +30 -30
- package/templates/project-pilot/INTEGRATION_CONTRACT_TEMPLATE.md +26 -26
- package/templates/project-pilot/OWNER_MAP_TEMPLATE.md +15 -15
- package/templates/project-pilot/PROJECT_PILOT_RULE_TEMPLATE.md +34 -34
- package/templates/project-pilot/REFACTOR_CONTRACT_TEMPLATE.md +32 -32
- package/templates/project-pilot/REMEDIATION_PLAN_TEMPLATE.md +33 -33
- package/templates/rules.d/deukcontext-mcp.md +31 -31
- package/templates/rules.d/platform-coexistence.md +29 -29
- package/templates/skills/context-recall/SKILL.md +3 -1
- package/templates/skills/doc-sync/SKILL.md +111 -0
- package/templates/skills/generated-file-guard/SKILL.md +3 -1
- package/templates/skills/persona-maid/SKILL.md +65 -0
- package/templates/skills/project-pilot/SKILL.md +14 -63
- package/templates/skills/role-closer/SKILL.md +27 -0
- package/templates/skills/role-implementer/SKILL.md +30 -0
- package/templates/skills/role-planner/SKILL.md +29 -0
- package/templates/skills/role-qa-verifier/SKILL.md +30 -0
- package/templates/skills/safe-refactor/SKILL.md +3 -1
- package/templates/skills/ticket-status-surface/SKILL.md +17 -0
- package/NOTICE.md +0 -19
- package/core-rules/GEMINI.md +0 -7
- package/docs/npm-publish-guide.ko.md +0 -70
- package/scripts/cli-init-commands.mjs +0 -1759
- package/scripts/cli-init-logic.mjs +0 -64
- package/scripts/cli-skill-commands.mjs +0 -212
- package/scripts/cli-ticket-command-shared.mjs +0 -60
- package/scripts/cli-ticket-commands.mjs +0 -2474
- package/scripts/cli-ticket-index.mjs +0 -322
- package/scripts/cli-ticket-parser.mjs +0 -210
- package/scripts/cli-utils.mjs +0 -602
- package/scripts/cli.mjs +0 -256
- package/scripts/lint-rules.mjs +0 -197
- package/scripts/publish-dual-npm.mjs +0 -141
- package/scripts/smoke-npm-docker.mjs +0 -102
- package/scripts/smoke-npm-local.mjs +0 -110
- package/scripts/update-download-badge.mjs +0 -103
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { dirname, basename } from "path";
|
|
2
|
+
import { mkdirSync } from "fs";
|
|
3
|
+
import { createHash } from "crypto";
|
|
4
|
+
import { DEUK_ROOT_DIR, buildWorkspaceAliases, hasWorkspaceMarker, makePath, normalizeRegistryPath, resolveUserHome, writeFileLF } from "./cli-utils.js";
|
|
5
|
+
// ─── 내부 헬퍼: 워크스페이스 레지스트리 ─────────────────────────────────
|
|
6
|
+
function hashPath(value) {
|
|
7
|
+
return createHash("sha256").update(normalizeRegistryPath(String(value || "")), "utf8").digest("hex");
|
|
8
|
+
}
|
|
9
|
+
function workspaceRegistryRoot(homeDir = resolveUserHome()) {
|
|
10
|
+
return makePath(homeDir, ".agent-flow", "workspace");
|
|
11
|
+
}
|
|
12
|
+
function safeRegistryFileName(name) {
|
|
13
|
+
const cleaned = String(name || "workspace")
|
|
14
|
+
.replace(/[^A-Za-z0-9._-]+/g, "-")
|
|
15
|
+
.replace(/^-+|-+$/g, "");
|
|
16
|
+
return `${cleaned || "workspace"}.json`;
|
|
17
|
+
}
|
|
18
|
+
// ─── 공개 API ─────────────────────────────────────────────────────────────
|
|
19
|
+
export function updateSiblingWorkspaceRegistry(cwd, opts = {}) {
|
|
20
|
+
const workspacePath = normalizeRegistryPath(cwd || "");
|
|
21
|
+
if (!hasWorkspaceMarker(workspacePath))
|
|
22
|
+
return false;
|
|
23
|
+
const homeDir = resolveUserHome(opts);
|
|
24
|
+
// #623: never register the user home or anything under ~/.deuk-agent as a
|
|
25
|
+
// workspace — that store holds relocated tickets, not a sibling workspace, and
|
|
26
|
+
// registering it makes ticket ids look ambiguous across "workspaces".
|
|
27
|
+
const homeNorm = normalizeRegistryPath(homeDir);
|
|
28
|
+
const storeNorm = normalizeRegistryPath(makePath(homeDir, DEUK_ROOT_DIR));
|
|
29
|
+
if (workspacePath === homeNorm
|
|
30
|
+
|| workspacePath === storeNorm
|
|
31
|
+
|| workspacePath.startsWith(storeNorm + "/")) {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
const dryRun = Boolean(opts.dryRun);
|
|
35
|
+
const parentRoot = dirname(workspacePath);
|
|
36
|
+
const workspaceName = basename(workspacePath);
|
|
37
|
+
const parentRootHash = hashPath(parentRoot);
|
|
38
|
+
const pathHash = hashPath(workspacePath);
|
|
39
|
+
const registryDir = makePath(workspaceRegistryRoot(homeDir), parentRootHash);
|
|
40
|
+
const registryPath = makePath(registryDir, safeRegistryFileName(workspaceName));
|
|
41
|
+
const payload = {
|
|
42
|
+
version: 1,
|
|
43
|
+
name: workspaceName,
|
|
44
|
+
path: workspacePath,
|
|
45
|
+
aliases: buildWorkspaceAliases(workspaceName, workspacePath),
|
|
46
|
+
parentRoot,
|
|
47
|
+
parentRootHash,
|
|
48
|
+
pathHash,
|
|
49
|
+
updatedAt: new Date().toISOString(),
|
|
50
|
+
};
|
|
51
|
+
if (!dryRun) {
|
|
52
|
+
mkdirSync(registryDir, { recursive: true });
|
|
53
|
+
writeFileLF(registryPath, JSON.stringify(payload, null, 2) + "\n");
|
|
54
|
+
}
|
|
55
|
+
return { registryPath, payload };
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=cli-init-workspace.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-init-workspace.js","sourceRoot":"","sources":["../../cli-init-workspace.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { resolveDocsLanguage } from "./cli-utils.js";
|
|
2
|
+
const CLI_LOCALES = {
|
|
3
|
+
en: {
|
|
4
|
+
"prompts.init.heading": "DeukAgentFlow init — let's configure your workspace.",
|
|
5
|
+
"prompts.init.workspaceKind": "What kind of workspace is this?",
|
|
6
|
+
"prompts.init.noManagedSurface": "No managed surface file found — will create with markers.",
|
|
7
|
+
"prompts.init.missingMarkers": "Managed surface file exists without managed markers — will append a managed block.",
|
|
8
|
+
"prompts.init.summary.workspaceKind": "Workspace Kind: {{value}}",
|
|
9
|
+
"prompts.init.summary.technicalSurface": "Technical Surface: {{value}}",
|
|
10
|
+
"prompts.init.summary.aiClients": "AI Clients: {{value}}",
|
|
11
|
+
"prompts.init.summary.allSupportedClients": "all supported clients",
|
|
12
|
+
"prompts.init.summary.docsLanguage": "Docs Language: {{value}}",
|
|
13
|
+
"prompts.init.summary.workflowMode": "Workflow Mode: {{value}}",
|
|
14
|
+
"prompts.init.summary.shareTickets": "Share Tickets: {{value}}",
|
|
15
|
+
"prompts.init.summary.shareYes": "Yes (Shared)",
|
|
16
|
+
"prompts.init.summary.shareNo": "No (Private)",
|
|
17
|
+
"prompts.init.summary.contextMcp": "Deuk AgentContext MCP: hidden during init",
|
|
18
|
+
"prompts.init.summary.externalSync": "External Sync: {{value}}",
|
|
19
|
+
"prompts.init.summary.enabled": "Enabled",
|
|
20
|
+
"prompts.init.summary.disabled": "Disabled",
|
|
21
|
+
"prompts.init.summary.syncUrl": "Sync URL: {{value}}",
|
|
22
|
+
"prompts.init.summary.surfaceMode": "Managed Surface: {{value}}",
|
|
23
|
+
"ticket.validation.selfServeRecipe": "Use the self-serve recipe from the printed rules surface: do not ask the user, call help, or search for templates.",
|
|
24
|
+
"ticket.phase.fillSlots": "First fill these slots in the ticket file:",
|
|
25
|
+
"init.migrate.convertedMarkers": "[MIGRATE] Converted legacy HTML markers to heading-based format in managed surface file",
|
|
26
|
+
"init.migrate.backupSaved": "[MIGRATE] Backup saved as {{path}}",
|
|
27
|
+
"init.migrate.dryRunConvertedMarkers": "[DRY-RUN] Would convert legacy HTML markers to heading-based format in managed surface file",
|
|
28
|
+
"init.migrate.replaceLegacyHtmlBlock": "[MIGRATE] {{action}} legacy HTML managed block: {{path}}",
|
|
29
|
+
"init.migrate.replaceLegacyPointer": "[MIGRATE] {{action}} legacy managed pointer: {{path}}",
|
|
30
|
+
"init.cleanup.strippedBlock": "stripped generated managed block",
|
|
31
|
+
"init.cleanup.removedPointer": "removed generated managed pointer",
|
|
32
|
+
"init.cleanup.strippedPointer": "stripped generated managed pointer",
|
|
33
|
+
"init.cleanup.message": "[CLEANUP] {{action}}: {{path}}",
|
|
34
|
+
"init.cleanup.summary": "[SUMMARY] {{action}} {{count}} nested generated managed pointer surface(s) under {{workspace}}.",
|
|
35
|
+
"lint.rules.missingCore": "core rules file not found",
|
|
36
|
+
"lint.rules.printsCurrentBody": "Core rules must state that deuk-agent-flow rules prints the current core rules body."
|
|
37
|
+
},
|
|
38
|
+
ko: {
|
|
39
|
+
"prompts.init.heading": "DeukAgentFlow init — 워크스페이스를 설정합니다.",
|
|
40
|
+
"prompts.init.workspaceKind": "이 워크스페이스 유형은 무엇인가요?",
|
|
41
|
+
"prompts.init.noManagedSurface": "관리 표면 파일이 없어 마커와 함께 생성합니다.",
|
|
42
|
+
"prompts.init.missingMarkers": "관리 표면 파일에 관리 마커가 없어 관리 블록을 추가합니다.",
|
|
43
|
+
"prompts.init.summary.workspaceKind": "워크스페이스 유형: {{value}}",
|
|
44
|
+
"prompts.init.summary.technicalSurface": "기술 표면: {{value}}",
|
|
45
|
+
"prompts.init.summary.aiClients": "AI 클라이언트: {{value}}",
|
|
46
|
+
"prompts.init.summary.allSupportedClients": "지원되는 모든 클라이언트",
|
|
47
|
+
"prompts.init.summary.docsLanguage": "문서 언어: {{value}}",
|
|
48
|
+
"prompts.init.summary.workflowMode": "워크플로우 모드: {{value}}",
|
|
49
|
+
"prompts.init.summary.shareTickets": "티켓 공유: {{value}}",
|
|
50
|
+
"prompts.init.summary.shareYes": "예 (공유)",
|
|
51
|
+
"prompts.init.summary.shareNo": "아니오 (개인)",
|
|
52
|
+
"prompts.init.summary.contextMcp": "Deuk AgentContext MCP: init 중 숨김",
|
|
53
|
+
"prompts.init.summary.externalSync": "외부 동기화: {{value}}",
|
|
54
|
+
"prompts.init.summary.enabled": "활성화",
|
|
55
|
+
"prompts.init.summary.disabled": "비활성화",
|
|
56
|
+
"prompts.init.summary.syncUrl": "동기화 URL: {{value}}",
|
|
57
|
+
"prompts.init.summary.surfaceMode": "관리 표면: {{value}}",
|
|
58
|
+
"ticket.validation.selfServeRecipe": "출력된 rules surface의 self-serve 레시피를 사용하세요. 사용자에게 다시 묻거나 help를 호출하거나 템플릿을 검색하지 마세요.",
|
|
59
|
+
"ticket.phase.fillSlots": "먼저 티켓 파일에 다음 슬롯을 채우세요:",
|
|
60
|
+
"init.migrate.convertedMarkers": "[MIGRATE] legacy HTML 마커를 heading 기반 관리 표면 형식으로 변환했습니다",
|
|
61
|
+
"init.migrate.backupSaved": "[MIGRATE] 백업 저장: {{path}}",
|
|
62
|
+
"init.migrate.dryRunConvertedMarkers": "[DRY-RUN] legacy HTML 마커를 heading 기반 관리 표면 형식으로 변환할 예정입니다",
|
|
63
|
+
"init.migrate.replaceLegacyHtmlBlock": "[MIGRATE] legacy HTML 관리 블록 {{action}}: {{path}}",
|
|
64
|
+
"init.migrate.replaceLegacyPointer": "[MIGRATE] legacy 관리 포인터 {{action}}: {{path}}",
|
|
65
|
+
"init.cleanup.strippedBlock": "생성된 관리 블록 제거",
|
|
66
|
+
"init.cleanup.removedPointer": "생성된 관리 포인터 삭제",
|
|
67
|
+
"init.cleanup.strippedPointer": "생성된 관리 포인터 제거",
|
|
68
|
+
"init.cleanup.message": "[CLEANUP] {{action}}: {{path}}",
|
|
69
|
+
"init.cleanup.summary": "[SUMMARY] {{workspace}} 아래 중첩 생성 관리 포인터 표면 {{count}}개를 {{action}}.",
|
|
70
|
+
"lint.rules.missingCore": "core rules 파일을 찾을 수 없습니다",
|
|
71
|
+
"lint.rules.printsCurrentBody": "Core rules는 deuk-agent-flow rules가 현재 core rules 본문을 출력한다고 명시해야 합니다."
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
export function resolveCliLocale(value = "auto", env = process.env) {
|
|
75
|
+
return resolveDocsLanguage(value, env);
|
|
76
|
+
}
|
|
77
|
+
export function cliText(key, { locale = "auto", env = process.env, vars = {} } = {}) {
|
|
78
|
+
const resolvedLocale = resolveCliLocale(locale, env);
|
|
79
|
+
const dictionary = CLI_LOCALES[resolvedLocale] || CLI_LOCALES.en;
|
|
80
|
+
const template = dictionary[key] || CLI_LOCALES.en[key] || key;
|
|
81
|
+
return String(template).replace(/\{\{(\w+)\}\}/g, (_match, name) => String(vars[name] ?? ""));
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=cli-locales.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-locales.js","sourceRoot":"","sources":["../../cli-locales.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { createInterface } from "readline";
|
|
2
|
+
import { existsSync, readFileSync } from "fs";
|
|
3
|
+
import { AGENT_TOOLS, WORKFLOW_MODE_EXECUTE, WORKSPACE_KINDS, makePath, normalizeWorkflowMode, resolveDocsLanguage } from "./cli-utils.js";
|
|
4
|
+
import { cliText } from "./cli-locales.js";
|
|
5
|
+
export async function ask(rl, question) {
|
|
6
|
+
return new Promise((resolve) => rl.question(question, resolve));
|
|
7
|
+
}
|
|
8
|
+
export async function askYesNo(question, defaultYes = true) {
|
|
9
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
10
|
+
try {
|
|
11
|
+
const ans = (await ask(rl, question + (defaultYes ? " [Y/n]: " : " [y/N]: "))).trim().toLowerCase();
|
|
12
|
+
if (!ans)
|
|
13
|
+
return defaultYes;
|
|
14
|
+
return ans === "y" || ans === "yes";
|
|
15
|
+
}
|
|
16
|
+
finally {
|
|
17
|
+
rl.close();
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export async function selectOne(rl, prompt, choices) {
|
|
21
|
+
console.log("\n" + prompt);
|
|
22
|
+
choices.forEach((c, i) => console.log(` ${i + 1}) ${c.label}`));
|
|
23
|
+
while (true) {
|
|
24
|
+
const ans = (await ask(rl, ` Choice [1-${choices.length}]: `)).trim();
|
|
25
|
+
const idx = parseInt(ans, 10) - 1;
|
|
26
|
+
if (idx >= 0 && idx < choices.length)
|
|
27
|
+
return choices[idx].value;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
export async function selectMany(rl, prompt, choices) {
|
|
31
|
+
console.log("\n" + prompt + " (comma-separated numbers, or 'all')");
|
|
32
|
+
choices.forEach((c, i) => console.log(` ${i + 1}) ${c.label}`));
|
|
33
|
+
while (true) {
|
|
34
|
+
const ans = (await ask(rl, ` Choices: `)).trim().toLowerCase();
|
|
35
|
+
if (ans === "all" || ans === "")
|
|
36
|
+
return choices.map((c) => c.value);
|
|
37
|
+
const parts = ans.split(/[,\s]+/).map((s) => parseInt(s, 10) - 1);
|
|
38
|
+
if (parts.every((i) => i >= 0 && i < choices.length))
|
|
39
|
+
return parts.map((i) => choices[i].value);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function hasAny(cwd, names) {
|
|
43
|
+
return names.some((name) => existsSync(makePath(cwd, name)));
|
|
44
|
+
}
|
|
45
|
+
export function inferInitDefaults(cwd, opts = {}) {
|
|
46
|
+
const packageJsonPath = makePath(cwd, "package.json");
|
|
47
|
+
const packageJson = existsSync(packageJsonPath)
|
|
48
|
+
? readFileSync(packageJsonPath, "utf8")
|
|
49
|
+
: "";
|
|
50
|
+
const stack = opts.stack
|
|
51
|
+
|| (hasAny(cwd, ["pyproject.toml", "requirements.txt", "notebooks"]) ? "data" : null)
|
|
52
|
+
|| (hasAny(cwd, ["Dockerfile", "docker-compose.yml", "docker-compose.yaml", "k8s", "terraform"]) ? "infra" : null)
|
|
53
|
+
|| (hasAny(cwd, ["Cargo.toml", "go.mod", "pom.xml", "build.gradle"]) ? "backend" : null)
|
|
54
|
+
|| (packageJson && /"(@vitejs\/|vite|next|react|vue|svelte|astro)"/i.test(packageJson) ? "web" : null)
|
|
55
|
+
|| (packageJson ? "backend" : null)
|
|
56
|
+
|| "none";
|
|
57
|
+
const tools = AGENT_TOOLS.map((tool) => tool.value);
|
|
58
|
+
return {
|
|
59
|
+
stack,
|
|
60
|
+
agentTools: opts.agentTools ?? tools,
|
|
61
|
+
docsLanguage: resolveDocsLanguage(opts.docsLanguage ?? "auto"),
|
|
62
|
+
workflowMode: normalizeWorkflowMode(opts.workflowMode ?? opts.workflow ?? opts.approval ?? WORKFLOW_MODE_EXECUTE),
|
|
63
|
+
shareTickets: opts.shareTickets ?? false,
|
|
64
|
+
contextMcp: opts.contextMcp ?? "skip",
|
|
65
|
+
remoteSync: opts.remoteSync ?? false,
|
|
66
|
+
pipelineUrl: opts.pipelineUrl || ""
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
export async function runInteractive(opts) {
|
|
70
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
71
|
+
try {
|
|
72
|
+
const locale = resolveDocsLanguage(opts.docsLanguage ?? "auto");
|
|
73
|
+
console.log(`\n${cliText("prompts.init.heading", { locale })}\n`);
|
|
74
|
+
const workspaceKind = await selectOne(rl, cliText("prompts.init.workspaceKind", { locale }), WORKSPACE_KINDS);
|
|
75
|
+
const defaults = inferInitDefaults(opts.cwd, opts);
|
|
76
|
+
opts.workspaceKind = workspaceKind;
|
|
77
|
+
opts.kind = workspaceKind;
|
|
78
|
+
opts.stack = defaults.stack;
|
|
79
|
+
opts.agentTools = defaults.agentTools;
|
|
80
|
+
opts.docsLanguage = defaults.docsLanguage;
|
|
81
|
+
opts.workflowMode = defaults.workflowMode;
|
|
82
|
+
opts.shareTickets = defaults.shareTickets;
|
|
83
|
+
opts.contextMcp = defaults.contextMcp;
|
|
84
|
+
opts.remoteSync = defaults.remoteSync;
|
|
85
|
+
opts.pipelineUrl = defaults.pipelineUrl;
|
|
86
|
+
console.log(`\n ${cliText("prompts.init.summary.workspaceKind", { locale, vars: { value: workspaceKind } })}`);
|
|
87
|
+
console.log(` ${cliText("prompts.init.summary.technicalSurface", { locale, vars: { value: opts.stack } })}`);
|
|
88
|
+
console.log(` ${cliText("prompts.init.summary.aiClients", { locale, vars: { value: opts.agentTools.join(", ") || cliText("prompts.init.summary.allSupportedClients", { locale }) } })}`);
|
|
89
|
+
console.log(` ${cliText("prompts.init.summary.docsLanguage", { locale, vars: { value: opts.docsLanguage } })}`);
|
|
90
|
+
console.log(` ${cliText("prompts.init.summary.workflowMode", { locale, vars: { value: opts.workflowMode } })}`);
|
|
91
|
+
console.log(` ${cliText("prompts.init.summary.shareTickets", { locale, vars: { value: opts.shareTickets ? cliText("prompts.init.summary.shareYes", { locale }) : cliText("prompts.init.summary.shareNo", { locale }) } })}`);
|
|
92
|
+
console.log(` ${cliText("prompts.init.summary.contextMcp", { locale })}`);
|
|
93
|
+
console.log(` ${cliText("prompts.init.summary.externalSync", { locale, vars: { value: opts.remoteSync ? cliText("prompts.init.summary.enabled", { locale }) : cliText("prompts.init.summary.disabled", { locale }) } })}`);
|
|
94
|
+
if (opts.remoteSync)
|
|
95
|
+
console.log(` ${cliText("prompts.init.summary.syncUrl", { locale, vars: { value: opts.pipelineUrl } })}\n`);
|
|
96
|
+
}
|
|
97
|
+
finally {
|
|
98
|
+
rl.close();
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=cli-prompts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-prompts.js","sourceRoot":"","sources":["../../cli-prompts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { basename, resolve, dirname, isAbsolute } from "path";
|
|
2
|
+
import { existsSync, readdirSync, readFileSync } from "fs";
|
|
3
|
+
import { DEUK_ROOT_DIR, makePath, parseFrontMatter } from "./cli-utils.js";
|
|
4
|
+
import YAML from "yaml";
|
|
5
|
+
/**
|
|
6
|
+
* Scans directories for rule markdown files, evaluates their Frontmatter conditions,
|
|
7
|
+
* and compiles a single rule string for injection.
|
|
8
|
+
*/
|
|
9
|
+
export function compileDynamicRules(cwd, bundleRoot, targetFileName) {
|
|
10
|
+
const bundleRulesDir = makePath(bundleRoot, "templates", "rules.d");
|
|
11
|
+
const localRulesDir = makePath(cwd, DEUK_ROOT_DIR, "project-rules");
|
|
12
|
+
const allRuleFiles = [];
|
|
13
|
+
// 1. Gather global rules
|
|
14
|
+
if (existsSync(bundleRulesDir)) {
|
|
15
|
+
readdirSync(bundleRulesDir).forEach(f => {
|
|
16
|
+
if (f.endsWith(".md"))
|
|
17
|
+
allRuleFiles.push(makePath(bundleRulesDir, f));
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
// 2. Gather local domain rules
|
|
21
|
+
if (existsSync(localRulesDir)) {
|
|
22
|
+
readdirSync(localRulesDir).forEach(f => {
|
|
23
|
+
if (f.endsWith(".md"))
|
|
24
|
+
allRuleFiles.push(makePath(localRulesDir, f));
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
let compiledContent = "";
|
|
28
|
+
for (const filePath of allRuleFiles) {
|
|
29
|
+
try {
|
|
30
|
+
const rawContent = readFileSync(filePath, "utf8");
|
|
31
|
+
const { meta, content } = parseFrontMatter(rawContent);
|
|
32
|
+
// Check if this rule is intended for the current target file (e.g., AGENTS.md)
|
|
33
|
+
if (meta.inject_target && !meta.inject_target.includes(targetFileName)) {
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
// Evaluate conditions
|
|
37
|
+
let shouldInclude = true;
|
|
38
|
+
if (meta.condition) {
|
|
39
|
+
shouldInclude = evaluateCondition(meta.condition, cwd);
|
|
40
|
+
}
|
|
41
|
+
if (shouldInclude) {
|
|
42
|
+
const sourceId = meta.id || basename(filePath);
|
|
43
|
+
compiledContent += `\n<!-- RULE MODULE: ${sourceId} -->\n`;
|
|
44
|
+
compiledContent += content.trim() + "\n";
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
console.warn(`[WARNING] Skipping malformed rule file at ${filePath}:`, err.message);
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return compiledContent.trim();
|
|
53
|
+
}
|
|
54
|
+
function normalizeProjects(projects, contextRoot) {
|
|
55
|
+
if (!Array.isArray(projects))
|
|
56
|
+
return [];
|
|
57
|
+
return projects
|
|
58
|
+
.filter(p => p && typeof p.path === "string")
|
|
59
|
+
.map(p => ({
|
|
60
|
+
...p,
|
|
61
|
+
path: isAbsolute(p.path) ? resolve(p.path) : resolve(contextRoot, p.path)
|
|
62
|
+
}));
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Attempts to locate and parse the DeukContext project registry from the workspace root.
|
|
66
|
+
* Current deployments store projects in ingest.yaml; config.yaml remains a legacy fallback.
|
|
67
|
+
*/
|
|
68
|
+
function resolveDeukContextProjects(cwd) {
|
|
69
|
+
// Go up directories until we find a sibling DeukAgentContext folder, or hit root
|
|
70
|
+
let current = resolve(cwd);
|
|
71
|
+
while (current && current !== "/") {
|
|
72
|
+
const candidates = [
|
|
73
|
+
makePath(current, "DeukAgentContext", ".local", "ingest.yaml"),
|
|
74
|
+
makePath(current, "DeukAgentContext", ".local", "config.yaml"),
|
|
75
|
+
makePath(current, "DeukContext", ".local", "ingest.yaml"),
|
|
76
|
+
makePath(current, "DeukContext", ".local", "config.yaml") // Legacy fallback
|
|
77
|
+
];
|
|
78
|
+
for (const candidatePath of candidates) {
|
|
79
|
+
if (existsSync(candidatePath)) {
|
|
80
|
+
try {
|
|
81
|
+
const raw = readFileSync(candidatePath, "utf8");
|
|
82
|
+
const parsed = YAML.parse(raw);
|
|
83
|
+
const contextRoot = dirname(dirname(candidatePath));
|
|
84
|
+
const projects = normalizeProjects(parsed?.projects, contextRoot);
|
|
85
|
+
if (projects.length > 0)
|
|
86
|
+
return projects;
|
|
87
|
+
}
|
|
88
|
+
catch (e) {
|
|
89
|
+
console.error(`Failed to parse DeukContext registry at ${candidatePath}:`, e);
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
const parent = dirname(current);
|
|
95
|
+
if (parent === current)
|
|
96
|
+
break;
|
|
97
|
+
current = parent;
|
|
98
|
+
}
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Evaluates Frontmatter conditions to determine if a rule should be included.
|
|
103
|
+
*/
|
|
104
|
+
function evaluateCondition(condition, cwd) {
|
|
105
|
+
if (!condition)
|
|
106
|
+
return true;
|
|
107
|
+
// Example: condition: { mcp: "deuk-agent-context" }
|
|
108
|
+
if (condition.mcp === "deuk-agent-context" || condition.mcp === "deuk_agent_context") {
|
|
109
|
+
const projects = resolveDeukContextProjects(cwd);
|
|
110
|
+
if (!projects || projects.length === 0)
|
|
111
|
+
return false;
|
|
112
|
+
// Check if the current cwd is managed by DeukContext
|
|
113
|
+
const isManaged = projects.some(p => {
|
|
114
|
+
// If the project path is a prefix of cwd, it's managed
|
|
115
|
+
return cwd.startsWith(p.path);
|
|
116
|
+
});
|
|
117
|
+
return isManaged;
|
|
118
|
+
}
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=cli-rule-compiler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-rule-compiler.js","sourceRoot":"","sources":["../../cli-rule-compiler.ts"],"names":[],"mappings":"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"}
|