gentle-pi 2.1.2 → 2.2.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 +70 -12
- 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 -1
- package/assets/agents/review-reliability.md +4 -1
- package/assets/agents/review-resilience.md +4 -1
- package/assets/agents/review-risk.md +4 -1
- package/assets/agents/sdd-apply.md +6 -1
- 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 +6 -1
- package/assets/agents/sdd-spec.md +6 -1
- package/assets/agents/sdd-status.md +6 -1
- package/assets/agents/sdd-sync.md +6 -1
- package/assets/agents/sdd-tasks.md +6 -1
- package/assets/agents/sdd-verify.md +6 -1
- package/assets/chains/4r-review.chain.md +2 -0
- package/assets/chains/sdd-full.chain.md +1 -1
- package/assets/chains/sdd-plan.chain.md +1 -1
- package/assets/chains/sdd-verify.chain.md +1 -1
- package/assets/orchestrator-delegation.md +246 -67
- package/assets/orchestrator.md +7 -14
- package/assets/sdd-orchestrator-workflow.md +154 -9
- package/assets/support/sdd-status-contract.md +19 -1
- 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/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/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 +5 -5
- package/docs/review-integration.md +22 -2
- package/extensions/gentle-ai.ts +1595 -201
- package/extensions/sdd-init.ts +19 -6
- package/extensions/skill-registry.ts +10 -2
- package/extensions/startup-banner.ts +10 -4
- package/lib/gentle-ai-binary.ts +173 -2
- package/lib/git-commit-transaction.ts +77 -17
- package/lib/native-review-cli.ts +528 -65
- package/lib/provider-contract-bundle.ts +704 -0
- package/lib/review-candidate-view.ts +527 -18
- package/lib/review-compact-contract.ts +59 -248
- package/lib/review-host-relay.ts +436 -0
- package/lib/review-integration-v2.ts +537 -36
- package/lib/review-relay-contract.ts +16 -0
- package/lib/sdd-preflight.ts +53 -1
- package/package.json +5 -2
- package/runtime/gentle-ai-binary.mjs +173 -2
- package/runtime/git-commit-transaction.mjs +75 -15
- package/runtime/native-review-cli.mjs +524 -61
- package/runtime/review-integration-v2.mjs +536 -35
- package/runtime/review-relay-contract.mjs +17 -0
- package/scripts/build-git-commit-transaction-runner.mjs +1 -0
- package/scripts/check-provider-contract.mjs +138 -0
- package/scripts/gentle-ai-installer.mjs +23 -13
- package/scripts/maintainer/provider-relay-matrix.mjs +219 -0
- package/scripts/mirror-provider-contract.mjs +143 -0
- package/scripts/test-packed-runner.mjs +16 -2
- package/scripts/verify-package-files.mjs +110 -33
- package/skills/_shared/review-ledger-contract.md +4 -6
- package/skills/gentle-ai/SKILL.md +4 -4
- package/skills/issue-creation/SKILL.md +94 -168
- package/skills/judgment-day/SKILL.md +7 -1
- package/skills/judgment-day/references/prompts-and-formats.md +2 -0
- package/skills/rdd-defect-workflow/SKILL.md +54 -0
- package/tests/background-subagents.test.ts +771 -0
- package/tests/crosslane/cross-lane.mjs +1169 -0
- package/tests/delegated-key-learnings-contract.test.ts +238 -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/result-artifact-v2-path.captured.json +12 -0
- package/tests/fixtures/devbinary/result-artifact-v2.captured.json +12 -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/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/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 +1 -1
- package/tests/gentle-ai-dev-binary-surfacing.test.ts +195 -0
- package/tests/gentle-ai-dev-binary.test.ts +336 -0
- package/tests/gentle-ai-installer.test.ts +46 -46
- package/tests/git-commit-transaction.test.ts +229 -1
- package/tests/maintainer/provider-relay.maintest.ts +265 -0
- package/tests/native-review-capability-contract.test.ts +48 -2
- package/tests/native-review-cli.test.ts +56 -0
- package/tests/native-review-consent.test.ts +164 -3
- package/tests/native-review-parity-runtime.test.ts +37 -0
- package/tests/native-review-parity.test.ts +218 -15
- package/tests/native-sdd-attempt-authority.test.ts +235 -0
- package/tests/orchestrator-budget.test.ts +30 -5
- package/tests/package-manifest.test.ts +98 -72
- 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 +355 -0
- package/tests/review-actor-tool-deny.test.ts +12 -13
- package/tests/review-candidate-view.test.ts +489 -9
- package/tests/review-compact-contract.test.ts +52 -119
- package/tests/review-controller-native-recovery.test.ts +643 -47
- package/tests/review-controller-native-routing.test.ts +1667 -222
- package/tests/review-controller-workspace-root.test.ts +17 -2
- package/tests/review-corrected-finalize-binding.test.ts +175 -0
- package/tests/review-dispatch-hydration-gap.test.ts +197 -0
- package/tests/review-host-relay-routing.test.ts +317 -0
- package/tests/review-host-relay.test.ts +520 -0
- package/tests/review-integration-v2-forward.test.ts +631 -0
- package/tests/review-integration-v2.test.ts +114 -0
- package/tests/review-ledger-contract.test.ts +12 -28
- package/tests/review-recovered-lineage-routing.test.ts +246 -0
- package/tests/review-relay-transport-agent.test.ts +249 -0
- package/tests/runtime-harness.mjs +242 -14
- package/tests/sdd-agent-tools.test.ts +18 -33
- package/tests/skill-collision-prefixes.test.ts +1 -0
- package/tests/skill-registry.test.ts +50 -1
- package/tests/verify-package-files.test.ts +62 -0
- package/assets/agents/review-refuter.md +0 -40
- package/assets/agents/review-validator.md +0 -23
- 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/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/review-compact.test.ts +0 -243
- package/tests/review-refuter-adapter.test.ts +0 -89
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import test from "node:test";
|
|
5
|
+
|
|
6
|
+
// ---------------------------------------------------------------------------
|
|
7
|
+
// Provider Defect Handoff — structural readback tests (issue #256, track 5)
|
|
8
|
+
//
|
|
9
|
+
// Pins the port of Gentle AI's v2.4.0-rc.8 provider-defect handoff consent
|
|
10
|
+
// contract (the gentle-ai.review-integration.consent/v3 envelope; canonical
|
|
11
|
+
// source internal/assets/generic/sdd-orchestrator.md at tag v2.4.0-rc.8 of
|
|
12
|
+
// Gentleman-Programming/gentle-ai) into Pi's lazy-loaded orchestrator assets.
|
|
13
|
+
// The contract is a prerelease (not in v2.3.0 stable). These tests assert
|
|
14
|
+
// structural presence, ordering, and the removal of stale rc.3-era rules; they
|
|
15
|
+
// do not execute any lifecycle command.
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
|
|
18
|
+
const REPO_ROOT = join(import.meta.dirname, "..");
|
|
19
|
+
const DELEGATION_PATH = join(REPO_ROOT, "assets", "orchestrator-delegation.md");
|
|
20
|
+
const SDD_WORKFLOW_PATH = join(REPO_ROOT, "assets", "sdd-orchestrator-workflow.md");
|
|
21
|
+
|
|
22
|
+
const DELEGATION = readFileSync(DELEGATION_PATH, "utf8");
|
|
23
|
+
const SDD_WORKFLOW = readFileSync(SDD_WORKFLOW_PATH, "utf8");
|
|
24
|
+
|
|
25
|
+
const CHOICE_TOKENS = ["report_and_continue", "continue_without_reporting", "stop_here"] as const;
|
|
26
|
+
|
|
27
|
+
// rc.8 choice-1 ordering mirrors gentle-ai v2.4.0-rc.8 blocking_prompt_contract_test.go; asserted only where phrases exist.
|
|
28
|
+
function assertChoice1Order(haystack: string, anchors: readonly string[], surface: string): void {
|
|
29
|
+
const positions = anchors.map((p) => haystack.indexOf(p));
|
|
30
|
+
anchors.forEach((p, i) => assert.notEqual(positions[i], -1, `${surface}: missing rc.8 choice-1 anchor: ${JSON.stringify(p)}`));
|
|
31
|
+
for (let i = 1; i < positions.length; i++) {
|
|
32
|
+
assert.ok(positions[i - 1] < positions[i], `${surface}: rc.8 anchor ${i} must precede ${i + 1}; got ${positions}`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const countOccurrences = (haystack: string, needle: string): number => haystack.split(needle).length - 1;
|
|
37
|
+
|
|
38
|
+
const DELEGATION_CHOICE1_ORDER = [
|
|
39
|
+
"complete a definitive lookup across open and closed issues for an equivalent defect",
|
|
40
|
+
"derive its evidence channel only from its build string",
|
|
41
|
+
"If the equivalent has no verifiable relevant published fix, add exactly one occurrence comment",
|
|
42
|
+
"A fix published only to the other evidence channel is not a relevant published fix",
|
|
43
|
+
"If the installed build predates that release, recommend installing the published fix",
|
|
44
|
+
"perform no further GitHub mutation and no blind retry",
|
|
45
|
+
"Confirmed creation requires the GitHub create operation to confirm a newly-created issue identity",
|
|
46
|
+
"execute the shared candidate-scoped continuation below",
|
|
47
|
+
] as const;
|
|
48
|
+
|
|
49
|
+
const SDD_CHOICE1_ORDER = [
|
|
50
|
+
"Complete a definitive lookup across open and closed issues",
|
|
51
|
+
"Derive the evidence channel only from the installed build string",
|
|
52
|
+
"If the installed build predates the relevant published fix",
|
|
53
|
+
"perform no further GitHub mutation and no blind retry",
|
|
54
|
+
] as const;
|
|
55
|
+
|
|
56
|
+
// ---------------------------------------------------------------------------
|
|
57
|
+
// 1 — assets/orchestrator-delegation.md structural presence
|
|
58
|
+
// ---------------------------------------------------------------------------
|
|
59
|
+
|
|
60
|
+
test("orchestrator-delegation.md carries the provider defect handoff section", () => {
|
|
61
|
+
assert.match(DELEGATION, /#### Gentle AI Provider Defect Handoff \(MANDATORY\)/);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
test("orchestrator-delegation.md references the prerelease consent/v3 contract", () => {
|
|
65
|
+
assert.match(DELEGATION, /prerelease/i);
|
|
66
|
+
assert.match(DELEGATION, /gentle-ai\.review-integration\.consent\/v3/);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
test("orchestrator-delegation.md lists all three semantic choice tokens", () => {
|
|
70
|
+
for (const token of CHOICE_TOKENS) {
|
|
71
|
+
assert.ok(
|
|
72
|
+
DELEGATION.includes(`\`${token}\``),
|
|
73
|
+
`orchestrator-delegation.md missing semantic choice token: ${token}`,
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
assert.match(DELEGATION, /\*\*Continue without reporting\*\*: Perform no GitHub search, write, comment, or label, and no report-side privacy scan is required/);
|
|
77
|
+
assert.match(DELEGATION, /\*\*Stop here\*\*: Perform no GitHub operation and no decline invocation; preserve all consumer state and STOP/);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
test("orchestrator-delegation.md orders the three choices: report_and_continue, continue_without_reporting, stop_here", () => {
|
|
81
|
+
const positions = CHOICE_TOKENS.map((token) => DELEGATION.indexOf(`\`${token}\``));
|
|
82
|
+
for (const pos of positions) {
|
|
83
|
+
assert.notEqual(pos, -1, "a choice token is missing; ordering assertion is meaningless");
|
|
84
|
+
}
|
|
85
|
+
assert.ok(
|
|
86
|
+
positions[0] < positions[1],
|
|
87
|
+
`report_and_continue must appear before continue_without_reporting; got positions ${positions}`,
|
|
88
|
+
);
|
|
89
|
+
assert.ok(
|
|
90
|
+
positions[1] < positions[2],
|
|
91
|
+
`continue_without_reporting must appear before stop_here; got positions ${positions}`,
|
|
92
|
+
);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
test("orchestrator-delegation.md preserves the rc.8 choice-1 sub-bullet ordering", () => {
|
|
96
|
+
assertChoice1Order(DELEGATION, DELEGATION_CHOICE1_ORDER, "orchestrator-delegation.md");
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
test("orchestrator-delegation.md states the admissibility-before-relay rule", () => {
|
|
100
|
+
assert.match(DELEGATION, /Before losslessly relaying any blocking choice envelope, classify its semantic admissibility/i);
|
|
101
|
+
assert.match(DELEGATION, /The test is what produced the failure, not what the work was doing when it happened/i);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
test("orchestrator-delegation.md states the never-offer-to-repair rule", () => {
|
|
105
|
+
assert.match(
|
|
106
|
+
DELEGATION,
|
|
107
|
+
/never offer to switch to, inspect, modify, or directly repair the Gentle AI repository/i,
|
|
108
|
+
);
|
|
109
|
+
assert.match(DELEGATION, /reject it as semantically inadmissible and issue this separate orchestrator-owned handoff envelope/i);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
test("orchestrator-delegation.md states the consent requirement", () => {
|
|
113
|
+
assert.match(DELEGATION, /Ask the user first, in the active orchestrator conversation language/i);
|
|
114
|
+
assert.match(DELEGATION, /for explicit consent to report the apparent defect/i);
|
|
115
|
+
assert.match(DELEGATION, /one single-select blocking envelope with exactly three semantic choices in this order/i);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
test("orchestrator-delegation.md states the privacy scrub requirement and ordering", () => {
|
|
119
|
+
assert.match(DELEGATION, /Immediately before the first GitHub operation, perform a final privacy scan/i);
|
|
120
|
+
assert.match(DELEGATION, /This scan precedes the definitive lookup, report creation, and occurrence comment/i);
|
|
121
|
+
assert.match(DELEGATION, /raw argv, absolute paths, private project names, usernames, hostnames, credentials, diffs, source contents, and environment values/i);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
test("orchestrator-delegation.md states the definitive lookup gate", () => {
|
|
125
|
+
assert.match(DELEGATION, /complete a definitive lookup across open and closed issues for an equivalent defect or canonical tracker/i);
|
|
126
|
+
assert.match(DELEGATION, /completed open\+closed lookup with a classifiable result; incomplete, error, or unknown is not definitive/i);
|
|
127
|
+
assert.match(DELEGATION, /Only a definitive lookup may branch to GitHub mutation/i);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
test("orchestrator-delegation.md states evidence-channel routing from installed build string", () => {
|
|
131
|
+
assert.match(DELEGATION, /derive its evidence channel only from its build string/i);
|
|
132
|
+
assert.match(DELEGATION, /recognized prerelease tags are `-rc\.` and `-main\.`; every other build is stable/i);
|
|
133
|
+
assert.match(DELEGATION, /That release is a relevant published fix only when it is in the installed build's evidence channel/i);
|
|
134
|
+
assert.match(DELEGATION, /A main-only commit, local\/source build, unmerged PR, or unsupported assertion is not published-fix evidence/i);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
test("orchestrator-delegation.md states other-channel occurrence routing", () => {
|
|
138
|
+
assert.match(DELEGATION, /A fix published only to the other evidence channel is not a relevant published fix for this occurrence: add exactly one occurrence comment/i);
|
|
139
|
+
assert.match(DELEGATION, /note where the fix is published/i);
|
|
140
|
+
assert.match(DELEGATION, /Do not recommend switching channels; channel choice is the user's/i);
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
test("orchestrator-delegation.md states outdated-build and regression routing", () => {
|
|
144
|
+
assert.match(DELEGATION, /If the installed build predates that release, recommend installing the published fix and reproducing; do not create or comment for that occurrence yet/i);
|
|
145
|
+
assert.match(DELEGATION, /treat it as a possible regression: reproduction on a build proven to contain that fix/i);
|
|
146
|
+
assert.match(DELEGATION, /comment on a suitable canonical tracker, or create a linked regression issue when that tracker is unsuitable/i);
|
|
147
|
+
assert.match(DELEGATION, /Never reopen automatically/i);
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
test("orchestrator-delegation.md states confirmed-creation identity requirement", () => {
|
|
151
|
+
assert.match(DELEGATION, /Confirmed creation requires the GitHub create operation to confirm a newly-created issue identity\/URL/i);
|
|
152
|
+
assert.match(DELEGATION, /Never infer creation from output text alone/i);
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
test("orchestrator-delegation.md states the uncertainty continuation (decline invocation runs, not withheld)", () => {
|
|
156
|
+
assert.match(DELEGATION, /perform no further GitHub mutation and no blind retry/i);
|
|
157
|
+
assert.match(
|
|
158
|
+
DELEGATION,
|
|
159
|
+
/execute the exact captured provider-owned decline invocation exactly once, validate it, re-enter native negotiated STATUS, and resume the already-held consumer continuation/i,
|
|
160
|
+
);
|
|
161
|
+
assert.match(DELEGATION, /do not search, comment, update, or retry creation until the exact created issue identity is resolved, then use the uncertainty continuation below/i);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
test("orchestrator-delegation.md states the exact-captured-decline-invocation rule", () => {
|
|
165
|
+
assert.match(DELEGATION, /Both continue choices execute that exact captured decline invocation exactly once/i);
|
|
166
|
+
assert.match(DELEGATION, /`choices\[answer="declined"\]\.invocation` from the `gentle-ai\.review-integration\.consent\/v3` envelope/i);
|
|
167
|
+
assert.match(
|
|
168
|
+
DELEGATION,
|
|
169
|
+
/Never synthesize the decline command, target, token, or consumer continuation from prose/i,
|
|
170
|
+
);
|
|
171
|
+
assert.match(DELEGATION, /fail closed with all consumer state preserved and do not run a substitute command/i);
|
|
172
|
+
assert.match(DELEGATION, /validate `action: "declined"`, `consent: "declined_this_candidate"`, and the exact target identity match/i);
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
test("orchestrator-delegation.md states handoff scope and mode preservation", () => {
|
|
176
|
+
assert.match(DELEGATION, /Do not invoke `gentle-ai review mode disable` at clone or global scope within this handoff/i);
|
|
177
|
+
assert.match(DELEGATION, /Do not turn RDD off or on within this handoff/i);
|
|
178
|
+
assert.match(DELEGATION, /The result carries no lineage or receipt; ordinary delivery is unmanaged by the candidate choice, and the next candidate asks again/i);
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
test("orchestrator-delegation.md states observed-evidence reporting", () => {
|
|
182
|
+
assert.match(DELEGATION, /Report observed evidence, not an unconfirmed root cause/i);
|
|
183
|
+
assert.match(DELEGATION, /sanitized version\/build, OS\/architecture\/client/i);
|
|
184
|
+
assert.match(DELEGATION, /bounded attempts and outcomes, failure envelopes, mutation outcome/i);
|
|
185
|
+
assert.match(DELEGATION, /expected and actual behavior, a minimal reproduction/i);
|
|
186
|
+
assert.match(DELEGATION, /safe opaque reason\/revision identifiers, and preserved-state evidence/i);
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
test("orchestrator-delegation.md states the resume route (published fix or maintainer-authorized recovery)", () => {
|
|
190
|
+
assert.match(DELEGATION, /Resume after an installed published fix or an explicit maintainer-authorized, documented native recovery or reset/i);
|
|
191
|
+
assert.match(DELEGATION, /A published prerelease or release candidate the user installed satisfies this/i);
|
|
192
|
+
assert.match(DELEGATION, /Never resume against unpublished code: a source checkout, a local build, or an unmerged pull request/i);
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
// ---------------------------------------------------------------------------
|
|
196
|
+
// 2 — Prohibited stale rc.3-era rules (must NOT survive in the handoff)
|
|
197
|
+
// ---------------------------------------------------------------------------
|
|
198
|
+
|
|
199
|
+
test("orchestrator-delegation.md does NOT carry the gentle-report label discipline", () => {
|
|
200
|
+
assert.equal(
|
|
201
|
+
DELEGATION.includes("gentle-report"),
|
|
202
|
+
false,
|
|
203
|
+
"the v2.4.0-rc.8 handoff removed the gentle-report label discipline; the string must not appear",
|
|
204
|
+
);
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
test("orchestrator-delegation.md does NOT make published fixes the sole resumption route", () => {
|
|
208
|
+
assert.equal(
|
|
209
|
+
DELEGATION.includes("Resume only after an installed published fix"),
|
|
210
|
+
false,
|
|
211
|
+
"rc.8 prohibits 'Resume only after an installed published fix' as the sole resumption route",
|
|
212
|
+
);
|
|
213
|
+
assert.equal(
|
|
214
|
+
DELEGATION.includes("latest version"),
|
|
215
|
+
false,
|
|
216
|
+
"rc.8 prohibits 'latest version' wording in the handoff",
|
|
217
|
+
);
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
test("orchestrator-delegation.md does NOT retain the rc.3 hard-stop that withholds the decline invocation", () => {
|
|
221
|
+
assert.equal(
|
|
222
|
+
DELEGATION.includes("Any report ambiguity or failure is a hard stop: preserve all consumer state and do not execute the decline invocation"),
|
|
223
|
+
false,
|
|
224
|
+
"rc.8 replaced the rc.3 hard-stop wedge with the uncertainty continuation that executes the decline invocation",
|
|
225
|
+
);
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
test("orchestrator-delegation.md does NOT reference the rc.3 canon", () => {
|
|
229
|
+
assert.equal(DELEGATION.includes("v2.4.0-rc.3"), false, "stale rc.3 version reference must be removed");
|
|
230
|
+
assert.equal(DELEGATION.includes("gentle-ai#2060"), false, "stale rc.3 issue reference must be removed");
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
// ---------------------------------------------------------------------------
|
|
234
|
+
// 3 — assets/sdd-orchestrator-workflow.md structural presence
|
|
235
|
+
// ---------------------------------------------------------------------------
|
|
236
|
+
|
|
237
|
+
test("sdd-orchestrator-workflow.md carries the provider defect handoff section", () => {
|
|
238
|
+
assert.match(SDD_WORKFLOW, /## Provider Defect Handoff/);
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
test("sdd-orchestrator-workflow.md references v2.4.0-rc.8 and the consent/v3 envelope", () => {
|
|
242
|
+
assert.match(SDD_WORKFLOW, /v2\.4\.0-rc\.8/);
|
|
243
|
+
assert.match(SDD_WORKFLOW, /gentle-ai\.review-integration\.consent\/v3/);
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
test("sdd-orchestrator-workflow.md lists all three semantic choice tokens in order", () => {
|
|
247
|
+
for (const token of CHOICE_TOKENS) {
|
|
248
|
+
assert.ok(
|
|
249
|
+
SDD_WORKFLOW.includes(`\`${token}\``),
|
|
250
|
+
`sdd-orchestrator-workflow.md missing semantic choice token: ${token}`,
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
const positions = CHOICE_TOKENS.map((token) => SDD_WORKFLOW.indexOf(`\`${token}\``));
|
|
255
|
+
for (const pos of positions) {
|
|
256
|
+
assert.notEqual(pos, -1, "a choice token is missing; ordering assertion is meaningless");
|
|
257
|
+
}
|
|
258
|
+
assert.ok(
|
|
259
|
+
positions[0] < positions[1],
|
|
260
|
+
`report_and_continue must appear before continue_without_reporting in sdd-orchestrator-workflow.md; got positions ${positions}`,
|
|
261
|
+
);
|
|
262
|
+
assert.ok(
|
|
263
|
+
positions[1] < positions[2],
|
|
264
|
+
`continue_without_reporting must appear before stop_here in sdd-orchestrator-workflow.md; got positions ${positions}`,
|
|
265
|
+
);
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
test("sdd-orchestrator-workflow.md preserves the rc.8 choice-1 ordering on the concise surface", () => {
|
|
269
|
+
assertChoice1Order(SDD_WORKFLOW, SDD_CHOICE1_ORDER, "sdd-orchestrator-workflow.md");
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
test("sdd-orchestrator-workflow.md references the full contract in orchestrator-delegation.md", () => {
|
|
273
|
+
assert.match(
|
|
274
|
+
SDD_WORKFLOW,
|
|
275
|
+
/The full contract lives in `assets\/orchestrator-delegation\.md` under `#### Gentle AI Provider Defect Handoff \(MANDATORY\)`/i,
|
|
276
|
+
);
|
|
277
|
+
// The pointer must resolve: the named heading has to exist on the delegation surface.
|
|
278
|
+
assert.match(DELEGATION, /^#### Gentle AI Provider Defect Handoff \(MANDATORY\)$/m);
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
test("sdd-orchestrator-workflow.md states the rc.8 concise rules", () => {
|
|
282
|
+
// admissibility
|
|
283
|
+
assert.match(SDD_WORKFLOW, /Classify admissibility before relaying/i);
|
|
284
|
+
// never-repair
|
|
285
|
+
assert.match(
|
|
286
|
+
SDD_WORKFLOW,
|
|
287
|
+
/Never offer to switch to, inspect, modify, or directly repair the Gentle AI repository/i,
|
|
288
|
+
);
|
|
289
|
+
// consent
|
|
290
|
+
assert.match(SDD_WORKFLOW, /Ask the user first, in the active conversation language, for explicit consent to report the apparent defect/i);
|
|
291
|
+
// privacy
|
|
292
|
+
assert.match(SDD_WORKFLOW, /Privacy scrub immediately before the first GitHub operation/i);
|
|
293
|
+
// definitive lookup
|
|
294
|
+
assert.match(SDD_WORKFLOW, /Complete a definitive lookup across open and closed issues in `Gentleman-Programming\/gentle-ai`/i);
|
|
295
|
+
// evidence channel
|
|
296
|
+
assert.match(SDD_WORKFLOW, /recognized prerelease tags are `-rc\.` and `-main\.`; every other build is stable/i);
|
|
297
|
+
assert.match(SDD_WORKFLOW, /never recommend switching channels/i);
|
|
298
|
+
// outdated + regression
|
|
299
|
+
assert.match(SDD_WORKFLOW, /If the installed build predates the relevant published fix, recommend installing it and reproducing/i);
|
|
300
|
+
assert.match(SDD_WORKFLOW, /treat it as a possible regression/i);
|
|
301
|
+
assert.match(SDD_WORKFLOW, /never reopen automatically/i);
|
|
302
|
+
// confirmed creation
|
|
303
|
+
assert.match(SDD_WORKFLOW, /Confirmed creation requires the GitHub create operation to confirm a newly-created issue identity\/URL/i);
|
|
304
|
+
// uncertainty continuation
|
|
305
|
+
assert.match(SDD_WORKFLOW, /perform no further GitHub mutation and no blind retry/i);
|
|
306
|
+
assert.match(SDD_WORKFLOW, /execute the exact captured provider-owned decline invocation exactly once, validate it, re-enter native negotiated STATUS, and resume the already-held consumer continuation/i);
|
|
307
|
+
// exact decline
|
|
308
|
+
assert.match(SDD_WORKFLOW, /Both continue choices execute that exact captured decline invocation exactly once/i);
|
|
309
|
+
assert.match(SDD_WORKFLOW, /never synthesize the decline command, target, token, or consumer continuation from prose/i);
|
|
310
|
+
// scope/mode
|
|
311
|
+
assert.match(SDD_WORKFLOW, /Do not invoke `gentle-ai review mode disable` at clone or global scope within this handoff/i);
|
|
312
|
+
assert.match(SDD_WORKFLOW, /Do not turn RDD off or on within this handoff/i);
|
|
313
|
+
// resume
|
|
314
|
+
assert.match(SDD_WORKFLOW, /Resume after an installed published fix or an explicit maintainer-authorized, documented native recovery or reset/i);
|
|
315
|
+
assert.match(SDD_WORKFLOW, /Never resume against unpublished code/i);
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
test("sdd-orchestrator-workflow.md does NOT carry the gentle-report label discipline", () => {
|
|
319
|
+
assert.equal(
|
|
320
|
+
SDD_WORKFLOW.includes("gentle-report"),
|
|
321
|
+
false,
|
|
322
|
+
"sdd-orchestrator-workflow.md must not reference the removed gentle-report label",
|
|
323
|
+
);
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
test("sdd-orchestrator-workflow.md does NOT make published fixes the sole resumption route", () => {
|
|
327
|
+
assert.equal(
|
|
328
|
+
SDD_WORKFLOW.includes("Resume only after an installed published fix"),
|
|
329
|
+
false,
|
|
330
|
+
"sdd-orchestrator-workflow.md must not state the prohibited sole-resumption route",
|
|
331
|
+
);
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
test("sdd-orchestrator-workflow.md does NOT retain the rc.3 hard-stop that withholds the decline invocation", () => {
|
|
335
|
+
assert.equal(
|
|
336
|
+
SDD_WORKFLOW.includes("Any report ambiguity or failure is a hard stop: preserve all consumer state and do not execute the decline invocation"),
|
|
337
|
+
false,
|
|
338
|
+
"sdd-orchestrator-workflow.md must not retain the rc.3 hard-stop wedge",
|
|
339
|
+
);
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
test("both handoff surfaces invoke `gentle-ai review mode disable` exactly once", () => {
|
|
343
|
+
// The delegation surface carries the contract inside the canon block, so its
|
|
344
|
+
// section is bounded by the following `####` canon heading, not by `## `.
|
|
345
|
+
const surfaces = [
|
|
346
|
+
["orchestrator-delegation.md", DELEGATION, /#### Gentle AI Provider Defect Handoff[\s\S]*?(?=\n#### SDD Edit-Authority|$)/],
|
|
347
|
+
["sdd-orchestrator-workflow.md", SDD_WORKFLOW, /## Provider Defect Handoff[\s\S]*?(?=\n## |$)/],
|
|
348
|
+
] as const;
|
|
349
|
+
for (const [name, asset, sectionPattern] of surfaces) {
|
|
350
|
+
const section = asset.match(sectionPattern)?.[0] ?? "";
|
|
351
|
+
assert.ok(section.length > 0, `${name}: provider defect handoff section not found`);
|
|
352
|
+
const n = countOccurrences(section, "gentle-ai review mode disable");
|
|
353
|
+
assert.equal(n, 1, `${name} must invoke "gentle-ai review mode disable" exactly once; got ${n}`);
|
|
354
|
+
}
|
|
355
|
+
});
|
|
@@ -12,13 +12,15 @@ const ROOT = join(import.meta.dirname, "..");
|
|
|
12
12
|
const ASSETS_AGENTS_DIR = join(ROOT, "assets", "agents");
|
|
13
13
|
const DENY_ALL_RULE = '"*": false';
|
|
14
14
|
|
|
15
|
+
// gentle-pi#311 P5: review-refuter.md and review-validator.md are retired —
|
|
16
|
+
// the adversarial roles execute through Go-owned pi processes via
|
|
17
|
+
// provider-rendered self-contained vectors, so no Pi agent definition exists
|
|
18
|
+
// for them to deny tools on.
|
|
15
19
|
const READ_ONLY_REVIEW_ACTORS = [
|
|
16
20
|
"review-risk.md",
|
|
17
21
|
"review-reliability.md",
|
|
18
22
|
"review-resilience.md",
|
|
19
23
|
"review-readability.md",
|
|
20
|
-
"review-refuter.md",
|
|
21
|
-
"review-validator.md",
|
|
22
24
|
"jd-judge-a.md",
|
|
23
25
|
"jd-judge-b.md",
|
|
24
26
|
] as const;
|
|
@@ -88,11 +90,15 @@ test("every read-only review actor leads its tool map with the deny-all rule", (
|
|
|
88
90
|
});
|
|
89
91
|
|
|
90
92
|
test("a tool absent from the allowlist resolves to denied under the deny-all rule", () => {
|
|
93
|
+
// Mirrors the tool names a real Pi child session can resolve. `glob` is
|
|
94
|
+
// deliberately absent: it is not a Pi builtin, so a lens that declares it
|
|
95
|
+
// silently loses filesystem discovery instead of failing loudly. Keeping
|
|
96
|
+
// the fiction here is what let that ship green.
|
|
91
97
|
const registry = [
|
|
92
98
|
"read",
|
|
93
99
|
"grep",
|
|
94
|
-
"glob",
|
|
95
100
|
"find",
|
|
101
|
+
"gentle_review_scope",
|
|
96
102
|
"edit",
|
|
97
103
|
"write",
|
|
98
104
|
"bash",
|
|
@@ -102,15 +108,8 @@ test("a tool absent from the allowlist resolves to denied under the deny-all rul
|
|
|
102
108
|
"subagent_run",
|
|
103
109
|
] as const;
|
|
104
110
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
assert.deepEqual(refuterActive, ["read", "grep", "find"]);
|
|
108
|
-
for (const omitted of ["edit", "write", "bash", "mem_save", "codegraph_explore", "mcp__slack__slack_send_message", "subagent_run"]) {
|
|
109
|
-
assert.ok(!refuterActive.includes(omitted), `review-refuter must deny omitted tool ${omitted}`);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
// The four lenses deny bash, matching gentle-ai's own Claude-runtime lens
|
|
113
|
-
// agents (`tools: Read, Grep, Glob`) exactly. Contract v2 is explicit: a
|
|
111
|
+
// The four lenses deny bash and add only the bounded scope reader required
|
|
112
|
+
// to consume controller-owned compact manifests. Contract v2 is explicit: a
|
|
114
113
|
// runtime that cannot enforce a per-command Git shell boundary exposes no
|
|
115
114
|
// shell and reports incomplete inspection rather than claiming backend
|
|
116
115
|
// enforcement. Pi has no per-command scoping layer, so unrestricted bash
|
|
@@ -124,7 +123,7 @@ test("a tool absent from the allowlist resolves to denied under the deny-all rul
|
|
|
124
123
|
// the other half of the same rule, not an exception to it.
|
|
125
124
|
for (const lens of ["review-risk", "review-resilience", "review-readability", "review-reliability"]) {
|
|
126
125
|
const lensActive = resolveActiveTools(readToolEntries(join(ASSETS_AGENTS_DIR, `${lens}.md`)), registry);
|
|
127
|
-
assert.deepEqual(lensActive, ["read", "grep", "
|
|
126
|
+
assert.deepEqual(lensActive, ["read", "grep", "find", "gentle_review_scope"], `${lens} must expose only candidate readers and the bounded scope reader`);
|
|
128
127
|
for (const omitted of ["bash", "edit", "write", "mem_save", "codegraph_explore", "mcp__slack__slack_send_message", "subagent_run"]) {
|
|
129
128
|
assert.ok(!lensActive.includes(omitted), `${lens} must deny ${omitted}`);
|
|
130
129
|
}
|