project-tiny-context-harness 0.6.2 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +342 -333
  3. package/assets/README.md +497 -487
  4. package/assets/README.zh-CN.md +266 -256
  5. package/assets/agents/.gitkeep +1 -1
  6. package/assets/agents/AGENTS_CORE.md +56 -56
  7. package/assets/context_templates/architecture.md +33 -33
  8. package/assets/context_templates/area.md +39 -39
  9. package/assets/context_templates/context.toml +30 -30
  10. package/assets/context_templates/deployment.md +35 -35
  11. package/assets/context_templates/global.md +55 -55
  12. package/assets/context_templates/product-surface-contract.md +63 -63
  13. package/assets/context_templates/verification.md +32 -32
  14. package/assets/github/.gitkeep +1 -1
  15. package/assets/github/harness.yml +41 -41
  16. package/assets/make/.gitkeep +1 -1
  17. package/assets/make/ty-context.mk +48 -48
  18. package/assets/skills/context_development_engineer/SKILL.md +90 -90
  19. package/assets/skills/context_full_project_export/SKILL.md +70 -70
  20. package/assets/skills/context_harness_upgrade/SKILL.md +60 -60
  21. package/assets/skills/context_product_plan/SKILL.md +77 -77
  22. package/assets/skills/context_surface_contract/SKILL.md +171 -171
  23. package/assets/skills/context_uiux_design/SKILL.md +99 -99
  24. package/assets/skills/long-task-workflow/SKILL.md +75 -71
  25. package/assets/skills/long-task-workflow/agents/openai.yaml +4 -4
  26. package/assets/skills/long-task-workflow/references/authority-lifecycle.md +53 -41
  27. package/assets/skills/long-task-workflow/references/contract-authoring.md +57 -43
  28. package/assets/skills/long-task-workflow/references/evidence-design.md +40 -32
  29. package/assets/skills/normal-long-task/SKILL.md +12 -12
  30. package/assets/skills/source-plan-authoring/SKILL.md +295 -295
  31. package/dist/commands/check-modularity.js +10 -10
  32. package/dist/commands/long-task-authoring.js +65 -65
  33. package/dist/commands/long-task-command-args.d.ts +3 -0
  34. package/dist/commands/long-task-command-args.js +20 -0
  35. package/dist/commands/long-task-revision.d.ts +1 -0
  36. package/dist/commands/long-task-revision.js +137 -0
  37. package/dist/commands/long-task.js +20 -120
  38. package/dist/lib/long-task-authority-revision-details.d.ts +2 -0
  39. package/dist/lib/long-task-authority-revision-details.js +10 -0
  40. package/dist/lib/long-task-authority-revision-diagnosis.d.ts +24 -0
  41. package/dist/lib/long-task-authority-revision-diagnosis.js +141 -0
  42. package/dist/lib/long-task-authority-revision-enforcement.d.ts +3 -1
  43. package/dist/lib/long-task-authority-revision-enforcement.js +17 -9
  44. package/dist/lib/long-task-authority-revision-summary.d.ts +11 -0
  45. package/dist/lib/long-task-authority-revision-summary.js +99 -0
  46. package/dist/lib/long-task-authority-revision-types.d.ts +44 -1
  47. package/dist/lib/long-task-authority-revision.js +9 -1
  48. package/dist/lib/long-task-delivery-compiler.d.ts +3 -0
  49. package/dist/lib/long-task-delivery-compiler.js +5 -2
  50. package/dist/lib/long-task-state.d.ts +3 -15
  51. package/dist/lib/long-task-status-v2.d.ts +2 -0
  52. package/dist/lib/long-task-status-v2.js +12 -2
  53. package/dist/lib/long-task-verifier-v2.d.ts +4 -0
  54. package/dist/lib/long-task-verifier-v2.js +1 -1
  55. package/migrations/README.md +8 -8
  56. package/package.json +5 -1
  57. package/source-mappings.yaml +25 -25
