coding-agent-harness 1.0.8 → 1.1.0
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 +10 -0
- package/CONTRIBUTING.md +8 -4
- package/README.md +12 -2
- package/README.zh-CN.md +10 -2
- package/SKILL.md +14 -3
- package/dist/build-dist.mjs +19 -6
- package/dist/check-dist-observation.mjs +57 -29
- package/dist/check-harness.mjs +0 -1
- package/dist/check-import-graph.mjs +44 -27
- package/dist/check-lite-forbidden-surfaces.mjs +121 -0
- package/dist/check-no-ts-nocheck.mjs +7 -7
- package/dist/check-runtime-emit.mjs +10 -3
- package/dist/check-type-boundaries.mjs +51 -9
- package/dist/commands/dashboard-command.mjs +52 -14
- package/dist/commands/migration-command.mjs +18 -8
- package/dist/commands/module-command.mjs +142 -0
- package/dist/commands/preset-command.mjs +51 -12
- package/dist/commands/registry.mjs +483 -0
- package/dist/commands/task-command.mjs +109 -52
- package/dist/harness.mjs +6 -304
- package/dist/lib/capability-registry.mjs +229 -53
- package/dist/lib/check-module-parallel.mjs +1 -6
- package/dist/lib/check-profiles.mjs +39 -46
- package/dist/lib/check-task-contracts.mjs +6 -4
- package/dist/lib/command-registry.mjs +248 -0
- package/dist/lib/core-shared.mjs +78 -3
- package/dist/lib/dashboard-data.mjs +203 -22
- package/dist/lib/dashboard-workbench.mjs +245 -21
- package/dist/lib/dashboard-writer.mjs +4 -1
- package/dist/lib/git-status-summary.mjs +0 -1
- package/dist/lib/governance-index-generator.mjs +7 -5
- package/dist/lib/governance-sync.mjs +46 -121
- package/dist/lib/governance-table-boundary.mjs +1 -14
- package/dist/lib/harness-core.mjs +4 -1
- package/dist/lib/harness-paths.mjs +115 -1
- package/dist/lib/impact-classifier.mjs +420 -0
- package/dist/lib/lesson-maintenance.mjs +1 -2
- package/dist/lib/markdown-utils.mjs +50 -1
- package/dist/lib/migration-planner.mjs +31 -16
- package/dist/lib/migration-support.mjs +5 -4
- package/dist/lib/module-registry.mjs +296 -0
- package/dist/lib/preset-audit-contracts.mjs +24 -1
- package/dist/lib/preset-engine.mjs +67 -29
- package/dist/lib/preset-registry.mjs +361 -71
- package/dist/lib/preset-runner.mjs +292 -26
- package/dist/lib/review-confirm-git-gate.mjs +73 -19
- package/dist/lib/status-builder.mjs +23 -8
- package/dist/lib/structure-migration.mjs +6 -4
- package/dist/lib/subagent-authorization-audit.mjs +8 -2
- package/dist/lib/task-archive-eligibility.mjs +65 -0
- package/dist/lib/task-audit-metadata.mjs +25 -11
- package/dist/lib/task-audit-migration.mjs +21 -14
- package/dist/lib/task-discovery-contract.mjs +32 -0
- package/dist/lib/task-index.mjs +3 -2
- package/dist/lib/task-lesson-candidates.mjs +1 -2
- package/dist/lib/task-lesson-sedimentation.mjs +310 -9
- package/dist/lib/task-lifecycle/create-task-helpers.mjs +6 -3
- package/dist/lib/task-lifecycle/phase-sync.mjs +0 -1
- package/dist/lib/task-lifecycle/preset-interop.mjs +16 -0
- package/dist/lib/task-lifecycle/review-confirm.mjs +34 -2
- package/dist/lib/task-lifecycle/review-gates.mjs +12 -5
- package/dist/lib/task-lifecycle/review-submission.mjs +1 -2
- package/dist/lib/task-lifecycle/scaffold-provenance.mjs +0 -1
- package/dist/lib/task-lifecycle/template-files.mjs +2 -5
- package/dist/lib/task-lifecycle.mjs +116 -160
- package/dist/lib/task-metadata.mjs +10 -5
- package/dist/lib/task-preset-contract-drift.mjs +45 -0
- package/dist/lib/task-repository.mjs +192 -0
- package/dist/lib/task-review-model.mjs +36 -17
- package/dist/lib/task-scanner.mjs +74 -23
- package/dist/lib/task-template-materials.mjs +131 -0
- package/dist/lib/task-tombstone-commands.mjs +186 -29
- package/dist/lib/types/check-profiles.js +1 -0
- package/dist/lib/types/impact.js +1 -0
- package/dist/lib/types/preset.js +1 -0
- package/dist/lib/types/task-lifecycle.js +1 -0
- package/dist/lib/types/task-scanner.js +1 -0
- package/dist/postinstall.mjs +2 -2
- package/dist/run-built-tests.mjs +10 -3
- package/docs-release/README.md +1 -0
- package/docs-release/architecture/document-contract-kernel/README.md +150 -0
- package/docs-release/architecture/document-contract-kernel/products/full-skill-overlay.md +29 -0
- package/docs-release/architecture/document-contract-kernel/products/lite-forbidden-surfaces.txt +26 -0
- package/docs-release/architecture/document-contract-kernel/products/lite-skill-overlay.md +37 -0
- package/docs-release/architecture/overview.md +2 -2
- package/docs-release/architecture/overview.zh-CN.md +2 -2
- package/docs-release/architecture/system-explainer/01-system-overview.md +11 -7
- package/docs-release/architecture/system-explainer/02-module-dependency.md +4 -4
- package/docs-release/architecture/system-explainer/03-task-lifecycle.md +17 -12
- package/docs-release/architecture/system-explainer/05-data-flow.md +6 -6
- package/docs-release/architecture/system-explainer/06-preset-and-migration.md +2 -2
- package/docs-release/architecture/system-explainer/README.md +1 -1
- package/docs-release/architecture/system-explainer/en-US/01-system-overview.md +12 -8
- package/docs-release/architecture/system-explainer/en-US/02-module-dependency.md +5 -5
- package/docs-release/architecture/system-explainer/en-US/03-task-lifecycle.md +19 -11
- package/docs-release/architecture/system-explainer/en-US/05-data-flow.md +5 -5
- package/docs-release/architecture/system-explainer/en-US/06-preset-and-migration.md +2 -2
- package/docs-release/architecture/system-explainer/en-US/README.md +1 -1
- package/docs-release/guides/agent-installation.en-US.md +4 -6
- package/docs-release/guides/agent-installation.md +11 -8
- package/docs-release/guides/contributing.md +10 -3
- package/docs-release/guides/contributing.zh-CN.md +10 -3
- package/docs-release/guides/legacy-migration-agent-prompt.md +1 -1
- package/docs-release/guides/legacy-migration-agent-prompt.zh-CN.md +1 -1
- package/docs-release/guides/migration-playbook.en-US.md +9 -6
- package/docs-release/guides/migration-playbook.md +9 -6
- package/docs-release/guides/preset-development.md +68 -2
- package/docs-release/guides/task-state-machine.en-US.md +8 -8
- package/docs-release/guides/task-state-machine.md +7 -7
- package/docs-release/guides/typescript-runtime-migration-closeout.md +17 -13
- package/package.json +16 -12
- package/postinstall.mjs +37 -0
- package/presets/legacy-migration/preset.yaml +5 -5
- package/presets/legacy-migration/templates/execution_strategy.append.md +1 -1
- package/presets/lesson-sedimentation/preset.yaml +3 -3
- package/presets/module/preset.yaml +2 -2
- package/presets/module/templates/execution_strategy.append.md +1 -1
- package/presets/module/templates/task_plan.append.md +3 -3
- package/presets/release-closeout/checks/check-release-package.mjs +6 -1
- package/presets/release-closeout/preset.yaml +9 -9
- package/presets/release-closeout/scripts/generate-release-package.mjs +387 -25
- package/presets/release-closeout/templates/task_plan.append.md +5 -5
- package/presets/standard-task/preset.yaml +2 -2
- package/references/agents-md-pattern.md +23 -17
- package/references/lessons-governance.md +2 -2
- package/references/module-parallel-standard.md +3 -6
- package/references/ssot-governance.md +2 -2
- package/references/taskr-gap-analysis.md +3 -3
- package/run-dist.mjs +34 -0
- package/skills/preset-creator/SKILL.md +40 -8
- package/skills/preset-creator/references/complex-task-skeleton/brief.md +32 -8
- package/skills/preset-creator/references/preset-package-skeleton.md +15 -5
- package/skills/preset-creator/references/structure-aware-paths.md +112 -0
- package/templates/AGENTS.md.template +28 -26
- package/templates/architecture/README.md +2 -2
- package/templates/architecture/service-catalog.md +2 -2
- package/templates/architecture/services/service-template.md +1 -1
- package/templates/dashboard/assets/app-src/00-state.js +5 -1
- package/templates/dashboard/assets/app-src/10-router.js +7 -0
- package/templates/dashboard/assets/app-src/20-overview.js +8 -8
- package/templates/dashboard/assets/app-src/30-tasks.js +132 -40
- package/templates/dashboard/assets/app-src/32-task-swimlane.js +314 -0
- package/templates/dashboard/assets/app-src/35-task-detail.js +35 -5
- package/templates/dashboard/assets/app-src/40-modules.js +257 -41
- package/templates/dashboard/assets/app-src/45-review.js +127 -1
- package/templates/dashboard/assets/app-src/90-bindings.js +185 -2
- package/templates/dashboard/assets/app.css +928 -53
- package/templates/dashboard/assets/app.css.manifest.json +2 -0
- package/templates/dashboard/assets/app.js +1071 -98
- package/templates/dashboard/assets/app.manifest.json +1 -0
- package/templates/dashboard/assets/css-src/00-foundation.css +12 -6
- package/templates/dashboard/assets/css-src/10-panels-flow.css +2 -2
- package/templates/dashboard/assets/css-src/30-task-index.css +21 -13
- package/templates/dashboard/assets/css-src/31-archive.css +94 -0
- package/templates/dashboard/assets/css-src/32-task-swimlane.css +487 -0
- package/templates/dashboard/assets/css-src/35-review-workspace.css +78 -0
- package/templates/dashboard/assets/css-src/40-detail-modules-migration.css +191 -14
- package/templates/dashboard/assets/css-src/50-responsive-overrides.css +23 -0
- package/templates/dashboard/assets/i18n.js +166 -2
- package/templates/development/README.md +9 -9
- package/templates/development/cross-repo-debugging.md +3 -3
- package/templates/development/external-context/service-template.md +1 -1
- package/templates/development/external-source-packs/README.md +2 -2
- package/templates/integrations/README.md +4 -4
- package/templates/integrations/api-contract.md +1 -1
- package/templates/integrations/event-contract.md +1 -1
- package/templates/integrations/third-party/vendor-template.md +1 -1
- package/templates/integrations/webhook-contract.md +1 -1
- package/templates/ledger/Harness-Ledger.md +1 -1
- package/templates/modules/module_brief.md +50 -0
- package/templates/modules/module_plan.md +49 -0
- package/templates/modules/registry_view.md +9 -0
- package/templates/modules/session_prompt_pack.md +55 -0
- package/templates/planning/brief.md +32 -8
- package/templates/planning/module_brief.md +28 -3
- package/templates/planning/module_plan.md +26 -11
- package/templates/planning/module_session_prompt.md +11 -2
- package/templates/planning/optional/slices/_slice-template/brief.md +28 -0
- package/templates/planning/review.md +1 -1
- package/templates/planning/visual_map.md +1 -1
- package/templates/reference/docs-library-standard.md +7 -7
- package/templates/reference/execution-workflow-standard.md +13 -0
- package/templates/reference/external-source-intake-standard.md +10 -10
- package/templates/reference/repo-governance-standard.md +1 -1
- package/templates/reference/review-routing-standard.md +4 -0
- package/templates/ssot/Module-Registry.md +4 -38
- package/templates/walkthrough/walkthrough-template.md +1 -1
- package/templates-zh-CN/AGENTS.md.template +27 -25
- package/templates-zh-CN/CLAUDE.md.template +1 -1
- package/templates-zh-CN/architecture/README.md +2 -2
- package/templates-zh-CN/architecture/service-catalog.md +2 -2
- package/templates-zh-CN/architecture/services/service-template.md +1 -1
- package/templates-zh-CN/development/README.md +9 -9
- package/templates-zh-CN/development/cross-repo-debugging.md +3 -3
- package/templates-zh-CN/development/external-context/service-template.md +1 -1
- package/templates-zh-CN/development/external-source-packs/README.md +2 -2
- package/templates-zh-CN/integrations/README.md +4 -4
- package/templates-zh-CN/integrations/api-contract.md +1 -1
- package/templates-zh-CN/integrations/event-contract.md +1 -1
- package/templates-zh-CN/integrations/third-party/vendor-template.md +1 -1
- package/templates-zh-CN/integrations/webhook-contract.md +1 -1
- package/templates-zh-CN/ledger/Harness-Ledger.md +1 -1
- package/templates-zh-CN/lessons/lesson-arch-process-change.md +1 -1
- package/templates-zh-CN/lessons/lesson-new-doc.md +3 -3
- package/templates-zh-CN/lessons/lesson-ref-change.md +4 -4
- package/templates-zh-CN/modules/module_brief.md +47 -0
- package/templates-zh-CN/modules/module_plan.md +48 -0
- package/templates-zh-CN/modules/registry_view.md +9 -0
- package/templates-zh-CN/modules/session_prompt_pack.md +50 -0
- package/templates-zh-CN/planning/INDEX.md +1 -0
- package/templates-zh-CN/planning/brief.md +26 -7
- package/templates-zh-CN/planning/module_brief.md +24 -2
- package/templates-zh-CN/planning/module_plan.md +35 -29
- package/templates-zh-CN/planning/module_session_prompt.md +15 -11
- package/templates-zh-CN/planning/optional/slices/_slice-template/brief.md +28 -11
- package/templates-zh-CN/planning/review.md +1 -1
- package/templates-zh-CN/reference/adversarial-review-standard.md +1 -1
- package/templates-zh-CN/reference/delivery-operating-model-standard.md +3 -3
- package/templates-zh-CN/reference/docs-library-standard.md +27 -27
- package/templates-zh-CN/reference/execution-workflow-standard.md +12 -2
- package/templates-zh-CN/reference/external-source-intake-standard.md +10 -10
- package/templates-zh-CN/reference/harness-ledger-standard.md +3 -3
- package/templates-zh-CN/reference/regression-ssot-governance.md +2 -2
- package/templates-zh-CN/reference/repo-governance-standard.md +1 -1
- package/templates-zh-CN/reference/review-routing-standard.md +3 -0
- package/templates-zh-CN/reference/walkthrough-standard.md +2 -2
- package/templates-zh-CN/reference/worktree-standard.md +1 -1
- package/templates-zh-CN/regression/Cadence-Ledger.md +2 -2
- package/templates-zh-CN/ssot/Delivery-SSoT.md +2 -2
- package/templates-zh-CN/ssot/Module-Registry.md +5 -44
- package/templates-zh-CN/ssot/Regression-SSoT.md +2 -2
- package/templates-zh-CN/walkthrough/walkthrough-template.md +4 -4
|
@@ -1,22 +1,27 @@
|
|
|
1
|
-
// @ts-nocheck
|
|
2
1
|
import fs from "node:fs";
|
|
3
2
|
import path from "node:path";
|
|
4
3
|
import { normalizeTarget, nowTimestamp, readFileSafe, toPosix, datePrefix, } from "./core-shared.mjs";
|
|
4
|
+
import { removeHeadingSectionOutsideFences } from "./markdown-utils.mjs";
|
|
5
5
|
import { collectTasks } from "./task-scanner.mjs";
|
|
6
|
+
import { resolveTaskDirectory } from "./task-lifecycle.mjs";
|
|
7
|
+
import { taskIdFromDirectory } from "./harness-paths.mjs";
|
|
8
|
+
import { assessArchiveEligibility, normalizeArchiveActor } from "./task-archive-eligibility.mjs";
|
|
9
|
+
import { normalizeReviewBoolean } from "./task-review-model.mjs";
|
|
6
10
|
import { beginGovernanceSync, commitGovernanceSync, releaseGovernanceSync, } from "./governance-sync.mjs";
|
|
7
|
-
export function supersedeTask(targetInput, oldRef, { by = "", reason = "" } = {}) {
|
|
11
|
+
export function supersedeTask(targetInput, oldRef, { by = "", reason = "", deletedBy = "", confirm = "", allowOpenFindings = false } = {}) {
|
|
8
12
|
if (!by)
|
|
9
13
|
throw new Error("task-supersede requires --by <new-task-id>");
|
|
10
14
|
const target = normalizeTarget(targetInput);
|
|
11
15
|
const oldTask = resolveTask(target, oldRef);
|
|
12
16
|
const newTask = resolveTask(target, by);
|
|
17
|
+
assertSoftDeleteEligible(oldTask, { reason, deletedBy, confirm, allowOpenFindings, action: "task-supersede" });
|
|
13
18
|
const governanceContext = beginGovernanceSync(target, { operation: `task-supersede ${oldTask.id}` });
|
|
14
19
|
try {
|
|
15
20
|
writeTombstone(target, oldTask, {
|
|
16
21
|
State: "superseded",
|
|
17
22
|
"Superseded By": newTask.id,
|
|
18
23
|
Reason: reason || "superseded",
|
|
19
|
-
Operator: "coordinator",
|
|
24
|
+
Operator: normalizeTombstoneActor(deletedBy) || "coordinator",
|
|
20
25
|
Timestamp: nowTimestamp(),
|
|
21
26
|
"Reopen Eligible": "yes",
|
|
22
27
|
"Archive Eligible": "no",
|
|
@@ -32,16 +37,43 @@ export function supersedeTask(targetInput, oldRef, { by = "", reason = "" } = {}
|
|
|
32
37
|
releaseGovernanceSync(governanceContext);
|
|
33
38
|
}
|
|
34
39
|
}
|
|
35
|
-
export function softDeleteTask(targetInput, taskRef,
|
|
40
|
+
export function softDeleteTask(targetInput, taskRef, options = {}) {
|
|
41
|
+
return deleteTask(targetInput, taskRef, { ...options, hard: false });
|
|
42
|
+
}
|
|
43
|
+
export function deleteTask(targetInput, taskRef, { hard = false, reason = "", deletedBy = "", confirm = "", allowOpenFindings = false } = {}) {
|
|
36
44
|
const target = normalizeTarget(targetInput);
|
|
37
45
|
const task = resolveTask(target, taskRef);
|
|
38
|
-
|
|
46
|
+
if (!hard) {
|
|
47
|
+
assertSoftDeleteEligible(task, { reason, deletedBy, confirm, allowOpenFindings, action: "task-delete" });
|
|
48
|
+
return writeDeletionState(target, task, "soft-deleted", reason || "soft-delete", "task-delete --soft", {
|
|
49
|
+
Operator: normalizeTombstoneActor(deletedBy) || "coordinator",
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
assertHardDeleteEligible(target, task, { reason, deletedBy, confirm });
|
|
53
|
+
const taskDir = path.join(target.projectRoot, task.path.replace(/^TARGET:/, ""));
|
|
54
|
+
const allowedPaths = collectTaskDirectoryFiles(taskDir).map((file) => toPosix(path.relative(target.projectRoot, file)));
|
|
55
|
+
const governanceContext = beginGovernanceSync(target, { operation: `task-delete --hard ${task.id}` });
|
|
56
|
+
try {
|
|
57
|
+
fs.rmSync(taskDir, { recursive: true, force: true });
|
|
58
|
+
const commit = commitGovernanceSync(governanceContext, allowedPaths, {
|
|
59
|
+
message: `chore(harness): hard delete task ${task.id}`,
|
|
60
|
+
});
|
|
61
|
+
return { taskId: task.id, deletionState: "hard-deleted", reason, governance: { commit } };
|
|
62
|
+
}
|
|
63
|
+
finally {
|
|
64
|
+
releaseGovernanceSync(governanceContext);
|
|
65
|
+
}
|
|
39
66
|
}
|
|
40
|
-
export function archiveTask(targetInput, taskRef, { reason = "" } = {}) {
|
|
67
|
+
export function archiveTask(targetInput, taskRef, { reason = "", archivedBy = "", archiveFields = {} } = {}) {
|
|
41
68
|
const target = normalizeTarget(targetInput);
|
|
42
69
|
const task = resolveTask(target, taskRef);
|
|
43
|
-
assertArchiveEligible(task);
|
|
44
|
-
|
|
70
|
+
const archiveAudit = assertArchiveEligible(task, { archivedBy });
|
|
71
|
+
const normalizedArchiveFields = normalizeArchiveFields(archiveFields);
|
|
72
|
+
assertNoReservedArchiveFields(normalizedArchiveFields);
|
|
73
|
+
return writeDeletionState(target, task, "archived", reason || "archive", "task-archive", {
|
|
74
|
+
...normalizedArchiveFields,
|
|
75
|
+
...archiveAudit,
|
|
76
|
+
});
|
|
45
77
|
}
|
|
46
78
|
export function reopenTask(targetInput, taskRef, { reason = "" } = {}) {
|
|
47
79
|
const target = normalizeTarget(targetInput);
|
|
@@ -50,7 +82,7 @@ export function reopenTask(targetInput, taskRef, { reason = "" } = {}) {
|
|
|
50
82
|
try {
|
|
51
83
|
const taskPlanPath = path.join(target.projectRoot, task.taskPlanPath.replace(/^TARGET:/, ""));
|
|
52
84
|
const content = readFileSafe(taskPlanPath);
|
|
53
|
-
const next = content
|
|
85
|
+
const next = removeHeadingSectionOutsideFences(content, /^##\s*(?:Task Tombstone|任务墓碑)\s*$/i);
|
|
54
86
|
fs.writeFileSync(taskPlanPath, next.endsWith("\n") ? next : `${next}\n`);
|
|
55
87
|
appendProgress(target, task, "task-reopen", reason || "reopened");
|
|
56
88
|
const commit = commitGovernanceSync(governanceContext, taskPaths(target, task), {
|
|
@@ -62,7 +94,8 @@ export function reopenTask(targetInput, taskRef, { reason = "" } = {}) {
|
|
|
62
94
|
releaseGovernanceSync(governanceContext);
|
|
63
95
|
}
|
|
64
96
|
}
|
|
65
|
-
function writeDeletionState(target, task, deletionState, reason, action) {
|
|
97
|
+
function writeDeletionState(target, task, deletionState, reason, action, archiveFields = {}) {
|
|
98
|
+
const normalizedArchiveFields = normalizeArchiveFields(archiveFields);
|
|
66
99
|
const governanceContext = beginGovernanceSync(target, { operation: `${action} ${task.id}` });
|
|
67
100
|
try {
|
|
68
101
|
writeTombstone(target, task, {
|
|
@@ -72,6 +105,7 @@ function writeDeletionState(target, task, deletionState, reason, action) {
|
|
|
72
105
|
Timestamp: nowTimestamp(),
|
|
73
106
|
"Reopen Eligible": "yes",
|
|
74
107
|
"Archive Eligible": deletionState === "archived" ? "yes" : "no",
|
|
108
|
+
...normalizedArchiveFields,
|
|
75
109
|
});
|
|
76
110
|
appendProgress(target, task, action, reason);
|
|
77
111
|
const commit = commitGovernanceSync(governanceContext, taskPaths(target, task), {
|
|
@@ -91,33 +125,121 @@ function contextFor(_target, context) {
|
|
|
91
125
|
}
|
|
92
126
|
function resolveTask(target, ref) {
|
|
93
127
|
const normalized = String(ref || "").trim();
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
if (
|
|
99
|
-
return
|
|
100
|
-
if (matches.length > 1)
|
|
101
|
-
throw new Error(`Ambiguous task reference: ${ref}`);
|
|
128
|
+
const resolvedTarget = target;
|
|
129
|
+
const taskDir = resolveTaskDirectory(resolvedTarget, normalized);
|
|
130
|
+
const taskId = taskIdFromDirectory(resolvedTarget.harness, taskDir);
|
|
131
|
+
const task = collectTasks(target).find((candidate) => candidate.id === taskId);
|
|
132
|
+
if (task)
|
|
133
|
+
return task;
|
|
102
134
|
throw new Error(`Task not found: ${ref}`);
|
|
103
135
|
}
|
|
104
|
-
function assertArchiveEligible(task) {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
if (blockingRisks.length)
|
|
110
|
-
throw new Error("tasks with open blocking review findings cannot be archived without an explicit human waiver");
|
|
111
|
-
if (task.materialsReady === false && task.reviewStatus !== "confirmed") {
|
|
112
|
-
throw new Error("tasks with incomplete closeout materials cannot be archived without an explicit human waiver");
|
|
113
|
-
}
|
|
136
|
+
function assertArchiveEligible(task, { archivedBy = "" } = {}) {
|
|
137
|
+
const result = assessArchiveEligibility(task, { archivedBy, now: nowTimestamp() });
|
|
138
|
+
if (!result.eligible)
|
|
139
|
+
throw new Error(result.reason);
|
|
140
|
+
return result.auditFields;
|
|
114
141
|
}
|
|
115
142
|
function writeTombstone(target, task, fields) {
|
|
116
143
|
const taskPlanPath = path.join(target.projectRoot, task.taskPlanPath.replace(/^TARGET:/, ""));
|
|
117
|
-
const content = readFileSafe(taskPlanPath)
|
|
144
|
+
const content = removeHeadingSectionOutsideFences(readFileSafe(taskPlanPath), /^##\s*(?:Task Tombstone|任务墓碑)\s*$/i);
|
|
118
145
|
const block = ["", "## Task Tombstone", "", "| Field | Value |", "| --- | --- |", ...Object.entries(fields).map(([key, value]) => `| ${key} | ${escapeCell(value)} |`), ""].join("\n");
|
|
119
146
|
fs.writeFileSync(taskPlanPath, `${content.trimEnd()}\n${block}`);
|
|
120
147
|
}
|
|
148
|
+
function assertSoftDeleteEligible(task, { reason = "", deletedBy = "", confirm = "", allowOpenFindings = false, action = "task-delete" } = {}) {
|
|
149
|
+
const risky = isRiskyMutationTask(task);
|
|
150
|
+
const hasOpenFindings = !isDraftState(task.state) && hasOpenBlockingFindings(task);
|
|
151
|
+
if (!risky && !hasOpenFindings)
|
|
152
|
+
return;
|
|
153
|
+
const missing = [];
|
|
154
|
+
if (!String(reason || "").trim())
|
|
155
|
+
missing.push("--reason");
|
|
156
|
+
if (!normalizeTombstoneActor(deletedBy))
|
|
157
|
+
missing.push("--deleted-by");
|
|
158
|
+
if (String(confirm || "").trim() !== task.id)
|
|
159
|
+
missing.push(`--confirm ${task.id}`);
|
|
160
|
+
if (hasOpenFindings && !allowOpenFindings)
|
|
161
|
+
missing.push("--allow-open-findings");
|
|
162
|
+
if (missing.length) {
|
|
163
|
+
throw new Error(`${action} would hide a risky task; required: ${missing.join(", ")}`);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
export function assertHardDeleteEligible(target, task, { reason = "", deletedBy = "", confirm = "" } = {}) {
|
|
167
|
+
const missing = [];
|
|
168
|
+
if (!String(reason || "").trim())
|
|
169
|
+
missing.push("--reason");
|
|
170
|
+
if (!normalizeTombstoneActor(deletedBy))
|
|
171
|
+
missing.push("--deleted-by");
|
|
172
|
+
if (String(confirm || "").trim() !== task.id)
|
|
173
|
+
missing.push(`--confirm ${task.id}`);
|
|
174
|
+
if (missing.length)
|
|
175
|
+
throw new Error(`task-delete --hard requires accountable safe draft confirmation: ${missing.join(", ")}`);
|
|
176
|
+
const blockers = [];
|
|
177
|
+
if (!isDraftState(task.state))
|
|
178
|
+
blockers.push(`state:${task.state}`);
|
|
179
|
+
if (task.deletionState !== "active")
|
|
180
|
+
blockers.push(`deletionState:${task.deletionState}`);
|
|
181
|
+
if (isRiskyMutationTask(task))
|
|
182
|
+
blockers.push("task has lifecycle, review, evidence, or closeout history");
|
|
183
|
+
if (!isDraftState(task.state) && hasOpenBlockingFindings(task))
|
|
184
|
+
blockers.push("task has open blocking findings");
|
|
185
|
+
const taskDir = path.join(target.projectRoot, task.path.replace(/^TARGET:/, ""));
|
|
186
|
+
const disallowedFiles = collectTaskDirectoryFiles(taskDir).filter((file) => !isSafeDraftFile(taskDir, file));
|
|
187
|
+
if (disallowedFiles.length)
|
|
188
|
+
blockers.push(`non-scaffold files: ${disallowedFiles.map((file) => toPosix(path.relative(taskDir, file))).join(", ")}`);
|
|
189
|
+
if (blockers.length)
|
|
190
|
+
throw new Error(`task-delete --hard only supports safe draft tasks; ${blockers.join("; ")}`);
|
|
191
|
+
}
|
|
192
|
+
function isRiskyMutationTask(task) {
|
|
193
|
+
return !isDraftState(task.state) ||
|
|
194
|
+
Boolean(task.reviewSubmitted) ||
|
|
195
|
+
task.reviewStatus === "confirmed" ||
|
|
196
|
+
Boolean(task.reviewConfirmation?.confirmed) ||
|
|
197
|
+
task.materialsReady === true && !isDraftState(task.state) ||
|
|
198
|
+
(task.evidence || []).length > 0 ||
|
|
199
|
+
(task.taskQueues || []).some((queue) => ["blocked", "review", "confirmed", "finalized", "lessons"].includes(queue));
|
|
200
|
+
}
|
|
201
|
+
function isDraftState(state) {
|
|
202
|
+
const normalized = String(state || "").trim().toLowerCase().replaceAll("-", "_").replace(/\s+/g, "_");
|
|
203
|
+
return ["planned", "not_started"].includes(normalized);
|
|
204
|
+
}
|
|
205
|
+
function hasOpenBlockingFindings(task) {
|
|
206
|
+
return (task.risks || []).some((risk) => normalizeReviewBoolean(risk.open) !== "no" && (normalizeReviewBoolean(risk.blocksRelease) === "yes" || ["P0", "P1", "P2"].includes(String(risk.severity))));
|
|
207
|
+
}
|
|
208
|
+
function normalizeTombstoneActor(value) {
|
|
209
|
+
return normalizeArchiveActor(value);
|
|
210
|
+
}
|
|
211
|
+
function collectTaskDirectoryFiles(taskDir) {
|
|
212
|
+
if (!fs.existsSync(taskDir))
|
|
213
|
+
return [];
|
|
214
|
+
const files = [];
|
|
215
|
+
const visit = (dir) => {
|
|
216
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
217
|
+
const full = path.join(dir, entry.name);
|
|
218
|
+
if (entry.isDirectory())
|
|
219
|
+
visit(full);
|
|
220
|
+
else if (entry.isFile())
|
|
221
|
+
files.push(full);
|
|
222
|
+
}
|
|
223
|
+
};
|
|
224
|
+
visit(taskDir);
|
|
225
|
+
return files.sort();
|
|
226
|
+
}
|
|
227
|
+
function isSafeDraftFile(taskDir, file) {
|
|
228
|
+
const relative = toPosix(path.relative(taskDir, file));
|
|
229
|
+
return [
|
|
230
|
+
"INDEX.md",
|
|
231
|
+
"brief.md",
|
|
232
|
+
"execution_strategy.md",
|
|
233
|
+
"findings.md",
|
|
234
|
+
"lesson_candidates.md",
|
|
235
|
+
"progress.md",
|
|
236
|
+
"review.md",
|
|
237
|
+
"task_plan.md",
|
|
238
|
+
"visual_map.md",
|
|
239
|
+
"walkthrough.md",
|
|
240
|
+
"long-running-task-contract.md",
|
|
241
|
+
].includes(relative) || /^artifacts\/INDEX\.md$/.test(relative) || /^references\/INDEX\.md$/.test(relative);
|
|
242
|
+
}
|
|
121
243
|
function appendSupersedes(target, task, oldId) {
|
|
122
244
|
const taskPlanPath = path.join(target.projectRoot, task.taskPlanPath.replace(/^TARGET:/, ""));
|
|
123
245
|
const content = readFileSafe(taskPlanPath);
|
|
@@ -135,3 +257,38 @@ function appendProgress(target, task, action, reason) {
|
|
|
135
257
|
function escapeCell(value) {
|
|
136
258
|
return String(value || "").replace(/\r?\n/g, " ").replaceAll("|", "\\|").trim();
|
|
137
259
|
}
|
|
260
|
+
function normalizeArchiveFields(fields) {
|
|
261
|
+
const entries = Object.entries(fields || {});
|
|
262
|
+
const normalized = {};
|
|
263
|
+
const seen = new Set();
|
|
264
|
+
for (const [rawKey, rawValue] of entries) {
|
|
265
|
+
const key = String(rawKey || "").trim();
|
|
266
|
+
if (!key || /[\r\n|]/.test(key))
|
|
267
|
+
throw new Error(`Invalid archive field key: ${key || "<empty>"}`);
|
|
268
|
+
const normalizedKey = key.toLowerCase();
|
|
269
|
+
if (seen.has(normalizedKey))
|
|
270
|
+
throw new Error(`Duplicate archive field key: ${key}`);
|
|
271
|
+
seen.add(normalizedKey);
|
|
272
|
+
normalized[key] = String(rawValue || "").replace(/\r?\n/g, " ").trim();
|
|
273
|
+
}
|
|
274
|
+
return normalized;
|
|
275
|
+
}
|
|
276
|
+
function assertNoReservedArchiveFields(fields) {
|
|
277
|
+
const reserved = new Set([
|
|
278
|
+
"state",
|
|
279
|
+
"reason",
|
|
280
|
+
"operator",
|
|
281
|
+
"timestamp",
|
|
282
|
+
"reopen eligible",
|
|
283
|
+
"archive eligible",
|
|
284
|
+
"archived by",
|
|
285
|
+
"archived at",
|
|
286
|
+
"review confirmed by",
|
|
287
|
+
"review confirmed at",
|
|
288
|
+
"review confirmation id",
|
|
289
|
+
"review commit sha",
|
|
290
|
+
]);
|
|
291
|
+
const blocked = Object.keys(fields).filter((key) => reserved.has(key.toLowerCase()));
|
|
292
|
+
if (blocked.length)
|
|
293
|
+
throw new Error(`Reserved archive field cannot be overridden: ${blocked.join(", ")}`);
|
|
294
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/postinstall.mjs
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
// @ts-nocheck
|
|
3
2
|
import { seedBundledPresets } from "./lib/harness-core.mjs";
|
|
4
3
|
if (process.env.CODING_AGENT_HARNESS_SKIP_POSTINSTALL === "1")
|
|
5
4
|
process.exit(0);
|
|
@@ -10,5 +9,6 @@ try {
|
|
|
10
9
|
console.log(`coding-agent-harness postinstall: ${summary} at ${result.target}`);
|
|
11
10
|
}
|
|
12
11
|
catch (error) {
|
|
13
|
-
|
|
12
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
13
|
+
console.warn(`coding-agent-harness postinstall: preset seed skipped (${message})`);
|
|
14
14
|
}
|
package/dist/run-built-tests.mjs
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
// @ts-nocheck
|
|
3
2
|
import fs from "node:fs";
|
|
4
3
|
import path from "node:path";
|
|
5
4
|
import { spawnSync } from "node:child_process";
|
|
@@ -9,7 +8,9 @@ const outDir = path.join(repoRoot, "tmp", `test-runner-emit-${process.pid}`);
|
|
|
9
8
|
const typescriptVersion = "5.9.3";
|
|
10
9
|
const options = parseArgs(process.argv.slice(2));
|
|
11
10
|
fs.rmSync(outDir, { recursive: true, force: true });
|
|
12
|
-
const
|
|
11
|
+
const npmArgs = ["exec", "--yes", "--package", `typescript@${typescriptVersion}`, "--", "tsc", "-p", "tsconfig.tests.json", "--outDir", outDir, "--noCheck"];
|
|
12
|
+
const npmCommand = resolveNpmCommand(npmArgs);
|
|
13
|
+
const emit = spawnSync(npmCommand.command, npmCommand.args, {
|
|
13
14
|
cwd: repoRoot,
|
|
14
15
|
encoding: "utf8",
|
|
15
16
|
stdio: "inherit",
|
|
@@ -36,7 +37,7 @@ const result = spawnSync(process.execPath, [runner], {
|
|
|
36
37
|
if (result.status !== 0)
|
|
37
38
|
process.exit(result.status || 1);
|
|
38
39
|
function parseArgs(argv) {
|
|
39
|
-
const parsed = {
|
|
40
|
+
const parsed = {};
|
|
40
41
|
for (let index = 0; index < argv.length; index += 1) {
|
|
41
42
|
const arg = argv[index];
|
|
42
43
|
if (arg === "--test") {
|
|
@@ -55,6 +56,12 @@ function requireValue(argv, index, option) {
|
|
|
55
56
|
throw new Error(`${option} requires a value`);
|
|
56
57
|
return value;
|
|
57
58
|
}
|
|
59
|
+
function resolveNpmCommand(npmArgs) {
|
|
60
|
+
const npmExecPath = process.env.npm_execpath;
|
|
61
|
+
if (npmExecPath)
|
|
62
|
+
return { command: process.execPath, args: [npmExecPath, ...npmArgs] };
|
|
63
|
+
return { command: process.platform === "win32" ? "npm.cmd" : "npm", args: npmArgs };
|
|
64
|
+
}
|
|
58
65
|
function linkPackageResources() {
|
|
59
66
|
for (const entry of [
|
|
60
67
|
"package.json",
|
package/docs-release/README.md
CHANGED
|
@@ -56,6 +56,7 @@ Not every document is written for the same reader.
|
|
|
56
56
|
### Architecture / 架构
|
|
57
57
|
|
|
58
58
|
- `architecture/overview.md` / `architecture/overview.zh-CN.md` — public architecture overview, including the CLI, dashboard, task lifecycle, migration rails, review gate, and release package surface. 公开架构总览,覆盖 CLI、Dashboard、任务生命周期、迁移轨道、审查门禁和发布包表面。
|
|
59
|
+
- `architecture/document-contract-kernel/README.md` — shared Document Contract Kernel for Full/Lite Skill semantics, compatibility matrix, change classification, Lite forbidden surfaces, and Lite to Full upgrade mapping.
|
|
59
60
|
|
|
60
61
|
### Methodology / 方法论
|
|
61
62
|
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# Document Contract Kernel
|
|
2
|
+
|
|
3
|
+
The Document Contract Kernel is the product and Skill contract shared by the
|
|
4
|
+
Full Coding Agent Harness Skill and the future Lite Skill. It defines the stable
|
|
5
|
+
document semantics that both product surfaces must preserve without turning Lite
|
|
6
|
+
into a runtime mode or forcing Full to lower its automation and audit bar.
|
|
7
|
+
|
|
8
|
+
This contract is public source material. Full and Lite Skill text should be
|
|
9
|
+
generated from this shared source plus product overlays. Until a generator is
|
|
10
|
+
introduced, changes to the concepts or compatibility matrix must update this
|
|
11
|
+
file and the product overlays in the same change.
|
|
12
|
+
|
|
13
|
+
## Kernel Naming Boundary
|
|
14
|
+
|
|
15
|
+
| Name | Layer | Responsibility | Must not do |
|
|
16
|
+
| --- | --- | --- | --- |
|
|
17
|
+
| Document Contract Kernel | Product / Skill contract | Shared document semantics, Lite/Full compatibility matrix, change classification, and upgrade mapping | Implement runtime behavior, read or write files, or define git, markdown, or path utilities |
|
|
18
|
+
| Domain Kernel | Runtime domain | Task identity, policy, state transitions, module ownership, and preset model | Describe Skill installation copy, package manager commands, UI text, or git transport |
|
|
19
|
+
| Infrastructure Kernel | Runtime infrastructure | Filesystem, path, template, markdown, git, date, id, and locale helpers | Own business semantics or product distribution semantics |
|
|
20
|
+
|
|
21
|
+
Always write the full name "Document Contract Kernel" in source and docs. Do not
|
|
22
|
+
shorten it to a generic `kernel/` label; that collides with later runtime
|
|
23
|
+
refactoring work.
|
|
24
|
+
|
|
25
|
+
## Shared Concepts
|
|
26
|
+
|
|
27
|
+
| Concept | Kernel semantic | Lite expression | Full expression |
|
|
28
|
+
| --- | --- | --- | --- |
|
|
29
|
+
| Agent entry | The first project protocol an agent reads before acting | `AGENTS.md` | `AGENTS.md` plus optional `CLAUDE.md` shim |
|
|
30
|
+
| Project context | Durable project facts, separate from chat memory | `context/architecture`, `context/development`, `context/integrations` | Same directories, with optional source packs and generated indexes |
|
|
31
|
+
| Task package | The smallest reviewable unit of work for one objective | `tasks/<id>/brief.md`, `task_plan.md`, `progress.md`, `walkthrough.md` | `planning/tasks/<id>/` or module task package |
|
|
32
|
+
| Brief | Purpose, scope, and first-read entry for the task | Required | Required |
|
|
33
|
+
| Task plan | Goal, scope, steps, acceptance criteria, and verification intent | Required | Required |
|
|
34
|
+
| Progress evidence | Execution log with evidence references | Required, hand-maintained | Required, may be updated by lifecycle command |
|
|
35
|
+
| Review | Independent review or human confirmation material | Optional | Required for standard and complex work |
|
|
36
|
+
| Visual map | Phase, state, and structure aid | Optional for simple work | Required in CLI-created task packages |
|
|
37
|
+
| Walkthrough | Closeout summary, validation, residual risks, and lesson decision | Required | Required |
|
|
38
|
+
| Regression | The project's important validation surfaces | Simple checklist | Regression SSoT, cadence, and checks |
|
|
39
|
+
| Lessons | Reusable learning from the work | Optional `lessons.md` | Lesson candidates plus promoted lesson details |
|
|
40
|
+
|
|
41
|
+
## Compatibility Matrix
|
|
42
|
+
|
|
43
|
+
Compatibility matrix version: `document-contract-kernel-v0.5`.
|
|
44
|
+
|
|
45
|
+
| Surface | Lite | Full | Kernel classification |
|
|
46
|
+
| --- | --- | --- | --- |
|
|
47
|
+
| `AGENTS.md` | Required | Required | Shared |
|
|
48
|
+
| `CLAUDE.md` | Optional shim | Optional shim | Shared optional |
|
|
49
|
+
| `context/` | Required | Required | Shared |
|
|
50
|
+
| `brief.md` | Required | Required | Shared |
|
|
51
|
+
| `task_plan.md` | Required | Required | Shared |
|
|
52
|
+
| `progress.md` | Required | Required | Shared |
|
|
53
|
+
| `walkthrough.md` | Required | Required | Shared |
|
|
54
|
+
| `review.md` | Optional | Required for standard and complex work | Shared with profile differences |
|
|
55
|
+
| `visual_map.md` | Optional for simple work | Required in CLI-created task packages | Shared with profile differences |
|
|
56
|
+
| `regression.md` | Simple checklist | Regression SSoT and cadence | Shared with profile differences |
|
|
57
|
+
| `lessons.md` | Optional simple table | Lesson candidates and promoted details | Shared with profile differences |
|
|
58
|
+
| `harness.yaml` | Forbidden | Required | Full-only |
|
|
59
|
+
| Generated ledger | Forbidden | Supported | Full-only |
|
|
60
|
+
| Dashboard / Workbench | Forbidden | Supported | Full-only |
|
|
61
|
+
| Preset | Forbidden | Supported | Full-only |
|
|
62
|
+
| Module Registry | Forbidden | Supported | Full-only |
|
|
63
|
+
| Lifecycle CLI commands | Forbidden | Supported | Full-only |
|
|
64
|
+
| `npm install` / `npx coding-agent-harness` | Forbidden | Allowed with user consent | Full-only |
|
|
65
|
+
| Node.js version requirement | Forbidden | Required by the source package and runtime | Full-only |
|
|
66
|
+
|
|
67
|
+
## Change Classification
|
|
68
|
+
|
|
69
|
+
Every PR or task that edits Skill, template, or public product docs must be
|
|
70
|
+
classified before implementation.
|
|
71
|
+
|
|
72
|
+
| Change type | Definition | Must sync | Must not do |
|
|
73
|
+
| --- | --- | --- | --- |
|
|
74
|
+
| Kernel change | Changes the base semantics of AGENTS, context, task package, progress, walkthrough, review, regression, or lessons | Lite overlay, Full overlay, and this compatibility matrix | Update only the Full Skill |
|
|
75
|
+
| Full-only change | CLI, Dashboard, Preset, module registry, generated ledger, transaction, migration, or runtime automation | Full Skill, runtime docs, and Full overlay | Leak into Lite source |
|
|
76
|
+
| Lite-only change | Document-only scaffold, lower cognitive load wording, and hand-maintained task material | Lite overlay | Weaken Full audit or automation requirements |
|
|
77
|
+
| Migration bridge | Maps Lite project material into a Full Harness project | Full migration docs and Lite upgrade note | Promise that Lite supports Full surfaces in place |
|
|
78
|
+
|
|
79
|
+
PR checklist:
|
|
80
|
+
|
|
81
|
+
- [ ] Does this change alter the Document Contract Kernel?
|
|
82
|
+
- [ ] If yes, did Lite and Full overlays both change?
|
|
83
|
+
- [ ] If yes, did the compatibility matrix version or content change?
|
|
84
|
+
- [ ] If Full-only, does the Lite forbidden-surface check still pass?
|
|
85
|
+
- [ ] If Lite-only, did Full retain its review, regression, and automation requirements?
|
|
86
|
+
|
|
87
|
+
## Lite Forbidden Surfaces
|
|
88
|
+
|
|
89
|
+
Lite is a document-only Skill surface. It must not contain product or runtime
|
|
90
|
+
surfaces that imply package installation, CLI operation, dashboard operation,
|
|
91
|
+
preset execution, generated governance, module registry ownership, lifecycle
|
|
92
|
+
commands, or a Node.js runtime requirement.
|
|
93
|
+
|
|
94
|
+
The canonical blocked pattern list is
|
|
95
|
+
`docs-release/architecture/document-contract-kernel/products/lite-forbidden-surfaces.txt`.
|
|
96
|
+
Run the guard with:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
node scripts/check-lite-forbidden-surfaces.mts
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
The guard scans Lite product source files only. It intentionally does not scan
|
|
103
|
+
this contract document or the forbidden pattern list, because those files must
|
|
104
|
+
name Full-only surfaces to define the boundary.
|
|
105
|
+
|
|
106
|
+
## Lite to Full Upgrade Path
|
|
107
|
+
|
|
108
|
+
A Lite project can be used as migration input for Full Harness adoption. Lite
|
|
109
|
+
does not promise that Full runtime adapters can read or update its files in
|
|
110
|
+
place.
|
|
111
|
+
|
|
112
|
+
1. Read Lite `AGENTS.md`, `context/`, `tasks/`, `regression.md`, and `lessons.md`.
|
|
113
|
+
2. Create the Full harness manifest and v2 directory structure.
|
|
114
|
+
3. Map `tasks/<id>/` into Full `planning/tasks/<id>/`.
|
|
115
|
+
4. If `review.md` or `visual_map.md` is missing, create adoption-needed follow-up
|
|
116
|
+
work or fill it within an approved migration budget.
|
|
117
|
+
5. Project Lite `regression.md` into Regression SSoT.
|
|
118
|
+
6. Project Lite `lessons.md` into lesson candidates, not promoted lesson details.
|
|
119
|
+
7. Run Full migration and check evidence before claiming Full adoption.
|
|
120
|
+
|
|
121
|
+
## Source, Overlay, Generator Path
|
|
122
|
+
|
|
123
|
+
The maintainable target is shared source plus product overlays:
|
|
124
|
+
|
|
125
|
+
```text
|
|
126
|
+
docs-release/architecture/document-contract-kernel/
|
|
127
|
+
README.md
|
|
128
|
+
products/
|
|
129
|
+
lite-skill-overlay.md
|
|
130
|
+
full-skill-overlay.md
|
|
131
|
+
lite-forbidden-surfaces.txt
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Future generator shape:
|
|
135
|
+
|
|
136
|
+
1. Render this shared Document Contract Kernel source.
|
|
137
|
+
2. Apply the Full or Lite product overlay.
|
|
138
|
+
3. Stamp the compatibility matrix version into the generated Skill.
|
|
139
|
+
4. Run Lite forbidden-surface checks after Lite render.
|
|
140
|
+
5. Run Full concept coverage checks after Full render.
|
|
141
|
+
|
|
142
|
+
Generated targets should be:
|
|
143
|
+
|
|
144
|
+
```text
|
|
145
|
+
SKILL.md
|
|
146
|
+
skills/coding-agent-harness-lite/SKILL.md
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
The Lite target is not created in Phase 0.5. This phase establishes the public
|
|
150
|
+
contract and drift guard that a later Lite implementation must use.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Full Skill Overlay Source
|
|
2
|
+
|
|
3
|
+
Compatibility matrix version: `document-contract-kernel-v0.5`.
|
|
4
|
+
|
|
5
|
+
The Full Skill keeps all Document Contract Kernel concepts and adds Full-only
|
|
6
|
+
automation, governance, migration, and runtime surfaces. Full must not copy or
|
|
7
|
+
fork the shared task semantics by hand.
|
|
8
|
+
|
|
9
|
+
## Shared Kernel Dependency
|
|
10
|
+
|
|
11
|
+
Full task packages, context documents, progress evidence, reviews,
|
|
12
|
+
walkthroughs, regression records, and lessons must stay compatible with the
|
|
13
|
+
Document Contract Kernel compatibility matrix.
|
|
14
|
+
|
|
15
|
+
## Full-only Surfaces
|
|
16
|
+
|
|
17
|
+
Full-only sections may describe package installation, CLI commands, Dashboard,
|
|
18
|
+
Workbench, Preset behavior, generated ledger files, Module Registry, lifecycle
|
|
19
|
+
commands, runtime checks, and source package requirements.
|
|
20
|
+
|
|
21
|
+
These sections must remain explicitly Full-only so later Lite generation can
|
|
22
|
+
exclude them without weakening Full's audit requirements.
|
|
23
|
+
|
|
24
|
+
## Coverage Rule
|
|
25
|
+
|
|
26
|
+
When a Full Skill edit changes the semantics of AGENTS, context, task package,
|
|
27
|
+
progress evidence, review, walkthrough, regression, or lessons, classify it as a
|
|
28
|
+
Kernel change and update the shared contract plus the Lite overlay in the same
|
|
29
|
+
task.
|
package/docs-release/architecture/document-contract-kernel/products/lite-forbidden-surfaces.txt
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Lines are regex patterns matched case-insensitively against Lite product source.
|
|
2
|
+
# The guard scans Lite source and generated Lite Skill files, not this list.
|
|
3
|
+
literal:npm install
|
|
4
|
+
regex:\bnpx\s+(?:--yes\s+)?coding-agent-harness\b
|
|
5
|
+
regex:\bharness\s+init\b
|
|
6
|
+
regex:\bharness\s+dev\b
|
|
7
|
+
regex:\bharness\s+check\b
|
|
8
|
+
regex:\bharness\s+(?:new-task|task-start|task-log|task-block|task-review|review-confirm|task-complete|lesson-promote|task-list)\b
|
|
9
|
+
literal:harness.yaml
|
|
10
|
+
literal:Dashboard
|
|
11
|
+
literal:Workbench
|
|
12
|
+
literal:Preset
|
|
13
|
+
literal:preset-creator
|
|
14
|
+
regex:generated\s+ledger
|
|
15
|
+
regex:generated\s+governance
|
|
16
|
+
regex:generated\s+indexes?
|
|
17
|
+
literal:Closeout-Index
|
|
18
|
+
literal:Module-Registry
|
|
19
|
+
literal:Module Registry
|
|
20
|
+
regex:lifecycle\s+CLI\s+commands?
|
|
21
|
+
regex:CLI\s+(?:checks?|commands?|operation|automation)
|
|
22
|
+
literal:Node.js version requirement
|
|
23
|
+
regex:node\s+version\s+requirement
|
|
24
|
+
regex:\bTaskRepository\b
|
|
25
|
+
regex:\bTaskOperations\b
|
|
26
|
+
regex:\bHarnessTransaction\b
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Lite Skill Overlay Source
|
|
2
|
+
|
|
3
|
+
Compatibility matrix version: `document-contract-kernel-v0.5`.
|
|
4
|
+
|
|
5
|
+
This source is for a future document-only Lite Skill. Lite keeps the shared
|
|
6
|
+
Document Contract Kernel concepts and removes runtime product surfaces.
|
|
7
|
+
|
|
8
|
+
## Positioning
|
|
9
|
+
|
|
10
|
+
Lite helps an agent set up and maintain a small project work protocol through
|
|
11
|
+
plain repository documents. It is document-only: the agent reads, writes, and
|
|
12
|
+
reviews project files directly.
|
|
13
|
+
|
|
14
|
+
## Required Lite Surfaces
|
|
15
|
+
|
|
16
|
+
- `AGENTS.md` as the agent entry protocol.
|
|
17
|
+
- `context/` for stable project facts.
|
|
18
|
+
- `tasks/` for reviewable task packages.
|
|
19
|
+
- `brief.md`, `task_plan.md`, `progress.md`, and `walkthrough.md` in each task.
|
|
20
|
+
- Optional `review.md`, `visual_map.md`, `regression.md`, and `lessons.md` when
|
|
21
|
+
the project needs them.
|
|
22
|
+
|
|
23
|
+
## Lite Operating Rules
|
|
24
|
+
|
|
25
|
+
- Keep all state human-readable and hand-maintainable.
|
|
26
|
+
- Do not require a project manifest.
|
|
27
|
+
- Do not require machine-produced project state.
|
|
28
|
+
- Treat missing review or visual material as adoption-needed if the project
|
|
29
|
+
later moves to the larger product.
|
|
30
|
+
- Keep upgrade notes short and link back to the compatibility matrix version.
|
|
31
|
+
|
|
32
|
+
## Upgrade Note
|
|
33
|
+
|
|
34
|
+
If the project later needs the larger Full Coding Agent Harness product, keep the
|
|
35
|
+
Lite documents as migration input. The shared document semantics are preserved so
|
|
36
|
+
an agent can map Lite task packages and context into the Full structure during an
|
|
37
|
+
explicit migration task.
|
|
@@ -118,7 +118,7 @@ flowchart LR
|
|
|
118
118
|
CLI --> Status["status / check<br/>derive health and failures"]
|
|
119
119
|
CLI --> Dashboard["dashboard / dev<br/>render human-readable state"]
|
|
120
120
|
CLI --> Migration["migrate-plan / migrate-run / migrate-verify<br/>legacy project adoption"]
|
|
121
|
-
CLI --> Task["new-task / task
|
|
121
|
+
CLI --> Task["new-task / task-*<br/>task lifecycle operations"]
|
|
122
122
|
CLI --> UserSkill["install-user / doctor-user<br/>local skill setup"]
|
|
123
123
|
|
|
124
124
|
Status --> Scanner["task scanner + check profiles"]
|
|
@@ -168,7 +168,7 @@ stateDiagram-v2
|
|
|
168
168
|
active --> in_review: task-review
|
|
169
169
|
in_review --> review_blocked: open P0-P2 finding
|
|
170
170
|
review_blocked --> in_review: finding closed or routed
|
|
171
|
-
in_review --> closing:
|
|
171
|
+
in_review --> closing: Workbench confirmation + task-complete
|
|
172
172
|
closing --> closed: closeout evidence linked
|
|
173
173
|
closed --> [*]
|
|
174
174
|
```
|
|
@@ -105,7 +105,7 @@ flowchart LR
|
|
|
105
105
|
CLI --> Status["status / check<br/>推导健康状态与失败项"]
|
|
106
106
|
CLI --> Dashboard["dashboard / dev<br/>渲染可读状态"]
|
|
107
107
|
CLI --> Migration["migrate-plan / migrate-run / migrate-verify<br/>旧项目迁移"]
|
|
108
|
-
CLI --> Task["new-task / task
|
|
108
|
+
CLI --> Task["new-task / task-*<br/>任务生命周期操作"]
|
|
109
109
|
CLI --> UserSkill["install-user / doctor-user<br/>本机 Skill 设置"]
|
|
110
110
|
|
|
111
111
|
Status --> Scanner["任务扫描器 + check profiles"]
|
|
@@ -153,7 +153,7 @@ stateDiagram-v2
|
|
|
153
153
|
active --> in_review: task-review
|
|
154
154
|
in_review --> review_blocked: 存在 P0-P2 finding
|
|
155
155
|
review_blocked --> in_review: finding 关闭或路由
|
|
156
|
-
in_review --> closing:
|
|
156
|
+
in_review --> closing: Workbench 人工确认 + task-complete
|
|
157
157
|
closing --> closed: 收口证据已链接
|
|
158
158
|
closed --> [*]
|
|
159
159
|
```
|