devworkspace 0.3.0 → 0.3.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/CHANGELOG.md +24 -0
- package/README.md +5 -4
- package/dist/agents/claude/adapter.d.ts +3 -14
- package/dist/agents/claude/adapter.js +46 -49
- package/dist/agents/claude/adapter.js.map +1 -1
- package/dist/agents/codex/adapter.d.ts +2 -0
- package/dist/agents/codex/adapter.js +61 -0
- package/dist/agents/codex/adapter.js.map +1 -0
- package/dist/agents/copilot/adapter.d.ts +2 -0
- package/dist/agents/copilot/adapter.js +62 -0
- package/dist/agents/copilot/adapter.js.map +1 -0
- package/dist/agents/cursor/adapter.d.ts +2 -0
- package/dist/agents/cursor/adapter.js +127 -0
- package/dist/agents/cursor/adapter.js.map +1 -0
- package/dist/agents/index.d.ts +15 -0
- package/dist/agents/index.js +54 -0
- package/dist/agents/index.js.map +1 -0
- package/dist/agents/shared.d.ts +20 -0
- package/dist/agents/shared.js +76 -0
- package/dist/agents/shared.js.map +1 -0
- package/dist/agents/types.d.ts +16 -1
- package/dist/agents/types.js.map +1 -1
- package/dist/cli/help.js +12 -5
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/render.d.ts +2 -1
- package/dist/cli/render.js +21 -0
- package/dist/cli/render.js.map +1 -1
- package/dist/cli/run.js +17 -6
- package/dist/cli/run.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/integrations/adapters/claudePlugin.d.ts +12 -0
- package/dist/integrations/adapters/claudePlugin.js +37 -8
- package/dist/integrations/adapters/claudePlugin.js.map +1 -1
- package/dist/integrations/adapters/pluginSkill.js +5 -0
- package/dist/integrations/adapters/pluginSkill.js.map +1 -1
- package/dist/security/files.js +10 -2
- package/dist/security/files.js.map +1 -1
- package/dist/security/redact.js +1 -1
- package/dist/security/redact.js.map +1 -1
- package/dist/services/agent.d.ts +12 -2
- package/dist/services/agent.js +96 -14
- package/dist/services/agent.js.map +1 -1
- package/dist/services/analysis.js +3 -3
- package/dist/services/analysis.js.map +1 -1
- package/dist/services/doctor.js +31 -14
- package/dist/services/doctor.js.map +1 -1
- package/dist/services/reset.js +45 -5
- package/dist/services/reset.js.map +1 -1
- package/dist/services/status.d.ts +2 -0
- package/dist/services/status.js +62 -10
- package/dist/services/status.js.map +1 -1
- package/dist/services/tasks.js +6 -1
- package/dist/services/tasks.js.map +1 -1
- package/dist/tasks/routing.js +14 -10
- package/dist/tasks/routing.js.map +1 -1
- package/dist/tasks/task.js +6 -2
- package/dist/tasks/task.js.map +1 -1
- package/dist/verification/scope.js +1 -1
- package/dist/verification/scope.js.map +1 -1
- package/docs/agents.md +60 -0
- package/docs/architecture.md +2 -2
- package/package.json +1 -1
package/dist/services/reset.js
CHANGED
|
@@ -3,7 +3,7 @@ import path from 'node:path';
|
|
|
3
3
|
import { removeManagedSection } from '../agents/claude/adapter.js';
|
|
4
4
|
import { SKILL_MARKER, SKILL_PATH } from '../agents/claude/content.js';
|
|
5
5
|
import { DevWorkspaceError } from '../errors/index.js';
|
|
6
|
-
import { findWorkspaceRoot, WORKSPACE_DIR, wsPaths } from '../core/workspace.js';
|
|
6
|
+
import { findWorkspaceRoot, loadProject, WORKSPACE_DIR, wsPaths } from '../core/workspace.js';
|
|
7
7
|
import { atomicWriteFile, pathExists } from '../utils/fs.js';
|
|
8
8
|
import { isInside } from '../utils/paths.js';
|
|
9
9
|
import { withLock } from '../utils/lock.js';
|
|
@@ -45,7 +45,27 @@ export async function resetWorkspace(o) {
|
|
|
45
45
|
];
|
|
46
46
|
const pending = [];
|
|
47
47
|
if (o.includeAgentFiles) {
|
|
48
|
-
|
|
48
|
+
const candidateFiles = [
|
|
49
|
+
'CLAUDE.md',
|
|
50
|
+
'.claude/CLAUDE.md',
|
|
51
|
+
'AGENTS.md',
|
|
52
|
+
'.cursorrules',
|
|
53
|
+
'.cursor/rules/devworkspace.mdc',
|
|
54
|
+
'.github/copilot-instructions.md',
|
|
55
|
+
];
|
|
56
|
+
try {
|
|
57
|
+
const p = await loadProject(ws);
|
|
58
|
+
for (const m of p.managedFiles) {
|
|
59
|
+
if (!candidateFiles.includes(m.path))
|
|
60
|
+
candidateFiles.push(m.path);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
/* project.json might be missing */
|
|
65
|
+
}
|
|
66
|
+
for (const rel of candidateFiles) {
|
|
67
|
+
if (rel === SKILL_PATH)
|
|
68
|
+
continue;
|
|
49
69
|
const full = path.join(root, ...rel.split('/'));
|
|
50
70
|
const text = await fs.readFile(full, 'utf8').catch(() => null);
|
|
51
71
|
if (text === null)
|
|
@@ -57,9 +77,29 @@ export async function resetWorkspace(o) {
|
|
|
57
77
|
}
|
|
58
78
|
continue;
|
|
59
79
|
}
|
|
60
|
-
if
|
|
80
|
+
// Check if remaining content is empty or contains only cursor rule frontmatter
|
|
81
|
+
const cleanContent = removed.content
|
|
82
|
+
.replace(/^---\r?\ndescription:[^\r\n]*\r?\nalwaysApply:[^\r\n]*\r?\n---\r?\n?/m, '')
|
|
83
|
+
.trim();
|
|
84
|
+
const isEmpty = removed.empty || cleanContent.length === 0;
|
|
85
|
+
if (isEmpty) {
|
|
61
86
|
actions.push({ path: rel, action: 'delete-file', note: 'contained only the DevWorkspace block' });
|
|
62
|
-
pending.push(() =>
|
|
87
|
+
pending.push(async () => {
|
|
88
|
+
await fs.rm(full, { force: true });
|
|
89
|
+
const parent = path.dirname(full);
|
|
90
|
+
if (parent !== root) {
|
|
91
|
+
const siblings = await fs.readdir(parent).catch(() => []);
|
|
92
|
+
if (siblings.length === 0) {
|
|
93
|
+
await fs.rmdir(parent).catch(() => undefined);
|
|
94
|
+
const grand = path.dirname(parent);
|
|
95
|
+
if (grand !== root) {
|
|
96
|
+
const grandSiblings = await fs.readdir(grand).catch(() => []);
|
|
97
|
+
if (grandSiblings.length === 0)
|
|
98
|
+
await fs.rmdir(grand).catch(() => undefined);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
});
|
|
63
103
|
}
|
|
64
104
|
else {
|
|
65
105
|
actions.push({ path: rel, action: 'remove-managed-section', note: 'your own content is kept' });
|
|
@@ -71,7 +111,7 @@ export async function resetWorkspace(o) {
|
|
|
71
111
|
if (skill !== null) {
|
|
72
112
|
if (skill.includes(SKILL_MARKER)) {
|
|
73
113
|
const dir = path.dirname(skillFile);
|
|
74
|
-
const others = (await fs.readdir(dir)).filter((n) => n !== 'SKILL.md');
|
|
114
|
+
const others = (await fs.readdir(dir).catch(() => [])).filter((n) => n !== 'SKILL.md');
|
|
75
115
|
actions.push({ path: SKILL_PATH, action: 'delete-file', note: 'DevWorkspace-managed skill' });
|
|
76
116
|
pending.push(async () => {
|
|
77
117
|
await fs.rm(skillFile, { force: true });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reset.js","sourceRoot":"","sources":["../../src/services/reset.ts"],"names":[],"mappings":"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","sourcesContent":["import { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport { removeManagedSection } from '../agents/claude/adapter.js';\nimport { SKILL_MARKER, SKILL_PATH } from '../agents/claude/content.js';\nimport { DevWorkspaceError } from '../errors/index.js';\nimport { findWorkspaceRoot, WORKSPACE_DIR, wsPaths } from '../core/workspace.js';\nimport { atomicWriteFile, pathExists } from '../utils/fs.js';\nimport { isInside } from '../utils/paths.js';\nimport { withLock } from '../utils/lock.js';\nimport type { ServiceOptions } from './common.js';\n\nexport interface ResetOptions extends ServiceOptions {\n /** Actually delete. Without it, reset only reports what it would remove. */\n confirm?: boolean;\n /** Also remove the DevWorkspace block from CLAUDE.md and the managed devworkspace skill. */\n includeAgentFiles?: boolean;\n}\n\nexport interface ResetAction {\n path: string;\n action: 'delete-folder' | 'remove-managed-section' | 'delete-file' | 'skip';\n note: string;\n}\n\nexport interface ResetResult {\n root: string;\n executed: boolean;\n actions: ResetAction[];\n fileCount: number;\n}\n\nasync function countFiles(dir: string): Promise<number> {\n let n = 0;\n for (const e of await fs.readdir(dir, { withFileTypes: true })) {\n if (e.isDirectory()) n += await countFiles(path.join(dir, e.name));\n else n++;\n }\n return n;\n}\n\n/**\n * Remove .devworkspace/ so the user can start again with `init`. Only DevWorkspace's own folder is ever deleted;\n * application files are never touched, and with includeAgentFiles only the managed block / managed skill are removed.\n */\nexport async function resetWorkspace(o: ResetOptions): Promise<ResetResult> {\n let root = await findWorkspaceRoot(o.cwd);\n if (!root && (await pathExists(path.join(o.cwd, WORKSPACE_DIR)))) root = path.resolve(o.cwd); // half-initialised workspace\n if (!root) {\n throw new DevWorkspaceError('NOT_FOUND', 'No .devworkspace folder found in this directory or any parent.', { hint: 'Nothing to reset.' });\n }\n const ws = wsPaths(root);\n const st = await fs.lstat(ws.dir);\n if (st.isSymbolicLink() || !st.isDirectory()) {\n throw new DevWorkspaceError('UNSAFE_PATH', '.devworkspace is a symlink or not a directory; refusing to delete it.', {\n hint: 'Remove it by hand if you are sure.',\n });\n }\n const real = await fs.realpath(ws.dir);\n if (!isInside(await fs.realpath(root), real) || path.basename(real) !== WORKSPACE_DIR) {\n throw new DevWorkspaceError('UNSAFE_PATH', 'Resolved workspace path is outside the project; refusing to delete it.');\n }\n\n const fileCount = await countFiles(ws.dir);\n const actions: ResetAction[] = [\n { path: `${WORKSPACE_DIR}/`, action: 'delete-folder', note: `${fileCount} file(s): knowledge, decisions, tasks, sessions, analysis and local state` },\n ];\n const pending: (() => Promise<void>)[] = [];\n\n if (o.includeAgentFiles) {\n for (const rel of ['CLAUDE.md', '.claude/CLAUDE.md']) {\n const full = path.join(root, ...rel.split('/'));\n const text = await fs.readFile(full, 'utf8').catch(() => null);\n if (text === null) continue;\n const removed = removeManagedSection(text);\n if (!removed) {\n if (text.includes('<!-- devworkspace:start') || text.includes('<!-- devworkspace:end')) {\n actions.push({ path: rel, action: 'skip', note: 'managed markers are unbalanced; edit by hand' });\n }\n continue;\n }\n if (removed.empty) {\n actions.push({ path: rel, action: 'delete-file', note: 'contained only the DevWorkspace block' });\n pending.push(() => fs.rm(full, { force: true }));\n } else {\n actions.push({ path: rel, action: 'remove-managed-section', note: 'your own content is kept' });\n pending.push(() => atomicWriteFile(full, removed.content));\n }\n }\n const skillFile = path.join(root, ...SKILL_PATH.split('/'));\n const skill = await fs.readFile(skillFile, 'utf8').catch(() => null);\n if (skill !== null) {\n if (skill.includes(SKILL_MARKER)) {\n const dir = path.dirname(skillFile);\n const others = (await fs.readdir(dir)).filter((n) => n !== 'SKILL.md');\n actions.push({ path: SKILL_PATH, action: 'delete-file', note: 'DevWorkspace-managed skill' });\n pending.push(async () => {\n await fs.rm(skillFile, { force: true });\n if (others.length === 0) await fs.rmdir(dir).catch(() => undefined);\n });\n } else {\n actions.push({ path: SKILL_PATH, action: 'skip', note: 'not managed by DevWorkspace (no marker); left alone' });\n }\n }\n }\n\n if (!o.confirm || o.dryRun) return { root, executed: false, actions, fileCount };\n\n await withLock(ws.dir, async () => {\n for (const w of pending) await w();\n });\n await fs.rm(ws.dir, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });\n return { root, executed: true, actions, fileCount };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"reset.js","sourceRoot":"","sources":["../../src/services/reset.ts"],"names":[],"mappings":"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","sourcesContent":["import { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport { removeManagedSection } from '../agents/claude/adapter.js';\nimport { SKILL_MARKER, SKILL_PATH } from '../agents/claude/content.js';\nimport { DevWorkspaceError } from '../errors/index.js';\nimport { findWorkspaceRoot, loadProject, WORKSPACE_DIR, wsPaths } from '../core/workspace.js';\nimport { atomicWriteFile, pathExists } from '../utils/fs.js';\nimport { isInside } from '../utils/paths.js';\nimport { withLock } from '../utils/lock.js';\nimport type { ServiceOptions } from './common.js';\n\nexport interface ResetOptions extends ServiceOptions {\n /** Actually delete. Without it, reset only reports what it would remove. */\n confirm?: boolean;\n /** Also remove the DevWorkspace block from CLAUDE.md and the managed devworkspace skill. */\n includeAgentFiles?: boolean;\n}\n\nexport interface ResetAction {\n path: string;\n action: 'delete-folder' | 'remove-managed-section' | 'delete-file' | 'skip';\n note: string;\n}\n\nexport interface ResetResult {\n root: string;\n executed: boolean;\n actions: ResetAction[];\n fileCount: number;\n}\n\nasync function countFiles(dir: string): Promise<number> {\n let n = 0;\n for (const e of await fs.readdir(dir, { withFileTypes: true })) {\n if (e.isDirectory()) n += await countFiles(path.join(dir, e.name));\n else n++;\n }\n return n;\n}\n\n/**\n * Remove .devworkspace/ so the user can start again with `init`. Only DevWorkspace's own folder is ever deleted;\n * application files are never touched, and with includeAgentFiles only the managed block / managed skill are removed.\n */\nexport async function resetWorkspace(o: ResetOptions): Promise<ResetResult> {\n let root = await findWorkspaceRoot(o.cwd);\n if (!root && (await pathExists(path.join(o.cwd, WORKSPACE_DIR)))) root = path.resolve(o.cwd); // half-initialised workspace\n if (!root) {\n throw new DevWorkspaceError('NOT_FOUND', 'No .devworkspace folder found in this directory or any parent.', { hint: 'Nothing to reset.' });\n }\n const ws = wsPaths(root);\n const st = await fs.lstat(ws.dir);\n if (st.isSymbolicLink() || !st.isDirectory()) {\n throw new DevWorkspaceError('UNSAFE_PATH', '.devworkspace is a symlink or not a directory; refusing to delete it.', {\n hint: 'Remove it by hand if you are sure.',\n });\n }\n const real = await fs.realpath(ws.dir);\n if (!isInside(await fs.realpath(root), real) || path.basename(real) !== WORKSPACE_DIR) {\n throw new DevWorkspaceError('UNSAFE_PATH', 'Resolved workspace path is outside the project; refusing to delete it.');\n }\n\n const fileCount = await countFiles(ws.dir);\n const actions: ResetAction[] = [\n { path: `${WORKSPACE_DIR}/`, action: 'delete-folder', note: `${fileCount} file(s): knowledge, decisions, tasks, sessions, analysis and local state` },\n ];\n const pending: (() => Promise<void>)[] = [];\n\n if (o.includeAgentFiles) {\n const candidateFiles = [\n 'CLAUDE.md',\n '.claude/CLAUDE.md',\n 'AGENTS.md',\n '.cursorrules',\n '.cursor/rules/devworkspace.mdc',\n '.github/copilot-instructions.md',\n ];\n try {\n const p = await loadProject(ws);\n for (const m of p.managedFiles) {\n if (!candidateFiles.includes(m.path)) candidateFiles.push(m.path);\n }\n } catch {\n /* project.json might be missing */\n }\n\n for (const rel of candidateFiles) {\n if (rel === SKILL_PATH) continue;\n const full = path.join(root, ...rel.split('/'));\n const text = await fs.readFile(full, 'utf8').catch(() => null);\n if (text === null) continue;\n const removed = removeManagedSection(text);\n if (!removed) {\n if (text.includes('<!-- devworkspace:start') || text.includes('<!-- devworkspace:end')) {\n actions.push({ path: rel, action: 'skip', note: 'managed markers are unbalanced; edit by hand' });\n }\n continue;\n }\n // Check if remaining content is empty or contains only cursor rule frontmatter\n const cleanContent = removed.content\n .replace(/^---\\r?\\ndescription:[^\\r\\n]*\\r?\\nalwaysApply:[^\\r\\n]*\\r?\\n---\\r?\\n?/m, '')\n .trim();\n const isEmpty = removed.empty || cleanContent.length === 0;\n\n if (isEmpty) {\n actions.push({ path: rel, action: 'delete-file', note: 'contained only the DevWorkspace block' });\n pending.push(async () => {\n await fs.rm(full, { force: true });\n const parent = path.dirname(full);\n if (parent !== root) {\n const siblings = await fs.readdir(parent).catch(() => []);\n if (siblings.length === 0) {\n await fs.rmdir(parent).catch(() => undefined);\n const grand = path.dirname(parent);\n if (grand !== root) {\n const grandSiblings = await fs.readdir(grand).catch(() => []);\n if (grandSiblings.length === 0) await fs.rmdir(grand).catch(() => undefined);\n }\n }\n }\n });\n } else {\n actions.push({ path: rel, action: 'remove-managed-section', note: 'your own content is kept' });\n pending.push(() => atomicWriteFile(full, removed.content));\n }\n }\n const skillFile = path.join(root, ...SKILL_PATH.split('/'));\n const skill = await fs.readFile(skillFile, 'utf8').catch(() => null);\n if (skill !== null) {\n if (skill.includes(SKILL_MARKER)) {\n const dir = path.dirname(skillFile);\n const others = (await fs.readdir(dir).catch(() => [])).filter((n) => n !== 'SKILL.md');\n actions.push({ path: SKILL_PATH, action: 'delete-file', note: 'DevWorkspace-managed skill' });\n pending.push(async () => {\n await fs.rm(skillFile, { force: true });\n if (others.length === 0) await fs.rmdir(dir).catch(() => undefined);\n });\n } else {\n actions.push({ path: SKILL_PATH, action: 'skip', note: 'not managed by DevWorkspace (no marker); left alone' });\n }\n }\n }\n\n if (!o.confirm || o.dryRun) return { root, executed: false, actions, fileCount };\n\n await withLock(ws.dir, async () => {\n for (const w of pending) await w();\n });\n await fs.rm(ws.dir, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });\n return { root, executed: true, actions, fileCount };\n}\n"]}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type Ws } from '../core/workspace.js';
|
|
2
2
|
import { type IntegrationReport } from '../integrations/index.js';
|
|
3
|
+
import type { AgentAdapter } from '../agents/types.js';
|
|
3
4
|
import { type ServiceOptions } from './common.js';
|
|
4
5
|
export interface TaskBrief {
|
|
5
6
|
id: string;
|
|
@@ -60,6 +61,7 @@ export interface StatusResult {
|
|
|
60
61
|
} | null;
|
|
61
62
|
corruptTasks: number;
|
|
62
63
|
}
|
|
64
|
+
export declare function detectInstalledAgents(ws: Ws): Promise<AgentAdapter[]>;
|
|
63
65
|
export declare function instructionsInstalled(ws: Ws): Promise<boolean>;
|
|
64
66
|
export declare function knowledgeWritten(ws: Ws): Promise<boolean>;
|
|
65
67
|
/** Cheap overview: small workspace files, Git status and a fingerprint check of the few files facts cite. Never scans the repository. */
|
package/dist/services/status.js
CHANGED
|
@@ -9,22 +9,74 @@ import { evaluateStaleness, loadFacts } from '../knowledge/facts.js';
|
|
|
9
9
|
import { listSessions } from '../sessions/session.js';
|
|
10
10
|
import { listTasks, nextRequiredStep } from '../tasks/task.js';
|
|
11
11
|
import { pathExists } from '../utils/fs.js';
|
|
12
|
-
import { SECTION_END } from '../agents/
|
|
12
|
+
import { SECTION_START, SECTION_END } from '../agents/shared.js';
|
|
13
13
|
import { SKILL_PATH } from '../agents/claude/content.js';
|
|
14
|
+
import { listAgentAdapters } from '../agents/index.js';
|
|
14
15
|
import { isoNow, managerEnv } from './common.js';
|
|
15
16
|
const brief = (t) => ({ id: t.id, title: t.title, type: t.type, status: t.status, updatedAt: t.updatedAt, next: nextRequiredStep(t) });
|
|
16
|
-
export async function
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
17
|
+
export async function detectInstalledAgents(ws) {
|
|
18
|
+
const installed = [];
|
|
19
|
+
for (const adapter of listAgentAdapters()) {
|
|
20
|
+
if (adapter.id === 'claude') {
|
|
21
|
+
let claudeFound = false;
|
|
22
|
+
for (const rel of ['CLAUDE.md', '.claude/CLAUDE.md']) {
|
|
23
|
+
try {
|
|
24
|
+
const text = await fs.readFile(path.join(ws.root, ...rel.split('/')), 'utf8');
|
|
25
|
+
if (text.includes(SECTION_START) && text.includes(SECTION_END) && (await pathExists(path.join(ws.root, ...SKILL_PATH.split('/'))))) {
|
|
26
|
+
claudeFound = true;
|
|
27
|
+
break;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
/* try next */
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
if (claudeFound)
|
|
35
|
+
installed.push(adapter);
|
|
36
|
+
}
|
|
37
|
+
else if (adapter.id === 'codex') {
|
|
38
|
+
try {
|
|
39
|
+
const text = await fs.readFile(path.join(ws.root, 'AGENTS.md'), 'utf8');
|
|
40
|
+
if (text.includes(SECTION_START) && text.includes(SECTION_END))
|
|
41
|
+
installed.push(adapter);
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
/* not found */
|
|
45
|
+
}
|
|
22
46
|
}
|
|
23
|
-
|
|
24
|
-
|
|
47
|
+
else if (adapter.id === 'cursor') {
|
|
48
|
+
let cursorFound = false;
|
|
49
|
+
for (const rel of ['.cursor/rules/devworkspace.mdc', '.cursorrules']) {
|
|
50
|
+
try {
|
|
51
|
+
const text = await fs.readFile(path.join(ws.root, ...rel.split('/')), 'utf8');
|
|
52
|
+
if (text.includes(SECTION_START) && text.includes(SECTION_END)) {
|
|
53
|
+
cursorFound = true;
|
|
54
|
+
break;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
/* try next */
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
if (cursorFound)
|
|
62
|
+
installed.push(adapter);
|
|
63
|
+
}
|
|
64
|
+
else if (adapter.id === 'copilot') {
|
|
65
|
+
try {
|
|
66
|
+
const text = await fs.readFile(path.join(ws.root, '.github', 'copilot-instructions.md'), 'utf8');
|
|
67
|
+
if (text.includes(SECTION_START) && text.includes(SECTION_END))
|
|
68
|
+
installed.push(adapter);
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
/* not found */
|
|
72
|
+
}
|
|
25
73
|
}
|
|
26
74
|
}
|
|
27
|
-
return
|
|
75
|
+
return installed;
|
|
76
|
+
}
|
|
77
|
+
export async function instructionsInstalled(ws) {
|
|
78
|
+
const installed = await detectInstalledAgents(ws);
|
|
79
|
+
return installed.length > 0;
|
|
28
80
|
}
|
|
29
81
|
export async function knowledgeWritten(ws) {
|
|
30
82
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/services/status.ts"],"names":[],"mappings":"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","sourcesContent":["import { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport { SCHEMA_VERSION, validateAnalysisState, validateCommands, type CommandEntry } from '../config/schemas.js';\nimport { findWorkspaceRoot, loadProject, wsPaths, type Ws } from '../core/workspace.js';\nimport { readVersioned } from '../core/versioned.js';\nimport { getGitState } from '../git/git.js';\nimport { inspectAll, type IntegrationReport } from '../integrations/index.js';\nimport { evaluateStaleness, loadFacts } from '../knowledge/facts.js';\nimport { listSessions } from '../sessions/session.js';\nimport { listTasks, nextRequiredStep, type Task } from '../tasks/task.js';\nimport { pathExists } from '../utils/fs.js';\nimport { SECTION_END } from '../agents/claude/content.js';\nimport { SKILL_PATH } from '../agents/claude/content.js';\nimport { isoNow, managerEnv, type ServiceOptions } from './common.js';\n\nexport interface TaskBrief {\n id: string;\n title: string;\n type: string;\n status: string;\n updatedAt: string;\n next: string;\n}\n\nexport interface StatusResult {\n initialized: boolean;\n root: string | null;\n project: { name: string; id: string } | null;\n workspace: 'Healthy' | 'Needs attention' | 'Not initialized' | 'Unreadable';\n workspaceProblem?: string;\n git: { available: boolean; isRepo: boolean; branch: string | null; workingTree: 'Clean' | 'Modified' | 'Unknown'; changes: number };\n knowledge: { state: 'Current' | 'Stale' | 'Empty' | 'Unknown'; facts: number; stale: number; analyzedAt: string | null; staleItems: { key: string; reason: string; recorded: boolean }[]; needsReview: number };\n onboarding: { instructionsInstalled: boolean; knowledgeWritten: boolean; ready: boolean };\n /** Shallow observation (files and PATH only; never VERIFIED). Run doctor or `integrations status` to verify. */\n integrations: IntegrationReport[];\n activeTasks: TaskBrief[];\n verification: { id: string; available: boolean; command: string | null; required: string; cwd?: string; mutates?: boolean }[];\n lastSession: { id: string; goal: string; next: string } | null;\n corruptTasks: number;\n}\n\nconst brief = (t: Task): TaskBrief => ({ id: t.id, title: t.title, type: t.type, status: t.status, updatedAt: t.updatedAt, next: nextRequiredStep(t) });\n\nexport async function instructionsInstalled(ws: Ws): Promise<boolean> {\n for (const rel of ['CLAUDE.md', '.claude/CLAUDE.md']) {\n try {\n const text = await fs.readFile(path.join(ws.root, ...rel.split('/')), 'utf8');\n if (text.includes('<!-- devworkspace:start') && text.includes(SECTION_END) && (await pathExists(path.join(ws.root, ...SKILL_PATH.split('/'))))) return true;\n } catch {\n /* try next */\n }\n }\n return false;\n}\n\nexport async function knowledgeWritten(ws: Ws): Promise<boolean> {\n try {\n return (await fs.stat(path.join(ws.contextDir, 'architecture.md'))).size >= 200;\n } catch {\n return false;\n }\n}\n\n/** Cheap overview: small workspace files, Git status and a fingerprint check of the few files facts cite. Never scans the repository. */\nexport async function getStatus(o: ServiceOptions, opts: { deep?: boolean } = {}): Promise<StatusResult> {\n const root = await findWorkspaceRoot(o.cwd);\n const git = await getGitState(root ?? o.cwd);\n const gitBrief: StatusResult['git'] = {\n available: git.available,\n isRepo: git.isRepo,\n branch: git.branch,\n workingTree: git.isRepo ? (git.dirty ? 'Modified' : 'Clean') : 'Unknown',\n changes: git.entries.length,\n };\n const base: StatusResult = {\n initialized: false,\n root,\n project: null,\n workspace: 'Not initialized',\n git: gitBrief,\n knowledge: { state: 'Unknown', facts: 0, stale: 0, analyzedAt: null, staleItems: [], needsReview: 0 },\n onboarding: { instructionsInstalled: false, knowledgeWritten: false, ready: false },\n integrations: [],\n activeTasks: [],\n verification: [],\n lastSession: null,\n corruptTasks: 0,\n };\n if (!root) return base;\n\n const ws = wsPaths(root);\n base.initialized = true;\n try {\n const project = await loadProject(ws);\n base.project = { name: project.name, id: project.projectId };\n base.workspace = 'Healthy';\n } catch (e) {\n return { ...base, workspace: 'Unreadable', workspaceProblem: (e as Error).message };\n }\n\n try {\n const facts = await loadFacts(ws);\n const view = await evaluateStaleness(ws.root, facts, isoNow(o));\n const items = [...view.recorded.map((x) => ({ ...x, recorded: true })), ...view.detected.map((x) => ({ ...x, recorded: false }))];\n const stale = items.length;\n let analyzedAt: string | null = null;\n if (await pathExists(ws.analysisState)) {\n analyzedAt = (await readVersioned(ws.analysisState, 'analysis', SCHEMA_VERSION, validateAnalysisState)).data.analyzedAt;\n }\n base.knowledge = { facts: facts.facts.length, stale, analyzedAt, staleItems: items, needsReview: view.needsReview.length, state: facts.facts.length === 0 ? 'Empty' : stale > 0 ? 'Stale' : 'Current' };\n } catch (e) {\n base.workspace = 'Needs attention';\n base.workspaceProblem = (e as Error).message;\n }\n\n if (await pathExists(ws.commands)) {\n try {\n const commands = (await readVersioned(ws.commands, 'commands', SCHEMA_VERSION, validateCommands)).data;\n base.verification = commands.checks.map((c: CommandEntry) => ({ id: c.id, available: c.available, command: c.command, required: c.required, ...(c.cwd ? { cwd: c.cwd } : {}), ...(c.mutates !== undefined ? { mutates: c.mutates } : {}) }));\n } catch (e) {\n base.workspace = 'Needs attention';\n base.workspaceProblem ??= (e as Error).message;\n }\n }\n\n const { tasks, corrupt } = await listTasks(ws);\n base.activeTasks = tasks.map(brief);\n base.corruptTasks = corrupt.length;\n if (corrupt.length > 0) base.workspace = 'Needs attention';\n const sessions = await listSessions(ws, 1);\n if (sessions[0]) base.lastSession = { id: sessions[0].id, goal: sessions[0].goal, next: sessions[0].next };\n\n base.integrations = await inspectAll(ws, managerEnv(o, root), { deep: !!opts.deep });\n base.onboarding.instructionsInstalled = await instructionsInstalled(ws);\n base.onboarding.knowledgeWritten = await knowledgeWritten(ws);\n base.onboarding.ready = base.onboarding.instructionsInstalled && base.onboarding.knowledgeWritten && base.knowledge.state !== 'Empty';\n return base;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/services/status.ts"],"names":[],"mappings":"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","sourcesContent":["import { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport { SCHEMA_VERSION, validateAnalysisState, validateCommands, type CommandEntry } from '../config/schemas.js';\nimport { findWorkspaceRoot, loadProject, wsPaths, type Ws } from '../core/workspace.js';\nimport { readVersioned } from '../core/versioned.js';\nimport { getGitState } from '../git/git.js';\nimport { inspectAll, type IntegrationReport } from '../integrations/index.js';\nimport { evaluateStaleness, loadFacts } from '../knowledge/facts.js';\nimport { listSessions } from '../sessions/session.js';\nimport { listTasks, nextRequiredStep, type Task } from '../tasks/task.js';\nimport { pathExists } from '../utils/fs.js';\nimport { SECTION_START, SECTION_END } from '../agents/shared.js';\nimport { SKILL_PATH } from '../agents/claude/content.js';\nimport { listAgentAdapters } from '../agents/index.js';\nimport type { AgentAdapter } from '../agents/types.js';\nimport { isoNow, managerEnv, type ServiceOptions } from './common.js';\n\nexport interface TaskBrief {\n id: string;\n title: string;\n type: string;\n status: string;\n updatedAt: string;\n next: string;\n}\n\nexport interface StatusResult {\n initialized: boolean;\n root: string | null;\n project: { name: string; id: string } | null;\n workspace: 'Healthy' | 'Needs attention' | 'Not initialized' | 'Unreadable';\n workspaceProblem?: string;\n git: { available: boolean; isRepo: boolean; branch: string | null; workingTree: 'Clean' | 'Modified' | 'Unknown'; changes: number };\n knowledge: { state: 'Current' | 'Stale' | 'Empty' | 'Unknown'; facts: number; stale: number; analyzedAt: string | null; staleItems: { key: string; reason: string; recorded: boolean }[]; needsReview: number };\n onboarding: { instructionsInstalled: boolean; knowledgeWritten: boolean; ready: boolean };\n /** Shallow observation (files and PATH only; never VERIFIED). Run doctor or `integrations status` to verify. */\n integrations: IntegrationReport[];\n activeTasks: TaskBrief[];\n verification: { id: string; available: boolean; command: string | null; required: string; cwd?: string; mutates?: boolean }[];\n lastSession: { id: string; goal: string; next: string } | null;\n corruptTasks: number;\n}\n\nconst brief = (t: Task): TaskBrief => ({ id: t.id, title: t.title, type: t.type, status: t.status, updatedAt: t.updatedAt, next: nextRequiredStep(t) });\n\nexport async function detectInstalledAgents(ws: Ws): Promise<AgentAdapter[]> {\n const installed: AgentAdapter[] = [];\n for (const adapter of listAgentAdapters()) {\n if (adapter.id === 'claude') {\n let claudeFound = false;\n for (const rel of ['CLAUDE.md', '.claude/CLAUDE.md']) {\n try {\n const text = await fs.readFile(path.join(ws.root, ...rel.split('/')), 'utf8');\n if (text.includes(SECTION_START) && text.includes(SECTION_END) && (await pathExists(path.join(ws.root, ...SKILL_PATH.split('/'))))) {\n claudeFound = true;\n break;\n }\n } catch {\n /* try next */\n }\n }\n if (claudeFound) installed.push(adapter);\n } else if (adapter.id === 'codex') {\n try {\n const text = await fs.readFile(path.join(ws.root, 'AGENTS.md'), 'utf8');\n if (text.includes(SECTION_START) && text.includes(SECTION_END)) installed.push(adapter);\n } catch {\n /* not found */\n }\n } else if (adapter.id === 'cursor') {\n let cursorFound = false;\n for (const rel of ['.cursor/rules/devworkspace.mdc', '.cursorrules']) {\n try {\n const text = await fs.readFile(path.join(ws.root, ...rel.split('/')), 'utf8');\n if (text.includes(SECTION_START) && text.includes(SECTION_END)) {\n cursorFound = true;\n break;\n }\n } catch {\n /* try next */\n }\n }\n if (cursorFound) installed.push(adapter);\n } else if (adapter.id === 'copilot') {\n try {\n const text = await fs.readFile(path.join(ws.root, '.github', 'copilot-instructions.md'), 'utf8');\n if (text.includes(SECTION_START) && text.includes(SECTION_END)) installed.push(adapter);\n } catch {\n /* not found */\n }\n }\n }\n return installed;\n}\n\nexport async function instructionsInstalled(ws: Ws): Promise<boolean> {\n const installed = await detectInstalledAgents(ws);\n return installed.length > 0;\n}\n\nexport async function knowledgeWritten(ws: Ws): Promise<boolean> {\n try {\n return (await fs.stat(path.join(ws.contextDir, 'architecture.md'))).size >= 200;\n } catch {\n return false;\n }\n}\n\n/** Cheap overview: small workspace files, Git status and a fingerprint check of the few files facts cite. Never scans the repository. */\nexport async function getStatus(o: ServiceOptions, opts: { deep?: boolean } = {}): Promise<StatusResult> {\n const root = await findWorkspaceRoot(o.cwd);\n const git = await getGitState(root ?? o.cwd);\n const gitBrief: StatusResult['git'] = {\n available: git.available,\n isRepo: git.isRepo,\n branch: git.branch,\n workingTree: git.isRepo ? (git.dirty ? 'Modified' : 'Clean') : 'Unknown',\n changes: git.entries.length,\n };\n const base: StatusResult = {\n initialized: false,\n root,\n project: null,\n workspace: 'Not initialized',\n git: gitBrief,\n knowledge: { state: 'Unknown', facts: 0, stale: 0, analyzedAt: null, staleItems: [], needsReview: 0 },\n onboarding: { instructionsInstalled: false, knowledgeWritten: false, ready: false },\n integrations: [],\n activeTasks: [],\n verification: [],\n lastSession: null,\n corruptTasks: 0,\n };\n if (!root) return base;\n\n const ws = wsPaths(root);\n base.initialized = true;\n try {\n const project = await loadProject(ws);\n base.project = { name: project.name, id: project.projectId };\n base.workspace = 'Healthy';\n } catch (e) {\n return { ...base, workspace: 'Unreadable', workspaceProblem: (e as Error).message };\n }\n\n try {\n const facts = await loadFacts(ws);\n const view = await evaluateStaleness(ws.root, facts, isoNow(o));\n const items = [...view.recorded.map((x) => ({ ...x, recorded: true })), ...view.detected.map((x) => ({ ...x, recorded: false }))];\n const stale = items.length;\n let analyzedAt: string | null = null;\n if (await pathExists(ws.analysisState)) {\n analyzedAt = (await readVersioned(ws.analysisState, 'analysis', SCHEMA_VERSION, validateAnalysisState)).data.analyzedAt;\n }\n base.knowledge = { facts: facts.facts.length, stale, analyzedAt, staleItems: items, needsReview: view.needsReview.length, state: facts.facts.length === 0 ? 'Empty' : stale > 0 ? 'Stale' : 'Current' };\n } catch (e) {\n base.workspace = 'Needs attention';\n base.workspaceProblem = (e as Error).message;\n }\n\n if (await pathExists(ws.commands)) {\n try {\n const commands = (await readVersioned(ws.commands, 'commands', SCHEMA_VERSION, validateCommands)).data;\n base.verification = commands.checks.map((c: CommandEntry) => ({ id: c.id, available: c.available, command: c.command, required: c.required, ...(c.cwd ? { cwd: c.cwd } : {}), ...(c.mutates !== undefined ? { mutates: c.mutates } : {}) }));\n } catch (e) {\n base.workspace = 'Needs attention';\n base.workspaceProblem ??= (e as Error).message;\n }\n }\n\n const { tasks, corrupt } = await listTasks(ws);\n base.activeTasks = tasks.map(brief);\n base.corruptTasks = corrupt.length;\n if (corrupt.length > 0) base.workspace = 'Needs attention';\n const sessions = await listSessions(ws, 1);\n if (sessions[0]) base.lastSession = { id: sessions[0].id, goal: sessions[0].goal, next: sessions[0].next };\n\n base.integrations = await inspectAll(ws, managerEnv(o, root), { deep: !!opts.deep });\n base.onboarding.instructionsInstalled = await instructionsInstalled(ws);\n base.onboarding.knowledgeWritten = await knowledgeWritten(ws);\n base.onboarding.ready = base.onboarding.instructionsInstalled && base.onboarding.knowledgeWritten && base.knowledge.state !== 'Empty';\n return base;\n}\n"]}
|
package/dist/services/tasks.js
CHANGED
|
@@ -25,7 +25,12 @@ export async function createTask(o, input) {
|
|
|
25
25
|
skipChecks.add('e2e');
|
|
26
26
|
if (classification.constraints.includes('no-tests'))
|
|
27
27
|
skipChecks.add('unit').add('integration').add('e2e');
|
|
28
|
-
|
|
28
|
+
if (classification.readOnly) {
|
|
29
|
+
verification = verification.map((v) => ({ ...v, status: 'SKIPPED', reason: 'user-override' }));
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
verification = verification.map((v) => (skipChecks.has(v.check) ? { ...v, status: 'SKIPPED', reason: 'user-override' } : v));
|
|
33
|
+
}
|
|
29
34
|
const title = (input.title ?? input.text).replace(/\s+/g, ' ').trim().slice(0, 100);
|
|
30
35
|
const task = createTaskObject({ title, type, description: input.text, verification, constraints: classification.constraints }, isoNow(o));
|
|
31
36
|
task.scope = await captureScope(ws.root, isoNow(o));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tasks.js","sourceRoot":"","sources":["../../src/services/tasks.ts"],"names":[],"mappings":"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","sourcesContent":["import { DevWorkspaceError } from '../errors/index.js';\nimport { loadProject, requireWorkspace } from '../core/workspace.js';\nimport { captureScope } from '../verification/scope.js';\nimport { gateContext, loadContract } from './verify.js';\nimport { classifyRequest, WORKFLOWS, type Classification, type WorkflowSpec } from '../tasks/routing.js';\nimport {\n assertNoSecrets,\n createTaskObject,\n evaluateGate,\n nextRequiredStep,\n listTasks,\n loadTask,\n requiredChecksFor,\n saveTask,\n transitionTask,\n type Evidence,\n type GateResult,\n type Task,\n type TaskStatus,\n type TaskType,\n type VerifyStatus,\n TASK_STATUSES,\n TASK_TYPES,\n VERIFY_STATUSES,\n} from '../tasks/task.js';\nimport { isoNow, mutate, type ServiceOptions } from './common.js';\n\nexport interface CreateTaskResult {\n task: Task;\n classification: Classification;\n workflow: WorkflowSpec;\n}\n\nexport async function createTask(o: ServiceOptions, input: { text: string; type?: string; title?: string }): Promise<CreateTaskResult> {\n return mutate(o, async (ws) => {\n const project = await loadProject(ws);\n const classification = classifyRequest(input.text);\n let type: TaskType = classification.type;\n if (input.type) {\n const up = input.type.toUpperCase();\n if (!(TASK_TYPES as readonly string[]).includes(up)) {\n throw new DevWorkspaceError('USAGE', `Unknown task type \"${input.type}\".`, { hint: `Use one of: ${TASK_TYPES.join(', ')}.` });\n }\n type = up as TaskType;\n }\n const contract = await loadContract(ws);\n let verification = requiredChecksFor(type, contract, project.settings.review);\n // Explicit user constraints stay visible: the check is kept but recorded as skipped at the user's request.\n const skipChecks = new Set<string>();\n if (classification.constraints.includes('no-e2e')) skipChecks.add('e2e');\n if (classification.constraints.includes('no-tests')) skipChecks.add('unit').add('integration').add('e2e');\n verification = verification.map((v) => (skipChecks.has(v.check) ? { ...v, status: 'SKIPPED' as const, reason: 'user-override' } : v));\n const title = (input.title ?? input.text).replace(/\\s+/g, ' ').trim().slice(0, 100);\n const task = createTaskObject({ title, type, description: input.text, verification, constraints: classification.constraints }, isoNow(o));\n task.scope = await captureScope(ws.root, isoNow(o));\n await saveTask(ws, task);\n return { task, classification: { ...classification, type }, workflow: WORKFLOWS[type] };\n });\n}\n\nexport async function showTask(o: ServiceOptions, id: string): Promise<{ task: Task; gate: GateResult; next: string }> {\n const ws = await requireWorkspace(o.cwd);\n const task = await loadTask(ws, id);\n const ctx = await gateContext(ws, task);\n return { task, gate: evaluateGate(task, ctx), next: nextRequiredStep(task, ctx) };\n}\n\nexport async function listTasksService(o: ServiceOptions, includeCompleted = false): ReturnType<typeof listTasks> {\n const ws = await requireWorkspace(o.cwd);\n return listTasks(ws, { includeCompleted });\n}\n\nexport interface TaskPatch {\n title?: string;\n summary?: string;\n criteria?: string[];\n plan?: string[];\n areas?: string[];\n decisions?: string[];\n blockers?: string[];\n clearBlockers?: boolean;\n require?: string[];\n}\n\nexport async function updateTask(o: ServiceOptions, id: string, patch: TaskPatch): Promise<Task> {\n return mutate(o, async (ws) => {\n const task = await loadTask(ws, id);\n if (patch.title) task.title = patch.title.trim().slice(0, 200);\n if (patch.summary !== undefined) task.completionSummary = patch.summary.trim().slice(0, 4000);\n task.acceptanceCriteria.push(...(patch.criteria ?? []));\n task.plan.push(...(patch.plan ?? []));\n task.affectedAreas.push(...(patch.areas ?? []).filter((a) => !task.affectedAreas.includes(a)));\n task.decisions.push(...(patch.decisions ?? []));\n if (patch.clearBlockers) task.blockers = [];\n task.blockers.push(...(patch.blockers ?? []));\n for (const check of patch.require ?? []) {\n const existing = task.verification.find((v) => v.check === check);\n if (existing) existing.required = true;\n else task.verification.push({ check, required: true, status: 'PENDING' });\n }\n task.updatedAt = isoNow(o);\n assertNoSecrets(task);\n await saveTask(ws, task);\n return task;\n });\n}\n\nexport async function setTaskStatus(o: ServiceOptions, id: string, status: string, note?: string): Promise<{ task: Task; gate: GateResult | null }> {\n const up = status.toUpperCase();\n if (!(TASK_STATUSES as readonly string[]).includes(up)) {\n throw new DevWorkspaceError('USAGE', `Unknown task status \"${status}\".`, { hint: `Use one of: ${TASK_STATUSES.join(', ')}.` });\n }\n return mutate(o, async (ws) => {\n const task = await loadTask(ws, id);\n const gate = transitionTask(task, up as TaskStatus, isoNow(o), note, up === 'COMPLETED' ? await gateContext(ws, task) : undefined);\n if (up === 'BLOCKED' && note) task.blockers.push(note.slice(0, 300));\n await saveTask(ws, task);\n return { task, gate };\n });\n}\n\nexport async function recordVerification(\n o: ServiceOptions,\n id: string,\n check: string,\n result: string,\n extra: { reason?: string; detail?: string; package?: string } = {},\n): Promise<Task> {\n const status = result.toUpperCase();\n const normalized = status === 'SKIP' ? 'SKIPPED' : status;\n if (!(VERIFY_STATUSES as readonly string[]).includes(normalized)) {\n throw new DevWorkspaceError('USAGE', `Unknown result \"${result}\".`, { hint: 'Use pass, fail, skip or pending.' });\n }\n return mutate(o, async (ws) => {\n const task = await loadTask(ws, id);\n let item = task.verification.find((v) => v.check === check);\n if (!item) {\n item = { check, required: false, status: 'PENDING' };\n task.verification.push(item);\n }\n item.status = normalized as VerifyStatus;\n item.updatedAt = isoNow(o);\n // A reported pass is a claim: DevWorkspace did not see the command run. It is kept as such, per package, and the\n // completion gate of a scoped task only accepts it with an explicit user override.\n if (normalized === 'PASS') {\n const pkg = !extra.package || extra.package === '' ? '.' : extra.package.replace(/\\/+$/, '');\n const claim: Evidence = { kind: 'claimed', at: item.updatedAt, package: pkg, ...(extra.reason === 'user-override' ? { userOverride: true } : {}), ...(extra.detail ? { note: extra.detail.slice(0, 200) } : {}) };\n // Never replace something DevWorkspace observed with somebody's say-so.\n if (!item.evidence?.some((e) => e.package === pkg && e.kind === 'executed')) item.evidence = [...(item.evidence ?? []).filter((e) => e.package !== pkg), claim];\n }\n if (extra.reason) item.reason = extra.reason;\n else delete item.reason;\n if (extra.detail) item.detail = extra.detail.slice(0, 500);\n task.updatedAt = item.updatedAt;\n assertNoSecrets(task);\n await saveTask(ws, task);\n return task;\n });\n}\n\nexport async function recordTests(o: ServiceOptions, id: string, phase: 'baseline' | 'after', passed: number, failed: number): Promise<Task> {\n if (!Number.isInteger(passed) || !Number.isInteger(failed) || passed < 0 || failed < 0) {\n throw new DevWorkspaceError('USAGE', '--passed and --failed must be non-negative integers.');\n }\n return mutate(o, async (ws) => {\n const task = await loadTask(ws, id);\n task.tests[phase] = { passed, failed };\n task.updatedAt = isoNow(o);\n await saveTask(ws, task);\n return task;\n });\n}\n\nexport async function attestTask(\n o: ServiceOptions,\n id: string,\n flags: { userWorkIntact?: boolean; knowledgeReviewed?: boolean; finalStateInspected?: boolean },\n): Promise<Task> {\n return mutate(o, async (ws) => {\n const task = await loadTask(ws, id);\n task.attestations = { ...task.attestations, ...Object.fromEntries(Object.entries(flags).filter(([, v]) => v !== undefined)) };\n task.updatedAt = isoNow(o);\n await saveTask(ws, task);\n return task;\n });\n}\n"]}
|
|
1
|
+
{"version":3,"file":"tasks.js","sourceRoot":"","sources":["../../src/services/tasks.ts"],"names":[],"mappings":"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","sourcesContent":["import { DevWorkspaceError } from '../errors/index.js';\nimport { loadProject, requireWorkspace } from '../core/workspace.js';\nimport { captureScope } from '../verification/scope.js';\nimport { gateContext, loadContract } from './verify.js';\nimport { classifyRequest, WORKFLOWS, type Classification, type WorkflowSpec } from '../tasks/routing.js';\nimport {\n assertNoSecrets,\n createTaskObject,\n evaluateGate,\n nextRequiredStep,\n listTasks,\n loadTask,\n requiredChecksFor,\n saveTask,\n transitionTask,\n type Evidence,\n type GateResult,\n type Task,\n type TaskStatus,\n type TaskType,\n type VerifyStatus,\n TASK_STATUSES,\n TASK_TYPES,\n VERIFY_STATUSES,\n} from '../tasks/task.js';\nimport { isoNow, mutate, type ServiceOptions } from './common.js';\n\nexport interface CreateTaskResult {\n task: Task;\n classification: Classification;\n workflow: WorkflowSpec;\n}\n\nexport async function createTask(o: ServiceOptions, input: { text: string; type?: string; title?: string }): Promise<CreateTaskResult> {\n return mutate(o, async (ws) => {\n const project = await loadProject(ws);\n const classification = classifyRequest(input.text);\n let type: TaskType = classification.type;\n if (input.type) {\n const up = input.type.toUpperCase();\n if (!(TASK_TYPES as readonly string[]).includes(up)) {\n throw new DevWorkspaceError('USAGE', `Unknown task type \"${input.type}\".`, { hint: `Use one of: ${TASK_TYPES.join(', ')}.` });\n }\n type = up as TaskType;\n }\n const contract = await loadContract(ws);\n let verification = requiredChecksFor(type, contract, project.settings.review);\n // Explicit user constraints stay visible: the check is kept but recorded as skipped at the user's request.\n const skipChecks = new Set<string>();\n if (classification.constraints.includes('no-e2e')) skipChecks.add('e2e');\n if (classification.constraints.includes('no-tests')) skipChecks.add('unit').add('integration').add('e2e');\n if (classification.readOnly) {\n verification = verification.map((v) => ({ ...v, status: 'SKIPPED' as const, reason: 'user-override' }));\n } else {\n verification = verification.map((v) => (skipChecks.has(v.check) ? { ...v, status: 'SKIPPED' as const, reason: 'user-override' } : v));\n }\n const title = (input.title ?? input.text).replace(/\\s+/g, ' ').trim().slice(0, 100);\n const task = createTaskObject({ title, type, description: input.text, verification, constraints: classification.constraints }, isoNow(o));\n task.scope = await captureScope(ws.root, isoNow(o));\n await saveTask(ws, task);\n return { task, classification: { ...classification, type }, workflow: WORKFLOWS[type] };\n });\n}\n\nexport async function showTask(o: ServiceOptions, id: string): Promise<{ task: Task; gate: GateResult; next: string }> {\n const ws = await requireWorkspace(o.cwd);\n const task = await loadTask(ws, id);\n const ctx = await gateContext(ws, task);\n return { task, gate: evaluateGate(task, ctx), next: nextRequiredStep(task, ctx) };\n}\n\nexport async function listTasksService(o: ServiceOptions, includeCompleted = false): ReturnType<typeof listTasks> {\n const ws = await requireWorkspace(o.cwd);\n return listTasks(ws, { includeCompleted });\n}\n\nexport interface TaskPatch {\n title?: string;\n summary?: string;\n criteria?: string[];\n plan?: string[];\n areas?: string[];\n decisions?: string[];\n blockers?: string[];\n clearBlockers?: boolean;\n require?: string[];\n}\n\nexport async function updateTask(o: ServiceOptions, id: string, patch: TaskPatch): Promise<Task> {\n return mutate(o, async (ws) => {\n const task = await loadTask(ws, id);\n if (patch.title) task.title = patch.title.trim().slice(0, 200);\n if (patch.summary !== undefined) task.completionSummary = patch.summary.trim().slice(0, 4000);\n task.acceptanceCriteria.push(...(patch.criteria ?? []));\n task.plan.push(...(patch.plan ?? []));\n task.affectedAreas.push(...(patch.areas ?? []).filter((a) => !task.affectedAreas.includes(a)));\n task.decisions.push(...(patch.decisions ?? []));\n if (patch.clearBlockers) task.blockers = [];\n task.blockers.push(...(patch.blockers ?? []));\n for (const check of patch.require ?? []) {\n const existing = task.verification.find((v) => v.check === check);\n if (existing) existing.required = true;\n else task.verification.push({ check, required: true, status: 'PENDING' });\n }\n task.updatedAt = isoNow(o);\n assertNoSecrets(task);\n await saveTask(ws, task);\n return task;\n });\n}\n\nexport async function setTaskStatus(o: ServiceOptions, id: string, status: string, note?: string): Promise<{ task: Task; gate: GateResult | null }> {\n const up = status.toUpperCase();\n if (!(TASK_STATUSES as readonly string[]).includes(up)) {\n throw new DevWorkspaceError('USAGE', `Unknown task status \"${status}\".`, { hint: `Use one of: ${TASK_STATUSES.join(', ')}.` });\n }\n return mutate(o, async (ws) => {\n const task = await loadTask(ws, id);\n const gate = transitionTask(task, up as TaskStatus, isoNow(o), note, up === 'COMPLETED' ? await gateContext(ws, task) : undefined);\n if (up === 'BLOCKED' && note) task.blockers.push(note.slice(0, 300));\n await saveTask(ws, task);\n return { task, gate };\n });\n}\n\nexport async function recordVerification(\n o: ServiceOptions,\n id: string,\n check: string,\n result: string,\n extra: { reason?: string; detail?: string; package?: string } = {},\n): Promise<Task> {\n const status = result.toUpperCase();\n const normalized = status === 'SKIP' ? 'SKIPPED' : status;\n if (!(VERIFY_STATUSES as readonly string[]).includes(normalized)) {\n throw new DevWorkspaceError('USAGE', `Unknown result \"${result}\".`, { hint: 'Use pass, fail, skip or pending.' });\n }\n return mutate(o, async (ws) => {\n const task = await loadTask(ws, id);\n let item = task.verification.find((v) => v.check === check);\n if (!item) {\n item = { check, required: false, status: 'PENDING' };\n task.verification.push(item);\n }\n item.status = normalized as VerifyStatus;\n item.updatedAt = isoNow(o);\n // A reported pass is a claim: DevWorkspace did not see the command run. It is kept as such, per package, and the\n // completion gate of a scoped task only accepts it with an explicit user override.\n if (normalized === 'PASS') {\n const pkg = !extra.package || extra.package === '' ? '.' : extra.package.replace(/\\/+$/, '');\n const claim: Evidence = { kind: 'claimed', at: item.updatedAt, package: pkg, ...(extra.reason === 'user-override' ? { userOverride: true } : {}), ...(extra.detail ? { note: extra.detail.slice(0, 200) } : {}) };\n // Never replace something DevWorkspace observed with somebody's say-so.\n if (!item.evidence?.some((e) => e.package === pkg && e.kind === 'executed')) item.evidence = [...(item.evidence ?? []).filter((e) => e.package !== pkg), claim];\n }\n if (extra.reason) item.reason = extra.reason;\n else delete item.reason;\n if (extra.detail) item.detail = extra.detail.slice(0, 500);\n task.updatedAt = item.updatedAt;\n assertNoSecrets(task);\n await saveTask(ws, task);\n return task;\n });\n}\n\nexport async function recordTests(o: ServiceOptions, id: string, phase: 'baseline' | 'after', passed: number, failed: number): Promise<Task> {\n if (!Number.isInteger(passed) || !Number.isInteger(failed) || passed < 0 || failed < 0) {\n throw new DevWorkspaceError('USAGE', '--passed and --failed must be non-negative integers.');\n }\n return mutate(o, async (ws) => {\n const task = await loadTask(ws, id);\n task.tests[phase] = { passed, failed };\n task.updatedAt = isoNow(o);\n await saveTask(ws, task);\n return task;\n });\n}\n\nexport async function attestTask(\n o: ServiceOptions,\n id: string,\n flags: { userWorkIntact?: boolean; knowledgeReviewed?: boolean; finalStateInspected?: boolean },\n): Promise<Task> {\n return mutate(o, async (ws) => {\n const task = await loadTask(ws, id);\n task.attestations = { ...task.attestations, ...Object.fromEntries(Object.entries(flags).filter(([, v]) => v !== undefined)) };\n task.updatedAt = isoNow(o);\n await saveTask(ws, task);\n return task;\n });\n}\n"]}
|
package/dist/tasks/routing.js
CHANGED
|
@@ -147,20 +147,22 @@ export const WORKFLOWS = {
|
|
|
147
147
|
},
|
|
148
148
|
};
|
|
149
149
|
const OVERRIDE_PATTERNS = [
|
|
150
|
-
['no-modify', /\b(?:only|just)\s+(?:explain|describe|investigate|look|read|review)\b|\b(?:do\s*n[o']t|don'?t|never)\s+(?:modify|change|edit|touch)\b|\bread[- ]only\b|\bno\s+changes\b/i],
|
|
151
|
-
['plan-only', /\b(?:only|just)\s+(?:make\s+|write\s+|give\s+me\s+)?a\s+plan\b|\bplan\s+only\b/i],
|
|
150
|
+
['no-modify', /\b(?:only|just)\s+(?:explain|describe|investigate|look|read|review)\b|\b(?:do\s*n[o']t|don'?t|never|without)\s+(?:modify|modifying|change|changing|edit|editing|touch|touching)\b|\bread[- ]only\b|\bno\s+changes\b/i],
|
|
151
|
+
['plan-only', /\b(?:only|just)\s+(?:make\s+|write\s+|give\s+me\s+)?a\s+plan\b|\bplan\s+only\b|\bwithout\s+implementing(?:\s+it)?\b/i],
|
|
152
152
|
['no-commit', /\b(?:do\s*n[o']t|don'?t|never)\s+commit\b|\bno\s+commits?\b/i],
|
|
153
153
|
['no-e2e', /\b(?:do\s*n[o']t|don'?t|skip|no)\s+(?:run\s+)?(?:the\s+)?(?:e2e|end[- ]to[- ]end)\b/i],
|
|
154
154
|
['no-tests', /\b(?:do\s*n[o']t|don'?t|skip)\s+(?:run\s+)?(?:any\s+|the\s+)?tests\b(?!\s+but)/i],
|
|
155
|
-
['no-fix', /\b(?:do\s*n[o']t|don'?t)\s+fix\b|\bwithout\s+fixing\b/i],
|
|
155
|
+
['no-fix', /\b(?:do\s*n[o']t|don'?t|never)\s+fix\b|\bwithout\s+fixing\b|\bno[- ]fix\b/i],
|
|
156
156
|
];
|
|
157
157
|
export function detectConstraints(text) {
|
|
158
158
|
return OVERRIDE_PATTERNS.filter(([, re]) => re.test(text)).map(([c]) => c);
|
|
159
159
|
}
|
|
160
160
|
const QUESTION_START = /^\s*(?:where|what|which|who|when|how\s+(?:does|do|is|are|can|should)|why|explain|describe|show\s+me|walk\s+me|is\s+there|are\s+there|can\s+you\s+(?:explain|tell|show)|tell\s+me|list|find)\b/i;
|
|
161
|
-
const IMPERATIVE_START = /^\s*(?:fix|add|implement|create|build|refactor|remove|delete|update|change|rename|write|make|migrate|upgrade|optimi[sz]e|release|publish|validate|ensure|prevent|enforce|guard|reject|restrict|handle|resolve|patch|repair|address|correct|replace|move|extract|rewrite|convert|improve|enable|disable|support|introduce|apply|configure|install|harden|secure|scope|isolate)\b/i;
|
|
161
|
+
const IMPERATIVE_START = /^\s*(?:fix|add|implement|create|build|refactor|remove|delete|update|change|rename|write|make|migrate|upgrade|optimi[sz]e|release|publish|validate|ensure|prevent|enforce|guard|reject|restrict|handle|resolve|patch|repair|address|correct|replace|move|extract|rewrite|convert|improve|enable|disable|support|introduce|apply|configure|install|harden|secure|scope|isolate|architect|design)\b/i;
|
|
162
162
|
/** A direct yes/no or open question: it ends in a question mark and does not start like an instruction. */
|
|
163
163
|
const DIRECT_QUESTION = /\?\s*$/;
|
|
164
|
+
/** Action-oriented release phrases where releasing is the primary engineering intent. */
|
|
165
|
+
const ACTIVE_RELEASE = /\b(?:prepare\s+release|cut\s+release|ready\s+release)\b|\b(?:release|publish|deploy|ship)\s+(?:the\s+)?(?:package|project|build|app|version|v\d+)\b|^\s*(?:release|publish|deploy|ship)\b|\brelease\s+(?:version\s+)?v?\d+/i;
|
|
164
166
|
/** Heuristic classifier used to propose a task type. The agent may override it; ambiguous input defaults to the safest (read-only) type. */
|
|
165
167
|
export function classifyRequest(text) {
|
|
166
168
|
const constraints = detectConstraints(text);
|
|
@@ -170,17 +172,17 @@ export function classifyRequest(text) {
|
|
|
170
172
|
type,
|
|
171
173
|
confidence,
|
|
172
174
|
constraints,
|
|
173
|
-
readOnly: WORKFLOWS[type].readOnly || constraints.includes('no-modify') || constraints.includes('plan-only'),
|
|
175
|
+
readOnly: WORKFLOWS[type].readOnly || constraints.includes('no-modify') || constraints.includes('plan-only') || constraints.includes('no-fix'),
|
|
174
176
|
});
|
|
175
177
|
if ((QUESTION_START.test(t) || DIRECT_QUESTION.test(t)) && !IMPERATIVE_START.test(t))
|
|
176
178
|
return make('QUESTION', 'high');
|
|
177
|
-
if (/\b(?:add|write|improve|increase)\s+(?:\w+\s+)?(?:unit\s+|e2e\s+|integration\s+)?tests?\b|\btest coverage\b|^\s*run\s+(?:the\s+|all\s+)?(?:\w+\s+)?tests?\b/i.test(t))
|
|
179
|
+
if (/\b(?:add|write|improve|increase)\s+(?:\w+\s+)?(?:unit\s+|e2e\s+|integration\s+|regression\s+|smoke\s+)?tests?\b|\btest coverage\b|^\s*run\s+(?:the\s+|all\s+)?(?:\w+\s+)?tests?\b|\b(?:mock|stub|fixture|fake|harness)\w*(?:\s+\w+)?\s+for\s+(?:\w+\s+)*tests?\b/i.test(t))
|
|
178
180
|
return make('TESTING', 'high');
|
|
179
|
-
if (/\b(?:upgrade|bump|update\s+dependenc\w*)\b/i.test(t))
|
|
181
|
+
if (/\b(?:upgrade|bump|update\s+(?:\w+\s+)?dependenc\w*)\b/i.test(t))
|
|
180
182
|
return make('MAINTENANCE', 'high');
|
|
181
183
|
if (/\b(?:vulnerab\w*|csrf|xss|sql injection|cve-\d+|cross-?tenant|tenant isolation|privilege escalation|idor)\b/i.test(t))
|
|
182
184
|
return make('SECURITY', 'high');
|
|
183
|
-
if (/\b(?:fix|bug|broken|crash(?:es|ing)?|regression|not working|fails?|failing|exception|error)\b/i.test(t))
|
|
185
|
+
if (/\b(?:fix|bug|broken|crash(?:es|ing)?|regression|not working|fails?|failing|exception|error|memory\s+leak|resource\s+leak|leak(?:s|ing)?|deadlock|infinite\s+loop)\b/i.test(t))
|
|
184
186
|
return make('BUG', 'high');
|
|
185
187
|
if (/\b(?:refactor|restructure|reorgani[sz]e|clean\s?up|simplify|de-?duplicate)\b/i.test(t))
|
|
186
188
|
return make('REFACTOR', 'high');
|
|
@@ -188,13 +190,15 @@ export function classifyRequest(text) {
|
|
|
188
190
|
return make('SECURITY', 'high');
|
|
189
191
|
if (/\b(?:performance|slow|latency|speed up|optimi[sz]e|throughput)\b/i.test(t))
|
|
190
192
|
return make('PERFORMANCE', 'high');
|
|
191
|
-
if (
|
|
193
|
+
if (ACTIVE_RELEASE.test(t))
|
|
194
|
+
return make('RELEASE', 'high');
|
|
195
|
+
if (/\b(?:document\w*|readme|docs?|changelog|jsdoc|docstring|guide)\b/i.test(t))
|
|
192
196
|
return make('DOCUMENTATION', 'high');
|
|
193
197
|
if (/\b(?:release|publish|deploy|ship|version bump)\b/i.test(t))
|
|
194
198
|
return make('RELEASE', 'high');
|
|
195
199
|
if (/\b(?:upgrade|bump|update\s+dependenc\w*|chore|lint(?:ing)?|format(?:ting)?)\b/i.test(t))
|
|
196
200
|
return make('MAINTENANCE', 'high');
|
|
197
|
-
if (/\b(?:redesign|re-?architect\w*|migrate\s+to|architecture)\b/i.test(t))
|
|
201
|
+
if (/\b(?:redesign|(?:re-?)?architect\w*|migrate\s+to|architecture)\b/i.test(t))
|
|
198
202
|
return make('ARCHITECTURE', 'high');
|
|
199
203
|
if (/\b(?:add|implement|create|build|support|introduce|enable|new)\b/i.test(t))
|
|
200
204
|
return make('FEATURE', 'high');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routing.js","sourceRoot":"","sources":["../../src/tasks/routing.ts"],"names":[],"mappings":"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","sourcesContent":["import type { TaskType } from './task.js';\n\nexport type Constraint = 'no-modify' | 'plan-only' | 'no-commit' | 'no-e2e' | 'no-tests' | 'no-fix';\n\nexport interface WorkflowSpec {\n type: TaskType;\n /** Highest context level normally needed (1 instructions … 6 tests/implementation). */\n contextDepth: 1 | 2 | 3 | 4 | 5 | 6;\n readOnly: boolean;\n trackTask: boolean;\n steps: string[];\n verification: string;\n agentSkills: string[];\n ponytail: string;\n knowledgeUpdate: string;\n}\n\n/** Single source of truth for routing. The generated Claude skill and docs/routing.md are rendered from this table. */\nexport const WORKFLOWS: Record<TaskType, WorkflowSpec> = {\n QUESTION: {\n type: 'QUESTION',\n contextDepth: 5,\n readOnly: true,\n trackTask: false,\n steps: [\n 'Read .devworkspace/context facts relevant to the topic (devworkspace context --topic <area>).',\n 'Use Graphify (if ready) or targeted search to locate the code; read only the files needed.',\n 'Answer with file references. State uncertainty explicitly.',\n ],\n verification: 'None. Do not modify files or run tests.',\n agentSkills: [],\n ponytail: 'Not used.',\n knowledgeUpdate: 'Only if you discovered a durable fact that is missing; record it with \"devworkspace fact add\".',\n },\n BUG: {\n type: 'BUG',\n contextDepth: 6,\n readOnly: false,\n trackTask: true,\n steps: [\n 'Check git status; protect uncommitted user changes.',\n 'Investigate and reproduce where practical.',\n 'Write a regression test and confirm it fails.',\n 'Fix the cause, confirm the test passes.',\n 'Run the applicable regression suite, then typecheck/lint/build as required by the testing contract.',\n 'Review the diff; record results with \"devworkspace task verify\".',\n ],\n verification: 'Regression test, applicable suite, typecheck, lint, build (whatever the testing contract marks required).',\n agentSkills: ['/test', '/review'],\n ponytail: 'Light review of the diff when review level is not \"off\".',\n knowledgeUpdate: 'Only if the bug revealed a persistent constraint or convention.',\n },\n FEATURE: {\n type: 'FEATURE',\n contextDepth: 6,\n readOnly: false,\n trackTask: true,\n steps: [\n 'Check git status. Read relevant facts and decisions.',\n 'Write acceptance criteria and a short plan (task update).',\n 'Write tests for the criteria, then implement.',\n 'Run targeted tests, then regression, then typecheck/lint/build.',\n 'Review the diff.',\n 'Update project knowledge for architecture, conventions or decisions that changed.',\n ],\n verification: 'Targeted tests, regression, typecheck, lint, build, review.',\n agentSkills: ['/spec', '/plan', '/build', '/test', '/review'],\n ponytail: 'Review for unnecessary complexity before completion.',\n knowledgeUpdate: 'Yes when the feature adds a module, integration, business rule or decision.',\n },\n REFACTOR: {\n type: 'REFACTOR',\n contextDepth: 6,\n readOnly: false,\n trackTask: true,\n steps: [\n 'Check git status. Analyse architecture, decisions and dependents (Graphify).',\n 'Record a baseline test result (devworkspace task tests --phase baseline).',\n 'Plan, then refactor in small verified steps.',\n 'Run targeted verification and the full regression suite; compare against the baseline.',\n 'Review the diff.',\n ],\n verification: 'Baseline vs after (no regressions), typecheck, lint, build, review.',\n agentSkills: ['/plan', '/code-simplify', '/review'],\n ponytail: 'Use for simplification review.',\n knowledgeUpdate: 'Yes if structure or conventions changed.',\n },\n DOCUMENTATION: {\n type: 'DOCUMENTATION',\n contextDepth: 4,\n readOnly: false,\n trackTask: false,\n steps: ['Read the code or facts being documented.', 'Edit documentation only.', 'Run documentation checks if the project has them (link or lint checks).'],\n verification: 'Only checks that apply to documentation.',\n agentSkills: [],\n ponytail: 'Not used.',\n knowledgeUpdate: 'Rarely.',\n },\n TESTING: {\n type: 'TESTING',\n contextDepth: 6,\n readOnly: false,\n trackTask: true,\n steps: ['Check git status.', 'Find existing test conventions.', 'Add tests; confirm they fail for the right reason where applicable.', 'Run the affected suite plus typecheck and lint.'],\n verification: 'Affected tests, typecheck, lint.',\n agentSkills: ['/test'],\n ponytail: 'Optional.',\n knowledgeUpdate: 'If the testing strategy or commands changed.',\n },\n PERFORMANCE: {\n type: 'PERFORMANCE',\n contextDepth: 6,\n readOnly: false,\n trackTask: true,\n steps: ['Measure first; record the baseline.', 'Change one thing at a time.', 'Re-measure and run the regression suite and build.', 'Review.'],\n verification: 'Before/after measurement, regression suite, build.',\n agentSkills: ['/webperf', '/review'],\n ponytail: 'Review for added complexity.',\n knowledgeUpdate: 'If a persistent constraint or decision emerged.',\n },\n SECURITY: {\n type: 'SECURITY',\n contextDepth: 6,\n readOnly: false,\n trackTask: true,\n steps: ['Check git status.', 'Understand the threat and the affected paths.', 'Test that demonstrates the issue, then fix.', 'Regression suite, typecheck, lint, build.', 'Security-focused review. Never print secret values.'],\n verification: 'Regression and exploit test, typecheck, lint, build, review.',\n agentSkills: ['/test', '/review'],\n ponytail: 'Use for bug and security review of the diff.',\n knowledgeUpdate: 'Yes for new security conventions or decisions.',\n },\n ARCHITECTURE: {\n type: 'ARCHITECTURE',\n contextDepth: 6,\n readOnly: false,\n trackTask: true,\n steps: ['Read facts, decisions and architecture notes; map structure with Graphify.', 'Present options and record the chosen one with \"devworkspace decision add\".', 'Plan and implement in verified steps.', 'Full verification and review.'],\n verification: 'Baseline vs after, typecheck, lint, build, review.',\n agentSkills: ['/spec', '/plan', '/build', '/review'],\n ponytail: 'Review for unnecessary abstraction.',\n knowledgeUpdate: 'Always: architecture notes and the decision record.',\n },\n RELEASE: {\n type: 'RELEASE',\n contextDepth: 6,\n readOnly: false,\n trackTask: true,\n steps: ['Check git status and branch.', 'Run the full testing contract including integration/e2e where available.', 'Update changelog and version per project convention.', 'Do not publish or push without explicit user authorisation.'],\n verification: 'Everything in the testing contract.',\n agentSkills: ['/ship'],\n ponytail: 'Optional final review.',\n knowledgeUpdate: 'If release process facts changed.',\n },\n MAINTENANCE: {\n type: 'MAINTENANCE',\n contextDepth: 4,\n readOnly: false,\n trackTask: true,\n steps: ['Check git status.', 'Make the change.', 'Run lint and build; run tests when behaviour could change.'],\n verification: 'Lint, build, tests if behaviour could change.',\n agentSkills: [],\n ponytail: 'Optional.',\n knowledgeUpdate: 'Only for changed commands or tooling.',\n },\n};\n\nconst OVERRIDE_PATTERNS: [Constraint, RegExp][] = [\n ['no-modify', /\\b(?:only|just)\\s+(?:explain|describe|investigate|look|read|review)\\b|\\b(?:do\\s*n[o']t|don'?t|never)\\s+(?:modify|change|edit|touch)\\b|\\bread[- ]only\\b|\\bno\\s+changes\\b/i],\n ['plan-only', /\\b(?:only|just)\\s+(?:make\\s+|write\\s+|give\\s+me\\s+)?a\\s+plan\\b|\\bplan\\s+only\\b/i],\n ['no-commit', /\\b(?:do\\s*n[o']t|don'?t|never)\\s+commit\\b|\\bno\\s+commits?\\b/i],\n ['no-e2e', /\\b(?:do\\s*n[o']t|don'?t|skip|no)\\s+(?:run\\s+)?(?:the\\s+)?(?:e2e|end[- ]to[- ]end)\\b/i],\n ['no-tests', /\\b(?:do\\s*n[o']t|don'?t|skip)\\s+(?:run\\s+)?(?:any\\s+|the\\s+)?tests\\b(?!\\s+but)/i],\n ['no-fix', /\\b(?:do\\s*n[o']t|don'?t)\\s+fix\\b|\\bwithout\\s+fixing\\b/i],\n];\n\nexport function detectConstraints(text: string): Constraint[] {\n return OVERRIDE_PATTERNS.filter(([, re]) => re.test(text)).map(([c]) => c);\n}\n\nexport interface Classification {\n type: TaskType;\n confidence: 'high' | 'low';\n constraints: Constraint[];\n /** True when the request must not change files (question type, or an explicit user override). */\n readOnly: boolean;\n}\n\nconst QUESTION_START = /^\\s*(?:where|what|which|who|when|how\\s+(?:does|do|is|are|can|should)|why|explain|describe|show\\s+me|walk\\s+me|is\\s+there|are\\s+there|can\\s+you\\s+(?:explain|tell|show)|tell\\s+me|list|find)\\b/i;\nconst IMPERATIVE_START =\n /^\\s*(?:fix|add|implement|create|build|refactor|remove|delete|update|change|rename|write|make|migrate|upgrade|optimi[sz]e|release|publish|validate|ensure|prevent|enforce|guard|reject|restrict|handle|resolve|patch|repair|address|correct|replace|move|extract|rewrite|convert|improve|enable|disable|support|introduce|apply|configure|install|harden|secure|scope|isolate)\\b/i;\n/** A direct yes/no or open question: it ends in a question mark and does not start like an instruction. */\nconst DIRECT_QUESTION = /\\?\\s*$/;\n\n/** Heuristic classifier used to propose a task type. The agent may override it; ambiguous input defaults to the safest (read-only) type. */\nexport function classifyRequest(text: string): Classification {\n const constraints = detectConstraints(text);\n // Negated phrases (\"don't fix anything\") describe limits, not the task itself.\n const t = OVERRIDE_PATTERNS.reduce((acc, [, re]) => acc.replace(new RegExp(re.source, re.flags + 'g'), ' '), text).trim();\n const make = (type: TaskType, confidence: 'high' | 'low'): Classification => ({\n type,\n confidence,\n constraints,\n readOnly: WORKFLOWS[type].readOnly || constraints.includes('no-modify') || constraints.includes('plan-only'),\n });\n if ((QUESTION_START.test(t) || DIRECT_QUESTION.test(t)) && !IMPERATIVE_START.test(t)) return make('QUESTION', 'high');\n if (/\\b(?:add|write|improve|increase)\\s+(?:\\w+\\s+)?(?:unit\\s+|e2e\\s+|integration\\s+)?tests?\\b|\\btest coverage\\b|^\\s*run\\s+(?:the\\s+|all\\s+)?(?:\\w+\\s+)?tests?\\b/i.test(t)) return make('TESTING', 'high');\n if (/\\b(?:upgrade|bump|update\\s+dependenc\\w*)\\b/i.test(t)) return make('MAINTENANCE', 'high');\n if (/\\b(?:vulnerab\\w*|csrf|xss|sql injection|cve-\\d+|cross-?tenant|tenant isolation|privilege escalation|idor)\\b/i.test(t)) return make('SECURITY', 'high');\n if (/\\b(?:fix|bug|broken|crash(?:es|ing)?|regression|not working|fails?|failing|exception|error)\\b/i.test(t)) return make('BUG', 'high');\n if (/\\b(?:refactor|restructure|reorgani[sz]e|clean\\s?up|simplify|de-?duplicate)\\b/i.test(t)) return make('REFACTOR', 'high');\n if (/\\b(?:vulnerab\\w*|security|csrf|xss|sql injection|sanitiz\\w*|harden\\w*|cve-\\d+|cross-?tenant|tenant isolation|ownership|authori[sz]ation|privilege escalation|idor)\\b/i.test(t)) return make('SECURITY', 'high');\n if (/\\b(?:performance|slow|latency|speed up|optimi[sz]e|throughput)\\b/i.test(t)) return make('PERFORMANCE', 'high');\n if (/\\b(?:document|readme|docs|changelog|jsdoc|docstring)\\b/i.test(t)) return make('DOCUMENTATION', 'high');\n if (/\\b(?:release|publish|deploy|ship|version bump)\\b/i.test(t)) return make('RELEASE', 'high');\n if (/\\b(?:upgrade|bump|update\\s+dependenc\\w*|chore|lint(?:ing)?|format(?:ting)?)\\b/i.test(t)) return make('MAINTENANCE', 'high');\n if (/\\b(?:redesign|re-?architect\\w*|migrate\\s+to|architecture)\\b/i.test(t)) return make('ARCHITECTURE', 'high');\n if (/\\b(?:add|implement|create|build|support|introduce|enable|new)\\b/i.test(t)) return make('FEATURE', 'high');\n // An instruction we cannot place is still a request to change something. Never default it to a read-only question.\n if (IMPERATIVE_START.test(t)) return make('FEATURE', 'low');\n return make('QUESTION', 'low');\n}\n\nexport function renderRoutingTable(): string {\n const rows = (Object.values(WORKFLOWS) as WorkflowSpec[]).map((w) => {\n const flags = [w.readOnly ? 'read-only' : 'modifies code', w.trackTask ? 'tracked task' : 'no task file'].join(', ');\n return `| ${w.type} | ${flags} | L${w.contextDepth} | ${w.verification} |`;\n });\n return ['| Type | Nature | Max context | Verification |', '| --- | --- | --- | --- |', ...rows].join('\\n');\n}\n"]}
|
|
1
|
+
{"version":3,"file":"routing.js","sourceRoot":"","sources":["../../src/tasks/routing.ts"],"names":[],"mappings":"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","sourcesContent":["import type { TaskType } from './task.js';\n\nexport type Constraint = 'no-modify' | 'plan-only' | 'no-commit' | 'no-e2e' | 'no-tests' | 'no-fix';\n\nexport interface WorkflowSpec {\n type: TaskType;\n /** Highest context level normally needed (1 instructions … 6 tests/implementation). */\n contextDepth: 1 | 2 | 3 | 4 | 5 | 6;\n readOnly: boolean;\n trackTask: boolean;\n steps: string[];\n verification: string;\n agentSkills: string[];\n ponytail: string;\n knowledgeUpdate: string;\n}\n\n/** Single source of truth for routing. The generated Claude skill and docs/routing.md are rendered from this table. */\nexport const WORKFLOWS: Record<TaskType, WorkflowSpec> = {\n QUESTION: {\n type: 'QUESTION',\n contextDepth: 5,\n readOnly: true,\n trackTask: false,\n steps: [\n 'Read .devworkspace/context facts relevant to the topic (devworkspace context --topic <area>).',\n 'Use Graphify (if ready) or targeted search to locate the code; read only the files needed.',\n 'Answer with file references. State uncertainty explicitly.',\n ],\n verification: 'None. Do not modify files or run tests.',\n agentSkills: [],\n ponytail: 'Not used.',\n knowledgeUpdate: 'Only if you discovered a durable fact that is missing; record it with \"devworkspace fact add\".',\n },\n BUG: {\n type: 'BUG',\n contextDepth: 6,\n readOnly: false,\n trackTask: true,\n steps: [\n 'Check git status; protect uncommitted user changes.',\n 'Investigate and reproduce where practical.',\n 'Write a regression test and confirm it fails.',\n 'Fix the cause, confirm the test passes.',\n 'Run the applicable regression suite, then typecheck/lint/build as required by the testing contract.',\n 'Review the diff; record results with \"devworkspace task verify\".',\n ],\n verification: 'Regression test, applicable suite, typecheck, lint, build (whatever the testing contract marks required).',\n agentSkills: ['/test', '/review'],\n ponytail: 'Light review of the diff when review level is not \"off\".',\n knowledgeUpdate: 'Only if the bug revealed a persistent constraint or convention.',\n },\n FEATURE: {\n type: 'FEATURE',\n contextDepth: 6,\n readOnly: false,\n trackTask: true,\n steps: [\n 'Check git status. Read relevant facts and decisions.',\n 'Write acceptance criteria and a short plan (task update).',\n 'Write tests for the criteria, then implement.',\n 'Run targeted tests, then regression, then typecheck/lint/build.',\n 'Review the diff.',\n 'Update project knowledge for architecture, conventions or decisions that changed.',\n ],\n verification: 'Targeted tests, regression, typecheck, lint, build, review.',\n agentSkills: ['/spec', '/plan', '/build', '/test', '/review'],\n ponytail: 'Review for unnecessary complexity before completion.',\n knowledgeUpdate: 'Yes when the feature adds a module, integration, business rule or decision.',\n },\n REFACTOR: {\n type: 'REFACTOR',\n contextDepth: 6,\n readOnly: false,\n trackTask: true,\n steps: [\n 'Check git status. Analyse architecture, decisions and dependents (Graphify).',\n 'Record a baseline test result (devworkspace task tests --phase baseline).',\n 'Plan, then refactor in small verified steps.',\n 'Run targeted verification and the full regression suite; compare against the baseline.',\n 'Review the diff.',\n ],\n verification: 'Baseline vs after (no regressions), typecheck, lint, build, review.',\n agentSkills: ['/plan', '/code-simplify', '/review'],\n ponytail: 'Use for simplification review.',\n knowledgeUpdate: 'Yes if structure or conventions changed.',\n },\n DOCUMENTATION: {\n type: 'DOCUMENTATION',\n contextDepth: 4,\n readOnly: false,\n trackTask: false,\n steps: ['Read the code or facts being documented.', 'Edit documentation only.', 'Run documentation checks if the project has them (link or lint checks).'],\n verification: 'Only checks that apply to documentation.',\n agentSkills: [],\n ponytail: 'Not used.',\n knowledgeUpdate: 'Rarely.',\n },\n TESTING: {\n type: 'TESTING',\n contextDepth: 6,\n readOnly: false,\n trackTask: true,\n steps: ['Check git status.', 'Find existing test conventions.', 'Add tests; confirm they fail for the right reason where applicable.', 'Run the affected suite plus typecheck and lint.'],\n verification: 'Affected tests, typecheck, lint.',\n agentSkills: ['/test'],\n ponytail: 'Optional.',\n knowledgeUpdate: 'If the testing strategy or commands changed.',\n },\n PERFORMANCE: {\n type: 'PERFORMANCE',\n contextDepth: 6,\n readOnly: false,\n trackTask: true,\n steps: ['Measure first; record the baseline.', 'Change one thing at a time.', 'Re-measure and run the regression suite and build.', 'Review.'],\n verification: 'Before/after measurement, regression suite, build.',\n agentSkills: ['/webperf', '/review'],\n ponytail: 'Review for added complexity.',\n knowledgeUpdate: 'If a persistent constraint or decision emerged.',\n },\n SECURITY: {\n type: 'SECURITY',\n contextDepth: 6,\n readOnly: false,\n trackTask: true,\n steps: ['Check git status.', 'Understand the threat and the affected paths.', 'Test that demonstrates the issue, then fix.', 'Regression suite, typecheck, lint, build.', 'Security-focused review. Never print secret values.'],\n verification: 'Regression and exploit test, typecheck, lint, build, review.',\n agentSkills: ['/test', '/review'],\n ponytail: 'Use for bug and security review of the diff.',\n knowledgeUpdate: 'Yes for new security conventions or decisions.',\n },\n ARCHITECTURE: {\n type: 'ARCHITECTURE',\n contextDepth: 6,\n readOnly: false,\n trackTask: true,\n steps: ['Read facts, decisions and architecture notes; map structure with Graphify.', 'Present options and record the chosen one with \"devworkspace decision add\".', 'Plan and implement in verified steps.', 'Full verification and review.'],\n verification: 'Baseline vs after, typecheck, lint, build, review.',\n agentSkills: ['/spec', '/plan', '/build', '/review'],\n ponytail: 'Review for unnecessary abstraction.',\n knowledgeUpdate: 'Always: architecture notes and the decision record.',\n },\n RELEASE: {\n type: 'RELEASE',\n contextDepth: 6,\n readOnly: false,\n trackTask: true,\n steps: ['Check git status and branch.', 'Run the full testing contract including integration/e2e where available.', 'Update changelog and version per project convention.', 'Do not publish or push without explicit user authorisation.'],\n verification: 'Everything in the testing contract.',\n agentSkills: ['/ship'],\n ponytail: 'Optional final review.',\n knowledgeUpdate: 'If release process facts changed.',\n },\n MAINTENANCE: {\n type: 'MAINTENANCE',\n contextDepth: 4,\n readOnly: false,\n trackTask: true,\n steps: ['Check git status.', 'Make the change.', 'Run lint and build; run tests when behaviour could change.'],\n verification: 'Lint, build, tests if behaviour could change.',\n agentSkills: [],\n ponytail: 'Optional.',\n knowledgeUpdate: 'Only for changed commands or tooling.',\n },\n};\n\nconst OVERRIDE_PATTERNS: [Constraint, RegExp][] = [\n ['no-modify', /\\b(?:only|just)\\s+(?:explain|describe|investigate|look|read|review)\\b|\\b(?:do\\s*n[o']t|don'?t|never|without)\\s+(?:modify|modifying|change|changing|edit|editing|touch|touching)\\b|\\bread[- ]only\\b|\\bno\\s+changes\\b/i],\n ['plan-only', /\\b(?:only|just)\\s+(?:make\\s+|write\\s+|give\\s+me\\s+)?a\\s+plan\\b|\\bplan\\s+only\\b|\\bwithout\\s+implementing(?:\\s+it)?\\b/i],\n ['no-commit', /\\b(?:do\\s*n[o']t|don'?t|never)\\s+commit\\b|\\bno\\s+commits?\\b/i],\n ['no-e2e', /\\b(?:do\\s*n[o']t|don'?t|skip|no)\\s+(?:run\\s+)?(?:the\\s+)?(?:e2e|end[- ]to[- ]end)\\b/i],\n ['no-tests', /\\b(?:do\\s*n[o']t|don'?t|skip)\\s+(?:run\\s+)?(?:any\\s+|the\\s+)?tests\\b(?!\\s+but)/i],\n ['no-fix', /\\b(?:do\\s*n[o']t|don'?t|never)\\s+fix\\b|\\bwithout\\s+fixing\\b|\\bno[- ]fix\\b/i],\n];\n\nexport function detectConstraints(text: string): Constraint[] {\n return OVERRIDE_PATTERNS.filter(([, re]) => re.test(text)).map(([c]) => c);\n}\n\nexport interface Classification {\n type: TaskType;\n confidence: 'high' | 'low';\n constraints: Constraint[];\n /** True when the request must not change files (question type, or an explicit user override). */\n readOnly: boolean;\n}\n\nconst QUESTION_START = /^\\s*(?:where|what|which|who|when|how\\s+(?:does|do|is|are|can|should)|why|explain|describe|show\\s+me|walk\\s+me|is\\s+there|are\\s+there|can\\s+you\\s+(?:explain|tell|show)|tell\\s+me|list|find)\\b/i;\nconst IMPERATIVE_START =\n /^\\s*(?:fix|add|implement|create|build|refactor|remove|delete|update|change|rename|write|make|migrate|upgrade|optimi[sz]e|release|publish|validate|ensure|prevent|enforce|guard|reject|restrict|handle|resolve|patch|repair|address|correct|replace|move|extract|rewrite|convert|improve|enable|disable|support|introduce|apply|configure|install|harden|secure|scope|isolate|architect|design)\\b/i;\n/** A direct yes/no or open question: it ends in a question mark and does not start like an instruction. */\nconst DIRECT_QUESTION = /\\?\\s*$/;\n/** Action-oriented release phrases where releasing is the primary engineering intent. */\nconst ACTIVE_RELEASE = /\\b(?:prepare\\s+release|cut\\s+release|ready\\s+release)\\b|\\b(?:release|publish|deploy|ship)\\s+(?:the\\s+)?(?:package|project|build|app|version|v\\d+)\\b|^\\s*(?:release|publish|deploy|ship)\\b|\\brelease\\s+(?:version\\s+)?v?\\d+/i;\n\n/** Heuristic classifier used to propose a task type. The agent may override it; ambiguous input defaults to the safest (read-only) type. */\nexport function classifyRequest(text: string): Classification {\n const constraints = detectConstraints(text);\n // Negated phrases (\"don't fix anything\") describe limits, not the task itself.\n const t = OVERRIDE_PATTERNS.reduce((acc, [, re]) => acc.replace(new RegExp(re.source, re.flags + 'g'), ' '), text).trim();\n const make = (type: TaskType, confidence: 'high' | 'low'): Classification => ({\n type,\n confidence,\n constraints,\n readOnly: WORKFLOWS[type].readOnly || constraints.includes('no-modify') || constraints.includes('plan-only') || constraints.includes('no-fix'),\n });\n if ((QUESTION_START.test(t) || DIRECT_QUESTION.test(t)) && !IMPERATIVE_START.test(t)) return make('QUESTION', 'high');\n if (/\\b(?:add|write|improve|increase)\\s+(?:\\w+\\s+)?(?:unit\\s+|e2e\\s+|integration\\s+|regression\\s+|smoke\\s+)?tests?\\b|\\btest coverage\\b|^\\s*run\\s+(?:the\\s+|all\\s+)?(?:\\w+\\s+)?tests?\\b|\\b(?:mock|stub|fixture|fake|harness)\\w*(?:\\s+\\w+)?\\s+for\\s+(?:\\w+\\s+)*tests?\\b/i.test(t)) return make('TESTING', 'high');\n if (/\\b(?:upgrade|bump|update\\s+(?:\\w+\\s+)?dependenc\\w*)\\b/i.test(t)) return make('MAINTENANCE', 'high');\n if (/\\b(?:vulnerab\\w*|csrf|xss|sql injection|cve-\\d+|cross-?tenant|tenant isolation|privilege escalation|idor)\\b/i.test(t)) return make('SECURITY', 'high');\n if (/\\b(?:fix|bug|broken|crash(?:es|ing)?|regression|not working|fails?|failing|exception|error|memory\\s+leak|resource\\s+leak|leak(?:s|ing)?|deadlock|infinite\\s+loop)\\b/i.test(t)) return make('BUG', 'high');\n if (/\\b(?:refactor|restructure|reorgani[sz]e|clean\\s?up|simplify|de-?duplicate)\\b/i.test(t)) return make('REFACTOR', 'high');\n if (/\\b(?:vulnerab\\w*|security|csrf|xss|sql injection|sanitiz\\w*|harden\\w*|cve-\\d+|cross-?tenant|tenant isolation|ownership|authori[sz]ation|privilege escalation|idor)\\b/i.test(t)) return make('SECURITY', 'high');\n if (/\\b(?:performance|slow|latency|speed up|optimi[sz]e|throughput)\\b/i.test(t)) return make('PERFORMANCE', 'high');\n if (ACTIVE_RELEASE.test(t)) return make('RELEASE', 'high');\n if (/\\b(?:document\\w*|readme|docs?|changelog|jsdoc|docstring|guide)\\b/i.test(t)) return make('DOCUMENTATION', 'high');\n if (/\\b(?:release|publish|deploy|ship|version bump)\\b/i.test(t)) return make('RELEASE', 'high');\n if (/\\b(?:upgrade|bump|update\\s+dependenc\\w*|chore|lint(?:ing)?|format(?:ting)?)\\b/i.test(t)) return make('MAINTENANCE', 'high');\n if (/\\b(?:redesign|(?:re-?)?architect\\w*|migrate\\s+to|architecture)\\b/i.test(t)) return make('ARCHITECTURE', 'high');\n if (/\\b(?:add|implement|create|build|support|introduce|enable|new)\\b/i.test(t)) return make('FEATURE', 'high');\n // An instruction we cannot place is still a request to change something. Never default it to a read-only question.\n if (IMPERATIVE_START.test(t)) return make('FEATURE', 'low');\n return make('QUESTION', 'low');\n}\n\nexport function renderRoutingTable(): string {\n const rows = (Object.values(WORKFLOWS) as WorkflowSpec[]).map((w) => {\n const flags = [w.readOnly ? 'read-only' : 'modifies code', w.trackTask ? 'tracked task' : 'no task file'].join(', ');\n return `| ${w.type} | ${flags} | L${w.contextDepth} | ${w.verification} |`;\n });\n return ['| Type | Nature | Max context | Verification |', '| --- | --- | --- | --- |', ...rows].join('\\n');\n}\n"]}
|
package/dist/tasks/task.js
CHANGED
|
@@ -219,7 +219,11 @@ export function evaluateGate(task, ctx) {
|
|
|
219
219
|
if (after.passed < baseline.passed)
|
|
220
220
|
failures.push(`regression: passing tests fell from ${baseline.passed} to ${after.passed}`);
|
|
221
221
|
}
|
|
222
|
-
|
|
222
|
+
const isReadOnly = task.constraints?.some((c) => c === 'no-modify' || c === 'no-fix' || c === 'plan-only');
|
|
223
|
+
if (isReadOnly && ctx?.scope && Object.keys(ctx.scope).length > 0) {
|
|
224
|
+
failures.push('files were modified despite read-only constraint (no-modify, no-fix, or plan-only)');
|
|
225
|
+
}
|
|
226
|
+
if (isCodeChanging(task.type) && !isReadOnly) {
|
|
223
227
|
if (!task.attestations.userWorkIntact)
|
|
224
228
|
failures.push('not confirmed: no user work was overwritten');
|
|
225
229
|
if (!task.attestations.knowledgeReviewed)
|
|
@@ -227,7 +231,7 @@ export function evaluateGate(task, ctx) {
|
|
|
227
231
|
if (!task.attestations.finalStateInspected)
|
|
228
232
|
failures.push('not confirmed: final repository state was inspected');
|
|
229
233
|
}
|
|
230
|
-
if ((isCodeChanging(task.type) || task.type === 'DOCUMENTATION') && !(task.completionSummary ?? '').trim()) {
|
|
234
|
+
if ((isCodeChanging(task.type) || task.type === 'DOCUMENTATION' || isReadOnly) && !(task.completionSummary ?? '').trim()) {
|
|
231
235
|
failures.push('completion summary is missing');
|
|
232
236
|
}
|
|
233
237
|
return { ok: failures.length === 0, failures, warnings };
|