devworkspace 0.3.0 → 0.3.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.
- package/CHANGELOG.md +42 -1
- package/README.md +8 -5
- 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/args.d.ts +42 -0
- package/dist/cli/args.js +12 -0
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/help.js +64 -10
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/render.d.ts +12 -1
- package/dist/cli/render.js +188 -0
- package/dist/cli/render.js.map +1 -1
- package/dist/cli/run.js +100 -9
- package/dist/cli/run.js.map +1 -1
- package/dist/config/schemas.d.ts +6 -0
- package/dist/config/schemas.js +6 -0
- package/dist/config/schemas.js.map +1 -1
- package/dist/core/version.d.ts +7 -0
- package/dist/core/version.js +13 -0
- package/dist/core/version.js.map +1 -1
- package/dist/core/workspace.d.ts +1 -0
- package/dist/core/workspace.js +1 -0
- package/dist/core/workspace.js.map +1 -1
- package/dist/discovery/commands.d.ts +1 -0
- package/dist/discovery/commands.js +3 -1
- package/dist/discovery/commands.js.map +1 -1
- package/dist/features/schema.d.ts +3 -0
- package/dist/features/schema.js +79 -0
- package/dist/features/schema.js.map +1 -0
- package/dist/features/types.d.ts +77 -0
- package/dist/features/types.js +2 -0
- package/dist/features/types.js.map +1 -0
- package/dist/features/validate.d.ts +14 -0
- package/dist/features/validate.js +124 -0
- package/dist/features/validate.js.map +1 -0
- package/dist/index.d.ts +8 -2
- package/dist/index.js +4 -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 +65 -14
- package/dist/services/doctor.js.map +1 -1
- package/dist/services/drift.d.ts +21 -0
- package/dist/services/drift.js +89 -0
- package/dist/services/drift.js.map +1 -0
- package/dist/services/features.d.ts +22 -0
- package/dist/services/features.js +105 -0
- package/dist/services/features.js.map +1 -0
- package/dist/services/graph.d.ts +97 -0
- package/dist/services/graph.js +342 -0
- package/dist/services/graph.js.map +1 -0
- package/dist/services/refresh.js +15 -0
- package/dist/services/refresh.js.map +1 -1
- package/dist/services/reset.js +45 -5
- package/dist/services/reset.js.map +1 -1
- package/dist/services/setup.d.ts +56 -0
- package/dist/services/setup.js +116 -0
- package/dist/services/setup.js.map +1 -0
- package/dist/services/status.d.ts +8 -0
- package/dist/services/status.js +78 -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/services/verify.d.ts +11 -0
- package/dist/services/verify.js +64 -2
- package/dist/services/verify.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-report/01-executive-summary.md +168 -0
- package/docs/architecture-report/02-system-architecture.md +356 -0
- package/docs/architecture-report/03-tools-and-technologies.md +112 -0
- package/docs/architecture-report/04-execution-flows.md +257 -0
- package/docs/architecture-report/05-codebase-map.md +150 -0
- package/docs/architecture-report/06-command-reference.md +446 -0
- package/docs/architecture-report/07-data-flow-and-integrations.md +268 -0
- package/docs/architecture-report/08-build-test-deployment.md +185 -0
- package/docs/architecture-report/09-security-and-reliability.md +165 -0
- package/docs/architecture-report/10-feature-status.md +110 -0
- package/docs/architecture-report/11-glossary.md +97 -0
- package/docs/architecture-report/README.md +103 -0
- package/docs/architecture-report/diagrams.md +446 -0
- package/docs/architecture.md +2 -2
- package/docs/getting-started.md +38 -1
- package/package.json +1 -1
|
@@ -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"]}
|
|
@@ -22,6 +22,17 @@ export interface RunCheckResult {
|
|
|
22
22
|
check: string;
|
|
23
23
|
runs: PackageRun[];
|
|
24
24
|
}
|
|
25
|
+
/** Check if a contract check represents an automated test suite. */
|
|
26
|
+
export declare function isTestCommand(id: string, command: string): boolean;
|
|
27
|
+
export interface ZeroTestResult {
|
|
28
|
+
isZeroTests: boolean;
|
|
29
|
+
reason?: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Detects known zero-test execution signatures from test runners (Vitest, Jest, Pytest, Mocha, Go, Cargo).
|
|
33
|
+
* Prevents commands that exit with code 0 because no tests were found (e.g. --passWithNoTests) from falsely passing.
|
|
34
|
+
*/
|
|
35
|
+
export declare function detectZeroTests(command: string, stdout: string, stderr: string): ZeroTestResult;
|
|
25
36
|
export declare function splitCommand(command: string): string[] | null;
|
|
26
37
|
/**
|
|
27
38
|
* PATH lookup on Windows finds the extensionless Unix shell script (`npm`) before `npm.cmd`, and that cannot be
|
package/dist/services/verify.js
CHANGED
|
@@ -21,6 +21,60 @@ export async function gateContext(ws, task, contract) {
|
|
|
21
21
|
const scope = task.scope ? scopeByPackage(await changedSince(ws.root, task.scope), checks) : null;
|
|
22
22
|
return { contract: checks, scope };
|
|
23
23
|
}
|
|
24
|
+
/** Check if a contract check represents an automated test suite. */
|
|
25
|
+
export function isTestCommand(id, command) {
|
|
26
|
+
if (id === 'unit' || id === 'integration' || id === 'e2e' || id === 'security')
|
|
27
|
+
return true;
|
|
28
|
+
return /\b(test|vitest|jest|pytest|playwright|cypress|mocha|ava|tap)\b/i.test(command);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Detects known zero-test execution signatures from test runners (Vitest, Jest, Pytest, Mocha, Go, Cargo).
|
|
32
|
+
* Prevents commands that exit with code 0 because no tests were found (e.g. --passWithNoTests) from falsely passing.
|
|
33
|
+
*/
|
|
34
|
+
export function detectZeroTests(command, stdout, stderr) {
|
|
35
|
+
const combined = `${stdout}\n${stderr}`;
|
|
36
|
+
const hasPassWithNoTests = /--passWithNoTests\b|--pass-with-no-tests\b/i.test(command);
|
|
37
|
+
// 1. Vitest zero-test patterns
|
|
38
|
+
if (/No test files found/i.test(combined)) {
|
|
39
|
+
return { isZeroTests: true, reason: 'Vitest reported no test files found' };
|
|
40
|
+
}
|
|
41
|
+
if (/Test Files\s+0\s+passed\s*\(0\)/i.test(combined) || /Test Files\s+0\s+failed\s*\(0\)/i.test(combined)) {
|
|
42
|
+
return { isZeroTests: true, reason: 'Vitest ran 0 test files' };
|
|
43
|
+
}
|
|
44
|
+
if (/Tests\s+0\s+passed\s*\(0\)/i.test(combined) && !/Tests\s+[1-9]\d*\s+passed/i.test(combined)) {
|
|
45
|
+
return { isZeroTests: true, reason: 'Vitest ran 0 tests' };
|
|
46
|
+
}
|
|
47
|
+
// 2. Jest zero-test patterns
|
|
48
|
+
if (/Ran all test suites matching.*No tests found/i.test(combined)) {
|
|
49
|
+
return { isZeroTests: true, reason: 'Jest found no test suites matching path' };
|
|
50
|
+
}
|
|
51
|
+
if (/Test Suites:\s*0\s*(?:passed,\s*)?0\s*total/i.test(combined) || /Test Suites:\s*0\s*total/i.test(combined)) {
|
|
52
|
+
return { isZeroTests: true, reason: 'Jest ran 0 test suites' };
|
|
53
|
+
}
|
|
54
|
+
if (/Tests:\s*0\s*(?:passed,\s*)?0\s*total/i.test(combined) || /Tests:\s*0\s*total/i.test(combined)) {
|
|
55
|
+
return { isZeroTests: true, reason: 'Jest ran 0 tests' };
|
|
56
|
+
}
|
|
57
|
+
// 3. Pytest zero-test patterns
|
|
58
|
+
if (/collected 0 items/i.test(combined) || /no tests ran in/i.test(combined)) {
|
|
59
|
+
return { isZeroTests: true, reason: 'Pytest collected and ran 0 items' };
|
|
60
|
+
}
|
|
61
|
+
// 4. Mocha / Node test runner zero-test patterns
|
|
62
|
+
if (/\b0 passing\b/i.test(combined) && !/[1-9]\d*\s+passing\b/i.test(combined)) {
|
|
63
|
+
return { isZeroTests: true, reason: 'Mocha reported 0 passing tests' };
|
|
64
|
+
}
|
|
65
|
+
// 5. Go / Cargo / other zero-test patterns
|
|
66
|
+
if (/\[no test files\]/i.test(combined)) {
|
|
67
|
+
return { isZeroTests: true, reason: 'Go test reported [no test files]' };
|
|
68
|
+
}
|
|
69
|
+
if (/running 0 tests/i.test(combined) && !/running [1-9]\d* tests/i.test(combined)) {
|
|
70
|
+
return { isZeroTests: true, reason: 'Cargo test ran 0 tests' };
|
|
71
|
+
}
|
|
72
|
+
// 6. Explicit passWithNoTests with no tests indicated
|
|
73
|
+
if (hasPassWithNoTests && (/no tests\b/i.test(combined) || /0 tests\b/i.test(combined) || /0 total\b/i.test(combined))) {
|
|
74
|
+
return { isZeroTests: true, reason: 'Command used --passWithNoTests and executed 0 tests' };
|
|
75
|
+
}
|
|
76
|
+
return { isZeroTests: false };
|
|
77
|
+
}
|
|
24
78
|
/** Anything a shell would interpret. Contract commands are run as an argument vector, never through a shell. */
|
|
25
79
|
const SHELL_SYNTAX = /[&|;<>$`(){}"'\\*?!%^\r\n]/;
|
|
26
80
|
export function splitCommand(command) {
|
|
@@ -102,8 +156,16 @@ export async function runTaskCheck(o, id, check, opts = {}) {
|
|
|
102
156
|
runs.push({ ...base, outcome: 'refused', safety: cls.safety, reason: `could not start: ${scrub(r.error)}` });
|
|
103
157
|
continue;
|
|
104
158
|
}
|
|
105
|
-
const
|
|
106
|
-
|
|
159
|
+
const zeroTestResult = isTestCommand(entry.id, entry.command ?? '')
|
|
160
|
+
? detectZeroTests(entry.command ?? '', r.stdout, r.stderr)
|
|
161
|
+
: { isZeroTests: false };
|
|
162
|
+
const isVacuous = r.ok && r.code === 0 && zeroTestResult.isZeroTests;
|
|
163
|
+
const passed = r.ok && r.code === 0 && !isVacuous;
|
|
164
|
+
const tail = !passed
|
|
165
|
+
? isVacuous
|
|
166
|
+
? `vacuous test pass: command exited with code 0 but executed 0 tests (${zeroTestResult.reason})`
|
|
167
|
+
: scrub((r.error ?? '') || (r.timedOut ? 'timed out' : '') || r.stderr.slice(-300) || r.stdout.slice(-300) || `exit ${r.code}`)
|
|
168
|
+
: undefined;
|
|
107
169
|
runs.push({ ...base, outcome: passed ? 'passed' : 'failed', safety: cls.safety, exitCode: r.code, durationMs, ...(tail ? { reason: tail } : {}) });
|
|
108
170
|
evidence.push({ kind: 'executed', at: isoNow(o), package: pkg, command: entry.command ?? undefined, exitCode: r.code, durationMs, scope: fingerprint ?? 'unknown', ...(tail ? { note: tail } : {}) });
|
|
109
171
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verify.js","sourceRoot":"","sources":["../../src/services/verify.ts"],"names":[],"mappings":"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","sourcesContent":["import path from 'node:path';\nimport { SCHEMA_VERSION, validateCommands, type CommandEntry } from '../config/schemas.js';\nimport { requireWorkspace, type Ws } from '../core/workspace.js';\nimport { readVersioned } from '../core/versioned.js';\nimport { DevWorkspaceError } from '../errors/index.js';\nimport { createRunner } from '../integrations/exec.js';\nimport { scrub } from '../integrations/manager.js';\nimport { loadTask, saveTask, type Evidence, type GateContext, type Task, type VerificationItem, type VerifyStatus, assertNoSecrets } from '../tasks/task.js';\nimport { pathExists } from '../utils/fs.js';\nimport { classifyCommand, isDeclared, loadTestEnv, readManifestEvidence, assertSafeTarget, removeDeclaration, saveDeclaration, type CommandSafety, type TestEnvDeclaration } from '../verification/safety.js';\nimport { changedSince, scopeByPackage } from '../verification/scope.js';\nimport { isoNow, mutate, type ServiceOptions } from './common.js';\n\nexport async function loadContract(ws: Ws): Promise<CommandEntry[]> {\n if (!(await pathExists(ws.commands))) return [];\n return (await readVersioned(ws.commands, 'commands', SCHEMA_VERSION, validateCommands)).data.checks;\n}\n\n/** Contract plus what the task has changed per package: everything the completion gate needs to judge it. */\nexport async function gateContext(ws: Ws, task: Task, contract?: CommandEntry[]): Promise<GateContext> {\n const checks = contract ?? (await loadContract(ws));\n const scope = task.scope ? scopeByPackage(await changedSince(ws.root, task.scope), checks) : null;\n return { contract: checks, scope };\n}\n\nexport type RunOutcome = 'passed' | 'failed' | 'refused' | 'not-affected';\n\nexport interface PackageRun {\n package: string;\n command: string | null;\n outcome: RunOutcome;\n exitCode?: number | null;\n durationMs?: number;\n /** Why DevWorkspace did not run it, or the scrubbed tail of a failure. */\n reason?: string;\n safety: CommandSafety['safety'];\n}\n\nexport interface RunCheckResult {\n task: Task;\n check: string;\n runs: PackageRun[];\n}\n\n/** Anything a shell would interpret. Contract commands are run as an argument vector, never through a shell. */\nconst SHELL_SYNTAX = /[&|;<>$`(){}\"'\\\\*?!%^\\r\\n]/;\n\nexport function splitCommand(command: string): string[] | null {\n if (SHELL_SYNTAX.test(command)) return null;\n const parts = command.trim().split(/\\s+/);\n return parts[0] ? parts : null;\n}\n\nconst DEFAULT_TIMEOUT_MS = 10 * 60_000;\n\n/**\n * PATH lookup on Windows finds the extensionless Unix shell script (`npm`) before `npm.cmd`, and that cannot be\n * spawned. Prefer the Windows launcher next to it. Elsewhere the lookup result is used as is.\n */\nexport async function resolveExecutable(found: string | null, name: string, platform: NodeJS.Platform, exists: (p: string) => Promise<boolean>): Promise<string> {\n if (!found) return name;\n if (platform !== 'win32' || /\\.(?:exe|cmd|bat|com)$/i.test(found)) return found;\n for (const ext of ['.cmd', '.exe', '.bat']) if (await exists(found + ext)) return found + ext;\n return found;\n}\n\n/**\n * Run one contract check for the packages the task changed, and record what really happened. DevWorkspace only runs\n * read-only, non-destructive commands; anything that may touch a database runs only after the user declared a test\n * environment for that package and check. Refusals are recorded as \"could not run\", never as a pass.\n */\nexport async function runTaskCheck(o: ServiceOptions, id: string, check: string, opts: { package?: string; timeoutMs?: number } = {}): Promise<RunCheckResult> {\n const ws = await requireWorkspace(o.cwd);\n const task = await loadTask(ws, id);\n const contract = await loadContract(ws);\n const wanted = opts.package ? (opts.package === '.' || opts.package === '' ? '.' : opts.package.replace(/\\/+$/, '')) : undefined;\n const entries = contract.filter((c) => c.id === check && c.available && (wanted === undefined || (c.cwd ?? '.') === wanted));\n if (entries.length === 0) {\n throw new DevWorkspaceError('NOT_FOUND', `The testing contract has no \"${check}\" command${wanted ? ` for package \"${wanted}\"` : ''}.`, {\n hint: 'See the contract with \"devworkspace context\", or add the command to .devworkspace/context/commands.json.',\n });\n }\n const scope = (await gateContext(ws, task, contract)).scope;\n const decls = await loadTestEnv(ws);\n const runner = o.runner ?? createRunner(o.env ?? process.env, o.platform);\n const runs: PackageRun[] = [];\n const evidence: Evidence[] = [];\n\n for (const entry of entries) {\n const pkg = entry.cwd ?? '.';\n const base = { package: pkg, command: entry.command };\n const fingerprint = scope === null ? 'unknown' : scope[pkg];\n if (wanted === undefined && fingerprint === undefined) {\n runs.push({ ...base, outcome: 'not-affected', safety: 'safe', reason: 'the task changed nothing in this package' });\n continue;\n }\n const manifest = await readManifestEvidence(ws.root, entry);\n const cls = classifyCommand(entry, manifest);\n if (cls.safety === 'blocked') {\n runs.push({ ...base, outcome: 'refused', safety: cls.safety, reason: `refused: ${cls.reasons.join('; ')}` });\n continue;\n }\n if (cls.safety === 'needs-test-environment' && !isDeclared(decls, pkg, check)) {\n runs.push({\n ...base,\n outcome: 'refused',\n safety: cls.safety,\n reason: `refused: ${cls.reasons.join('; ')}. Run it yourself against a test environment you control, then declare it with: devworkspace testenv declare --package ${pkg} --check ${check} --target \"<description>\" --yes`,\n });\n continue;\n }\n const argv = splitCommand(entry.command ?? '');\n if (!argv) {\n runs.push({ ...base, outcome: 'refused', safety: cls.safety, reason: 'refused: the command uses shell syntax, and DevWorkspace never runs a shell' });\n continue;\n }\n const exe = await resolveExecutable(await runner.which(argv[0]!), argv[0]!, o.platform ?? process.platform, pathExists);\n const started = Date.now();\n const r = await runner.run({ command: exe, args: argv.slice(1), cwd: pkg === '.' ? ws.root : path.join(ws.root, ...pkg.split('/')), timeoutMs: opts.timeoutMs ?? DEFAULT_TIMEOUT_MS });\n const durationMs = Date.now() - started;\n if (r.code === null && !r.timedOut && r.error) {\n // The command never started (missing executable, bad cwd): that is \"could not run\", not a test failure.\n runs.push({ ...base, outcome: 'refused', safety: cls.safety, reason: `could not start: ${scrub(r.error)}` });\n continue;\n }\n const passed = r.ok && r.code === 0;\n const tail = passed ? undefined : scrub((r.error ?? '') || (r.timedOut ? 'timed out' : '') || r.stderr.slice(-300) || r.stdout.slice(-300) || `exit ${r.code}`);\n runs.push({ ...base, outcome: passed ? 'passed' : 'failed', safety: cls.safety, exitCode: r.code, durationMs, ...(tail ? { reason: tail } : {}) });\n evidence.push({ kind: 'executed', at: isoNow(o), package: pkg, command: entry.command ?? undefined, exitCode: r.code, durationMs, scope: fingerprint ?? 'unknown', ...(tail ? { note: tail } : {}) });\n }\n\n const updated = await mutate(o, async (w) => {\n const t = await loadTask(w, id);\n let item = t.verification.find((v) => v.check === check);\n if (!item) {\n item = { check, required: false, status: 'PENDING' };\n t.verification.push(item);\n }\n for (const e of evidence) item.evidence = [...(item.evidence ?? []).filter((x) => x.package !== e.package), e];\n item.status = summarize(item, runs);\n const refused = runs.filter((r) => r.outcome === 'refused');\n if (item.status === 'COULD_NOT_RUN') item.detail = refused.map((r) => `${r.package}: ${r.reason}`).join(' | ').slice(0, 500);\n else delete item.detail;\n delete item.reason;\n item.updatedAt = isoNow(o);\n t.updatedAt = item.updatedAt;\n assertNoSecrets(t);\n await saveTask(w, t);\n return t;\n });\n return { task: updated, check, runs };\n}\n\nfunction summarize(item: VerificationItem, runs: PackageRun[]): VerifyStatus {\n if (runs.some((r) => r.outcome === 'failed')) return 'FAIL';\n if (runs.some((r) => r.outcome === 'refused')) return 'COULD_NOT_RUN';\n if (runs.some((r) => r.outcome === 'passed')) return 'PASS';\n return item.status;\n}\n\n// ---------- declared test environments ----------\n\nexport async function declareTestEnv(o: ServiceOptions, input: { package: string; checks: string[]; target: string; yes: boolean }): Promise<TestEnvDeclaration> {\n if (!input.yes) {\n throw new DevWorkspaceError('USAGE', 'Declaring a test environment is a statement that running these checks there is safe; confirm with --yes.', {\n hint: 'DevWorkspace cannot verify a database target (it never reads connection settings). This records your assertion, locally, and nothing else.',\n });\n }\n assertSafeTarget(input.target);\n const ws = await requireWorkspace(o.cwd);\n const pkg = input.package === '' ? '.' : input.package.replace(/\\/+$/, '');\n const contract = await loadContract(ws);\n if (!contract.some((c) => c.available && (c.cwd ?? '.') === pkg)) {\n throw new DevWorkspaceError('NOT_FOUND', `The testing contract has no commands for package \"${pkg}\".`, { hint: 'Use a package directory shown by \"devworkspace context\".' });\n }\n const allowed = new Set(['unit', 'integration', 'e2e', 'security']);\n const bad = input.checks.filter((c) => !allowed.has(c));\n if (input.checks.length === 0 || bad.length > 0) {\n throw new DevWorkspaceError('USAGE', `--check must be one or more of: ${[...allowed].join(', ')}.`, { hint: 'Migrations, seeds and resets are never run by DevWorkspace.' });\n }\n const decl: TestEnvDeclaration = { package: pkg, checks: [...new Set(input.checks)].sort(), target: input.target.trim(), declaredAt: isoNow(o) };\n await mutate(o, async (w) => saveDeclaration(w, decl));\n return decl;\n}\n\nexport async function listTestEnv(o: ServiceOptions): Promise<TestEnvDeclaration[]> {\n return loadTestEnv(await requireWorkspace(o.cwd));\n}\n\nexport async function revokeTestEnv(o: ServiceOptions, pkg: string): Promise<boolean> {\n return mutate(o, async (w) => removeDeclaration(w, pkg === '' ? '.' : pkg.replace(/\\/+$/, '')));\n}\n"]}
|
|
1
|
+
{"version":3,"file":"verify.js","sourceRoot":"","sources":["../../src/services/verify.ts"],"names":[],"mappings":"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","sourcesContent":["import path from 'node:path';\nimport { SCHEMA_VERSION, validateCommands, type CommandEntry } from '../config/schemas.js';\nimport { requireWorkspace, type Ws } from '../core/workspace.js';\nimport { readVersioned } from '../core/versioned.js';\nimport { DevWorkspaceError } from '../errors/index.js';\nimport { createRunner } from '../integrations/exec.js';\nimport { scrub } from '../integrations/manager.js';\nimport { loadTask, saveTask, type Evidence, type GateContext, type Task, type VerificationItem, type VerifyStatus, assertNoSecrets } from '../tasks/task.js';\nimport { pathExists } from '../utils/fs.js';\nimport { classifyCommand, isDeclared, loadTestEnv, readManifestEvidence, assertSafeTarget, removeDeclaration, saveDeclaration, type CommandSafety, type TestEnvDeclaration } from '../verification/safety.js';\nimport { changedSince, scopeByPackage } from '../verification/scope.js';\nimport { isoNow, mutate, type ServiceOptions } from './common.js';\n\nexport async function loadContract(ws: Ws): Promise<CommandEntry[]> {\n if (!(await pathExists(ws.commands))) return [];\n return (await readVersioned(ws.commands, 'commands', SCHEMA_VERSION, validateCommands)).data.checks;\n}\n\n/** Contract plus what the task has changed per package: everything the completion gate needs to judge it. */\nexport async function gateContext(ws: Ws, task: Task, contract?: CommandEntry[]): Promise<GateContext> {\n const checks = contract ?? (await loadContract(ws));\n const scope = task.scope ? scopeByPackage(await changedSince(ws.root, task.scope), checks) : null;\n return { contract: checks, scope };\n}\n\nexport type RunOutcome = 'passed' | 'failed' | 'refused' | 'not-affected';\n\nexport interface PackageRun {\n package: string;\n command: string | null;\n outcome: RunOutcome;\n exitCode?: number | null;\n durationMs?: number;\n /** Why DevWorkspace did not run it, or the scrubbed tail of a failure. */\n reason?: string;\n safety: CommandSafety['safety'];\n}\n\nexport interface RunCheckResult {\n task: Task;\n check: string;\n runs: PackageRun[];\n}\n\n/** Check if a contract check represents an automated test suite. */\nexport function isTestCommand(id: string, command: string): boolean {\n if (id === 'unit' || id === 'integration' || id === 'e2e' || id === 'security') return true;\n return /\\b(test|vitest|jest|pytest|playwright|cypress|mocha|ava|tap)\\b/i.test(command);\n}\n\nexport interface ZeroTestResult {\n isZeroTests: boolean;\n reason?: string;\n}\n\n/**\n * Detects known zero-test execution signatures from test runners (Vitest, Jest, Pytest, Mocha, Go, Cargo).\n * Prevents commands that exit with code 0 because no tests were found (e.g. --passWithNoTests) from falsely passing.\n */\nexport function detectZeroTests(command: string, stdout: string, stderr: string): ZeroTestResult {\n const combined = `${stdout}\\n${stderr}`;\n const hasPassWithNoTests = /--passWithNoTests\\b|--pass-with-no-tests\\b/i.test(command);\n\n // 1. Vitest zero-test patterns\n if (/No test files found/i.test(combined)) {\n return { isZeroTests: true, reason: 'Vitest reported no test files found' };\n }\n if (/Test Files\\s+0\\s+passed\\s*\\(0\\)/i.test(combined) || /Test Files\\s+0\\s+failed\\s*\\(0\\)/i.test(combined)) {\n return { isZeroTests: true, reason: 'Vitest ran 0 test files' };\n }\n if (/Tests\\s+0\\s+passed\\s*\\(0\\)/i.test(combined) && !/Tests\\s+[1-9]\\d*\\s+passed/i.test(combined)) {\n return { isZeroTests: true, reason: 'Vitest ran 0 tests' };\n }\n\n // 2. Jest zero-test patterns\n if (/Ran all test suites matching.*No tests found/i.test(combined)) {\n return { isZeroTests: true, reason: 'Jest found no test suites matching path' };\n }\n if (/Test Suites:\\s*0\\s*(?:passed,\\s*)?0\\s*total/i.test(combined) || /Test Suites:\\s*0\\s*total/i.test(combined)) {\n return { isZeroTests: true, reason: 'Jest ran 0 test suites' };\n }\n if (/Tests:\\s*0\\s*(?:passed,\\s*)?0\\s*total/i.test(combined) || /Tests:\\s*0\\s*total/i.test(combined)) {\n return { isZeroTests: true, reason: 'Jest ran 0 tests' };\n }\n\n // 3. Pytest zero-test patterns\n if (/collected 0 items/i.test(combined) || /no tests ran in/i.test(combined)) {\n return { isZeroTests: true, reason: 'Pytest collected and ran 0 items' };\n }\n\n // 4. Mocha / Node test runner zero-test patterns\n if (/\\b0 passing\\b/i.test(combined) && !/[1-9]\\d*\\s+passing\\b/i.test(combined)) {\n return { isZeroTests: true, reason: 'Mocha reported 0 passing tests' };\n }\n\n // 5. Go / Cargo / other zero-test patterns\n if (/\\[no test files\\]/i.test(combined)) {\n return { isZeroTests: true, reason: 'Go test reported [no test files]' };\n }\n if (/running 0 tests/i.test(combined) && !/running [1-9]\\d* tests/i.test(combined)) {\n return { isZeroTests: true, reason: 'Cargo test ran 0 tests' };\n }\n\n // 6. Explicit passWithNoTests with no tests indicated\n if (hasPassWithNoTests && (/no tests\\b/i.test(combined) || /0 tests\\b/i.test(combined) || /0 total\\b/i.test(combined))) {\n return { isZeroTests: true, reason: 'Command used --passWithNoTests and executed 0 tests' };\n }\n\n return { isZeroTests: false };\n}\n\n/** Anything a shell would interpret. Contract commands are run as an argument vector, never through a shell. */\nconst SHELL_SYNTAX = /[&|;<>$`(){}\"'\\\\*?!%^\\r\\n]/;\n\nexport function splitCommand(command: string): string[] | null {\n if (SHELL_SYNTAX.test(command)) return null;\n const parts = command.trim().split(/\\s+/);\n return parts[0] ? parts : null;\n}\n\nconst DEFAULT_TIMEOUT_MS = 10 * 60_000;\n\n/**\n * PATH lookup on Windows finds the extensionless Unix shell script (`npm`) before `npm.cmd`, and that cannot be\n * spawned. Prefer the Windows launcher next to it. Elsewhere the lookup result is used as is.\n */\nexport async function resolveExecutable(found: string | null, name: string, platform: NodeJS.Platform, exists: (p: string) => Promise<boolean>): Promise<string> {\n if (!found) return name;\n if (platform !== 'win32' || /\\.(?:exe|cmd|bat|com)$/i.test(found)) return found;\n for (const ext of ['.cmd', '.exe', '.bat']) if (await exists(found + ext)) return found + ext;\n return found;\n}\n\n/**\n * Run one contract check for the packages the task changed, and record what really happened. DevWorkspace only runs\n * read-only, non-destructive commands; anything that may touch a database runs only after the user declared a test\n * environment for that package and check. Refusals are recorded as \"could not run\", never as a pass.\n */\nexport async function runTaskCheck(o: ServiceOptions, id: string, check: string, opts: { package?: string; timeoutMs?: number } = {}): Promise<RunCheckResult> {\n const ws = await requireWorkspace(o.cwd);\n const task = await loadTask(ws, id);\n const contract = await loadContract(ws);\n const wanted = opts.package ? (opts.package === '.' || opts.package === '' ? '.' : opts.package.replace(/\\/+$/, '')) : undefined;\n const entries = contract.filter((c) => c.id === check && c.available && (wanted === undefined || (c.cwd ?? '.') === wanted));\n if (entries.length === 0) {\n throw new DevWorkspaceError('NOT_FOUND', `The testing contract has no \"${check}\" command${wanted ? ` for package \"${wanted}\"` : ''}.`, {\n hint: 'See the contract with \"devworkspace context\", or add the command to .devworkspace/context/commands.json.',\n });\n }\n const scope = (await gateContext(ws, task, contract)).scope;\n const decls = await loadTestEnv(ws);\n const runner = o.runner ?? createRunner(o.env ?? process.env, o.platform);\n const runs: PackageRun[] = [];\n const evidence: Evidence[] = [];\n\n for (const entry of entries) {\n const pkg = entry.cwd ?? '.';\n const base = { package: pkg, command: entry.command };\n const fingerprint = scope === null ? 'unknown' : scope[pkg];\n if (wanted === undefined && fingerprint === undefined) {\n runs.push({ ...base, outcome: 'not-affected', safety: 'safe', reason: 'the task changed nothing in this package' });\n continue;\n }\n const manifest = await readManifestEvidence(ws.root, entry);\n const cls = classifyCommand(entry, manifest);\n if (cls.safety === 'blocked') {\n runs.push({ ...base, outcome: 'refused', safety: cls.safety, reason: `refused: ${cls.reasons.join('; ')}` });\n continue;\n }\n if (cls.safety === 'needs-test-environment' && !isDeclared(decls, pkg, check)) {\n runs.push({\n ...base,\n outcome: 'refused',\n safety: cls.safety,\n reason: `refused: ${cls.reasons.join('; ')}. Run it yourself against a test environment you control, then declare it with: devworkspace testenv declare --package ${pkg} --check ${check} --target \"<description>\" --yes`,\n });\n continue;\n }\n const argv = splitCommand(entry.command ?? '');\n if (!argv) {\n runs.push({ ...base, outcome: 'refused', safety: cls.safety, reason: 'refused: the command uses shell syntax, and DevWorkspace never runs a shell' });\n continue;\n }\n const exe = await resolveExecutable(await runner.which(argv[0]!), argv[0]!, o.platform ?? process.platform, pathExists);\n const started = Date.now();\n const r = await runner.run({ command: exe, args: argv.slice(1), cwd: pkg === '.' ? ws.root : path.join(ws.root, ...pkg.split('/')), timeoutMs: opts.timeoutMs ?? DEFAULT_TIMEOUT_MS });\n const durationMs = Date.now() - started;\n if (r.code === null && !r.timedOut && r.error) {\n // The command never started (missing executable, bad cwd): that is \"could not run\", not a test failure.\n runs.push({ ...base, outcome: 'refused', safety: cls.safety, reason: `could not start: ${scrub(r.error)}` });\n continue;\n }\n const zeroTestResult = isTestCommand(entry.id, entry.command ?? '')\n ? detectZeroTests(entry.command ?? '', r.stdout, r.stderr)\n : { isZeroTests: false };\n const isVacuous = r.ok && r.code === 0 && zeroTestResult.isZeroTests;\n const passed = r.ok && r.code === 0 && !isVacuous;\n const tail = !passed\n ? isVacuous\n ? `vacuous test pass: command exited with code 0 but executed 0 tests (${zeroTestResult.reason})`\n : scrub((r.error ?? '') || (r.timedOut ? 'timed out' : '') || r.stderr.slice(-300) || r.stdout.slice(-300) || `exit ${r.code}`)\n : undefined;\n runs.push({ ...base, outcome: passed ? 'passed' : 'failed', safety: cls.safety, exitCode: r.code, durationMs, ...(tail ? { reason: tail } : {}) });\n evidence.push({ kind: 'executed', at: isoNow(o), package: pkg, command: entry.command ?? undefined, exitCode: r.code, durationMs, scope: fingerprint ?? 'unknown', ...(tail ? { note: tail } : {}) });\n }\n\n const updated = await mutate(o, async (w) => {\n const t = await loadTask(w, id);\n let item = t.verification.find((v) => v.check === check);\n if (!item) {\n item = { check, required: false, status: 'PENDING' };\n t.verification.push(item);\n }\n for (const e of evidence) item.evidence = [...(item.evidence ?? []).filter((x) => x.package !== e.package), e];\n item.status = summarize(item, runs);\n const refused = runs.filter((r) => r.outcome === 'refused');\n if (item.status === 'COULD_NOT_RUN') item.detail = refused.map((r) => `${r.package}: ${r.reason}`).join(' | ').slice(0, 500);\n else delete item.detail;\n delete item.reason;\n item.updatedAt = isoNow(o);\n t.updatedAt = item.updatedAt;\n assertNoSecrets(t);\n await saveTask(w, t);\n return t;\n });\n return { task: updated, check, runs };\n}\n\nfunction summarize(item: VerificationItem, runs: PackageRun[]): VerifyStatus {\n if (runs.some((r) => r.outcome === 'failed')) return 'FAIL';\n if (runs.some((r) => r.outcome === 'refused')) return 'COULD_NOT_RUN';\n if (runs.some((r) => r.outcome === 'passed')) return 'PASS';\n return item.status;\n}\n\n// ---------- declared test environments ----------\n\nexport async function declareTestEnv(o: ServiceOptions, input: { package: string; checks: string[]; target: string; yes: boolean }): Promise<TestEnvDeclaration> {\n if (!input.yes) {\n throw new DevWorkspaceError('USAGE', 'Declaring a test environment is a statement that running these checks there is safe; confirm with --yes.', {\n hint: 'DevWorkspace cannot verify a database target (it never reads connection settings). This records your assertion, locally, and nothing else.',\n });\n }\n assertSafeTarget(input.target);\n const ws = await requireWorkspace(o.cwd);\n const pkg = input.package === '' ? '.' : input.package.replace(/\\/+$/, '');\n const contract = await loadContract(ws);\n if (!contract.some((c) => c.available && (c.cwd ?? '.') === pkg)) {\n throw new DevWorkspaceError('NOT_FOUND', `The testing contract has no commands for package \"${pkg}\".`, { hint: 'Use a package directory shown by \"devworkspace context\".' });\n }\n const allowed = new Set(['unit', 'integration', 'e2e', 'security']);\n const bad = input.checks.filter((c) => !allowed.has(c));\n if (input.checks.length === 0 || bad.length > 0) {\n throw new DevWorkspaceError('USAGE', `--check must be one or more of: ${[...allowed].join(', ')}.`, { hint: 'Migrations, seeds and resets are never run by DevWorkspace.' });\n }\n const decl: TestEnvDeclaration = { package: pkg, checks: [...new Set(input.checks)].sort(), target: input.target.trim(), declaredAt: isoNow(o) };\n await mutate(o, async (w) => saveDeclaration(w, decl));\n return decl;\n}\n\nexport async function listTestEnv(o: ServiceOptions): Promise<TestEnvDeclaration[]> {\n return loadTestEnv(await requireWorkspace(o.cwd));\n}\n\nexport async function revokeTestEnv(o: ServiceOptions, pkg: string): Promise<boolean> {\n return mutate(o, async (w) => removeDeclaration(w, pkg === '' ? '.' : pkg.replace(/\\/+$/, '')));\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 };
|