@@ -0,0 +1,141 @@
1
+ import path from "node:path";
2
+ import { compileDeliveryContract } from "./long-task-delivery-compiler.js";
3
+ import { projectAuthorityRevisionDecision } from "./long-task-authority-revision-summary.js";
4
+ import { activeAuthorityIdentityMatches, loadActiveLongTaskAuthority, } from "./long-task-state.js";
5
+ import { allCompiledChecks, runDeliveryChecks, selectChecks, } from "./long-task-verifier-v2.js";
6
+ import { createWorkspaceSnapshot, repositoryRoot, } from "./long-task-workspace.js";
7
+ export async function diagnoseAuthorityRevision(workdirInput, selection = {}) {
8
+ const repository = await repositoryRoot(process.cwd());
9
+ const loaded = await loadActiveLongTaskAuthority(repository, {
10
+ migrate_legacy: true,
11
+ });
12
+ const active = loaded.authority;
13
+ if (!active)
14
+ throw new Error("active_task_missing");
15
+ const workdir = path.resolve(workdirInput);
16
+ if (active.workdir !== workdir)
17
+ throw new Error("active_task_workdir_mismatch");
18
+ const revisionCapture = {
19
+ proposal: null,
20
+ };
21
+ const candidate = await compileDeliveryContract(workdir, repository, {
22
+ revise: true,
23
+ previous_authority: active.authority_snapshot,
24
+ authority_revision_mode: "diagnose",
25
+ on_authority_revision(value) {
26
+ revisionCapture.proposal = value;
27
+ },
28
+ });
29
+ if (candidate.task.id !== active.task_id)
30
+ throw new Error("active_task_id_mismatch");
31
+ if (!(await activeIdentityStillMatches(repository, active)))
32
+ throw new Error("active_authority_changed_during_revision_diagnosis");
33
+ const proposal = revisionCapture.proposal;
34
+ if (!proposal)
35
+ return result({
36
+ status: "no_authority_change",
37
+ activeIdentity: active.active_authority_identity,
38
+ candidateIdentity: candidate.compiled_identity,
39
+ revision: null,
40
+ selection,
41
+ });
42
+ const decision = projectAuthorityRevisionDecision(proposal);
43
+ if (proposal.change_class === "monotonic_evidence_strengthening")
44
+ return result({
45
+ status: "monotonic_revision_available",
46
+ activeIdentity: active.active_authority_identity,
47
+ candidateIdentity: candidate.compiled_identity,
48
+ revision: decision,
49
+ selection,
50
+ });
51
+ if (proposal.change_class !== "scope_only_expansion")
52
+ return result({
53
+ status: "protected_change_previewed",
54
+ activeIdentity: active.active_authority_identity,
55
+ candidateIdentity: candidate.compiled_identity,
56
+ revision: decision,
57
+ selection,
58
+ });
59
+ const selected = selectChecks(candidate, selection);
60
+ const activeCheckIds = new Set(allCompiledChecks(active.authority_snapshot).map((check) => check.internal_id));
61
+ const runnable = selected.filter((check) => activeCheckIds.has(check.internal_id));
62
+ const skipped = selected
63
+ .filter((check) => !activeCheckIds.has(check.internal_id))
64
+ .map((check) => check.internal_id)
65
+ .sort();
66
+ if (!runnable.length)
67
+ return result({
68
+ status: "scope_candidate_previewed",
69
+ activeIdentity: active.active_authority_identity,
70
+ candidateIdentity: candidate.compiled_identity,
71
+ revision: decision,
72
+ selection,
73
+ skipped,
74
+ });
75
+ const snapshot = await createWorkspaceSnapshot(candidate.repository_root, candidate.workdir, `revision-diagnosis-${candidate.task.id}`);
76
+ try {
77
+ const run = await runDeliveryChecks(candidate, snapshot, runnable, true);
78
+ const unchanged = await activeIdentityStillMatches(repository, active);
79
+ if (!unchanged)
80
+ run.findings.push(activeAuthorityChangedFinding());
81
+ return result({
82
+ status: unchanged ? "scope_candidate_exercised" : "candidate_stale",
83
+ activeIdentity: active.active_authority_identity,
84
+ candidateIdentity: candidate.compiled_identity,
85
+ revision: decision,
86
+ selection,
87
+ skipped,
88
+ diagnosticsExecuted: true,
89
+ snapshotSha256: snapshot.manifest.snapshot_sha256,
90
+ checkResults: run.check_results,
91
+ findings: run.findings,
92
+ });
93
+ }
94
+ finally {
95
+ await snapshot.dispose();
96
+ }
97
+ }
98
+ async function activeIdentityStillMatches(repository, active) {
99
+ try {
100
+ const current = (await loadActiveLongTaskAuthority(repository)).authority;
101
+ return (current !== null &&
102
+ activeAuthorityIdentityMatches(current, {
103
+ task_id: active.task_id,
104
+ authority_revision: active.authority_revision,
105
+ compiled_identity: active.active_authority_identity,
106
+ worktree_identity: active.worktree_identity,
107
+ }));
108
+ }
109
+ catch {
110
+ return false;
111
+ }
112
+ }
113
+ function activeAuthorityChangedFinding() {
114
+ return {
115
+ code: "active_authority_changed_during_revision_diagnosis",
116
+ outcome_key: null,
117
+ check_key: null,
118
+ message: "Active Authority changed while candidate diagnosis was running.",
119
+ next_action: "Discard these transient results and diagnose the current Contract against the new Active Authority.",
120
+ };
121
+ }
122
+ function result(input) {
123
+ return {
124
+ schema_version: "long-task-authority-revision-diagnosis-v2",
125
+ status: input.status,
126
+ active_compiled_identity: input.activeIdentity,
127
+ candidate_compiled_identity: input.candidateIdentity,
128
+ revision: input.revision,
129
+ acceptance_authorized: false,
130
+ progress_written: false,
131
+ pending_revision_written: false,
132
+ diagnostics_executed: input.diagnosticsExecuted ?? false,
133
+ selected_outcome: input.selection.outcome ?? null,
134
+ selected_check: input.selection.check ?? null,
135
+ skipped_candidate_checks: input.skipped ?? [],
136
+ snapshot_sha256: input.snapshotSha256 ?? null,
137
+ check_results: input.checkResults ?? [],
138
+ findings: input.findings ?? [],
139
+ completed_at: new Date().toISOString(),
140
+ };
141
+ }
@@ -1,3 +1,5 @@
1
+ import type { AuthorityRevisionProposalV2 } from "./long-task-authority-revision-types.js";
1
2
  import type { AuthorityHashesV2, CompiledDeliveryContractV2, CompiledOutcomeV2, DeliveryContractV2, NextAuthorityMaterialsV2, VerifierIdentityV2 } from "./long-task-delivery-types.js";
2
3
  export declare function assertRiskNotDowngraded(previous: CompiledDeliveryContractV2, nextLevel: "standard" | "strict", nextReasons: string[]): void;
