gentle-pi 2.5.0 → 2.6.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.
Files changed (189) hide show
  1. package/README.md +139 -30
  2. package/assets/agents/gentle-ai-worker.md +4 -0
  3. package/assets/agents/jd-fix-agent.md +18 -0
  4. package/assets/agents/jd-judge-a.md +1 -1
  5. package/assets/agents/jd-judge-b.md +1 -1
  6. package/assets/agents/sdd-apply.md +7 -5
  7. package/assets/agents/sdd-archive.md +5 -3
  8. package/assets/agents/sdd-design.md +4 -0
  9. package/assets/agents/sdd-explore.md +4 -0
  10. package/assets/agents/sdd-init.md +4 -0
  11. package/assets/agents/sdd-onboard.md +4 -0
  12. package/assets/agents/sdd-proposal.md +4 -0
  13. package/assets/agents/sdd-remediate.md +37 -0
  14. package/assets/agents/sdd-research.md +26 -3
  15. package/assets/agents/sdd-spec.md +4 -0
  16. package/assets/agents/sdd-status.md +9 -75
  17. package/assets/agents/sdd-sync.md +4 -0
  18. package/assets/agents/sdd-tasks.md +4 -0
  19. package/assets/agents/sdd-verify.md +5 -3
  20. package/assets/chains/sdd-full.chain.md +4 -0
  21. package/assets/chains/sdd-plan.chain.md +4 -0
  22. package/assets/chains/sdd-verify.chain.md +4 -0
  23. package/assets/migrations/managed-assets-v2.5.0.json +7 -0
  24. package/assets/orchestrator-delegation.md +21 -3
  25. package/assets/sdd-orchestrator-workflow.md +54 -21
  26. package/assets/support/sdd-status-contract.md +34 -90
  27. package/contracts/telemetry/runtime-aggregate-v1.schema.json +65 -0
  28. package/docs/telemetry.md +57 -1
  29. package/docs/windows-startup-console-visibility.md +18 -0
  30. package/extensions/ask-user-choice.ts +143 -15
  31. package/extensions/codegraph-tools.ts +1 -0
  32. package/extensions/gentle-agents.ts +799 -50
  33. package/extensions/gentle-ai.ts +2033 -322
  34. package/extensions/gentle-shell.ts +145 -42
  35. package/extensions/gentle-todo.ts +47 -12
  36. package/extensions/quiet-tools.ts +1 -0
  37. package/extensions/runtime-metrics.ts +130 -0
  38. package/extensions/sdd-init.ts +2 -2
  39. package/extensions/startup-banner.ts +52 -75
  40. package/lib/agent-profiles.ts +550 -0
  41. package/lib/agents-completion-delivery.ts +72 -0
  42. package/lib/agents-config.ts +7 -10
  43. package/lib/agents-history.ts +9 -1
  44. package/lib/agents-messaging.ts +187 -0
  45. package/lib/agents-protocol.ts +77 -5
  46. package/lib/agents-runner.ts +548 -26
  47. package/lib/agents-thread-view.ts +57 -0
  48. package/lib/agents-view-layout.ts +40 -0
  49. package/lib/agents-view.ts +548 -191
  50. package/lib/agents-widget.ts +33 -14
  51. package/lib/gentle-ai-binary.ts +3 -1
  52. package/lib/gentle-ai-renderer.ts +8 -6
  53. package/lib/native-review-cli.ts +283 -1
  54. package/lib/orchestrator-presence.ts +337 -0
  55. package/lib/profiles-orchestrator.ts +203 -0
  56. package/lib/review-candidate-view-owner.ts +296 -46
  57. package/lib/review-candidate-view.ts +30 -20
  58. package/lib/review-consent-component.ts +247 -0
  59. package/lib/review-consent-ui.ts +53 -8
  60. package/lib/review-host-relay.ts +28 -0
  61. package/lib/review-integration-v2.ts +187 -5
  62. package/lib/review-last-event-controller.ts +7 -4
  63. package/lib/review-reminder-receipt.ts +74 -0
  64. package/lib/review-session-standing-permission.ts +27 -6
  65. package/lib/runtime-metrics-children.ts +199 -0
  66. package/lib/runtime-metrics-delivery.ts +68 -0
  67. package/lib/runtime-metrics-native.ts +166 -0
  68. package/lib/runtime-metrics-pi-identity.ts +113 -0
  69. package/lib/runtime-metrics-policy.ts +51 -0
  70. package/lib/runtime-metrics.ts +255 -0
  71. package/lib/sdd-preflight.ts +362 -81
  72. package/lib/sdd-research-capabilities.ts +228 -0
  73. package/lib/sdd-status.ts +29 -7
  74. package/lib/session-worktree-registry.ts +118 -0
  75. package/lib/shell-bar.ts +47 -1
  76. package/lib/shell-card.ts +1 -4
  77. package/lib/shell-changes-view.ts +362 -37
  78. package/lib/shell-changes.ts +81 -1
  79. package/lib/shell-prompt.ts +11 -15
  80. package/lib/shell-sidebar-banner.ts +11 -0
  81. package/lib/shell-sidebar-layout.ts +213 -0
  82. package/lib/shell-sidebar.ts +41 -0
  83. package/lib/shell-todo.ts +28 -11
  84. package/lib/telemetry-trigger.ts +2 -0
  85. package/package.json +6 -3
  86. package/runtime/gentle-ai-binary.mjs +3 -1
  87. package/runtime/native-review-cli.mjs +283 -1
  88. package/runtime/review-integration-v2.mjs +187 -5
  89. package/runtime/telemetry-trigger.mjs +2 -0
  90. package/scripts/build-runtime-modules.mjs +9 -1
  91. package/scripts/check-types.mjs +125 -0
  92. package/scripts/gentle-ai-installer.mjs +10 -10
  93. package/scripts/install-gentle-ai.mjs +12 -0
  94. package/scripts/install-tui-mode-setting.mjs +114 -0
  95. package/scripts/test-packed-runner.mjs +16 -2
  96. package/scripts/types-baseline.json +99 -0
  97. package/scripts/verify-package-files.mjs +4 -2
  98. package/skills/_shared/review-ledger-contract.md +17 -1
  99. package/skills/issue-creation/SKILL.md +3 -3
  100. package/skills/judgment-day/SKILL.md +17 -3
  101. package/skills/judgment-day/references/prompts-and-formats.md +14 -3
  102. package/tests/agent-profiles.test.ts +722 -0
  103. package/tests/agents-completion-delivery.test.ts +94 -0
  104. package/tests/agents-config.test.ts +62 -0
  105. package/tests/agents-fake-child.ts +15 -1
  106. package/tests/agents-grouping.test.ts +179 -0
  107. package/tests/agents-integration.test.ts +100 -0
  108. package/tests/agents-messaging.test.ts +94 -0
  109. package/tests/agents-protocol.test.ts +45 -0
  110. package/tests/agents-queries.test.ts +190 -0
  111. package/tests/agents-responsive.test.ts +43 -0
  112. package/tests/agents-runner.test.ts +571 -14
  113. package/tests/agents-thread-view.test.ts +45 -0
  114. package/tests/agents-view.test.ts +476 -65
  115. package/tests/agents-widget.test.ts +31 -1
  116. package/tests/artifact-language.test.ts +25 -2
  117. package/tests/ask-user-choice.test.ts +169 -3
  118. package/tests/asset-installation-runtime.test.ts +108 -0
  119. package/tests/autonomous-guard.test.ts +116 -1
  120. package/tests/codegraph-tools.test.ts +2 -1
  121. package/tests/delegated-key-learnings-contract.test.ts +1 -1
  122. package/tests/devbinary/native-review-parity.devtest.ts +2 -0
  123. package/tests/feature-request-form.test.ts +67 -0
  124. package/tests/fixtures/agents-messaging-child.mjs +5 -0
  125. package/tests/fixtures/runtime-metrics-native-batches.json +6 -0
  126. package/tests/gentle-agents.test.ts +1460 -33
  127. package/tests/gentle-ai-binary.test.ts +7 -2
  128. package/tests/gentle-ai-installer.test.ts +47 -47
  129. package/tests/gentle-ai-renderer.test.ts +38 -0
  130. package/tests/gentle-ai.test.ts +944 -4
  131. package/tests/gentle-shell.test.ts +303 -12
  132. package/tests/gentle-todo.test.ts +54 -10
  133. package/tests/install-tui-mode-setting.test.ts +324 -0
  134. package/tests/issue-creation-skill.test.ts +22 -0
  135. package/tests/model-routing-authority.test.ts +12 -0
  136. package/tests/native-review-capability-contract.test.ts +12 -1
  137. package/tests/native-review-cli.test.ts +277 -3
  138. package/tests/native-review-parity.test.ts +14 -7
  139. package/tests/native-sdd-attempt-authority.test.ts +7 -2
  140. package/tests/orchestrator-presence.test.ts +389 -0
  141. package/tests/package-manifest.test.ts +232 -7
  142. package/tests/profiles-orchestrator.test.ts +208 -0
  143. package/tests/quiet-tool-rendering.test.ts +1 -0
  144. package/tests/rdd-aware-verification-contract.test.ts +10 -0
  145. package/tests/review-agent-end-preflight.test.ts +332 -24
  146. package/tests/review-candidate-view.test.ts +304 -6
  147. package/tests/review-consent-ui.test.ts +352 -0
  148. package/tests/review-contract-prompt.test.ts +14 -0
  149. package/tests/review-controller-native-routing.test.ts +563 -3
  150. package/tests/review-controller.test.ts +1 -1
  151. package/tests/review-host-relay-restart-parity.test.ts +142 -1
  152. package/tests/review-host-relay-routing.test.ts +364 -4
  153. package/tests/review-host-relay.test.ts +29 -0
  154. package/tests/review-integration-v2-forward.test.ts +44 -0
  155. package/tests/review-integration-v2.test.ts +164 -0
  156. package/tests/review-last-event-closure.test.ts +105 -1
  157. package/tests/review-ledger-contract.test.ts +61 -6
  158. package/tests/review-reminder-receipt.test.ts +62 -0
  159. package/tests/review-session-standing-permission-controller.test.ts +52 -4
  160. package/tests/review-session-standing-permission.test.ts +30 -0
  161. package/tests/runtime-harness.mjs +447 -39
  162. package/tests/runtime-metrics-children.test.ts +206 -0
  163. package/tests/runtime-metrics-delivery.test.ts +85 -0
  164. package/tests/runtime-metrics-extension.test.ts +187 -0
  165. package/tests/runtime-metrics-native.test.ts +209 -0
  166. package/tests/runtime-metrics-pi-identity.test.ts +113 -0
  167. package/tests/runtime-metrics-policy.test.ts +62 -0
  168. package/tests/runtime-metrics.test.ts +184 -0
  169. package/tests/sdd-agent-tools.test.ts +10 -1
  170. package/tests/sdd-execution-routing-contract.test.ts +28 -0
  171. package/tests/sdd-managed-runtime-settlement.test.ts +331 -0
  172. package/tests/sdd-native-managed-uptake.test.ts +253 -0
  173. package/tests/sdd-planning-routing-contract.test.ts +45 -0
  174. package/tests/sdd-preflight.test.ts +252 -8
  175. package/tests/sdd-research-capabilities.test.ts +256 -0
  176. package/tests/sdd-research-live.test.ts +241 -0
  177. package/tests/sdd-selection-transport.test.ts +504 -0
  178. package/tests/sdd-status.test.ts +51 -0
  179. package/tests/session-worktree-registry.test.ts +135 -0
  180. package/tests/shell-card.test.ts +24 -3
  181. package/tests/shell-changes-view.test.ts +471 -8
  182. package/tests/shell-changes.test.ts +168 -0
  183. package/tests/shell-prompt.test.ts +28 -6
  184. package/tests/shell-sidebar-banner.test.ts +23 -0
  185. package/tests/shell-sidebar-layout.test.ts +387 -0
  186. package/tests/shell-sidebar.test.ts +50 -0
  187. package/tests/shell-todo.test.ts +100 -11
  188. package/tests/startup-banner.test.ts +126 -0
  189. package/tests/telemetry-trigger.test.ts +3 -1
