project-tiny-context-harness 0.2.82 → 0.2.83

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/README.md +9 -3
  2. package/assets/README.md +9 -3
  3. package/assets/README.zh-CN.md +7 -1
  4. package/assets/protected-harness-baseline.json +18 -0
  5. package/assets/skills/composite-long-task-workflow/SKILL.md +19 -1
  6. package/assets/skills/composite-long-task-workflow/assets/execution-binding.template.md +10 -0
  7. package/assets/skills/composite-long-task-workflow/assets/goal-objective.template.md +6 -15
  8. package/assets/skills/composite-long-task-workflow/references/composite-long-task-workflow-protocol.md +26 -14
  9. package/dist/commands/composite-long-task.js +45 -2
  10. package/dist/lib/superpowers-task-ac010.d.ts +6 -0
  11. package/dist/lib/superpowers-task-ac010.js +26 -0
  12. package/dist/lib/superpowers-task-assertion-normalizers.js +4 -0
  13. package/dist/lib/superpowers-task-assertions.js +18 -4
  14. package/dist/lib/superpowers-task-attempt.d.ts +4 -0
  15. package/dist/lib/superpowers-task-attempt.js +102 -0
  16. package/dist/lib/superpowers-task-command-specs.d.ts +3 -0
  17. package/dist/lib/superpowers-task-command-specs.js +52 -0
  18. package/dist/lib/superpowers-task-compile.d.ts +4 -1
  19. package/dist/lib/superpowers-task-compile.js +7 -1
  20. package/dist/lib/superpowers-task-contradictions.d.ts +6 -0
  21. package/dist/lib/superpowers-task-contradictions.js +126 -0
  22. package/dist/lib/superpowers-task-current-evidence.d.ts +3 -0
  23. package/dist/lib/superpowers-task-current-evidence.js +154 -0
  24. package/dist/lib/superpowers-task-derive.js +14 -0
  25. package/dist/lib/superpowers-task-evidence-kernel.d.ts +12 -0
  26. package/dist/lib/superpowers-task-evidence-kernel.js +351 -0
  27. package/dist/lib/superpowers-task-evidence-records.d.ts +2 -0
  28. package/dist/lib/superpowers-task-evidence-records.js +55 -0
  29. package/dist/lib/superpowers-task-evidence.d.ts +10 -0
  30. package/dist/lib/superpowers-task-evidence.js +141 -0
  31. package/dist/lib/superpowers-task-gates.js +36 -24
  32. package/dist/lib/superpowers-task-harness-drift.d.ts +11 -0
  33. package/dist/lib/superpowers-task-harness-drift.js +86 -0
  34. package/dist/lib/superpowers-task-protected-baseline.d.ts +10 -0
  35. package/dist/lib/superpowers-task-protected-baseline.js +47 -0
  36. package/dist/lib/superpowers-task-state-schema.d.ts +99 -3
  37. package/dist/lib/superpowers-task-state-schema.js +23 -1
  38. package/dist/lib/superpowers-task-state-shape.d.ts +3 -0
  39. package/dist/lib/superpowers-task-state-shape.js +50 -0
  40. package/dist/lib/superpowers-task-state.js +7 -36
  41. package/dist/lib/superpowers-task-status.js +11 -1
  42. package/dist/lib/superpowers-task-under-specified.d.ts +7 -0
  43. package/dist/lib/superpowers-task-under-specified.js +61 -0
  44. package/dist/lib/superpowers-task-validator.js +5 -27
  45. package/package.json +1 -1
  46. package/source-mappings.yaml +3 -0