3
- export declare function enforceAuthorityRevision(previous: CompiledDeliveryContractV2, nextContract: DeliveryContractV2, nextHashes: AuthorityHashesV2, nextMaterials: NextAuthorityMaterialsV2, nextGlobalChecks: CompiledDeliveryContractV2["global"]["acceptance"]["checks"], nextOutcomes: CompiledOutcomeV2[], nextVerifier: VerifierIdentityV2, workdir: string, riskFloor: "standard" | "strict"): Promise<void>;
4
+ export declare function buildAuthorityRevisionProposal(previous: CompiledDeliveryContractV2, nextContract: DeliveryContractV2, nextHashes: AuthorityHashesV2, nextMaterials: NextAuthorityMaterialsV2, nextGlobalChecks: CompiledDeliveryContractV2["global"]["acceptance"]["checks"], nextOutcomes: CompiledOutcomeV2[], nextVerifier: VerifierIdentityV2, riskFloor: "standard" | "strict"): AuthorityRevisionProposalV2;
5
+ export declare function enforceAuthorityRevision(proposal: AuthorityRevisionProposalV2, workdir: string): Promise<void>;
@@ -1,6 +1,7 @@
1
1
  import { changedAuthoritySections } from "./long-task-authority.js";
2
2
  import { authorityMaterialHashes, compiledAuthorityMaterials, } from "./long-task-authority-materials.js";
3
- import { authorityRevisionDiff, } from "./long-task-authority-revision.js";
3
+ import { authorityRevisionDiff } from "./long-task-authority-revision.js";
4
+ import { classifyAuthorityRevision, summarizeAuthorityRevision, } from "./long-task-authority-revision-summary.js";
4
5
  import { authorityRevisionApproved, writePendingAuthorityRevision, } from "./long-task-state.js";
5
6
  import { canonicalValueJson, sha256Hex } from "./strict-codec.js";
