deuk-agent-flow 4.2.7 → 5.0.2

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.
Files changed (80) hide show
  1. package/CHANGELOG.ko.md +259 -0
  2. package/CHANGELOG.md +769 -124
  3. package/LICENSE +0 -0
  4. package/README.ko.md +97 -17
  5. package/README.md +108 -25
  6. package/bin/deuk-agent-flow.js +11 -13
  7. package/bin/deuk-agent-rule.js +1 -1
  8. package/bundled/README.md +3 -0
  9. package/bundled/deuk-agent-flow.vsix +0 -0
  10. package/core-rules/AGENTS.md +30 -120
  11. package/docs/architecture.ko.md +155 -2
  12. package/docs/architecture.md +155 -2
  13. package/docs/assets/agentflow-panel-skills.png +0 -0
  14. package/docs/assets/agentflow-panel.png +0 -0
  15. package/docs/how-it-works.ko.md +109 -52
  16. package/docs/how-it-works.md +128 -71
  17. package/docs/principles.ko.md +68 -68
  18. package/docs/principles.md +68 -68
  19. package/docs/usage-guide.ko.md +251 -212
  20. package/package.json +42 -45
  21. package/scripts/bundle-vscode-vsix.ts +67 -0
  22. package/scripts/{cli-args.mjs → cli-args.ts} +49 -12
  23. package/scripts/cli-init-commands.ts +99 -0
  24. package/scripts/cli-init-logic.ts +46 -0
  25. package/scripts/{cli-prompts.mjs → cli-prompts.ts} +19 -34
  26. package/scripts/{cli-rule-compiler.mjs → cli-rule-compiler.ts} +128 -112
  27. package/scripts/cli-skill-commands.ts +707 -0
  28. package/scripts/{cli-telemetry-commands.mjs → cli-telemetry-commands.ts} +25 -22
  29. package/scripts/cli-ticket-command-shared.ts +4 -0
  30. package/scripts/cli-ticket-commands.ts +3723 -0
  31. package/scripts/cli-ticket-index.ts +283 -0
  32. package/scripts/{cli-ticket-migration.mjs → cli-ticket-migration.ts} +44 -68
  33. package/scripts/cli-ticket-parser.ts +100 -0
  34. package/scripts/{cli-usage-commands.mjs → cli-usage-commands.ts} +325 -326
  35. package/scripts/cli-utils.ts +1560 -0
  36. package/scripts/cli.ts +695 -0
  37. package/scripts/{lint-md.mjs → lint-md.ts} +32 -42
  38. package/scripts/lint-rules.ts +203 -0
  39. package/scripts/{merge-logic.mjs → merge-logic.ts} +44 -44
  40. package/scripts/{plan-parser.mjs → plan-parser.ts} +53 -53
  41. package/templates/MODULE_RULE_TEMPLATE.md +11 -11
  42. package/templates/PROJECT_RULE.md +46 -47
  43. package/templates/TICKET_TEMPLATE.ko.md +48 -44
  44. package/templates/TICKET_TEMPLATE.md +48 -44
  45. package/templates/project-memory.md +19 -0
  46. package/templates/project-pilot/CONFORMANCE_GATE_TEMPLATE.md +25 -25
  47. package/templates/project-pilot/DRIFT_CHECKLIST.md +27 -27
  48. package/templates/project-pilot/FLOW_CONTRACT_TEMPLATE.md +26 -26
  49. package/templates/project-pilot/IMPLEMENTATION_MATRIX_TEMPLATE.md +30 -30
  50. package/templates/project-pilot/INTEGRATION_CONTRACT_TEMPLATE.md +26 -26
  51. package/templates/project-pilot/OWNER_MAP_TEMPLATE.md +15 -15
  52. package/templates/project-pilot/PROJECT_PILOT_RULE_TEMPLATE.md +34 -34
  53. package/templates/project-pilot/REFACTOR_CONTRACT_TEMPLATE.md +32 -32
  54. package/templates/project-pilot/REMEDIATION_PLAN_TEMPLATE.md +33 -33
  55. package/templates/rules.d/deukcontext-mcp.md +31 -31
  56. package/templates/rules.d/platform-coexistence.md +29 -29
  57. package/templates/skills/context-recall/SKILL.md +3 -1
  58. package/templates/skills/doc-sync/SKILL.md +111 -0
  59. package/templates/skills/generated-file-guard/SKILL.md +3 -1
  60. package/templates/skills/persona-maid/SKILL.md +65 -0
  61. package/templates/skills/project-pilot/SKILL.md +14 -63
  62. package/templates/skills/safe-refactor/SKILL.md +3 -1
  63. package/templates/skills/ticket-status-surface/SKILL.md +17 -0
  64. package/NOTICE.md +0 -19
  65. package/core-rules/GEMINI.md +0 -7
  66. package/docs/npm-publish-guide.ko.md +0 -70
  67. package/scripts/cli-init-commands.mjs +0 -1759
  68. package/scripts/cli-init-logic.mjs +0 -64
  69. package/scripts/cli-skill-commands.mjs +0 -212
  70. package/scripts/cli-ticket-command-shared.mjs +0 -60
  71. package/scripts/cli-ticket-commands.mjs +0 -2474
  72. package/scripts/cli-ticket-index.mjs +0 -322
  73. package/scripts/cli-ticket-parser.mjs +0 -210
  74. package/scripts/cli-utils.mjs +0 -602
  75. package/scripts/cli.mjs +0 -256
  76. package/scripts/lint-rules.mjs +0 -197
  77. package/scripts/publish-dual-npm.mjs +0 -141
  78. package/scripts/smoke-npm-docker.mjs +0 -102
  79. package/scripts/smoke-npm-local.mjs +0 -110
  80. package/scripts/update-download-badge.mjs +0 -103