@@ -0,0 +1,61 @@
1
+ import { isMachineVerifiableLayer } from "./superpowers-task-assertions.js";
2
+ const GENERATED_ONLY_EVIDENCE = /\b(matrix|verdict|validator|final[-_ ]?card|final[-_ ]?summary|evidence[-_ ]?index|derived\/)/i;
3
+ const MACHINE_UI_PROOF = /\b(browser|ui_browser|e2e|smoke|trace|playwright|route|owner surface)\b/i;
4
+ const MANUAL_ONLY_TEST = /\b(查看页面|人工确认|manual confirm|manually inspect|visual check only)\b/i;
5
+ export function findUnderSpecifiedAcs(state) {
6
+ return Object.entries(state.graph?.acceptance_criteria ?? {})
7
+ .map(([acId, ac]) => ({ ac_id: acId, reasons: underSpecifiedReasons(acId, ac) }))
8
+ .filter((item) => item.reasons.length > 0);
9
+ }
10
+ export function underSpecifiedReasons(acId, ac) {
11
+ if (ac.machine_blocking !== true && ac.assertion_result_required !== true) {
12
+ return [];
13
+ }
14
+ const reasons = [];
15
+ if (!trimmed(ac.assertion_command)) {
16
+ reasons.push(`${acId} under_specified: assertion_command is required for machine_blocking AC`);
17
+ }
18
+ if ((ac.assertion_artifacts ?? []).length === 0) {
19
+ reasons.push(`${acId} under_specified: assertion_artifacts are required for machine_blocking AC`);
20
+ }
21
+ if ((ac.positive_assertions ?? []).length === 0) {
22
+ reasons.push(`${acId} under_specified: positive_assertions are required for machine_blocking AC`);
23
+ }
24
+ if ((ac.negative_assertions ?? []).length === 0) {
25
+ reasons.push(`${acId} under_specified: negative_assertions are required for machine_blocking AC`);
26
+ }
27
+ if ((ac.invalid_completion_signals ?? []).length === 0) {
28
+ reasons.push(`${acId} under_specified: invalid_completion_signals are required for machine_blocking AC`);
29
+ }
30
+ if (ac.assertion_result_required !== true) {
31
+ reasons.push(`${acId} under_specified: machine_blocking AC must require assertion_result`);
32
+ }
33
+ const requiredLayers = ac.required_proof_layers ?? [];
34
+ if (requiredLayers.some((layer) => isMachineVerifiableLayer(`${acId}.${layer}`)) && !trimmed(ac.assertion_command)) {
35
+ reasons.push(`${acId} under_specified: machine proof layers cannot produce assertion_result without assertion_command`);
36
+ }
37
+ if (requiredLayers.includes("ui_browser") && !MACHINE_UI_PROOF.test(acEvidenceText(ac))) {
38
+ reasons.push(`${acId} under_specified: ui_browser AC requires browser/e2e/smoke/trace-backed proof`);
39
+ }
40
+ const finalEvidence = ac.final_evidence_expected ?? [];
41
+ if (finalEvidence.length > 0 && finalEvidence.every((item) => GENERATED_ONLY_EVIDENCE.test(item))) {
42
+ reasons.push(`${acId} under_specified: final_evidence_expected only names generated summary artifacts`);
43
+ }
44
+ const testCases = ac.test_cases ?? [];
45
+ if (testCases.length > 0 && testCases.every((item) => MANUAL_ONLY_TEST.test(item))) {
46
+ reasons.push(`${acId} under_specified: test_cases are manual-only`);
47
+ }
48
+ return reasons;
49
+ }
50
+ function acEvidenceText(ac) {
51
+ return [
52
+ ac.assertion_command ?? "",
53
+ ...(ac.assertion_artifacts ?? []),
54
+ ...(ac.verification_method ?? []),
55
+ ...(ac.test_cases ?? []),
56
+ ...(ac.final_evidence_expected ?? [])
57
+ ].join("\n");
58
+ }
59
+ function trimmed(value) {
60
+ return Boolean(value && value.trim());
61
+ }
@@ -4,7 +4,10 @@ import { findSensitiveEvidence } from "./plan-acceptance-evidence.js";
4
4
  import { primitiveText, repoRelative, resolveInputDir } from "./plan-validator-common.js";
5
5
  import { derivedMatchesState } from "./superpowers-task-derive.js";