6
7
  export function assertRiskNotDowngraded(previous, nextLevel, nextReasons) {
@@ -11,11 +12,11 @@ export function assertRiskNotDowngraded(previous, nextLevel, nextReasons) {
11
12
  if (removed.length)
12
13
  throw new Error(`authority_risk_downgrade_rejected:${removed.join(",")}`);
13
14
  }
14
- export async function enforceAuthorityRevision(previous, nextContract, nextHashes, nextMaterials, nextGlobalChecks, nextOutcomes, nextVerifier, workdir, riskFloor) {
15
+ export function buildAuthorityRevisionProposal(previous, nextContract, nextHashes, nextMaterials, nextGlobalChecks, nextOutcomes, nextVerifier, riskFloor) {
15
16
  const previousMaterials = compiledAuthorityMaterials(previous);
16
17
  const diff = authorityRevisionDiff(previous, nextContract, nextHashes, nextMaterials, nextGlobalChecks, nextOutcomes, nextVerifier);
17
- if (!diff.reduction_reasons.length)
18
- return;
18
+ const changeClass = classifyAuthorityRevision(diff);
19
+ const approvalSummary = summarizeAuthorityRevision(diff, nextContract.outcomes.map((outcome) => outcome.key));
19
20
  const unsignedRevision = {
20
21
  previous_hashes: previous.authority_hashes,
21
22
  next_hashes: nextHashes,
@@ -26,16 +27,23 @@ export async function enforceAuthorityRevision(previous, nextContract, nextHashe
26
27
  changed_authority_sections: changedAuthoritySections(previous.authority_hashes, nextHashes),
27
28
  revision_diff: diff,
28
29
  new_risk_floor: riskFloor,
29
- affected_outcomes_or_contracts: nextContract.outcomes.map((outcome) => outcome.key),
30
+ affected_outcomes_or_contracts: approvalSummary.affected_outcomes,
31
+ change_class: changeClass,
32
+ approval_required: diff.reduction_reasons.length > 0,
33
+ approval_summary: approvalSummary,
30
34
  };
31
35
  const revisionIdentity = sha256Hex(canonicalValueJson(unsignedRevision));
32
- if (!(await authorityRevisionApproved(workdir, revisionIdentity))) {
36
+ return { ...unsignedRevision, revision_identity: revisionIdentity };
37
+ }
38
+ export async function enforceAuthorityRevision(proposal, workdir) {
39
+ if (!proposal.approval_required)
40
+ return;
41
+ if (!(await authorityRevisionApproved(workdir, proposal.revision_identity))) {
33
42
  await writePendingAuthorityRevision(workdir, {
34
43
  schema_version: "long-task-authority-revision-pending-v2",
35
- ...unsignedRevision,
36
- revision_identity: revisionIdentity,
44
+ ...proposal,
37
45
  created_at: new Date().toISOString(),
38
46
  });
39
- throw new Error(`authority_change_requires_user_decision:${revisionIdentity}`);
47
+ throw new Error(`authority_change_requires_user_decision:${proposal.revision_identity}`);
40
48
  }
41
49
  }
@@ -0,0 +1,11 @@
1
+ import type { AuthorityRevisionApprovalSummaryV2, AuthorityRevisionChangeClassV2, AuthorityRevisionDecisionV2, AuthorityRevisionDiffV2 } from "./long-task-authority-revision-types.js";
2
+ export declare function classifyAuthorityRevision(diff: AuthorityRevisionDiffV2): AuthorityRevisionChangeClassV2;
3
+ export declare function summarizeAuthorityRevision(diff: AuthorityRevisionDiffV2, outcomeKeys: string[]): AuthorityRevisionApprovalSummaryV2;
4
+ export declare function projectAuthorityRevisionDecision(value: {
5
+ revision_identity: string;
6
+ revision_diff: AuthorityRevisionDiffV2;
7
+ affected_outcomes_or_contracts: string[];
8
+ change_class?: AuthorityRevisionChangeClassV2;
9
+ approval_required?: boolean;
10
+ approval_summary?: AuthorityRevisionApprovalSummaryV2;
11
+ }): AuthorityRevisionDecisionV2;
@@ -0,0 +1,99 @@
1
+ const SCOPE_EXPANSION_REASONS = new Set([
2
+ "owner_path_expanded",
3
+ "expected_change_path_expanded",
4
+ "allowed_path_expanded",
5
+ ]);
6
+ const PROOF_REDUCTION_REASONS = new Set([
7
+ "check_removed",
8
+ "negative_assertion_removed",
9
+ "proof_surface_changed",
10
+ "runner_definition_changed",
11
+ "verification_input_removed_or_replaced",
12
+ "input_path_coverage_reduced",
13
+ "expected_output_requirement_weakened",
14
+ "artifact_removed",
15
+ "environment_requirement_removed",
16
+ "binding_removed_or_expanded",
17
+ "obligation_removed_or_weakened",
18
+ "rollback_or_recovery_weakened",
19
+ "counterfactual_removed",
20
+ "population_weakened",
21
+ "verifier_content_changed",
22
+ "acceptance_not_monotonic",
23
+ ]);
24
+ export function classifyAuthorityRevision(diff) {
25
+ if (!diff.reduction_reasons.length)
26
+ return "monotonic_evidence_strengthening";
27
+ if (diff.reduction_reasons.every((reason) => SCOPE_EXPANSION_REASONS.has(reason)))
28
+ return "scope_only_expansion";
29
+ return "protected_semantic_or_proof_change";
30
+ }
31
+ export function summarizeAuthorityRevision(diff, outcomeKeys) {
32
+ const affectedOutcomes = scopeAffectedOutcomes(diff);
33
+ const changeClass = classifyAuthorityRevision(diff);
34
+ return {
35
+ product_semantics_changed: diff.product_claims_added.length > 0 ||
36
+ diff.product_claims_removed.length > 0 ||
37
+ diff.product_claims_changed.length > 0 ||
38
+ diff.product_semantics_changed.length > 0,
39
+ global_or_technical_semantics_changed: diff.global_semantics_changed.length > 0 ||
40
+ diff.technical_obligations_changed,
41
+ source_or_claims_changed: diff.source_claims_changed ||
42
+ diff.source_claims_added.length > 0 ||
43
+ diff.source_claims_removed_or_changed.length > 0 ||
44
+ diff.source_paths_removed_or_replaced.length > 0 ||
45
+ diff.source_files_added.length > 0 ||
46
+ diff.source_files_removed.length > 0 ||
47
+ diff.source_files_changed.length > 0,
48
+ context_authority_changed: diff.context_snapshot_mode_changed ||
49
+ diff.context_topology_changed ||
50
+ diff.context_files_added.length > 0 ||
51
+ diff.context_files_removed.length > 0 ||
52
+ diff.context_files_changed.length > 0,
53
+ acceptance_or_proof_weakened: diff.reduction_reasons.some((reason) => PROOF_REDUCTION_REASONS.has(reason)),
54
+ verifier_or_runner_changed: diff.verifier_content_changed ||
55
+ diff.verifier_runtime_locator_changed ||
56
+ diff.runner_definitions_changed.length > 0,
57
+ write_scope_expanded: diff.owner_or_path_boundary_changed,
58
+ risk_changed: diff.risk_changed,
59
+ external_confirmations_changed: diff.external_confirmations_changed,
60
+ added_verification_dependencies: uniqueSorted([
61
+ ...diff.verification_inputs_added,
62
+ ...diff.input_paths_added,
63
+ ]),
64
+ expanded_owner_paths: uniqueSorted(diff.owner_paths_expanded),
65
+ expanded_expected_change_paths: uniqueSorted(diff.expected_change_paths_expanded),
66
+ expanded_allowed_support_paths: uniqueSorted(diff.allowed_paths_expanded),
67
+ protected_reasons: uniqueSorted(diff.reduction_reasons),
68
+ affected_outcomes: changeClass === "scope_only_expansion" && affectedOutcomes.length > 0
69
+ ? affectedOutcomes
70
+ : uniqueSorted(outcomeKeys),
71
+ };
72
+ }
73
+ export function projectAuthorityRevisionDecision(value) {
74
+ const diff = {
75
+ ...value.revision_diff,
76
+ verification_inputs_added: value.revision_diff.verification_inputs_added ?? [],
77
+ input_paths_added: value.revision_diff.input_paths_added ?? [],
78
+ external_confirmations_changed: value.revision_diff.external_confirmations_changed ?? false,
79
+ };
80
+ return {
81
+ revision_identity: value.revision_identity,
82
+ change_class: value.change_class ?? classifyAuthorityRevision(diff),
83
+ approval_required: value.approval_required ?? true,
84
+ approval_summary: value.approval_summary ??
85
+ summarizeAuthorityRevision(diff, value.affected_outcomes_or_contracts),
86
+ };
87
+ }
88
+ function scopeAffectedOutcomes(diff) {
89
+ return uniqueSorted([
90
+ ...diff.owner_paths_expanded,
91
+ ...diff.expected_change_paths_expanded,
92
+ ...diff.allowed_paths_expanded,
93
+ ]
94
+ .map((entry) => entry.split(":", 1)[0])
95
+ .filter((key) => key.length > 0 && key !== "GLOBAL"));
96
+ }
97
+ function uniqueSorted(values) {
98
+ return [...new Set(values)].sort((left, right) => left.localeCompare(right));
99
+ }
@@ -1,4 +1,44 @@
1
- import type { VerifierIdentityV2 } from "./long-task-authority-types.js";
1
+ import type { AuthorityHashesV2, AuthorityMaterialHashesV2, NextAuthorityMaterialsV2, VerifierIdentityV2 } from "./long-task-authority-types.js";
2
+ export type AuthorityRevisionChangeClassV2 = "monotonic_evidence_strengthening" | "scope_only_expansion" | "protected_semantic_or_proof_change";
3
+ export interface AuthorityRevisionApprovalSummaryV2 {
4
+ product_semantics_changed: boolean;
5
+ global_or_technical_semantics_changed: boolean;
6
+ source_or_claims_changed: boolean;
7
+ context_authority_changed: boolean;
8
+ acceptance_or_proof_weakened: boolean;
9
+ verifier_or_runner_changed: boolean;
10
+ write_scope_expanded: boolean;
11
+ risk_changed: boolean;
12
+ external_confirmations_changed: boolean;
13
+ added_verification_dependencies: string[];
14
+ expanded_owner_paths: string[];
15
+ expanded_expected_change_paths: string[];
16
+ expanded_allowed_support_paths: string[];
17
+ protected_reasons: string[];
18
+ affected_outcomes: string[];
19
+ }
20
+ export interface AuthorityRevisionProposalV2 {
21
+ previous_hashes: AuthorityHashesV2;
22
+ next_hashes: AuthorityHashesV2;
23
+ previous_materials: NextAuthorityMaterialsV2;
24
+ next_materials: NextAuthorityMaterialsV2;
25
+ previous_material_hashes: AuthorityMaterialHashesV2;
26
+ next_material_hashes: AuthorityMaterialHashesV2;
27
+ changed_authority_sections: string[];
28
+ revision_diff: AuthorityRevisionDiffV2;
29
+ new_risk_floor: "standard" | "strict";
30
+ affected_outcomes_or_contracts: string[];
31
+ change_class: AuthorityRevisionChangeClassV2;
32
+ approval_required: boolean;
33
+ approval_summary: AuthorityRevisionApprovalSummaryV2;
34
+ revision_identity: string;
35
+ }
36
+ export interface AuthorityRevisionDecisionV2 {
37
+ revision_identity: string;
38
+ change_class: AuthorityRevisionChangeClassV2;
39
+ approval_required: boolean;
40
+ approval_summary: AuthorityRevisionApprovalSummaryV2;
41
+ }
2
42
  export interface AuthorityRevisionDiffV2 {
3
43
  product_claims_added: string[];
4
44
  product_claims_removed: string[];
@@ -26,7 +66,9 @@ export interface AuthorityRevisionDiffV2 {
26
66
  allowed_paths_expanded: string[];
27
67
  forbidden_paths_removed: string[];
28
68
  runner_definitions_changed: string[];
69
+ verification_inputs_added: string[];
29
70
  verification_inputs_removed_or_replaced: string[];
71
+ input_paths_added: string[];
30
72
  input_paths_removed_or_narrowed: string[];
31
73
  expected_output_paths_removed_or_weakened: string[];
32
74
  artifacts_removed: string[];
@@ -36,6 +78,7 @@ export interface AuthorityRevisionDiffV2 {
36
78
  rollback_or_recovery_weakened: string[];
37
79
  counterfactuals_removed: string[];
38
80
  population_weakened: string[];
81
+ external_confirmations_changed: boolean;
39
82
  verifier_content_changed: boolean;
40
83
  verifier_runtime_locator_changed: boolean;
41
84
  verifier_files_changed: string[];
@@ -1,7 +1,7 @@
1
1
  import { acceptanceSemanticsChanged, isMonotonicAcceptanceStrengthening, } from "./long-task-authority.js";
2
2
  import { authorityMaterialRevisionDiff, changedProductClaimSemantics, sourceClaimAdditions, } from "./long-task-authority-material-diff.js";
3
3
  import { compileProductClaimCoverage } from "./long-task-claims.js";
4
- import { addedValues, bindingReductions, changedRunnerFields, checkIndex, counterfactualReductions, expandedPatterns, globalCounterfactualReductions, obligationReductions, removedExactValues, removedGlobalForbiddenPaths, removedOrNarrowedInputPaths, removedOrReplacedVerificationInputs, removedOrWeakenedExpectedOutputPaths, removedStructuredValues, removedValues, rollbackReductions, same, sourceClaimReductions, } from "./long-task-authority-revision-details.js";
4
+ import { addedInputPaths, addedVerificationInputs, addedValues, bindingReductions, changedRunnerFields, checkIndex, counterfactualReductions, expandedPatterns, globalCounterfactualReductions, obligationReductions, removedExactValues, removedGlobalForbiddenPaths, removedOrNarrowedInputPaths, removedOrReplacedVerificationInputs, removedOrWeakenedExpectedOutputPaths, removedStructuredValues, removedValues, rollbackReductions, same, sourceClaimReductions, } from "./long-task-authority-revision-details.js";
5
5
  import { verifierAuthorityDiff } from "./long-task-verifier-authority.js";
6
6
  export function authorityRevisionDiff(previous, next, nextHashes, nextMaterials, nextGlobalChecks, nextOutcomes, nextVerifier) {
7
7
  const materialDiff = authorityMaterialRevisionDiff(previous, nextMaterials);
@@ -19,7 +19,9 @@ export function authorityRevisionDiff(previous, next, nextHashes, nextMaterials,
19
19
  const negativeAssertionsRemoved = [];
20
20
  const proofSurfacesChanged = [];
21
21
  const runnerDefinitionsChanged = [];
22
+ const verificationInputsAdded = [];
22
23
  const verificationInputsRemovedOrReplaced = [];
24
+ const inputPathsAdded = [];
23
25
  const inputPathsRemovedOrNarrowed = [];
24
26
  const expectedOutputPathsRemovedOrWeakened = [];
25
27
  const artifactsRemoved = [];
@@ -34,7 +36,9 @@ export function authorityRevisionDiff(previous, next, nextHashes, nextMaterials,
34
36
  if (before.proof_surface !== after.proof_surface)
35
37
  proofSurfacesChanged.push(`${identity}:${before.proof_surface}->${after.proof_surface}`);
36
38
  runnerDefinitionsChanged.push(...changedRunnerFields(identity, before, after));
39
+ verificationInputsAdded.push(...addedVerificationInputs(identity, before, after));
37
40
  verificationInputsRemovedOrReplaced.push(...removedOrReplacedVerificationInputs(identity, before, after));
41
+ inputPathsAdded.push(...addedInputPaths(identity, before, after));
38
42
  inputPathsRemovedOrNarrowed.push(...removedOrNarrowedInputPaths(identity, before, after));
39
43
  expectedOutputPathsRemovedOrWeakened.push(...removedOrWeakenedExpectedOutputPaths(identity, before, after));
40
44
  artifactsRemoved.push(...removedExactValues(identity, before.artifact_globs, after.artifact_globs));
@@ -76,6 +80,7 @@ export function authorityRevisionDiff(previous, next, nextHashes, nextMaterials,
76
80
  const riskChanged = previous.authority_hashes.risk_authority_hash !==
77
81
  nextHashes.risk_authority_hash;
78
82
  const acceptanceChanged = acceptanceSemanticsChanged(previous, next);
83
+ const externalConfirmationsChanged = !same(previous.global.acceptance.external_confirmations, next.global.acceptance.external_confirmations);
79
84
  const monotonic = isMonotonicAcceptanceStrengthening(previous, next);
80
85
  const reductionReasons = [
81
86
  ...(productClaimsAdded.length ? ["product_claim_added"] : []),
@@ -157,7 +162,9 @@ export function authorityRevisionDiff(previous, next, nextHashes, nextMaterials,
157
162
  allowed_paths_expanded: allowedPathsExpanded,
158
163
  forbidden_paths_removed: forbiddenPathsRemoved,
159
164
  runner_definitions_changed: runnerDefinitionsChanged,
165
+ verification_inputs_added: verificationInputsAdded,
160
166
  verification_inputs_removed_or_replaced: verificationInputsRemovedOrReplaced,
167
+ input_paths_added: inputPathsAdded,
161
168
  input_paths_removed_or_narrowed: inputPathsRemovedOrNarrowed,
162
169
  expected_output_paths_removed_or_weakened: expectedOutputPathsRemovedOrWeakened,
163
170
  artifacts_removed: artifactsRemoved,
@@ -167,6 +174,7 @@ export function authorityRevisionDiff(previous, next, nextHashes, nextMaterials,
167
174
  rollback_or_recovery_weakened: rollbackOrRecoveryWeakened,
168
175
  counterfactuals_removed: counterfactualsRemoved,
169
176
  population_weakened: populationWeakened,
177
+ external_confirmations_changed: externalConfirmationsChanged,
170
178
  ...verifierDiff,
171
179
  source_claims_changed: previous.authority_hashes.source_authority_hash !==
172
180
  nextHashes.source_authority_hash,
@@ -1,4 +1,5 @@
1
1
  import type { CompiledDeliveryContractV2, InitialTaskBaseV2 } from "./long-task-delivery-types.js";
2
+ import type { AuthorityRevisionProposalV2 } from "./long-task-authority-revision-types.js";
2
3
  export interface CompileDeliveryOptionsV2 {
3
4
  require_completion_gate?: boolean;
4
5
  revise?: boolean;
@@ -6,5 +7,7 @@ export interface CompileDeliveryOptionsV2 {
6
7
  initial_task_base?: InitialTaskBaseV2;
7
8
  authority_revision?: number;
8
9
  previous_authority?: CompiledDeliveryContractV2 | null;
10
+ authority_revision_mode?: "enforce" | "diagnose";
11
+ on_authority_revision?: (proposal: AuthorityRevisionProposalV2) => void;
9
12
  }
10
13
  export declare function compileDeliveryContract(workdirInput: string, projectRootInput?: string, options?: CompileDeliveryOptionsV2): Promise<CompiledDeliveryContractV2>;
@@ -5,7 +5,7 @@ import { canonicalValueJson, sha256Hex } from "./strict-codec.js";
5
5
  import { changedAuthoritySections, computeAuthorityHashes, } from "./long-task-authority.js";
6
6
  import { authorityMaterialsChanged, compiledAuthorityMaterials, computeAuthorityMaterials, } from "./long-task-authority-materials.js";
7
7
  import { normalizeContextAuthoritySnapshot } from "./long-task-context-authority.js";
8
- import { assertRiskNotDowngraded, enforceAuthorityRevision, } from "./long-task-authority-revision-enforcement.js";
8
+ import { assertRiskNotDowngraded, buildAuthorityRevisionProposal, enforceAuthorityRevision, } from "./long-task-authority-revision-enforcement.js";
9
9
  import { validateActualRiskSurfaces } from "./long-task-risk-surfaces.js";
10
10
  import { captureVerifierIdentity } from "./long-task-verifier-identity.js";
11
11
  import { verifierAuthorityDiff } from "./long-task-verifier-authority.js";
@@ -83,7 +83,10 @@ export async function compileDeliveryContract(workdirInput, projectRootInput = p
83
83
  if (options.revise && authorityChanged) {
84
84
  assertRiskNotDowngraded(previous, risk.effective_level, risk.reasons);
85
85
  authorityRevision = previous.authority_revision + 1;
86
- await enforceAuthorityRevision(previous, contract, authorityHashes, authorityMaterials, globalChecks, outcomes, verifier, workdir, risk.minimum_level);
86
+ const proposal = buildAuthorityRevisionProposal(previous, contract, authorityHashes, authorityMaterials, globalChecks, outcomes, verifier, risk.minimum_level);
87
+ options.on_authority_revision?.(proposal);
88
+ if (options.authority_revision_mode !== "diagnose")
89
+ await enforceAuthorityRevision(proposal, workdir);
87
90
  }
88
91
  }
89
92
  const unsigned = {
@@ -1,4 +1,5 @@
1
- import type { AuthorityMaterialHashesV2, AuthorityHashesV2, CompiledDeliveryContractV2, FinalReceiptV2, InitialTaskBaseV2, NextAuthorityMaterialsV2, ProgressRecordV2, VerifierIdentityV2 } from "./long-task-delivery-types.js";
1
+ import type { CompiledDeliveryContractV2, FinalReceiptV2, InitialTaskBaseV2, ProgressRecordV2, VerifierIdentityV2 } from "./long-task-delivery-types.js";
2
+ import type { AuthorityRevisionProposalV2 } from "./long-task-authority-revision-types.js";
2
3
  export interface ActiveLongTaskAuthorityV3 {
3
4
  schema_version: "active-long-task-authority-v3";
4
5
  task_id: string;
@@ -34,21 +35,8 @@ export interface StagedCompiledDeliveryContractV2 {
34
35
  publish(): Promise<void>;
35
36
  discard(): Promise<void>;
36
37
  }
37
- export interface PendingAuthorityRevisionV2 {
38
+ export interface PendingAuthorityRevisionV2 extends AuthorityRevisionProposalV2 {
38
39
  schema_version: "long-task-authority-revision-pending-v2";
39
- previous_hashes: AuthorityHashesV2;
40
- next_hashes: AuthorityHashesV2;
41
- previous_materials: NextAuthorityMaterialsV2;
42
- next_materials: NextAuthorityMaterialsV2;
43
- previous_material_hashes: AuthorityMaterialHashesV2;
44
- next_material_hashes: AuthorityMaterialHashesV2;
45
- changed_authority_sections: string[];
46
- revision_diff: Record<string, unknown> & {
47
- reduction_reasons: string[];
48
- };
49
- new_risk_floor: "standard" | "strict";
50
- affected_outcomes_or_contracts: string[];
51
- revision_identity: string;
52
40
  created_at: string;
53
41
  }
54
42
  export declare function runtimePath(workdir: string, file?: string): string;
@@ -1,3 +1,4 @@
1
+ import type { AuthorityRevisionDecisionV2 } from "./long-task-authority-revision-types.js";
1
2
  import type { ExternalConfirmationV2, FinalReceiptV2, LongTaskFindingV2, OutcomeStatusV2 } from "./long-task-delivery-types.js";
2
3
  import { type AuditGateStatusV2 } from "./long-task-status-projection.js";
3
4
  export interface DeliveryStatusV2 {
@@ -17,6 +18,7 @@ export interface DeliveryStatusV2 {
17
18
  progress_passing: string[];
18
19
  progress_failing: string[];
19
20
  findings: LongTaskFindingV2[];
21
+ pending_authority_revision: AuthorityRevisionDecisionV2 | null;
20
22
  }
21
23
  export declare function readDeliveryStatus(workdir: string): Promise<DeliveryStatusV2>;
22
24
  export declare function resumeDeliveryTask(workdir: string): Promise<Record<string, unknown>>;
@@ -1,8 +1,9 @@
1
1
  import path from "node:path";
2
2
  import { compileDeliveryContract } from "./long-task-delivery-compiler.js";
3
+ import { projectAuthorityRevisionDecision } from "./long-task-authority-revision-summary.js";
3
4
  import { runDeliveryFinalGate } from "./long-task-final-v2.js";
4
5
  import { deliveryCompileFreshness } from "./long-task-freshness.js";
5
- import { activeAuthorityLockExists, clearActiveBindingCas, inspectCompiledCache, loadActiveLongTaskAuthority, readActiveLongTaskBinding, readFinalReceipt, readProgressRecords, } from "./long-task-state.js";
6
+ import { activeAuthorityLockExists, clearActiveBindingCas, inspectCompiledCache, loadActiveLongTaskAuthority, readActiveLongTaskBinding, readFinalReceipt, readPendingAuthorityRevision, readProgressRecords, } from "./long-task-state.js";
6
7
  import { projectDeliveryStatus, } from "./long-task-status-projection.js";
7
8
  import { captureWorkspaceManifest, currentGitState, repositoryRoot, } from "./long-task-workspace.js";
8
9
  export async function readDeliveryStatus(workdir) {
@@ -20,7 +21,10 @@ async function readDeliveryStatusForAuthority(active) {
20
21
  const cacheStatus = await inspectCompiledCache(active);
21
22
  const current = await captureWorkspaceManifest(compiled.repository_root, compiled.workdir);
22
23
  const stale = await deliveryCompileFreshness(compiled);
23
- const progress = await readProgressRecords(active.workdir);
24
+ const [progress, pending] = await Promise.all([
25
+ readProgressRecords(active.workdir),
26
+ readPendingAuthorityRevision(active.workdir),
27
+ ]);
24
28
  let receipt = null;
25
29
  let receiptError = null;
26
30
  try {
@@ -53,6 +57,9 @@ async function readDeliveryStatusForAuthority(active) {
53
57
  needs_reverify: projection.needsReverify,
54
58
  progress_passing: projection.progressPassing,
55
59
  progress_failing: projection.progressFailing,
60
+ pending_authority_revision: pending
61
+ ? projectAuthorityRevisionDecision(pending)
62
+ : null,
56
63
  findings: [
57
64
  ...projection.findings,
58
65
  ...(cacheStatus === "compiled_cache_matching"
@@ -96,6 +103,7 @@ export async function resumeDeliveryTask(workdir) {
96
103
  needs_reverify: status.needs_reverify,
97
104
  progress_passing: status.progress_passing,
98
105
  progress_failing: status.progress_failing,
106
+ pending_authority_revision: status.pending_authority_revision,
99
107
  recent_findings: status.findings,
100
108
  next_safe_action: nextAction(status),
101
109
  };
@@ -273,6 +281,8 @@ function externalPendingMessage(confirmations) {
273
281
  return `Machine-verifiable scope accepted. Complete external delivery remains pending: ${pending}. Do not report complete external delivery.`;
274
282
  }
275
283
  function nextAction(status) {
284
+ if (status.pending_authority_revision)
285
+ return `Ask the user to approve or reject Authority Revision ${status.pending_authority_revision.revision_identity}; keep the previous Authority active until then.`;
276
286
  if (status.findings.length)
277
287
  return status.findings.at(-1).next_action;
278
288
  if (status.ready_outcomes.length)
@@ -11,3 +11,7 @@ export declare function verifyDeliveryContract(workdir: string, selection?: {
11
11
  }): Promise<TargetedVerificationResultV2>;
12
12
  export declare function runDeliveryChecks(compiled: CompiledDeliveryContractV2, snapshot: WorkspaceSnapshotV2, checks: CompiledCheckV2[], includeCounterfactuals: boolean, finalGate?: boolean): Promise<DeliveryRunV2>;
13
13
  export declare function allCompiledChecks(compiled: CompiledDeliveryContractV2): CompiledCheckV2[];
14
+ export declare function selectChecks(compiled: CompiledDeliveryContractV2, selection: {
15
+ outcome?: string;
16
+ check?: string;
17
+ }): CompiledCheckV2[];
@@ -214,7 +214,7 @@ export function allCompiledChecks(compiled) {
214
214
  ...compiled.outcomes.flatMap((outcome) => outcome.acceptance.checks),
215
215
  ];
216
216
  }
217
- function selectChecks(compiled, selection) {
217
+ export function selectChecks(compiled, selection) {
218
218
  const checks = allCompiledChecks(compiled);
219
219
  if (selection.outcome &&
220
220
  !compiled.outcomes.some((outcome) => outcome.key === selection.outcome))
@@ -1,8 +1,8 @@
1
- # Migrations
2
-
3
- Schema migrations for Harness config and managed file layout belong here.
4
-
5
- Version 0.6.0 includes `long-task-v1-retirement`. It safely removes the
6
- retired repo-local Hook, reports a legacy active projection as
7
- `manual_required`, and deliberately does not import V1 progress or receipts
8
- into the V2 Claim/Evidence authority.
1
+ # Migrations
2
+
3
+ Schema migrations for Harness config and managed file layout belong here.
4
+
5
+ Version 0.6.0 includes `long-task-v1-retirement`. It safely removes the
6
+ retired repo-local Hook, reports a legacy active projection as
7
+ `manual_required`, and deliberately does not import V1 progress or receipts
8
+ into the V2 Claim/Evidence authority.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "project-tiny-context-harness",
3
- "version": "0.6.2",
3
+ "version": "0.7.1",
4
4
  "description": "Minimal project memory and validation harness for AI coding agents.",
5
5
  "license": "MIT",
6
6
  "author": "Seven128",
@@ -53,6 +53,8 @@
53
53
  "test:default:built": "node ../../tests/ty-context/run-package-suite.mjs default",
54
54
  "test:default": "npm run build && npm run test:default:built",
55
55
  "test:built": "npm run test:default:built && npm run test:long-task-workflow:built",
56
+ "test:trust:built": "npm run test:default:built && npm run test:long-task-trust:built",
57
+ "test:trust": "npm run build && npm run test:trust:built",
56
58
  "pretest": "npm run build",
57
59
  "test": "npm run test:built",
58
60
  "test:workflow-default:built": "node --test --test-concurrency=1 ../../tests/ty-context/workflow-contract-routing.test.mjs",
@@ -60,6 +62,8 @@
60
62
  "test:delivery-contract": "npm run build && npm run test:delivery-contract:built",
61
63
  "test:long-task-workflow:built": "node ../../tests/ty-context/run-package-suite.mjs long-task",
62
64
  "test:long-task-workflow": "npm run build && npm run test:long-task-workflow:built",
65
+ "test:long-task-trust:built": "node ../../tests/ty-context/run-package-suite.mjs long-task-trust",
66
+ "test:long-task-trust": "npm run build && npm run test:long-task-trust:built",
63
67
  "test:long-task-performance": "npm run build && node ../../tests/ty-context/long-task-performance.mjs",
64
68
  "prepack": "npm run build"
65
69
  },