gentle-pi 2.1.2 → 2.3.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/README.md +108 -79
- package/assets/agents/gentle-ai-worker.md +7 -3
- package/assets/agents/jd-fix-agent.md +1 -1
- package/assets/agents/jd-judge-a.md +3 -1
- package/assets/agents/jd-judge-b.md +3 -1
- package/assets/agents/review-readability.md +4 -3
- package/assets/agents/review-reliability.md +4 -3
- package/assets/agents/review-resilience.md +4 -3
- package/assets/agents/review-risk.md +4 -3
- package/assets/agents/sdd-apply.md +11 -4
- package/assets/agents/sdd-archive.md +6 -1
- package/assets/agents/sdd-design.md +6 -1
- package/assets/agents/sdd-explore.md +6 -2
- package/assets/agents/sdd-init.md +10 -2
- package/assets/agents/sdd-onboard.md +6 -1
- package/assets/agents/sdd-proposal.md +8 -1
- package/assets/agents/sdd-research.md +54 -0
- package/assets/agents/sdd-spec.md +6 -1
- package/assets/agents/sdd-status.md +10 -5
- package/assets/agents/sdd-sync.md +6 -1
- package/assets/agents/sdd-tasks.md +8 -4
- package/assets/agents/sdd-verify.md +27 -2
- package/assets/chains/4r-review.chain.md +2 -0
- package/assets/chains/sdd-full.chain.md +2 -2
- package/assets/chains/sdd-plan.chain.md +1 -1
- package/assets/chains/sdd-verify.chain.md +2 -2
- package/assets/orchestrator-delegation.md +145 -160
- package/assets/orchestrator-memory.md +2 -0
- package/assets/orchestrator.md +25 -48
- package/assets/sdd-orchestrator-workflow.md +163 -25
- package/assets/support/sdd-status-contract.md +24 -6
- package/contracts/review-integration/v1/fixtures/consent.fixture.json +3 -3
- package/contracts/review-integration/v1/fixtures/start-v2.fixture.json +19 -28
- package/contracts/review-integration/v1/fixtures/start.fixture.json +1 -10
- package/contracts/review-integration/v1/fixtures/status-v2.fixture.json +12 -21
- package/contracts/review-integration/v1/schemas/correction-plan-request.schema.json +49 -0
- package/contracts/review-integration/v1/schemas/operation.schema.json +76 -0
- package/contracts/review-integration/v1/schemas/repair.schema.json +39 -0
- package/contracts/review-integration/v1/schemas/status-v2.schema.json +4 -2
- package/contracts/review-integration/v1/schemas/status.schema.json +4 -2
- package/contracts/review-integration/v1/schemas/transition-execution.schema.json +42 -0
- package/contracts/review-integration/v2/fixtures/consent.fixture.json +1 -1
- package/contracts/review-integration/v2/fixtures/start.fixture.json +1 -10
- package/contracts/review-integration/v2/fixtures/status.fixture.json +1 -10
- package/contracts/review-integration/v2/schemas/failure.schema.json +5 -1
- package/contracts/review-integration/v2/schemas/last-event-closure.schema.json +66 -0
- package/contracts/review-integration/v2/schemas/opencode-provider-role.schema.json +14 -0
- package/contracts/review-integration/v2/schemas/operation.schema.json +6 -1
- package/contracts/review-integration/v2/schemas/repair.schema.json +4 -2
- package/contracts/review-integration/v2/schemas/start.schema.json +5 -2
- package/contracts/review-integration/v2/schemas/status.schema.json +4 -2
- package/contracts/review-provider-contract-mirror/provider-contract.lock.json +30 -0
- package/contracts/review-provider-contract-mirror/v1.1.0/bundle/README.md +12 -0
- package/contracts/review-provider-contract-mirror/v1.1.0/bundle/manifest.json +65 -0
- package/contracts/review-provider-contract-mirror/v1.1.0/bundle/schemas/lens.schema.json +16 -0
- package/contracts/review-provider-contract-mirror/v1.1.0/bundle/schemas/refuter.schema.json +1 -0
- package/contracts/review-provider-contract-mirror/v1.1.0/bundle/schemas/targeted-validator.schema.json +1 -0
- package/contracts/review-provider-contract-mirror/v1.1.0/bundle/vectors/lens.json +1 -0
- package/contracts/review-provider-contract-mirror/v1.1.0/bundle/vectors/refuter.json +1 -0
- package/contracts/review-provider-contract-mirror/v1.1.0/bundle/vectors/targeted-validator.json +1 -0
- package/contracts/review-provider-contract-mirror/v1.1.0/generated/provider-capabilities.baseline.json +15 -0
- package/contracts/review-provider-contract-mirror/v1.1.0/generated/provider-roles.baseline.json +42 -0
- package/docs/native-authority-architecture.md +14 -16
- package/docs/review-integration.md +27 -353
- package/extensions/ask-user-choice.ts +151 -0
- package/extensions/gentle-ai.ts +2710 -3211
- package/extensions/quiet-tools.ts +515 -32
- package/extensions/sdd-init.ts +21 -12
- package/extensions/skill-registry.ts +10 -2
- package/extensions/startup-banner.ts +10 -4
- package/lib/gentle-ai-binary.ts +173 -2
- package/lib/gentle-ai-renderer.ts +70 -0
- package/lib/model-routing-authority.ts +133 -0
- package/lib/native-review-cli.ts +676 -781
- package/lib/opaque-pi-reviewer-adapter.ts +284 -0
- package/lib/provider-contract-bundle.ts +704 -0
- package/lib/review-candidate-view.ts +836 -118
- package/lib/review-compact-contract.ts +59 -248
- package/lib/review-host-relay.ts +578 -0
- package/lib/review-integration-v2.ts +1254 -221
- package/lib/review-last-event-controller.ts +35 -0
- package/lib/review-relay-contract.ts +16 -0
- package/lib/sdd-preflight.ts +230 -67
- package/lib/sdd-status.ts +66 -111
- package/lib/terminal-theme.ts +1 -1
- package/package.json +83 -79
- package/runtime/gentle-ai-binary.mjs +174 -3
- package/runtime/native-review-cli.mjs +610 -715
- package/runtime/review-integration-v2.mjs +1223 -190
- package/runtime/review-relay-contract.mjs +17 -0
- package/scripts/{build-git-commit-transaction-runner.mjs → build-runtime-modules.mjs} +5 -5
- package/scripts/check-provider-contract.mjs +138 -0
- package/scripts/gentle-ai-installer.mjs +85 -22
- package/scripts/maintainer/provider-relay-matrix.mjs +403 -0
- package/scripts/mirror-provider-contract.mjs +143 -0
- package/scripts/test-packed-runner.mjs +20 -9
- package/scripts/verify-package-files.mjs +119 -43
- package/skills/_shared/review-ledger-contract.md +11 -19
- package/skills/chained-pr/SKILL.md +3 -0
- package/skills/cognitive-doc-design/SKILL.md +1 -1
- package/skills/comment-writer/SKILL.md +1 -1
- package/skills/gentle-ai/SKILL.md +7 -74
- package/skills/issue-creation/SKILL.md +94 -168
- package/skills/judgment-day/SKILL.md +9 -5
- package/skills/judgment-day/references/prompts-and-formats.md +2 -0
- package/skills/rdd-defect-workflow/SKILL.md +54 -0
- package/skills/release/SKILL.md +3 -3
- package/skills/skill-registry/SKILL.md +1 -1
- package/skills/work-unit-commits/SKILL.md +3 -1
- package/tests/artifact-language.test.ts +24 -11
- package/tests/ask-user-choice.test.ts +264 -0
- package/tests/background-subagents.test.ts +771 -0
- package/tests/codegraph-tools.test.ts +3 -3
- package/tests/crosslane/cross-lane.mjs +16 -0
- package/tests/delegated-key-learnings-contract.test.ts +240 -0
- package/tests/devbinary/native-review-parity.devtest.ts +167 -250
- package/tests/devbinary/pi-host-relay.devtest.ts +867 -0
- package/tests/fixtures/devbinary/capabilities-v2.1.derived.json +331 -0
- package/tests/fixtures/devbinary/capabilities-v2.2.captured.json +340 -0
- package/tests/fixtures/devbinary/consent-v3.captured.json +37 -0
- package/tests/fixtures/devbinary/failure-v2-capture-evidence.captured.json +16 -0
- package/tests/fixtures/devbinary/last-event-capture-correction-plan.captured.json +10 -0
- package/tests/fixtures/devbinary/last-event-capture-refuter-approved.captured.json +20 -0
- package/tests/fixtures/devbinary/last-event-capture-refuter-correction-required.captured.json +26 -0
- package/tests/fixtures/devbinary/last-event-capture-result-approved.captured.json +8 -0
- package/tests/fixtures/devbinary/last-event-capture-result-correction-required.captured.json +26 -0
- package/tests/fixtures/devbinary/last-event-capture-validation-approved.captured.json +8 -0
- package/tests/fixtures/devbinary/last-event-closure.provenance.md +13 -0
- package/tests/fixtures/devbinary/result-artifact-v2-path.captured.json +12 -0
- package/tests/fixtures/devbinary/result-artifact-v2.captured.json +12 -0
- package/tests/fixtures/devbinary/review-acknowledged-v1.captured.json +9 -0
- package/tests/fixtures/devbinary/review-acknowledged.provenance.md +31 -0
- package/tests/fixtures/devbinary/start-v3-consent-declined.captured.json +19 -0
- package/tests/fixtures/devbinary/start-v3-consent-granted.captured.json +109 -0
- package/tests/fixtures/devbinary/start-v3-zero-lens-closed.captured.json +21 -0
- package/tests/fixtures/devbinary/status-v5-capture-result-submission.captured.json +184 -0
- package/tests/fixtures/devbinary/status-v5-repository-context.captured.json +138 -0
- package/tests/fixtures/devbinary/status-v5.captured.json +88 -0
- package/tests/fixtures/native-review-cli/v2.5.0-rc.1/PROVENANCE.txt +15 -0
- package/tests/fixtures/provider-contract-bundle/v1.1.0/README.md +12 -0
- package/tests/fixtures/provider-contract-bundle/v1.1.0/manifest.json +65 -0
- package/tests/fixtures/provider-contract-bundle/v1.1.0/schemas/lens.schema.json +16 -0
- package/tests/fixtures/provider-contract-bundle/v1.1.0/schemas/refuter.schema.json +1 -0
- package/tests/fixtures/provider-contract-bundle/v1.1.0/schemas/targeted-validator.schema.json +1 -0
- package/tests/fixtures/provider-contract-bundle/v1.1.0/vectors/lens.json +1 -0
- package/tests/fixtures/provider-contract-bundle/v1.1.0/vectors/refuter.json +1 -0
- package/tests/fixtures/provider-contract-bundle/v1.1.0/vectors/targeted-validator.json +1 -0
- package/tests/gentle-ai-binary.test.ts +83 -13
- package/tests/gentle-ai-dev-binary-surfacing.test.ts +195 -0
- package/tests/gentle-ai-dev-binary.test.ts +159 -0
- package/tests/gentle-ai-installer.test.ts +138 -48
- package/tests/gentle-ai.test.ts +820 -131
- package/tests/gentle-theme.test.ts +133 -0
- package/tests/maintainer/provider-relay.maintest.ts +601 -0
- package/tests/model-routing-authority.test.ts +257 -0
- package/tests/native-review-capability-contract.test.ts +75 -2
- package/tests/native-review-cli.test.ts +588 -908
- package/tests/native-review-consent.test.ts +283 -38
- package/tests/native-review-parity-runtime.test.ts +108 -350
- package/tests/native-review-parity.test.ts +684 -732
- package/tests/native-sdd-attempt-authority.test.ts +235 -0
- package/tests/opaque-pi-reviewer-adapter.test.ts +266 -0
- package/tests/orchestrator-budget.test.ts +158 -89
- package/tests/orchestrator-rdd-ownership.test.ts +103 -0
- package/tests/package-manifest.test.ts +128 -100
- package/tests/provider-contract-bundle.test.ts +385 -0
- package/tests/provider-contract-mirror.test.ts +206 -0
- package/tests/provider-defect-handoff.test.ts +252 -0
- package/tests/quiet-tool-rendering.test.ts +1055 -28
- package/tests/review-actor-tool-deny.test.ts +12 -13
- package/tests/review-authority-recovery-docs.test.ts +1 -2
- package/tests/review-candidate-view.test.ts +898 -12
- package/tests/review-compact-contract.test.ts +29 -122
- package/tests/review-controller-lock-status.test.ts +2 -2
- package/tests/review-controller-native-recovery.test.ts +366 -857
- package/tests/review-controller-native-routing.test.ts +1253 -4199
- package/tests/review-controller-retired-ops.test.ts +1 -1
- package/tests/review-controller-workspace-root.test.ts +236 -70
- package/tests/review-controller.test.ts +26 -816
- package/tests/review-corrected-finalize-binding.test.ts +134 -0
- package/tests/review-dispatch-hydration-gap.test.ts +145 -0
- package/tests/review-gate.test.ts +0 -45
- package/tests/review-host-relay-restart-parity.test.ts +360 -0
- package/tests/review-host-relay-routing.test.ts +352 -0
- package/tests/review-host-relay.test.ts +754 -0
- package/tests/review-integration-v2-forward.test.ts +654 -0
- package/tests/review-integration-v2.test.ts +317 -129
- package/tests/review-last-event-closure.test.ts +408 -0
- package/tests/review-ledger-contract.test.ts +106 -60
- package/tests/review-recovered-lineage-routing.test.ts +199 -0
- package/tests/review-relay-transport-agent.test.ts +322 -0
- package/tests/review-snapshot.test.ts +3 -2
- package/tests/runtime-harness.mjs +573 -180
- package/tests/sdd-agent-tools.test.ts +53 -32
- package/tests/sdd-preflight.test.ts +81 -15
- package/tests/sdd-status.test.ts +109 -110
- package/tests/skill-collision-prefixes.test.ts +6 -8
- package/tests/skill-registry.test.ts +50 -1
- package/tests/verify-package-files.test.ts +62 -0
- package/tests/writer-edit-surface-scope.test.ts +230 -0
- package/themes/Gentleman-Cute.json +94 -0
- package/themes/Gentleman-Sexy.json +92 -0
- package/assets/agents/review-refuter.md +0 -40
- package/assets/agents/review-validator.md +0 -23
- package/lib/git-commit-transaction.ts +0 -801
- package/lib/native-review-remediation.ts +0 -49
- package/lib/review-compact.ts +0 -947
- package/lib/review-refuter-adapter.ts +0 -129
- package/lib/review-runtime-contract.ts +0 -68
- package/prompts/gcl.md +0 -54
- package/prompts/gis.md +0 -25
- package/prompts/gpr.md +0 -41
- package/prompts/gwr.md +0 -31
- package/runtime/git-commit-transaction.mjs +0 -802
- package/scripts/run-git-commit-transaction.mjs +0 -35
- package/tests/fixtures/native-review-cli/v2.1.2/bind-sdd.json +0 -25
- package/tests/fixtures/native-review-cli/v2.1.2/finalize.json +0 -8
- package/tests/fixtures/native-review-cli/v2.1.2/sdd-status-engram.json +0 -139
- package/tests/fixtures/native-review-cli/v2.1.2/sdd-status.json +0 -200
- package/tests/fixtures/native-review-cli/v2.1.2/start.json +0 -12
- package/tests/fixtures/native-review-cli/v2.1.2/validate-allow.json +0 -24
- package/tests/fixtures/native-review-cli/v2.1.2/validate-deny-empty-context.json +0 -20
- package/tests/fixtures/native-review-cli/v2.1.2/validate-deny.json +0 -28
- package/tests/fixtures/native-review-cli/v2.1.3/sdd-status-engram.json +0 -139
- package/tests/fixtures/native-review-cli/v2.1.3/sdd-status.json +0 -200
- package/tests/git-commit-transaction.test.ts +0 -302
- package/tests/review-compact.test.ts +0 -243
- package/tests/review-refuter-adapter.test.ts +0 -89
|
@@ -1,200 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"schemaName": "gentle-ai.sdd-status",
|
|
3
|
-
"schemaVersion": 1,
|
|
4
|
-
"changeName": "native-review-authority-parity",
|
|
5
|
-
"artifactStore": "openspec",
|
|
6
|
-
"planningHome": {
|
|
7
|
-
"mode": "repo-local",
|
|
8
|
-
"path": "/tmp/gentle-ai-v212-contract-9XGIB4/openspec"
|
|
9
|
-
},
|
|
10
|
-
"changeRoot": "/tmp/gentle-ai-v212-contract-9XGIB4/openspec/changes/native-review-authority-parity",
|
|
11
|
-
"artifactPaths": {
|
|
12
|
-
"proposal": [
|
|
13
|
-
"/tmp/gentle-ai-v212-contract-9XGIB4/openspec/changes/native-review-authority-parity/proposal.md"
|
|
14
|
-
],
|
|
15
|
-
"specs": [
|
|
16
|
-
"/tmp/gentle-ai-v212-contract-9XGIB4/openspec/changes/native-review-authority-parity/specs/review/spec.md"
|
|
17
|
-
],
|
|
18
|
-
"design": [
|
|
19
|
-
"/tmp/gentle-ai-v212-contract-9XGIB4/openspec/changes/native-review-authority-parity/design.md"
|
|
20
|
-
],
|
|
21
|
-
"tasks": [
|
|
22
|
-
"/tmp/gentle-ai-v212-contract-9XGIB4/openspec/changes/native-review-authority-parity/tasks.md"
|
|
23
|
-
],
|
|
24
|
-
"applyProgress": [],
|
|
25
|
-
"verifyReport": [
|
|
26
|
-
"/tmp/gentle-ai-v212-contract-9XGIB4/openspec/changes/native-review-authority-parity/verify-report.md"
|
|
27
|
-
],
|
|
28
|
-
"reviewPolicy": [],
|
|
29
|
-
"reviewLedger": [],
|
|
30
|
-
"reviewReceipt": [],
|
|
31
|
-
"reviewBundle": [],
|
|
32
|
-
"reviewContext": [],
|
|
33
|
-
"reviewState": [
|
|
34
|
-
"/tmp/gentle-ai-v212-contract-9XGIB4/openspec/changes/native-review-authority-parity/reviews/transaction.json"
|
|
35
|
-
]
|
|
36
|
-
},
|
|
37
|
-
"contextFiles": {
|
|
38
|
-
"proposal": [
|
|
39
|
-
"/tmp/gentle-ai-v212-contract-9XGIB4/openspec/changes/native-review-authority-parity/proposal.md"
|
|
40
|
-
],
|
|
41
|
-
"specs": [
|
|
42
|
-
"/tmp/gentle-ai-v212-contract-9XGIB4/openspec/changes/native-review-authority-parity/specs/review/spec.md"
|
|
43
|
-
],
|
|
44
|
-
"design": [
|
|
45
|
-
"/tmp/gentle-ai-v212-contract-9XGIB4/openspec/changes/native-review-authority-parity/design.md"
|
|
46
|
-
],
|
|
47
|
-
"tasks": [
|
|
48
|
-
"/tmp/gentle-ai-v212-contract-9XGIB4/openspec/changes/native-review-authority-parity/tasks.md"
|
|
49
|
-
],
|
|
50
|
-
"applyProgress": [],
|
|
51
|
-
"verifyReport": [
|
|
52
|
-
"/tmp/gentle-ai-v212-contract-9XGIB4/openspec/changes/native-review-authority-parity/verify-report.md"
|
|
53
|
-
],
|
|
54
|
-
"reviewPolicy": [],
|
|
55
|
-
"reviewLedger": [],
|
|
56
|
-
"reviewReceipt": [],
|
|
57
|
-
"reviewBundle": [],
|
|
58
|
-
"reviewContext": [],
|
|
59
|
-
"reviewState": [
|
|
60
|
-
"/tmp/gentle-ai-v212-contract-9XGIB4/openspec/changes/native-review-authority-parity/reviews/transaction.json"
|
|
61
|
-
]
|
|
62
|
-
},
|
|
63
|
-
"artifacts": {
|
|
64
|
-
"applyProgress": "missing",
|
|
65
|
-
"design": "done",
|
|
66
|
-
"proposal": "done",
|
|
67
|
-
"reviewBundle": "missing",
|
|
68
|
-
"reviewContext": "missing",
|
|
69
|
-
"reviewLedger": "missing",
|
|
70
|
-
"reviewReceipt": "missing",
|
|
71
|
-
"reviewState": "done",
|
|
72
|
-
"specs": "done",
|
|
73
|
-
"tasks": "done",
|
|
74
|
-
"verifyReport": "done"
|
|
75
|
-
},
|
|
76
|
-
"taskProgress": {
|
|
77
|
-
"total": 1,
|
|
78
|
-
"completed": 1,
|
|
79
|
-
"pending": 0,
|
|
80
|
-
"allComplete": true
|
|
81
|
-
},
|
|
82
|
-
"dependencies": {
|
|
83
|
-
"proposal": "all_done",
|
|
84
|
-
"specs": "all_done",
|
|
85
|
-
"design": "all_done",
|
|
86
|
-
"tasks": "all_done",
|
|
87
|
-
"apply": "all_done",
|
|
88
|
-
"verify": "all_done",
|
|
89
|
-
"archive": "ready"
|
|
90
|
-
},
|
|
91
|
-
"applyState": "all_done",
|
|
92
|
-
"actionContext": {
|
|
93
|
-
"mode": "repo-local",
|
|
94
|
-
"workspaceRoot": "/tmp/gentle-ai-v212-contract-9XGIB4",
|
|
95
|
-
"allowedEditRoots": [
|
|
96
|
-
"/tmp/gentle-ai-v212-contract-9XGIB4"
|
|
97
|
-
]
|
|
98
|
-
},
|
|
99
|
-
"relationships": {
|
|
100
|
-
"dependsOn": [],
|
|
101
|
-
"supersedes": [],
|
|
102
|
-
"amends": [],
|
|
103
|
-
"conflictsWith": [],
|
|
104
|
-
"sameDomainActiveChanges": []
|
|
105
|
-
},
|
|
106
|
-
"remediationState": {
|
|
107
|
-
"required": false,
|
|
108
|
-
"complete": false,
|
|
109
|
-
"failedEvidenceRevision": "",
|
|
110
|
-
"lineageId": "",
|
|
111
|
-
"generation": 0,
|
|
112
|
-
"fixBatch": 0,
|
|
113
|
-
"reason": ""
|
|
114
|
-
},
|
|
115
|
-
"reviewGate": {
|
|
116
|
-
"result": "allow",
|
|
117
|
-
"reason": "explicit bound compact authority exactly matches the current repository"
|
|
118
|
-
},
|
|
119
|
-
"reviewTransaction": {
|
|
120
|
-
"schema": "gentle-ai.review-transaction/v1",
|
|
121
|
-
"lineage_id": "issue-1099-corrected-candidate-review-20260710",
|
|
122
|
-
"mode": "ordinary_4r",
|
|
123
|
-
"generation": 1,
|
|
124
|
-
"state": "reviewing",
|
|
125
|
-
"snapshot": {
|
|
126
|
-
"kind": "current-changes",
|
|
127
|
-
"base_tree": "ba040f17cdcd2a5960361971eaff79684c48847a",
|
|
128
|
-
"candidate_tree": "5bc2f4bdd086d064bc3ada255f16c631facc6839",
|
|
129
|
-
"paths_digest": "sha256:4a52771035fe6ef25f0155b11c052a661879b1cd1af4bbe5cd337118a9dd29dd",
|
|
130
|
-
"intended_untracked": [
|
|
131
|
-
"assets/agents/gentle-ai-explore.md",
|
|
132
|
-
"assets/agents/gentle-ai-verify.md"
|
|
133
|
-
],
|
|
134
|
-
"intended_untracked_proof": "sha256:ea65650186e3d14ed53ae4912a2a30127863fe9aec0e4c14050e4fa154b0bfa3",
|
|
135
|
-
"paths": [
|
|
136
|
-
"assets/agents/gentle-ai-explore.md",
|
|
137
|
-
"assets/agents/gentle-ai-verify.md",
|
|
138
|
-
"assets/orchestrator-delegation.md",
|
|
139
|
-
"assets/orchestrator.md",
|
|
140
|
-
"tests/package-manifest.test.ts",
|
|
141
|
-
"tests/sdd-agent-tools.test.ts"
|
|
142
|
-
],
|
|
143
|
-
"identity": "sha256:d88627d276b790d1ed58abc44118d1d95a9620d9755d5e61c8fbda0f97cea53c"
|
|
144
|
-
},
|
|
145
|
-
"base_tree": "ba040f17cdcd2a5960361971eaff79684c48847a",
|
|
146
|
-
"paths_digest": "sha256:4a52771035fe6ef25f0155b11c052a661879b1cd1af4bbe5cd337118a9dd29dd",
|
|
147
|
-
"initial_review_tree": "5bc2f4bdd086d064bc3ada255f16c631facc6839",
|
|
148
|
-
"final_candidate_tree": "5bc2f4bdd086d064bc3ada255f16c631facc6839",
|
|
149
|
-
"fix_delta_hash": "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
|
150
|
-
"policy_hash": "sha256:9197a98b8c5ceac34da4e8d213908d68023f215e891ecb85dfe9fb0b355f9482",
|
|
151
|
-
"ledger_hash": "",
|
|
152
|
-
"ledger_findings_hash": "",
|
|
153
|
-
"evidence_hash": "",
|
|
154
|
-
"judge_proofs": [],
|
|
155
|
-
"counters": {
|
|
156
|
-
"full_reviews": 1,
|
|
157
|
-
"refuter_batches": 0,
|
|
158
|
-
"fix_batches": 0,
|
|
159
|
-
"scoped_fix_validations": 0,
|
|
160
|
-
"final_verifications": 0,
|
|
161
|
-
"fix_rounds": 0,
|
|
162
|
-
"scoped_rejudgments": 0,
|
|
163
|
-
"judge_executions": 0
|
|
164
|
-
},
|
|
165
|
-
"findings": [],
|
|
166
|
-
"classifications": {},
|
|
167
|
-
"outcomes": {},
|
|
168
|
-
"fix_finding_ids": [],
|
|
169
|
-
"pending_refuter_ids": [],
|
|
170
|
-
"fix_caused_findings": [],
|
|
171
|
-
"follow_ups": []
|
|
172
|
-
},
|
|
173
|
-
"phaseInstructions": {
|
|
174
|
-
"apply": [
|
|
175
|
-
"Change: native-review-authority-parity",
|
|
176
|
-
"State: all_done",
|
|
177
|
-
"Read proposal, specs, design, and tasks before editing.",
|
|
178
|
-
"Implement only unchecked tasks and update tasks.md checkboxes as work completes."
|
|
179
|
-
],
|
|
180
|
-
"verify": [
|
|
181
|
-
"Change: native-review-authority-parity",
|
|
182
|
-
"State: all_done",
|
|
183
|
-
"Verify implementation against proposal, specs, design, and task completion.",
|
|
184
|
-
"Run final verification only after every task is complete; apply-progress never makes final verification ready."
|
|
185
|
-
],
|
|
186
|
-
"remediate": [
|
|
187
|
-
"Change: native-review-authority-parity",
|
|
188
|
-
"Remediation is allowed only when the persisted review transaction has remaining mode-specific budget.",
|
|
189
|
-
"Bind focused tests, runtime harness evidence, and rollback evidence to the exact failed evidence revision.",
|
|
190
|
-
"A bare remediation envelope or stale failed revision never completes remediation."
|
|
191
|
-
],
|
|
192
|
-
"archive": [
|
|
193
|
-
"Change: native-review-authority-parity",
|
|
194
|
-
"State: ready",
|
|
195
|
-
"Archive only when verify-report.md exists and every task checkbox is complete."
|
|
196
|
-
]
|
|
197
|
-
},
|
|
198
|
-
"nextRecommended": "archive",
|
|
199
|
-
"blockedReasons": []
|
|
200
|
-
}
|
|
@@ -1,302 +0,0 @@
|
|
|
1
|
-
import assert from "node:assert/strict";
|
|
2
|
-
import { execFileSync } from "node:child_process";
|
|
3
|
-
import { chmodSync, existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
4
|
-
import { tmpdir } from "node:os";
|
|
5
|
-
import { join } from "node:path";
|
|
6
|
-
import test from "node:test";
|
|
7
|
-
import { setTimeout as delay } from "node:timers/promises";
|
|
8
|
-
import {
|
|
9
|
-
COMMIT_TRANSACTION_STATE,
|
|
10
|
-
assertNoUnresolvedCommitTransaction,
|
|
11
|
-
inspectCommitTransaction,
|
|
12
|
-
prepareCommitTransactionInvocation,
|
|
13
|
-
reconcileCommitTransaction,
|
|
14
|
-
runGitCommitTransaction,
|
|
15
|
-
verifyCommitTransactionResult,
|
|
16
|
-
} from "../lib/git-commit-transaction.ts";
|
|
17
|
-
import type { NativeReviewCli, NativeValidateResult } from "../lib/native-review-cli.ts";
|
|
18
|
-
|
|
19
|
-
function git(cwd: string, ...arguments_: string[]): string {
|
|
20
|
-
return execFileSync("git", arguments_, { cwd, encoding: "utf8" }).trim();
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function repository(t: test.TestContext): string {
|
|
24
|
-
const cwd = mkdtempSync(join(tmpdir(), "gentle-pi-commit-transaction-"));
|
|
25
|
-
t.after(() => rmSync(cwd, { recursive: true, force: true }));
|
|
26
|
-
git(cwd, "init", "-b", "main");
|
|
27
|
-
git(cwd, "config", "user.name", "Commit Transaction Test");
|
|
28
|
-
git(cwd, "config", "user.email", "commit-transaction@example.invalid");
|
|
29
|
-
writeFileSync(join(cwd, "tracked.txt"), "base\n");
|
|
30
|
-
git(cwd, "add", "tracked.txt");
|
|
31
|
-
git(cwd, "commit", "-m", "base");
|
|
32
|
-
return cwd;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function installHook(cwd: string, name: string, body: string): void {
|
|
36
|
-
const hooks = git(cwd, "rev-parse", "--path-format=absolute", "--git-path", "hooks");
|
|
37
|
-
mkdirSync(hooks, { recursive: true });
|
|
38
|
-
const path = join(hooks, name);
|
|
39
|
-
writeFileSync(path, `#!/bin/sh\nset -eu\n${body}\n`);
|
|
40
|
-
chmodSync(path, 0o700);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
function stage(cwd: string, content = "candidate\n"): string {
|
|
44
|
-
writeFileSync(join(cwd, "tracked.txt"), content);
|
|
45
|
-
git(cwd, "add", "tracked.txt");
|
|
46
|
-
return git(cwd, "write-tree");
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
function invocation(cwd: string, lineageId: string, arguments_: readonly string[] = ["-m", "candidate"]) {
|
|
50
|
-
const intendedTree = git(cwd, "write-tree");
|
|
51
|
-
const command = `git commit ${arguments_.map((value) => JSON.stringify(value)).join(" ")}`;
|
|
52
|
-
return prepareCommitTransactionInvocation({
|
|
53
|
-
command,
|
|
54
|
-
cwd,
|
|
55
|
-
arguments: arguments_,
|
|
56
|
-
authorization: {
|
|
57
|
-
lineageId,
|
|
58
|
-
storeRevision: "sha256:" + "a".repeat(64),
|
|
59
|
-
fingerprint: "sha256:" + "b".repeat(64),
|
|
60
|
-
intendedTree,
|
|
61
|
-
},
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
function native(cwd: string, lineageId: string, result: NativeValidateResult["result"] = "allow"): NativeReviewCli {
|
|
66
|
-
return {
|
|
67
|
-
async validate(request) {
|
|
68
|
-
const tree = git(cwd, "write-tree");
|
|
69
|
-
return {
|
|
70
|
-
allowed: result === "allow",
|
|
71
|
-
result,
|
|
72
|
-
action: result === "allow" ? "continue" : result === "scope-changed" ? "create-new-lineage" : "explicit-maintainer-action",
|
|
73
|
-
reason: result === "allow" ? "receipt allows exact tree" : "post-hook tree differs from receipt",
|
|
74
|
-
gateContext: {
|
|
75
|
-
lineageId,
|
|
76
|
-
storeRevision: "sha256:" + "c".repeat(64),
|
|
77
|
-
raw: { gate: request.gate, lineage_id: lineageId, candidate_tree: tree },
|
|
78
|
-
},
|
|
79
|
-
};
|
|
80
|
-
},
|
|
81
|
-
} as NativeReviewCli;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
test("a non-mutating pre-commit hook runs once and HEAD proves the native-authorized tree", async (t) => {
|
|
85
|
-
const cwd = repository(t);
|
|
86
|
-
stage(cwd);
|
|
87
|
-
const count = join(cwd, ".git", "hook-count");
|
|
88
|
-
installHook(cwd, "pre-commit", `printf '1\\n' >> ${JSON.stringify(count)}`);
|
|
89
|
-
const before = git(cwd, "rev-parse", "HEAD");
|
|
90
|
-
const result = await runGitCommitTransaction(invocation(cwd, "non-mutating"), { nativeReviewCli: native(cwd, "non-mutating") });
|
|
91
|
-
assert.notEqual(result.head, before);
|
|
92
|
-
assert.equal(result.tree, git(cwd, "rev-parse", "HEAD^{tree}"));
|
|
93
|
-
assert.equal(readFileSync(count, "utf8"), "1\n");
|
|
94
|
-
assert.deepEqual(inspectCommitTransaction(cwd), { status: "clean" });
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
test("a mutating hook creates no commit until the post-hook tree is reviewed, then exact retry skips the hook", async (t) => {
|
|
98
|
-
const cwd = repository(t);
|
|
99
|
-
stage(cwd, "unformatted\n");
|
|
100
|
-
const count = join(cwd, ".git", "hook-count");
|
|
101
|
-
installHook(cwd, "pre-commit", `printf 'formatted\\n' > tracked.txt\ngit add tracked.txt\nprintf '1\\n' >> ${JSON.stringify(count)}`);
|
|
102
|
-
const before = git(cwd, "rev-parse", "HEAD");
|
|
103
|
-
await assert.rejects(
|
|
104
|
-
runGitCommitTransaction(invocation(cwd, "before-format"), { nativeReviewCli: native(cwd, "before-format", "scope-changed") }),
|
|
105
|
-
/not the authorized tree/,
|
|
106
|
-
);
|
|
107
|
-
assert.equal(git(cwd, "rev-parse", "HEAD"), before);
|
|
108
|
-
assert.equal(inspectCommitTransaction(cwd).record?.state, COMMIT_TRANSACTION_STATE.AWAITING_REVIEW);
|
|
109
|
-
assert.throws(() => assertNoUnresolvedCommitTransaction(cwd), /publication is blocked/);
|
|
110
|
-
const result = await runGitCommitTransaction(invocation(cwd, "after-format"), { nativeReviewCli: native(cwd, "after-format") });
|
|
111
|
-
assert.equal(result.tree, git(cwd, "rev-parse", "HEAD^{tree}"));
|
|
112
|
-
assert.equal(readFileSync(count, "utf8"), "1\n");
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
test("a failing pre-commit hook creates no commit and leaves explicit recovery state", async (t) => {
|
|
116
|
-
const cwd = repository(t);
|
|
117
|
-
stage(cwd);
|
|
118
|
-
installHook(cwd, "pre-commit", "exit 23");
|
|
119
|
-
const before = git(cwd, "rev-parse", "HEAD");
|
|
120
|
-
await assert.rejects(runGitCommitTransaction(invocation(cwd, "hook-failure"), { nativeReviewCli: native(cwd, "hook-failure") }), /hook failed/);
|
|
121
|
-
assert.equal(git(cwd, "rev-parse", "HEAD"), before);
|
|
122
|
-
assert.equal(inspectCommitTransaction(cwd).record?.state, COMMIT_TRANSACTION_STATE.HOOK_FAILED);
|
|
123
|
-
assert.match(inspectCommitTransaction(cwd).record?.error ?? "", /exit 23/);
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
test("a native scope-changed denial on the unmutated authorized tree awaits explicit review", async (t) => {
|
|
127
|
-
const cwd = repository(t);
|
|
128
|
-
const authorizedTree = stage(cwd);
|
|
129
|
-
const before = git(cwd, "rev-parse", "HEAD");
|
|
130
|
-
let validations = 0;
|
|
131
|
-
const denying = native(cwd, "scope-changed-denial", "scope-changed");
|
|
132
|
-
const counting = {
|
|
133
|
-
async validate(request) {
|
|
134
|
-
validations += 1;
|
|
135
|
-
return denying.validate(request);
|
|
136
|
-
},
|
|
137
|
-
} as NativeReviewCli;
|
|
138
|
-
await assert.rejects(
|
|
139
|
-
runGitCommitTransaction(invocation(cwd, "scope-changed-denial"), { nativeReviewCli: counting }),
|
|
140
|
-
/native pre-commit validation denied the post-hook tree: scope-changed/,
|
|
141
|
-
);
|
|
142
|
-
assert.equal(validations, 1, "the unmutated tree must pass the mutation guard and reach native validation");
|
|
143
|
-
assert.equal(git(cwd, "rev-parse", "HEAD"), before);
|
|
144
|
-
assert.equal(git(cwd, "write-tree"), authorizedTree, "the denied index stays exactly as authorized");
|
|
145
|
-
const inspection = inspectCommitTransaction(cwd);
|
|
146
|
-
assert.equal(inspection.record?.state, COMMIT_TRANSACTION_STATE.AWAITING_REVIEW);
|
|
147
|
-
assert.equal(inspection.record?.error, "post-hook tree differs from receipt");
|
|
148
|
-
assert.equal(typeof inspection.record?.native_result, "object", "the native denial must be recorded on the transaction");
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
test("a non-scope-changed native denial fails validation and requires explicit recovery", async (t) => {
|
|
152
|
-
const cwd = repository(t);
|
|
153
|
-
stage(cwd);
|
|
154
|
-
const before = git(cwd, "rev-parse", "HEAD");
|
|
155
|
-
await assert.rejects(
|
|
156
|
-
runGitCommitTransaction(invocation(cwd, "invalidated-denial"), { nativeReviewCli: native(cwd, "invalidated-denial", "invalidated") }),
|
|
157
|
-
/native pre-commit validation denied the post-hook tree: invalidated/,
|
|
158
|
-
);
|
|
159
|
-
assert.equal(git(cwd, "rev-parse", "HEAD"), before);
|
|
160
|
-
assert.equal(inspectCommitTransaction(cwd).record?.state, COMMIT_TRANSACTION_STATE.VALIDATION_FAILED);
|
|
161
|
-
await assert.rejects(
|
|
162
|
-
runGitCommitTransaction(invocation(cwd, "invalidated-denial"), { nativeReviewCli: native(cwd, "invalidated-denial") }),
|
|
163
|
-
/requires explicit recovery from state validation-failed/,
|
|
164
|
-
);
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
test("a mutating pre-commit hook fails closed even when native validation would allow the post-hook tree", async (t) => {
|
|
168
|
-
const cwd = repository(t);
|
|
169
|
-
const authorizedTree = stage(cwd, "unformatted\n");
|
|
170
|
-
const count = join(cwd, ".git", "hook-count");
|
|
171
|
-
installHook(cwd, "pre-commit", `printf 'formatted\\n' > tracked.txt\ngit add tracked.txt\nprintf '1\\n' >> ${JSON.stringify(count)}`);
|
|
172
|
-
const before = git(cwd, "rev-parse", "HEAD");
|
|
173
|
-
// The fake native CLI allows whatever tree the index holds, so the only
|
|
174
|
-
// defense against committing the hook-mutated tree is the transaction's
|
|
175
|
-
// own binding to the invocation's authorized tree.
|
|
176
|
-
await assert.rejects(
|
|
177
|
-
runGitCommitTransaction(invocation(cwd, "permissive-native"), { nativeReviewCli: native(cwd, "permissive-native") }),
|
|
178
|
-
/pre-commit hook mutated the staged candidate/,
|
|
179
|
-
);
|
|
180
|
-
assert.equal(git(cwd, "rev-parse", "HEAD"), before, "no commit object may be created from the mutated index");
|
|
181
|
-
assert.equal(readFileSync(count, "utf8"), "1\n", "the mutating hook must have run exactly once");
|
|
182
|
-
assert.notEqual(git(cwd, "write-tree"), authorizedTree, "the mutated index is preserved for inspection");
|
|
183
|
-
const inspection = inspectCommitTransaction(cwd);
|
|
184
|
-
assert.equal(inspection.record?.state, COMMIT_TRANSACTION_STATE.AWAITING_REVIEW);
|
|
185
|
-
assert.match(inspection.record?.error ?? "", /normalize sources and re-run review explicitly, or make the hook convergent/);
|
|
186
|
-
assert.throws(() => assertNoUnresolvedCommitTransaction(cwd), /publication is blocked/);
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
test("a convergent pre-commit hook runs exactly once and commits the exact authorized tree", async (t) => {
|
|
190
|
-
const cwd = repository(t);
|
|
191
|
-
const authorizedTree = stage(cwd, "formatted\n");
|
|
192
|
-
const count = join(cwd, ".git", "hook-count");
|
|
193
|
-
installHook(cwd, "pre-commit", `printf 'formatted\\n' > tracked.txt\ngit add tracked.txt\nprintf '1\\n' >> ${JSON.stringify(count)}`);
|
|
194
|
-
const before = git(cwd, "rev-parse", "HEAD");
|
|
195
|
-
const result = await runGitCommitTransaction(invocation(cwd, "convergent"), { nativeReviewCli: native(cwd, "convergent") });
|
|
196
|
-
assert.notEqual(result.head, before);
|
|
197
|
-
assert.equal(result.tree, authorizedTree);
|
|
198
|
-
assert.equal(git(cwd, "rev-parse", "HEAD^{tree}"), authorizedTree);
|
|
199
|
-
assert.equal(readFileSync(count, "utf8"), "1\n", "the convergent hook must have run exactly once");
|
|
200
|
-
assert.deepEqual(inspectCommitTransaction(cwd), { status: "clean" });
|
|
201
|
-
});
|
|
202
|
-
|
|
203
|
-
test("a repository with no hooks commits the authorized tree unchanged", async (t) => {
|
|
204
|
-
const cwd = repository(t);
|
|
205
|
-
const authorizedTree = stage(cwd);
|
|
206
|
-
const before = git(cwd, "rev-parse", "HEAD");
|
|
207
|
-
const result = await runGitCommitTransaction(invocation(cwd, "no-hooks"), { nativeReviewCli: native(cwd, "no-hooks") });
|
|
208
|
-
assert.notEqual(result.head, before);
|
|
209
|
-
assert.equal(result.tree, authorizedTree);
|
|
210
|
-
assert.equal(git(cwd, "rev-parse", "HEAD^{tree}"), authorizedTree);
|
|
211
|
-
assert.deepEqual(inspectCommitTransaction(cwd), { status: "clean" });
|
|
212
|
-
});
|
|
213
|
-
|
|
214
|
-
test("the Git-created HEAD tree is proven equal to the authorized tree on success", async (t) => {
|
|
215
|
-
const cwd = repository(t);
|
|
216
|
-
const authorizedTree = stage(cwd);
|
|
217
|
-
const result = await runGitCommitTransaction(invocation(cwd, "head-proof"), { nativeReviewCli: native(cwd, "head-proof") });
|
|
218
|
-
assert.equal(result.tree, authorizedTree);
|
|
219
|
-
assert.equal(git(cwd, "rev-parse", "HEAD^{tree}"), authorizedTree);
|
|
220
|
-
const verified = verifyCommitTransactionResult(cwd, result.transactionId);
|
|
221
|
-
assert.deepEqual(verified, { transactionId: result.transactionId, status: "committed", head: result.head, tree: authorizedTree });
|
|
222
|
-
});
|
|
223
|
-
|
|
224
|
-
test("message hooks cannot change the index after native authorization", async (t) => {
|
|
225
|
-
const cwd = repository(t);
|
|
226
|
-
stage(cwd);
|
|
227
|
-
installHook(cwd, "prepare-commit-msg", "printf 'late mutation\\n' > tracked.txt\ngit add tracked.txt");
|
|
228
|
-
const before = git(cwd, "rev-parse", "HEAD");
|
|
229
|
-
await assert.rejects(runGitCommitTransaction(invocation(cwd, "late-mutation"), { nativeReviewCli: native(cwd, "late-mutation") }), /Git commit failed/);
|
|
230
|
-
assert.equal(git(cwd, "rev-parse", "HEAD"), before);
|
|
231
|
-
assert.equal(inspectCommitTransaction(cwd).record?.state, COMMIT_TRANSACTION_STATE.COMMIT_FAILED);
|
|
232
|
-
});
|
|
233
|
-
|
|
234
|
-
test("amend and post-commit crash reconciliation preserve the exact authorized tree", async (t) => {
|
|
235
|
-
const cwd = repository(t);
|
|
236
|
-
const authorizedTree = stage(cwd, "amended\n");
|
|
237
|
-
const amended = await runGitCommitTransaction(invocation(cwd, "amend", ["--amend", "--no-edit"]), { nativeReviewCli: native(cwd, "amend") });
|
|
238
|
-
assert.equal(amended.tree, authorizedTree);
|
|
239
|
-
stage(cwd, "after-crash\n");
|
|
240
|
-
await assert.rejects(
|
|
241
|
-
runGitCommitTransaction(invocation(cwd, "crash"), { nativeReviewCli: native(cwd, "crash"), failpoint: "after-commit-before-proof" }),
|
|
242
|
-
/test interruption/,
|
|
243
|
-
);
|
|
244
|
-
assert.equal(inspectCommitTransaction(cwd).record?.state, COMMIT_TRANSACTION_STATE.COMMIT_RUNNING);
|
|
245
|
-
assert.deepEqual(reconcileCommitTransaction(cwd), { status: "clean" });
|
|
246
|
-
assert.deepEqual(inspectCommitTransaction(cwd), { status: "clean" });
|
|
247
|
-
});
|
|
248
|
-
|
|
249
|
-
test("a post-commit hook cannot replace the exact commit created by Git", async (t) => {
|
|
250
|
-
const cwd = repository(t);
|
|
251
|
-
stage(cwd, "intermediate\n");
|
|
252
|
-
git(cwd, "commit", "-m", "intermediate");
|
|
253
|
-
stage(cwd);
|
|
254
|
-
installHook(cwd, "post-commit", [
|
|
255
|
-
"original=$(git rev-parse HEAD)",
|
|
256
|
-
"tree=$(git rev-parse HEAD^{tree})",
|
|
257
|
-
"alternate_parent=$(git rev-parse HEAD~2)",
|
|
258
|
-
"replacement=$(printf 'replacement\\n' | git commit-tree \"$tree\" -p \"$alternate_parent\")",
|
|
259
|
-
"git update-ref HEAD \"$replacement\" \"$original\"",
|
|
260
|
-
].join("\n"));
|
|
261
|
-
await assert.rejects(
|
|
262
|
-
runGitCommitTransaction(invocation(cwd, "post-commit-replacement"), { nativeReviewCli: native(cwd, "post-commit-replacement") }),
|
|
263
|
-
/different commit|identity changed/,
|
|
264
|
-
);
|
|
265
|
-
assert.equal(inspectCommitTransaction(cwd).record?.state, COMMIT_TRANSACTION_STATE.INCIDENT);
|
|
266
|
-
});
|
|
267
|
-
|
|
268
|
-
test("cancellation cannot strand a commit after HEAD advances", async (t) => {
|
|
269
|
-
const cwd = repository(t);
|
|
270
|
-
stage(cwd);
|
|
271
|
-
// Deterministic cancellation ordering (issue #178): a wall-clock
|
|
272
|
-
// AbortSignal.timeout raced Git's own progress on loaded CI runners and
|
|
273
|
-
// could abort before HEAD advanced. Git only runs the post-commit hook
|
|
274
|
-
// after the commit object exists and HEAD has advanced, so the hook
|
|
275
|
-
// reports that it started and then blocks until the test releases it.
|
|
276
|
-
// Aborting between those two events guarantees the cancellation lands
|
|
277
|
-
// while the commit process is still running and strictly after HEAD
|
|
278
|
-
// advanced, on every runner.
|
|
279
|
-
const started = join(cwd, ".git", "post-commit-started");
|
|
280
|
-
const release = join(cwd, ".git", "post-commit-release");
|
|
281
|
-
installHook(cwd, "post-commit", [
|
|
282
|
-
`printf '1\\n' > ${JSON.stringify(started)}`,
|
|
283
|
-
`while [ ! -e ${JSON.stringify(release)} ]; do sleep 0.02; done`,
|
|
284
|
-
].join("\n"));
|
|
285
|
-
const before = git(cwd, "rev-parse", "HEAD");
|
|
286
|
-
const abort = new AbortController();
|
|
287
|
-
const pending = runGitCommitTransaction(invocation(cwd, "commit-cancellation"), {
|
|
288
|
-
nativeReviewCli: native(cwd, "commit-cancellation"),
|
|
289
|
-
signal: abort.signal,
|
|
290
|
-
});
|
|
291
|
-
let settled = false;
|
|
292
|
-
void pending.then(() => { settled = true; }, () => { settled = true; });
|
|
293
|
-
while (!existsSync(started) && !settled) await delay(10);
|
|
294
|
-
assert.equal(settled, false, "commit transaction finished before the post-commit hook confirmed HEAD advanced");
|
|
295
|
-
abort.abort();
|
|
296
|
-
writeFileSync(release, "release\n");
|
|
297
|
-
const result = await pending;
|
|
298
|
-
assert.equal(abort.signal.aborted, true);
|
|
299
|
-
assert.notEqual(result.head, before);
|
|
300
|
-
assert.equal(result.status, "committed");
|
|
301
|
-
assert.deepEqual(inspectCommitTransaction(cwd), { status: "clean" });
|
|
302
|
-
});
|