@@ -38,6 +38,14 @@ async function main() {
38
38
  if ((mode !== "--write" && mode !== "--check") || process.argv.length !== 3) {
39
39
  throw new Error("usage: build-runtime-modules.mjs --write|--check");
40
40
  }
41
+ // Pi loads these directly as TypeScript. Check syntax without generating
42
+ // another runtime copy or expanding the published module boundary.
43
+ for (const path of ["lib/runtime-metrics-delivery.ts", "lib/runtime-metrics-native.ts",
44
+ "lib/runtime-metrics-children.ts", "extensions/runtime-metrics.ts"]) {
45
+ const source = await readFile(join(root, path), "utf8");
46
+ assertNoTrailingWhitespace(source, path);
47
+ stripTypeScriptTypes(source, { mode: "strip" });
48
+ }
41
49
  const runtime = join(root, "runtime");
42
50
  if (mode === "--write") await mkdir(runtime, { recursive: true });
43
51
  const drift = [];
@@ -59,7 +67,7 @@ async function main() {
59
67
  if (drift.length > 0) {
60
68
  throw new Error(`generated runtime is stale: ${drift.join(", ")}`);
61
69
  }
62
- process.stdout.write(`runtime ${mode === "--write" ? "generated" : "matches TypeScript sources"} (${sources.length} modules)\n`);
70
+ process.stdout.write(`runtime ${mode === "--write" ? "generated" : "matches TypeScript sources"} (${sources.length} generated modules; one-shot metrics sources validated)\n`);
63
71
  }
64
72
 
65
73
  main().catch((error) => {
@@ -0,0 +1,125 @@
1
+ #!/usr/bin/env node
2
+ // Type gate for a project that does not compile cleanly yet.
3
+ //
4
+ // `tsc --noEmit` reports a fixed set of diagnostics on this repository today, so
5
+ // the gate is a ratchet rather than a clean pass: it fails when the number of
6
+ // diagnostics grows for any (file, error code) pair, or when the total grows.
7
+ // Fixing diagnostics and refreshing the baseline is the intended way to shrink
8
+ // it.
9
+ //
10
+ // Known blind spot, stated rather than hidden: keying on (file, code) counts is
11
+ // what keeps the baseline stable while files are edited, because line numbers
12
+ // shift. A single change that removes one diagnostic and introduces another of
13
+ // the same code in the same file therefore passes. The total check catches that
14
+ // whenever the counts differ at all.
15
+ //
16
+ // Usage:
17
+ // node scripts/check-types.mjs fail on any new diagnostic
18
+ // node scripts/check-types.mjs --update rewrite the baseline and exit 0
19
+
20
+ import { execFileSync } from "node:child_process";
21
+ import { readFileSync, writeFileSync } from "node:fs";
22
+ import { createRequire } from "node:module";
23
+ import { dirname, join, relative } from "node:path";
24
+ import { fileURLToPath } from "node:url";
25
+
26
+ const packageRoot = dirname(dirname(fileURLToPath(import.meta.url)));
27
+ const baselinePath = join(packageRoot, "scripts", "types-baseline.json");
28
+ const configPath = join(packageRoot, "tsconfig.json");
29
+ const DIAGNOSTIC = /^(.*?)\((\d+),(\d+)\): error (TS\d+): (.*)$/;
30
+ const REPORT_LIMIT = 20;
31
+
32
+ function relativeToPackage(file) {
33
+ return relative(packageRoot, file).split("\\").join("/");
34
+ }
35
+
36
+ function compile() {
37
+ let tsc;
38
+ try {
39
+ tsc = createRequire(import.meta.url).resolve("typescript/bin/tsc");
40
+ } catch {
41
+ console.error("types: cannot resolve the TypeScript compiler. Run `pnpm install` first.");
42
+ process.exit(1);
43
+ }
44
+ try {
45
+ execFileSync(process.execPath, [tsc, "-p", configPath], {
46
+ cwd: packageRoot,
47
+ encoding: "utf8",
48
+ stdio: ["ignore", "pipe", "pipe"],
49
+ });
50
+ return "";
51
+ } catch (error) {
52
+ // tsc exits non-zero when it reports diagnostics and writes them to stdout.
53
+ return `${error.stdout ?? ""}${error.stderr ?? ""}`;
54
+ }
55
+ }
56
+
57
+ function summarize(output) {
58
+ const counts = new Map();
59
+ const samples = new Map();
60
+ let total = 0;
61
+ for (const line of output.split(/\r?\n/)) {
62
+ const match = DIAGNOSTIC.exec(line);
63
+ if (!match) continue;
64
+ const key = `${relativeToPackage(match[1])} ${match[4]}`;
65
+ counts.set(key, (counts.get(key) ?? 0) + 1);
66
+ if (!samples.has(key)) samples.set(key, match[5].trim());
67
+ total += 1;
68
+ }
69
+ return { counts, samples, total };
70
+ }
71
+
72
+ function writeBaseline(summary) {
73
+ const byFileAndCode = Object.fromEntries([...summary.counts].sort(([left], [right]) => left.localeCompare(right)));
74
+ const payload = {
75
+ note: "Recorded TypeScript diagnostics. Regenerate with `node scripts/check-types.mjs --update` after fixing or deliberately accepting diagnostics. This file may only shrink without a review decision.",
76
+ total: summary.total,
77
+ byFileAndCode,
78
+ };
79
+ writeFileSync(baselinePath, `${JSON.stringify(payload, null, 2)}\n`);
80
+ }
81
+
82
+ const summary = summarize(compile());
83
+
84
+ if (process.argv.includes("--update")) {
85
+ writeBaseline(summary);
86
+ console.log(`types: baseline recorded ${summary.total} diagnostic(s) across ${summary.counts.size} file/code pair(s)`);
87
+ process.exit(0);
88
+ }
89
+
90
+ let baseline;
91
+ try {
92
+ baseline = JSON.parse(readFileSync(baselinePath, "utf8"));
93
+ } catch (error) {
94
+ console.error(`types: cannot read ${relativeToPackage(baselinePath)}: ${error instanceof Error ? error.message : String(error)}`);
95
+ process.exit(1);
96
+ }
97
+
98
+ const regressions = [];
99
+ for (const [key, count] of summary.counts) {
100
+ const recorded = baseline.byFileAndCode[key] ?? 0;
101
+ if (count > recorded) regressions.push({ key, added: count - recorded, message: summary.samples.get(key) ?? "" });
102
+ }
103
+
104
+ const totalGrew = summary.total > baseline.total;
105
+
106
+ if (regressions.length > 0 || totalGrew) {
107
+ if (regressions.length > 0) {
108
+ console.error(`types: ${regressions.length} file/code pair(s) report more diagnostics than recorded:`);
109
+ for (const regression of regressions.slice(0, REPORT_LIMIT)) {
110
+ console.error(` +${regression.added} ${regression.key} ${regression.message.slice(0, 100)}`);
111
+ }
112
+ if (regressions.length > REPORT_LIMIT) console.error(` ... and ${regressions.length - REPORT_LIMIT} more`);
113
+ }
114
+ if (totalGrew) {
115
+ console.error(`types: total ${summary.total} exceeds the recorded ${baseline.total}`);
116
+ }
117
+ console.error("Fix the new diagnostics, or run `node scripts/check-types.mjs --update` when they are deliberately accepted.");
118
+ process.exit(1);
119
+ }
120
+
121
+ const improved = [...Object.entries(baseline.byFileAndCode)].filter(([key, count]) => (summary.counts.get(key) ?? 0) < count).length;
122
+ console.log(
123
+ `types: ${summary.total} recorded diagnostic(s), no regressions` +
124
+ (improved > 0 ? `; ${improved} file/code pair(s) improved, run --update to shrink the baseline` : ""),
125
+ );
@@ -36,7 +36,7 @@ const WINDOWS_SYSTEM_ROOT = "C:\\Windows";
36
36
  // version check below) derives from this constant instead of repeating the
37
37
  // literal, so a pin bump cannot leave a stale copy behind. See
38
38
  // scripts/install-gentle-ai.mjs for the incident that motivated this.
39
- export const INSTALLER_VERSION = "2.7.0";
39
+ export const INSTALLER_VERSION = "2.8.0";
40
40
  export const RELEASE_BASE_URL = `https://github.com/Gentleman-Programming/gentle-ai/releases/download/v${INSTALLER_VERSION}/`;
41
41
  export const GENTLE_AI_INSTALL_METHOD = Object.freeze({
42
42
  SIGNED_RELEASE_ASSET: "signed-release-asset",
@@ -45,10 +45,10 @@ export const GENTLE_AI_INSTALL_METHOD = Object.freeze({
45
45
  export const GENTLE_AI_WINDOWS_SOURCE_PACKAGE_PATH = "github.com/gentleman-programming/gentle-ai/v2/cmd/gentle-ai";
46
46
  export const GENTLE_AI_WINDOWS_SOURCE_MODULE = "github.com/gentleman-programming/gentle-ai/v2";
47
47
  export const GENTLE_AI_WINDOWS_SOURCE_TAG = `v${INSTALLER_VERSION}`;
48
- // `go mod download -json github.com/gentleman-programming/gentle-ai/v2@v2.7.0`
48
+ // `go mod download -json github.com/gentleman-programming/gentle-ai/v2@v2.8.0`
49
49
  // with GOSUMDB=sum.golang.org reports this exact module SumDB checksum, and the
50
- // tag resolves to commit 4e4470b3, the published v2.7.0 release head.
51
- export const GENTLE_AI_WINDOWS_SOURCE_MODULE_CHECKSUM = "h1:SE4KCLo3y1qWaTq+7HJKZ1DkAAAl+w+82YY0+qQkFwM=";
50
+ // tag resolves to commit 890ca948, the published v2.8.0 release head.
51
+ export const GENTLE_AI_WINDOWS_SOURCE_MODULE_CHECKSUM = "h1:QNdrYDxq/Bi08o9PCk0jc4r5YObLdFmRCLXjKMqsze8=";
52
52
  export const GENTLE_AI_WINDOWS_SOURCE_PACKAGE = `${GENTLE_AI_WINDOWS_SOURCE_PACKAGE_PATH}@${GENTLE_AI_WINDOWS_SOURCE_TAG}`;
53
53
  export const GENTLE_AI_WINDOWS_MINIMUM_GO_VERSION = "1.25.10";
54
54
  export const GENTLE_AI_GO_TOOLCHAIN_UNAVAILABLE_CODE = "GENTLE_AI_GO_TOOLCHAIN_UNAVAILABLE";
@@ -67,7 +67,7 @@ export class GentleAiInstallerError extends Error {
67
67
  // Sentinel used while a re-pinned gentle-ai release is not yet published. A
68
68
  // sentinel digest can never match a real SHA-256, so installation fails closed,
69
69
  // and verify-package-files.mjs refuses to pack/publish while any digest below
70
- // still holds it. The v2.7.0 digests are pinned from the published release:
70
+ // still holds it. The v2.8.0 digests are pinned from the published release:
71
71
  // archive sha256 values verified against the minisign-signed checksums.txt and
72
72
  // freshly computed hashes; binary sha256 values computed from the extracted
73
73
  // executables.
@@ -109,15 +109,15 @@ async function downloadPinnedGentleAiAsset(asset, destination, options) {
109
109
  }
110
110
 
111
111
  // Windows is absent from signed release archives on purpose. gentle-ai stopped
112
- // distributing unsigned Windows builds in c4b764d0, so v2.7.0 publishes signed
112
+ // distributing unsigned Windows builds in c4b764d0, so v2.8.0 publishes signed
113
113
  // Darwin/Linux archives only. Windows x64/arm64 uses the separately verified
114
114
  // exact-tag Go SumDB source-build path below; restore archive rows only when
115
115
  // upstream ships signed Windows assets.
116
116
  export const GENTLE_AI_RELEASE_ASSETS = Object.freeze({
117
- "darwin/amd64": asset("gentle-ai_2.7.0_darwin_amd64.tar.gz", "5edf1e38894d6b2c1d257583cf4da23e2471812ed2efd0de33cbeef608339609", "e7aa77701e3cfd8a382a756ff2f257ba1a94ab4699050b3c3ac8e6237eb53950", "gentle-ai"),
118
- "darwin/arm64": asset("gentle-ai_2.7.0_darwin_arm64.tar.gz", "a9efa8cf182d853b7d0115efbc73a83465d435ec429f6465bea9181ea8022fde", "497932a73664a958cf46b0b131277da4a41a48f8d7da4f777d1157f8ffa9f646", "gentle-ai"),
119
- "linux/amd64": asset("gentle-ai_2.7.0_linux_amd64.tar.gz", "ff765a183247fe31d4739ff6df3d6874740979987ea310de3856c8a6e85375e9", "8748b9f18c05a831692abc0ae560fdc50a4e4c8f492705edcce7f65e067a7b12", "gentle-ai"),
120
- "linux/arm64": asset("gentle-ai_2.7.0_linux_arm64.tar.gz", "d8e114cd4d226f6c974813a49fce4d3e2028f4880b87e08f270eadf0a0607561", "65dd6bd7249d5eb7a2c948eebd0aee1bf2e85e1a2123e9b3782e978b167c3875", "gentle-ai"),
117
+ "darwin/amd64": asset("gentle-ai_2.8.0_darwin_amd64.tar.gz", "9c735e51916c31135926e62b21ac990216d810907a73894f68ec47bb0648d22d", "3880084f118533102a02eb0656a709db9817d330f82de8f533868667e0ac449d", "gentle-ai"),
118
+ "darwin/arm64": asset("gentle-ai_2.8.0_darwin_arm64.tar.gz", "b62d01aadba484e79869e11878d47e81cd692ebce93a5de454d0889db65fac54", "fed81b2b3dbec02ab5f06ce73364b43d28c532231813a01e2015d585f08cbb2e", "gentle-ai"),
119
+ "linux/amd64": asset("gentle-ai_2.8.0_linux_amd64.tar.gz", "56378fd47cfee127d5982398e79248194d3c7624d268efda9823a6b061a018b7", "df19c4ac20cfdfc0cc0c98c75cda42106340ca9966009f5dfb61575c1ada27c8", "gentle-ai"),
120
+ "linux/arm64": asset("gentle-ai_2.8.0_linux_arm64.tar.gz", "41726bffee269206e5fe96d7bd900164d01f478d8916bdfba446a7991903dfc1", "a93fff44ea583546d37ce833cc2a0f14afec118ae4209c305cafcadb91f67bac", "gentle-ai"),
121
121
  });
122
122
 
123
123
  // A pinned asset is either a signed archive or, for a prerelease pin only,
@@ -4,6 +4,7 @@
4
4
  // v2.1.11 while writing v2.2.0 to disk, which is the one moment an operator
5
5
  // most needs the number to be true.
6
6
  import { INSTALLER_VERSION, installGentleAi } from "./gentle-ai-installer.mjs";
7
+ import { installTuiModeSetting } from "./install-tui-mode-setting.mjs";
7
8
 
8
9
  if (process.env.GENTLE_PI_SKIP_GENTLE_AI_INSTALL === "1") {
9
10
  console.warn("GENTLE_PI_SKIP_GENTLE_AI_INSTALL=1: skipped package-local Gentle AI installation; native review operations will fail with package-local-binary-missing until gentle-pi is reinstalled.");
@@ -16,3 +17,14 @@ if (process.env.GENTLE_PI_SKIP_GENTLE_AI_INSTALL === "1") {
16
17
  process.exitCode = 1;
17
18
  }
18
19
  }
20
+
21
+ // A native failure never changes settings; the explicit native-only skip does.
22
+ if (!process.exitCode) {
23
+ try {
24
+ const result = await installTuiModeSetting();
25
+ if (result.changed) console.log("gentle-pi enabled fullscreen in global Pi settings; /settings can switch back to regular.");
26
+ } catch (error) {
27
+ console.error(`gentle-pi could not enable fullscreen: ${error instanceof Error ? error.message : String(error)}`);
28
+ process.exitCode = 1;
29
+ }
30
+ }
@@ -0,0 +1,114 @@
1
+ import { closeSync, constants, fchmodSync, fsyncSync, fstatSync, lstatSync, mkdirSync, openSync, readFileSync, realpathSync, renameSync, rmdirSync, unlinkSync, writeFileSync } from "node:fs";
2
+ import { homedir } from "node:os";
3
+ import { dirname, join, resolve } from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ import { randomUUID } from "node:crypto";
6
+ import { setTimeout as delay } from "node:timers/promises";
7
+
8
+ function inspect(path) {
9
+ try { return lstatSync(path); }
10
+ catch (error) { if (error.code === "ENOENT") return undefined; throw error; }
11
+ }
12
+
13
+ function sameFile(left, right) {
14
+ return left && right && left.dev === right.dev && left.ino === right.ino;
15
+ }
16
+
17
+ function assertDirectories(paths) {
18
+ for (const path of paths) {
19
+ const stat = inspect(path);
20
+ if (!stat?.isDirectory() || stat.isSymbolicLink() || realpathSync(path) !== path) {
21
+ throw new Error(`Unsafe fullscreen settings installation path: ${path}`);
22
+ }
23
+ }
24
+ }
25
+
26
+ function readSettings(path) {
27
+ const before = inspect(path);
28
+ if (!before) return { stat: undefined, text: undefined, value: {} };
29
+ if (!before.isFile() || before.isSymbolicLink()) throw new Error("settings.json must be a regular, non-symlink file");
30
+ const fd = openSync(path, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0));
31
+ try {
32
+ if (!sameFile(before, fstatSync(fd))) throw new Error("settings.json changed while opening");
33
+ const text = readFileSync(fd, "utf8");
34
+ const value = JSON.parse(text.replace(/^\uFEFF/, ""));
35
+ if (value === null || typeof value !== "object" || Array.isArray(value)) throw new Error("settings.json must contain a JSON object");
36
+ return { stat: before, text, value };
37
+ } finally { closeSync(fd); }
38
+ }
39
+
40
+ // Pi uses proper-lockfile with realpath:false: its cooperative lock is the
41
+ // settings.json.lock directory. Do not steal stale locks. Keep the synchronous
42
+ // critical section below shorter than proper-lockfile's default stale window.
43
+ async function acquireLock(path) {
44
+ for (let attempt = 0; attempt < 10; attempt++) {
45
+ try {
46
+ mkdirSync(path, { mode: 0o700 });
47
+ return inspect(path);
48
+ } catch (error) {
49
+ if (error.code !== "EEXIST") throw error;
50
+ if (attempt === 9) throw new Error("Fullscreen settings lock is busy; retry installation when other settings writers finish");
51
+ await delay(20);
52
+ }
53
+ }
54
+ }
55
+
56
+ /** Only physically owned global Pi npm or exact Git installs may mutate Pi settings.
57
+ * Atomic rename protects readers from partial JSON, not arbitrary writers or
58
+ * malicious same-user ancestor swaps. No lifecycle cwd or store symlink grants ownership.
59
+ */
60
+ export async function installTuiModeSetting(options = {}) {
61
+ const env = options.env ?? process.env;
62
+ const requestedHome = resolve(env.GENTLE_PI_AGENT_HOME || env.PI_CODING_AGENT_DIR || join(options.home ?? homedir(), ".pi", "agent"));
63
+ const packageRoot = resolve(options.packageRoot ?? dirname(dirname(fileURLToPath(import.meta.url))));
64
+ let home;
65
+ try { home = realpathSync(requestedHome); }
66
+ catch (error) { if (error.code === "ENOENT") return { changed: false, recognized: false }; throw error; }
67
+ const installations = [
68
+ {
69
+ packageRoot: join(home, "npm", "node_modules", "gentle-pi"),
70
+ paths: [home, join(home, "npm"), join(home, "npm", "node_modules"), join(home, "npm", "node_modules", "gentle-pi")],
71
+ },
72
+ {
73
+ packageRoot: join(home, "git", "github.com", "Gentleman-Programming", "gentle-pi"),
74
+ paths: [home, join(home, "git"), join(home, "git", "github.com"), join(home, "git", "github.com", "Gentleman-Programming"), join(home, "git", "github.com", "Gentleman-Programming", "gentle-pi")],
75
+ },
76
+ ];
77
+ // Canonical agent-home aliases (including macOS /var) are supported.
78
+ // pnpm's physical store, npm links, and Git aliases are not owned global installs.
79
+ const installation = installations.find(({ packageRoot: expected }) => realpathSync(packageRoot) === expected);
80
+ if (!installation) return { changed: false, recognized: false };
81
+ assertDirectories(installation.paths);
82
+ const settingsPath = join(home, "settings.json");
83
+ const lockPath = `${settingsPath}.lock`;
84
+ const lock = await acquireLock(lockPath);
85
+ const started = Date.now();
86
+ let staging;
87
+ try {
88
+ assertDirectories(installation.paths);
89
+ const original = readSettings(settingsPath);
90
+ if (original.value.tuiMode === "fullscreen") return { changed: false, recognized: true };
91
+ staging = join(home, `.settings-fullscreen-${randomUUID()}.tmp`);
92
+ const fd = openSync(staging, "wx", original.stat ? original.stat.mode & 0o777 : 0o600);
93
+ try {
94
+ if (original.stat) fchmodSync(fd, original.stat.mode & 0o777);
95
+ writeFileSync(fd, `${JSON.stringify({ ...original.value, tuiMode: "fullscreen" }, null, 2)}\n`, "utf8");
96
+ fsyncSync(fd);
97
+ } finally { closeSync(fd); }
98
+ assertDirectories(installation.paths);
99
+ const latest = readSettings(settingsPath);
100
+ if (latest.text !== original.text || (original.stat ? !sameFile(original.stat, latest.stat) : latest.stat !== undefined)) {
101
+ throw new Error("settings.json changed concurrently; retry installation");
102
+ }
103
+ if (!sameFile(lock, inspect(lockPath)) || Date.now() - started >= 5000) throw new Error("Fullscreen settings lock ownership expired; retry installation");
104
+ renameSync(staging, settingsPath);
105
+ staging = undefined;
106
+ return { changed: true, recognized: true };
107
+ } finally {
108
+ // Only clean our own artifacts while the original parent remains canonical.
109
+ if (realpathSync(home) === home) {
110
+ if (staging) unlinkSync(staging);
111
+ if (sameFile(lock, inspect(lockPath))) rmdirSync(lockPath);
112
+ }
113
+ }
114
+ }
@@ -12,6 +12,10 @@ const root = fileURLToPath(new URL("..", import.meta.url));
12
12
  const temporary = mkdtempSync(join(tmpdir(), "gentle-pi-packed-runner-"));
13
13
  const packDirectory = join(temporary, "pack");
14
14
  const installDirectory = join(temporary, "install");
15
+ // Every child inherits only disposable Pi homes, never the operator's settings.
16
+ const agentHome = join(temporary, "agent");
17
+ const piAgentHome = join(temporary, "pi-agent");
18
+ const isolatedEnv = { ...process.env, GENTLE_PI_AGENT_HOME: agentHome, PI_CODING_AGENT_DIR: piAgentHome };
15
19
 
16
20
  function windowsNpmInvocation() {
17
21
  const candidates = [];
@@ -32,12 +36,16 @@ function windowsNpmInvocation() {
32
36
 
33
37
  function runNpm(arguments_, options) {
34
38
  const invocation = process.platform === "win32" ? windowsNpmInvocation() : { file: "npm", prefix: [] };
35
- return execFileSync(invocation.file, [...invocation.prefix, ...arguments_], options);
39
+ return execFileSync(invocation.file, [...invocation.prefix, ...arguments_], { ...options, env: isolatedEnv });
36
40
  }
37
41
 
38
42
  try {
39
43
  mkdirSync(packDirectory);
40
44
  mkdirSync(installDirectory);
45
+ mkdirSync(agentHome);
46
+ mkdirSync(piAgentHome);
47
+ const originalSettings = '{ "tuiMode": "regular", "theme": "packed-fixture" }\n';
48
+ writeFileSync(join(agentHome, "settings.json"), originalSettings);
41
49
  const packed = JSON.parse(runNpm(["pack", "--ignore-scripts", "--json", "--pack-destination", packDirectory], {
42
50
  cwd: root,
43
51
  encoding: "utf8",
@@ -50,7 +58,13 @@ try {
50
58
  cwd: installDirectory,
51
59
  stdio: "inherit",
52
60
  });
61
+ // This is an ordinary npm consumer, not Pi's managed global npm directory.
62
+ assert.equal(readFileSync(join(agentHome, "settings.json"), "utf8"), originalSettings);
63
+ assert.deepEqual(readdirSync(agentHome), ["settings.json"]);
64
+ assert.deepEqual(readdirSync(piAgentHome), []);
65
+ assert.equal(existsSync(join(installDirectory, ".pi", "settings.json")), false);
53
66
  const packageRoot = join(installDirectory, "node_modules", "gentle-pi");
67
+ assert.ok(existsSync(join(packageRoot, "scripts", "install-tui-mode-setting.mjs")));
54
68
  const { nativeReviewAbandonAuthorization } = await import(pathToFileURL(join(packageRoot, "runtime", "native-review-cli.mjs")).href);
55
69
  const abandonAuthorization = nativeReviewAbandonAuthorization({
56
70
  lineage: "review-abc",
@@ -77,7 +91,7 @@ try {
77
91
  const versions = readdirSync(join(packageRoot, ".gentle-ai"), { withFileTypes: true }).filter((entry) => entry.isDirectory() && /^v\d+\.\d+\.\d+(?:-[0-9A-Za-z][0-9A-Za-z.]*)?$/.test(entry.name));
78
92
  if (versions.length !== 1) throw new Error("packed install did not contain exactly one package-local Gentle AI version");
79
93
  const executable = join(packageRoot, ".gentle-ai", versions[0].name, process.platform === "win32" ? "gentle-ai.exe" : "gentle-ai");
80
- const capabilities = JSON.parse(execFileSync(executable, ["review", "capabilities", "--contract", "gentle-ai.review-integration/v2"], { cwd: installDirectory, encoding: "utf8" }));
94
+ const capabilities = JSON.parse(execFileSync(executable, ["review", "capabilities", "--contract", "gentle-ai.review-integration/v2"], { cwd: installDirectory, encoding: "utf8", env: isolatedEnv }));
81
95
  // Decode with the PACKED consumer's own decoder rather than comparing the
82
96
  // schema string against a list hand-copied into this script. The copy was a
83
97
  // second, silent pin: it accepted only `capabilities/v2`, so the moment the
@@ -0,0 +1,99 @@
1
+ {
2
+ "note": "Recorded TypeScript diagnostics. Regenerate with `node scripts/check-types.mjs --update` after fixing or deliberately accepting diagnostics. This file may only shrink without a review decision.",
3
+ "total": 205,
4
+ "byFileAndCode": {
5
+ "extensions/codegraph-tools.ts TS2339": 1,
6
+ "extensions/codegraph-tools.ts TS2345": 1,
7
+ "extensions/gentle-agents.ts TS2322": 3,
8
+ "extensions/gentle-ai.ts TS2322": 5,
9
+ "extensions/gentle-ai.ts TS2339": 11,
10
+ "extensions/gentle-ai.ts TS2345": 15,
11
+ "extensions/gentle-ai.ts TS2365": 1,
12
+ "extensions/gentle-ai.ts TS2488": 2,
13
+ "extensions/gentle-ai.ts TS2554": 1,
14
+ "extensions/gentle-ai.ts TS2740": 1,
15
+ "extensions/gentle-shell.ts TS2556": 1,
16
+ "extensions/quiet-tools.ts TS2339": 1,
17
+ "extensions/quiet-tools.ts TS2352": 2,
18
+ "lib/agents-messaging.ts TS2322": 1,
19
+ "lib/native-review-cli.ts TS2304": 6,
20
+ "lib/native-review-cli.ts TS2339": 1,
21
+ "lib/native-review-cli.ts TS2345": 1,
22
+ "lib/review-candidate-view.ts TS2353": 2,
23
+ "lib/review-compact-contract.ts TS2322": 2,
24
+ "lib/review-compact-contract.ts TS2365": 1,
25
+ "lib/review-integration-v2.ts TS2322": 2,
26
+ "lib/review-integration-v2.ts TS2352": 2,
27
+ "lib/review-publication-gate.ts TS2365": 2,
28
+ "lib/review-transaction.ts TS2322": 1,
29
+ "lib/review-transaction.ts TS2345": 1,
30
+ "lib/runtime-metrics-children.ts TS2345": 2,
31
+ "lib/sdd-preflight.ts TS2352": 1,
32
+ "lib/sdd-preflight.ts TS2365": 1,
33
+ "lib/shell-sidebar-layout.ts TS2341": 1,
34
+ "tests/agents-queries.test.ts TS2322": 1,
35
+ "tests/agents-queries.test.ts TS2345": 3,
36
+ "tests/agents-runner-process.test.ts TS2322": 1,
37
+ "tests/devbinary/native-review-parity.devtest.ts TS2339": 1,
38
+ "tests/devbinary/pi-host-relay.devtest.ts TS2339": 3,
39
+ "tests/gentle-agents.test.ts TS2339": 1,
40
+ "tests/gentle-agents.test.ts TS2352": 2,
41
+ "tests/gentle-ai-binary.test.ts TS2339": 2,
42
+ "tests/gentle-ai-installer.test.ts TS2339": 7,
43
+ "tests/gentle-ai-installer.test.ts TS2556": 1,
44
+ "tests/gentle-ai-renderer.test.ts TS2345": 6,
45
+ "tests/gentle-ai.test.ts TS2339": 1,
46
+ "tests/gentle-ai.test.ts TS2352": 8,
47
+ "tests/gentle-ai.test.ts TS2353": 1,
48
+ "tests/gentle-shell.test.ts TS2352": 1,
49
+ "tests/gentle-shell.test.ts TS2540": 1,
50
+ "tests/gentle-shell.test.ts TS2554": 1,
51
+ "tests/maintainer/provider-relay.maintest.ts TS2339": 17,
52
+ "tests/maintainer/provider-relay.maintest.ts TS2345": 1,
53
+ "tests/maintainer/provider-relay.maintest.ts TS2540": 2,
54
+ "tests/native-binary-gate.test.ts TS2339": 2,
55
+ "tests/native-review-consent.test.ts TS2554": 1,
56
+ "tests/native-review-parity-runtime.test.ts TS2339": 1,
57
+ "tests/quiet-tool-rendering.test.ts TS2339": 1,
58
+ "tests/quiet-tool-rendering.test.ts TS2345": 1,
59
+ "tests/review-agent-end-preflight.test.ts TS2339": 2,
60
+ "tests/review-agent-end-preflight.test.ts TS2345": 1,
61
+ "tests/review-candidate-view.test.ts TS2353": 4,
62
+ "tests/review-candidate-view.test.ts TS2540": 2,
63
+ "tests/review-candidate-view.test.ts TS2554": 2,
64
+ "tests/review-controller-native-recovery.test.ts TS2345": 1,
65
+ "tests/review-controller-native-routing.test.ts TS2339": 2,
66
+ "tests/review-controller-workspace-root.test.ts TS2322": 2,
67
+ "tests/review-correction-lifecycle.test.ts TS2339": 4,
68
+ "tests/review-gate.test.ts TS2322": 5,
69
+ "tests/review-gate.test.ts TS2345": 4,
70
+ "tests/review-gate.test.ts TS2740": 1,
71
+ "tests/review-graph-schema.test.ts TS2352": 2,
72
+ "tests/review-host-relay-routing.test.ts TS2345": 1,
73
+ "tests/review-host-relay-routing.test.ts TS2739": 1,
74
+ "tests/review-integration-v2-forward.test.ts TS2322": 1,
75
+ "tests/review-last-event-closure.test.ts TS2322": 1,
76
+ "tests/review-policy-judgment-day.test.ts TS2345": 1,
77
+ "tests/review-policy-ordinary.test.ts TS2345": 1,
78
+ "tests/review-policy-ordinary.test.ts TS2554": 1,
79
+ "tests/review-risk-assessment.test.ts TS2345": 1,
80
+ "tests/review-risk-assessment.test.ts TS2352": 1,
81
+ "tests/review-session-standing-permission-controller.test.ts TS2339": 1,
82
+ "tests/review-session-standing-permission-controller.test.ts TS2345": 1,
83
+ "tests/review-session-standing-permission-controller.test.ts TS2352": 1,
84
+ "tests/review-session-standing-permission-ipc.test.ts TS2322": 4,
85
+ "tests/review-test-fixtures.ts TS2739": 1,
86
+ "tests/review-transaction.test.ts TS2339": 1,
87
+ "tests/runtime-metrics-extension.test.ts TS2345": 1,
88
+ "tests/sdd-preflight.test.ts TS2352": 1,
89
+ "tests/sdd-preflight.test.ts TS2554": 2,
90
+ "tests/sdd-research-capabilities.test.ts TS2339": 1,
91
+ "tests/sdd-research-capabilities.test.ts TS2698": 1,
92
+ "tests/sdd-research-live.test.ts TS2322": 1,
93
+ "tests/shell-sidebar-layout.test.ts TS2339": 1,
94
+ "tests/shell-sidebar-layout.test.ts TS2345": 1,
95
+ "tests/shell-usage-view.test.ts TS2322": 1,
96
+ "tests/skill-registry.test.ts TS2345": 5,
97
+ "tests/writer-edit-surface-scope.test.ts TS2352": 1
98
+ }
99
+ }
@@ -30,6 +30,7 @@ const requiredPaths = [
30
30
  "assets/agents/sdd-init.md",
31
31
  "assets/agents/sdd-onboard.md",
32
32
  "assets/agents/sdd-proposal.md",
33
+ "assets/agents/sdd-remediate.md",
33
34
  "assets/agents/sdd-research.md",
34
35
  "assets/agents/sdd-spec.md",
35
36
  "assets/agents/sdd-status.md",
@@ -180,6 +181,7 @@ const contractHashes = {
180
181
  "contracts/review-integration/v2/schemas/repair.schema.json": "98a85fd45a8ae7f6211ffeeb3f9c478fa1dd1c17f385751f15f2111e6c3ab167",
181
182
  "contracts/review-integration/v2/schemas/start.schema.json": "2991e3fcca672d9257d61b6a336fb34e58b15a8e03f8a09a7adf892cae6a8085",
182
183
  "contracts/review-integration/v2/schemas/status.schema.json": "c4dcc736cfc6300560a3c4262d2d982368529d5c49d58d499552a3b0beef9212",
184
+ "contracts/telemetry/runtime-aggregate-v1.schema.json": "26be905d39fe8274e049e1270553695b7540a3b24571d42eb7d96c5a7deb48b5",
183
185
  "docs/review-integration.md": "95a3df92785bc4d9f3b99e702aaf817ae0440bd16c83218d2c3f2aca67c280fb",
184
186
  };
185
187
 
@@ -338,7 +340,7 @@ async function main() {
338
340
  });
339
341
 
340
342
  if (driftedContracts.length > 0) {
341
- console.error("gentle-pi packaged review-integration/v1 and review-integration/v2 contract bytes drifted from the pinned v2.7.0 runtime's vendored Gentle AI contract artifacts:");
343
+ console.error("gentle-pi packaged review-integration/v1 and review-integration/v2 contract bytes drifted from the pinned v2.8.0 runtime's vendored Gentle AI contract artifacts:");
342
344
  for (const drift of driftedContracts) console.error(`- ${drift.relativePath}: expected ${drift.expected}, got ${drift.actual}`);
343
345
  process.exit(1);
344
346
  }
@@ -383,7 +385,7 @@ async function main() {
383
385
  process.exit(1);
384
386
  }
385
387
 
386
- console.log(`gentle-pi package resource check passed (${requiredPaths.length} files; ${Object.keys(contractHashes).length} exact byte-pinned contract artifacts for the v2.7.0 runtime).`);
388
+ console.log(`gentle-pi package resource check passed (${requiredPaths.length} files; ${Object.keys(contractHashes).length} exact byte-pinned contract artifacts for the v2.8.0 runtime).`);
387
389
  }
388
390
 
389
391
  const isMainModule = process.argv[1] !== undefined && import.meta.url === pathToFileURL(process.argv[1]).href;
@@ -79,7 +79,7 @@ Dangerous-command confirmation/safety and destructive-review-maintenance consent
79
79
 
80
80
  ## Judgment Day
81
81
 
82
- Judgment Day starts only when explicitly requested and replaces ordinary review for that lineage.
82
+ Judgment Day is independent: it neither enables nor replaces ordinary review; a separately requested ordinary review remains independent.
83
83
 
84
84
  Judgment Day starts with exactly two blind judges and zero refuters.
85
85
 
@@ -87,4 +87,20 @@ Judgment Day alone may iterate discovery and scoped re-judgment, for at most two
87
87
 
88
88
  Findings surviving round two escalate; no third-round transition exists.
89
89
 
90
+ A standalone `jd-fix-agent` dispatch requires no graph-v1 or native review lineage and is accepted only with this exact Markdown shape. The correction batch contains only one round (`1 of 2` or `2 of 2`) and one lowercase SHA-256. The exact frozen finding rows are one JSON object per line, use only the canonical row fields, and exactly match the authorized IDs.
91
+
92
+ ```markdown
93
+ ## Judgment Day activation
94
+ User explicitly requested Judgment Day.
95
+ ## Exact authorized severe IDs
96
+ - `JD-A-001`
97
+ ## Judgment Day correction batch
98
+ Round: 1 of 2.
99
+ Frozen ledger SHA-256: `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`
100
+ ## Exact frozen finding rows
101
+ {"id":"JD-A-001","lens":"judgment-day","location":"path/to/authorized-file.ts:1","severity":"CRITICAL","status_at_freeze":"open","evidence_class":"deterministic","evidence_claim":"Concrete user-impact claim supported by the frozen location."}
102
+ ## Allowed edit surfaces
103
+ path/to/authorized-file.ts
104
+ ```
105
+
90
106
  Judgment Day stays mutable on graph-v1. Its reducer, replay, object-store, lock, snapshot, and graph receipt-validation dependencies remain live even though ordinary authority is native.
@@ -46,7 +46,7 @@ LABEL_ARGS+=(--label "$LABEL") # Repeat only for each permitted discovered label
46
46
  gh issue list --repo "$TARGET" --state all --search "$QUERY" --limit 1000
47
47
  ```
48
48
 
49
- If results are saturated or completeness is uncertain, narrow the read-only search or stop. Comment on a confirmed duplicate instead of creating one. Before commenting on a confirmed duplicate, perform the same privacy scan/redaction on the exact comment body as for publication.
49
+ The agent must complete the duplicate search proactively and retain evidence of its result. If results are saturated or completeness is uncertain, narrow the read-only search or stop. Comment on a confirmed duplicate instead of creating one. Before commenting on a confirmed duplicate, perform the same privacy scan/redaction on the exact comment body as for publication.
50
50
  2. Select one repository-provided form only when its declared purpose matches. If multiple forms match and policy does not distinguish them, stop and request that decision.
51
51
  3. For a YAML form, read its schema and establish controls in declared order. Support only `input`, `textarea`, `dropdown`, and `checkboxes`. Markdown controls are non-answer guidance: honor their visible instructions when collecting and materializing adjacent answers, but do not render them as response sections. Fail closed before mutation on malformed, unsupported, missing, or ambiguous required structure or answers. A malformed schema, or missing or ambiguous required answers, fail closed: do not open a browser or mutate. A browser handoff is available only when the user explicitly requests browser completion or a syntactically valid selected form cannot safely/faithfully be represented by the automated path; otherwise report why automation is unsafe and stop.
52
52
 
@@ -54,7 +54,7 @@ LABEL_ARGS+=(--label "$LABEL") # Repeat only for each permitted discovered label
54
54
  | --- | --- |
55
55
  | `input` / `textarea` | Preserve the visible label. Require an answer when `validations.required` is true; otherwise render `_No response_`. |
56
56
  | `dropdown` | Preserve visible labels and options. Require exact selected option text; single-select has one selection, and multi-select preserves selections in declared options order. A required dropdown needs at least one valid selection; an optional dropdown with no selection renders `_No response_`. |
57
- | `checkboxes` | Preserve the visible label and every option as `- [x]` or `- [ ]` in declared order. Enforce individually required checkboxes and require explicit first-person affirmation for first-person option text. |
57
+ | `checkboxes` | Preserve the visible label and every option as `- [x]` or `- [ ]` in declared order. Enforce individually required checkboxes. For agent-verifiable operational options, proactively complete the action and mark it only with retained evidence; the agent may explicitly attest only its own evidence-backed work and must not attribute its actions to the user. Personal facts, consent, legal declarations, and other first-person user assertions require explicit user affirmation; require explicit first-person affirmation for such user declarations. Do not blanket-check checkboxes: a request to publish does not affirm any checkbox. |
58
58
 
59
59
  For each answer, render `### <visible label>` followed by its materialized value. For `textarea.attributes.render`, fence the answer with the declared language and a fence long enough for its content. Never invent answers, selections, confirmations, or labels.
60
60
 
@@ -62,7 +62,7 @@ A Markdown template may be completed only from known evidence into the same priv
62
62
 
63
63
  ## Review And Publication
64
64
 
65
- Before the single create attempt, review the target, title, selected form or permitted fallback, exact body, and permitted labels. Perform a privacy scan immediately before publication: replace private project names, usernames, hostnames, home paths, credentials, and private network addresses with useful placeholders without removing reproduction structure.
65
+ Before the single create attempt, review the target, title, selected form or permitted fallback, exact body, and permitted labels. The agent must complete the privacy scan/redaction of the exact body immediately before publication and retain evidence of it: replace private project names, usernames, hostnames, home paths, credentials, and private network addresses with useful placeholders without removing reproduction structure.
66
66
 
67
67
  Create one owner-only temporary directory outside the repository for both private files; restrict it to the current user and clean up both files on every exit/outcome:
68
68
 
@@ -11,12 +11,10 @@ metadata:
11
11
 
12
12
  Load this skill only when the user explicitly requests Judgment Day, Judgement Day, dual/adversarial review, or an equivalent trigger. Resolve one exact target before starting.
13
13
 
14
- Judgment Day is a standalone developer tool: judges run whenever asked, on any runtime, and need no review transaction, runtime identity, or delivery-receipt machinery to start. It neither enables nor replaces an ordinary 4R lifecycle; a separately requested ordinary review remains independent.
14
+ Judgment Day is a standalone developer tool: judges run whenever asked, on any runtime, and need no review transaction, runtime identity, or delivery-receipt machinery to start. Judgment Day is independent: it neither enables nor replaces ordinary review; a separately requested ordinary review remains independent.
15
15
 
16
16
  Judgment Day starts only when explicitly requested. It does not start, configure, or consume ordinary review for that lineage.
17
17
 
18
- Historical compatibility note (obsolete): Judgment Day starts only when explicitly requested and replaces ordinary review for that lineage. Current behavior is the independent lifecycle above.
19
-
20
18
  ## Transaction Rules
21
19
 
22
20
  Judgment Day starts with exactly two blind judges and zero refuters.
@@ -57,6 +55,22 @@ WARNING and SUGGESTION candidates become one-time informational rows and never s
57
55
 
58
56
  ## Fix Boundary
59
57
 
58
+ A standalone `jd-fix-agent` dispatch requires no graph-v1 or native review lineage and is accepted only as one standalone agent with this exact Markdown shape. The `## Judgment Day activation` section contains only `User explicitly requested Judgment Day.`. The parent replaces the example ID, frozen ledger hash, row data, and surface with controller-authorized values. The correction batch contains only one round (`1 of 2` or `2 of 2`) and one lowercase SHA-256. The exact frozen finding rows are one JSON object per line, use only the canonical row fields, and exactly match the authorized IDs.
59
+
60
+ ```markdown
61
+ ## Judgment Day activation
62
+ User explicitly requested Judgment Day.
63
+ ## Exact authorized severe IDs
64
+ - `JD-A-001`
65
+ ## Judgment Day correction batch
66
+ Round: 1 of 2.
67
+ Frozen ledger SHA-256: `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`
68
+ ## Exact frozen finding rows
69
+ {"id":"JD-A-001","lens":"judgment-day","location":"path/to/authorized-file.ts:1","severity":"CRITICAL","status_at_freeze":"open","evidence_class":"deterministic","evidence_claim":"Concrete user-impact claim supported by the frozen location."}
70
+ ## Allowed edit surfaces
71
+ path/to/authorized-file.ts
72
+ ```
73
+
60
74
  Fix only the exact controller-authorized severe IDs in the one supplied batch.
61
75
 
62
76
  Do not add findings, alter frozen claims, authorize transitions, deliver, publish, or start another actor.