@@ -1,64 +0,0 @@
1
- import { existsSync, appendFileSync, writeFileSync, mkdirSync, readFileSync } from "fs";
2
- import { join } from "path";
3
- import { AGENT_ROOT_DIR, LEGACY_IGNORE_DIR, LEGACY_TICKET_DIR, LEGACY_TICKET_DIR_PLURAL, TICKET_DIR_NAME } from "./cli-utils.mjs";
4
-
5
- const GITIGNORE_AGENT_MARKER = "# deuk-agent-flow: agent hub directory (local, not committed by default)";
6
- const LEGACY_GITIGNORE_AGENT_MARKER = "# deuk-agent-rule: agent hub directory (local, not committed by default)";
7
-
8
- function hasExactGitignoreLine(content, line) {
9
- return content
10
- .split(/\r?\n/)
11
- .map(s => s.trim())
12
- .includes(line);
13
- }
14
-
15
- function removeExactGitignoreLines(content, lines) {
16
- const remove = new Set(lines);
17
- return content
18
- .split(/\r?\n/)
19
- .filter(line => !remove.has(line.trim()))
20
- .join("\n");
21
- }
22
-
23
- export function ensureTicketDirAndGitignore(opts) {
24
- const ticketPath = join(opts.cwd, TICKET_DIR_NAME);
25
- const gitignorePath = join(opts.cwd, ".gitignore");
26
- const ignoreLine = AGENT_ROOT_DIR + "/";
27
-
28
- if (opts.dryRun) return;
29
-
30
- mkdirSync(ticketPath, { recursive: true });
31
- if (opts.shareTickets) {
32
- console.log(`[INIT] Ticket sharing enabled. Skipping .gitignore entry for ${AGENT_ROOT_DIR}/`);
33
- return;
34
- }
35
-
36
- let gi = existsSync(gitignorePath) ? readFileSync(gitignorePath, "utf8") : "";
37
-
38
- // 1. Create document directories
39
- const docsPath = join(opts.cwd, AGENT_ROOT_DIR, "docs");
40
- mkdirSync(join(docsPath, "plan"), { recursive: true });
41
- mkdirSync(join(docsPath, "archive"), { recursive: true });
42
-
43
- // Also check for legacy ignore lines to clean up or at least check presence
44
- const legacyIgnore1 = `${LEGACY_TICKET_DIR}/`;
45
- const legacyIgnore2 = `${LEGACY_TICKET_DIR_PLURAL}/`;
46
- const legacyIgnore3 = LEGACY_IGNORE_DIR;
47
- const cleanedGi = removeExactGitignoreLines(gi, [legacyIgnore1, legacyIgnore2, legacyIgnore3, LEGACY_GITIGNORE_AGENT_MARKER]);
48
- if (cleanedGi !== gi) {
49
- writeFileSync(gitignorePath, cleanedGi.replace(/\n*$/, "\n"), "utf8");
50
- gi = cleanedGi;
51
- console.log("[INIT] Removed legacy deuk-agent-rule .gitignore entries");
52
- }
53
-
54
- const hasIgnoreLine = hasExactGitignoreLine(gi, ignoreLine);
55
- const hasMarkerLine = hasExactGitignoreLine(gi, GITIGNORE_AGENT_MARKER);
56
- if ((!hasIgnoreLine || !hasMarkerLine) && !opts.shareTickets) {
57
- const linesToAdd = [];
58
- if (!hasMarkerLine) linesToAdd.push(GITIGNORE_AGENT_MARKER);
59
- if (!hasIgnoreLine) linesToAdd.push(ignoreLine);
60
- const block = "\n" + linesToAdd.join("\n") + "\n";
61
- appendFileSync(gitignorePath, block, "utf8");
62
- console.log(`[INIT] Added ${ignoreLine} to .gitignore`);
63
- }
64
- }
@@ -1,212 +0,0 @@
1
- import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "fs";
2
- import { dirname, join } from "path";
3
- import { fileURLToPath } from "url";
4
- import { AGENT_ROOT_DIR } from "./cli-utils.mjs";
5
-
6
- const SKILL_IDS = ["safe-refactor", "generated-file-guard", "context-recall", "project-pilot"];
7
- const SKILL_ROOT = "templates/skills";
8
- const CONFIG_FILE = `${AGENT_ROOT_DIR}/skills.json`;
9
- const PACKAGE_ROOT = join(dirname(fileURLToPath(import.meta.url)), "..");
10
- const SKILL_PATHS = {
11
- installedRoot: join(AGENT_ROOT_DIR, "skills"),
12
- templateRoot: SKILL_ROOT,
13
- claudeRoot: join(".claude", "skills"),
14
- cursorPointer: join(".cursor", "rules", "deuk-agent-skills.mdc"),
15
- };
16
-
17
- function safeReadJson(absPath, fallback = null) {
18
- if (!existsSync(absPath)) return fallback;
19
- try {
20
- return JSON.parse(readFileSync(absPath, "utf8"));
21
- } catch {
22
- return fallback;
23
- }
24
- }
25
-
26
- function repoSkillPath(cwd, id) {
27
- return join(cwd, SKILL_PATHS.installedRoot, id, "SKILL.md");
28
- }
29
-
30
- function sourceSkillPath(cwd, id) {
31
- const repoTemplate = join(cwd, SKILL_PATHS.templateRoot, id, "SKILL.md");
32
- if (existsSync(repoTemplate)) return repoTemplate;
33
- return join(PACKAGE_ROOT, SKILL_ROOT, id, "SKILL.md");
34
- }
35
-
36
- function loadSkillSource(cwd, id) {
37
- const source = sourceSkillPath(cwd, id);
38
- if (!existsSync(source)) throw new Error(`skill not found: ${id}`);
39
- return readFileSync(source, "utf8");
40
- }
41
-
42
- function loadSkillConfig(cwd) {
43
- const path = join(cwd, CONFIG_FILE);
44
- return safeReadJson(path, { version: 1, installed: [], exposed: {} });
45
- }
46
-
47
- function detectExposedPlatforms(cwd, id) {
48
- const platforms = [];
49
- const claudePath = join(cwd, SKILL_PATHS.claudeRoot, id, "SKILL.md");
50
- if (existsSync(claudePath)) {
51
- platforms.push("claude");
52
- }
53
-
54
- const cursorPath = join(cwd, SKILL_PATHS.cursorPointer);
55
- if (existsSync(cursorPath)) {
56
- try {
57
- const body = readFileSync(cursorPath, "utf8");
58
- if (body.includes(`.deuk-agent/skills/${id}/SKILL.md`)) {
59
- platforms.push("cursor");
60
- }
61
- } catch {
62
- // Ignore pointer read failures and fall back to config-based exposure only.
63
- }
64
- }
65
-
66
- return platforms;
67
- }
68
-
69
- function writeSkillConfig(cwd, config, dryRun) {
70
- if (dryRun) return;
71
- const path = join(cwd, CONFIG_FILE);
72
- mkdirSync(dirname(path), { recursive: true });
73
- writeFileSync(path, JSON.stringify(config, null, 2), "utf8");
74
- }
75
-
76
- function ensureKnownSkill(id) {
77
- if (!SKILL_IDS.includes(id)) throw new Error(`unknown skill: ${id}`);
78
- }
79
-
80
- export function listSkills(cwd = process.cwd()) {
81
- const config = loadSkillConfig(cwd);
82
- return SKILL_IDS.map(id => ({
83
- id,
84
- installed: config.installed.includes(id) || existsSync(repoSkillPath(cwd, id)),
85
- exposed: Array.from(new Set([
86
- ...Object.entries(config.exposed || {})
87
- .filter(([, ids]) => Array.isArray(ids) && ids.includes(id))
88
- .map(([platform]) => platform),
89
- ...detectExposedPlatforms(cwd, id)
90
- ]))
91
- }));
92
- }
93
-
94
- export function addSkill(opts = {}) {
95
- const cwd = opts.cwd || process.cwd();
96
- const id = opts.skill;
97
- ensureKnownSkill(id);
98
- const body = loadSkillSource(cwd, id);
99
- const target = repoSkillPath(cwd, id);
100
- const config = loadSkillConfig(cwd);
101
-
102
- if (!opts.dryRun) {
103
- mkdirSync(dirname(target), { recursive: true });
104
- writeFileSync(target, body, "utf8");
105
- }
106
-
107
- if (!config.installed.includes(id)) config.installed.push(id);
108
- writeSkillConfig(cwd, config, opts.dryRun);
109
- return { id, target };
110
- }
111
-
112
- function exposeClaude(cwd, ids, dryRun) {
113
- for (const id of ids) {
114
- const body = readFileSync(repoSkillPath(cwd, id), "utf8");
115
- const target = join(cwd, SKILL_PATHS.claudeRoot, id, "SKILL.md");
116
- if (!dryRun) {
117
- mkdirSync(dirname(target), { recursive: true });
118
- writeFileSync(target, body, "utf8");
119
- }
120
- }
121
- }
122
-
123
- function exposeCursor(cwd, ids, dryRun) {
124
- const target = join(cwd, SKILL_PATHS.cursorPointer);
125
- const body = [
126
- "---",
127
- "description: \"DeukAgentFlow skill pointers\"",
128
- "globs: [\"**/*\"]",
129
- "alwaysApply: false",
130
- "---",
131
- "# DeukAgentFlow Skills",
132
- "",
133
- "These are thin behavior playbooks. They do not override `core-rules/AGENTS.md`, TDW, APC, Phase Gate, or PROJECT_RULE.md.",
134
- "",
135
- ...ids.map(id => `- ${id}: .deuk-agent/skills/${id}/SKILL.md`),
136
- ""
137
- ].join("\n");
138
- if (!dryRun) {
139
- mkdirSync(dirname(target), { recursive: true });
140
- writeFileSync(target, body, "utf8");
141
- }
142
- }
143
-
144
- export function exposeSkills(opts = {}) {
145
- const cwd = opts.cwd || process.cwd();
146
- const platform = String(opts.platform || "").toLowerCase();
147
- if (!["claude", "cursor"].includes(platform)) throw new Error("skill expose requires --platform claude|cursor");
148
-
149
- const config = loadSkillConfig(cwd);
150
- const ids = config.installed || [];
151
- if (ids.length === 0) throw new Error("no skills installed; run skill add first");
152
- for (const id of ids) {
153
- if (!existsSync(repoSkillPath(cwd, id))) addSkill({ cwd, skill: id, dryRun: opts.dryRun });
154
- }
155
-
156
- if (platform === "claude") exposeClaude(cwd, ids, opts.dryRun);
157
- if (platform === "cursor") exposeCursor(cwd, ids, opts.dryRun);
158
-
159
- config.exposed = config.exposed || {};
160
- config.exposed[platform] = Array.from(new Set([...(config.exposed[platform] || []), ...ids]));
161
- writeSkillConfig(cwd, config, opts.dryRun);
162
- return { platform, ids };
163
- }
164
-
165
- export function lintSkills(cwd = process.cwd()) {
166
- const paths = [];
167
- for (const root of [join(cwd, SKILL_ROOT), join(cwd, SKILL_PATHS.installedRoot)]) {
168
- if (!existsSync(root)) continue;
169
- for (const id of readdirSync(root)) {
170
- const path = join(root, id, "SKILL.md");
171
- if (existsSync(path)) paths.push(path);
172
- }
173
- }
174
-
175
- const violations = [];
176
- const forbidden = [/ignore ticket/i, /skip verification/i, /override (tdw|apc|phase gate)/i, /edit generated output directly/i];
177
- for (const path of paths) {
178
- const body = readFileSync(path, "utf8");
179
- if (!/Authority:.*core-rules\/AGENTS\.md/i.test(body)) violations.push(`${path}: missing authority line`);
180
- for (const pattern of forbidden) {
181
- if (pattern.test(body)) violations.push(`${path}: forbidden phrase ${pattern}`);
182
- }
183
- }
184
- return { ok: violations.length === 0, paths, violations };
185
- }
186
-
187
- export async function runSkill(action, opts = {}) {
188
- if (action === "list") {
189
- const rows = listSkills(opts.cwd);
190
- if (opts.json) console.log(JSON.stringify(rows, null, 2));
191
- else rows.forEach(row => console.log(`${row.id} installed=${row.installed ? "yes" : "no"} exposed=${row.exposed.join(",") || "-"}`));
192
- return;
193
- }
194
- if (action === "add") {
195
- const result = addSkill(opts);
196
- console.log(`skill added: ${result.id}`);
197
- return;
198
- }
199
- if (action === "expose") {
200
- const result = exposeSkills(opts);
201
- console.log(`skills exposed: ${result.platform} ${result.ids.join(",")}`);
202
- return;
203
- }
204
- if (action === "lint") {
205
- const result = lintSkills(opts.cwd);
206
- if (opts.json) console.log(JSON.stringify(result, null, 2));
207
- else console.log(result.ok ? "skill:lint ok" : `skill:lint failed ${result.violations.length}`);
208
- if (!result.ok) throw new Error(result.violations.join("\n"));
209
- return;
210
- }
211
- throw new Error("Unknown skill action: " + action);
212
- }
@@ -1,60 +0,0 @@
1
- import { existsSync, readFileSync } from "fs";
2
- import { join } from "path";
3
- import { AGENT_ROOT_DIR, computeTicketPath, parseFrontMatter } from "./cli-utils.mjs";
4
-
5
- export const TICKET_REPORTS_SUBDIR = "plan";
6
-
7
- export function resolveTicketReportDir(cwd) {
8
- return join(cwd, AGENT_ROOT_DIR, "docs", TICKET_REPORTS_SUBDIR);
9
- }
10
-
11
- export function resolveTicketPath(cwd, relPath) {
12
- return join(cwd, String(relPath || ""));
13
- }
14
-
15
- export function resolveTicketEntryPath(cwd, entry) {
16
- return resolveTicketPath(cwd, entry?.path || "");
17
- }
18
-
19
- export function resolveTicketEntryOrComputedPath(cwd, entry) {
20
- return resolveTicketPath(cwd, entry?.path || computeTicketPath(entry));
21
- }
22
-
23
- export function resolveTicketKnowledgeDir(cwd) {
24
- return join(cwd, AGENT_ROOT_DIR, "knowledge");
25
- }
26
-
27
- export function readTicketDocument(cwd, entry, options = {}) {
28
- const shouldCompute = options.computePath || !entry?.path;
29
- const absPath = shouldCompute
30
- ? resolveTicketEntryOrComputedPath(cwd, entry)
31
- : resolveTicketEntryPath(cwd, entry);
32
-
33
- const parse = options.parse ?? true;
34
- const requireExists = options.requireExists ?? true;
35
- const action = options.action || "ticket";
36
-
37
- const exists = existsSync(absPath);
38
- if (!exists && requireExists) {
39
- const target = entry?.path || "unknown";
40
- throw new Error(`${action}: Ticket file not found: ${target}`);
41
- }
42
-
43
- if (!exists) {
44
- return {
45
- absPath,
46
- exists: false,
47
- body: "",
48
- meta: {},
49
- content: ""
50
- };
51
- }
52
-
53
- const body = readFileSync(absPath, "utf8");
54
- if (!parse) {
55
- return { absPath, exists: true, body, meta: {}, content: "" };
56
- }
57
-
58
- const parsed = parseFrontMatter(body);
59
- return { absPath, exists: true, body, ...parsed };
60
- }