6
6
  import { validatePlanCompletionConformance } from "./superpowers-task-conformance.js";
7
+ import { scanSuperpowersContradictions } from "./superpowers-task-contradictions.js";
8
+ import { evaluateTrustedEvidenceKernel } from "./superpowers-task-evidence-kernel.js";
7
9
  import { fullPopulationRequired, validateDeliveryContract, validateScopeConflicts } from "./superpowers-task-delivery.js";
10
+ import { hasUsableShape, validateShape } from "./superpowers-task-state-shape.js";
8
11
  import { loadSuperpowersState, sha256 } from "./superpowers-task-state.js";
9
12
  import { validateCanonicalStatuses } from "./superpowers-task-status.js";
10
13
  import { isRecord } from "./superpowers-task-state-schema.js";
@@ -39,6 +42,8 @@ export async function validateSuperpowersState(projectRoot, args = []) {
39
42
  validateScopeConflicts(state, errors);
40
43
  validateEvidenceRecords(state, errors);
41
44
  validateProofLayers(state, errors);
45
+ errors.push(...(await evaluateTrustedEvidenceKernel(targetDir, state)).errors);
46
+ errors.push(...(await scanSuperpowersContradictions(targetDir, state)).errors);
42
47
  validateAuditor(state, errors);
43
48
  validateFinalCompletion(state, errors);
44
49
  errors.push(...(await derivedMatchesState(targetDir, state)));
@@ -61,33 +66,6 @@ async function validateSourceHashes(workdir, state, errors) {
61
66
  }
62
67
  }
63
68
  }
64
- function validateShape(state, errors) {
65
- if (state.meta?.schema_version !== "superpowers-task-state-v1") {
66
- errors.push("task-state.json schema_version must be superpowers-task-state-v1");
67
- }
68
- for (const key of ["meta", "sources", "context", "delivery", "graph", "slices", "evidence", "gates", "progress", "blockers", "final"]) {
69
- if (!(key in state)) {
70
- errors.push(`task-state.json is missing section: ${key}`);
71
- }
72
- }
73
- }
74
- function hasUsableShape(state) {
75
- const candidate = state;
76
- return (isRecord(candidate.meta) &&
77
- isRecord(candidate.sources) &&
78
- isRecord(candidate.context) &&
79
- isRecord(candidate.delivery) &&
80
- isRecord(candidate.graph) &&
81
- isRecord(candidate.graph.plan_items) &&
82
- isRecord(candidate.graph.acceptance_criteria) &&
83
- isRecord(candidate.graph.proof_layers) &&
84
- Array.isArray(candidate.slices) &&
85
- Array.isArray(candidate.evidence) &&
86
- isRecord(candidate.gates) &&
87
- isRecord(candidate.progress) &&
88
- Array.isArray(candidate.blockers) &&
89
- isRecord(candidate.final));
90
- }
91
69
  function validateGraphReferences(state, errors) {
92
70
  const planIds = new Set(Object.keys(state.graph?.plan_items ?? {}));
93
71
  const acIds = new Set(Object.keys(state.graph?.acceptance_criteria ?? {}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "project-tiny-context-harness",
3
- "version": "0.2.82",
3
+ "version": "0.2.83",
4
4
  "description": "Minimal project memory and validation harness for AI coding agents.",
5
5
  "license": "MIT",
6
6
  "author": "Seven128",
@@ -17,6 +17,9 @@ source_mappings:
17
17
  - source: ".codex/ty-context-managed/make/ty-context.mk"
18
18
  target: "packages/ty-context/assets/make/ty-context.mk"
19
19
  mode: "copy-file"
20
+ - source: ".codex/ty-context-managed/protected-harness-baseline.json"
21
+ target: "packages/ty-context/assets/protected-harness-baseline.json"
22
+ mode: "copy-file"
20
23
  - source: ".codex/ty-context-managed/minimal_tools"
21
24
  target: "packages/ty-context/assets/tools"
22
25
  mode: "copy-tree"