gentle-pi 2.2.0 → 2.4.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 +76 -79
- package/assets/agents/review-readability.md +0 -2
- package/assets/agents/review-reliability.md +0 -2
- package/assets/agents/review-resilience.md +0 -2
- package/assets/agents/review-risk.md +0 -2
- package/assets/agents/sdd-apply.md +5 -3
- package/assets/agents/sdd-explore.md +1 -0
- package/assets/agents/sdd-proposal.md +2 -0
- package/assets/agents/sdd-research.md +54 -0
- package/assets/agents/sdd-status.md +4 -4
- package/assets/agents/sdd-tasks.md +2 -3
- package/assets/agents/sdd-verify.md +21 -1
- package/assets/chains/sdd-full.chain.md +1 -1
- package/assets/chains/sdd-verify.chain.md +1 -1
- package/assets/orchestrator-delegation.md +56 -249
- package/assets/orchestrator-memory.md +2 -0
- package/assets/orchestrator.md +20 -40
- package/assets/sdd-orchestrator-workflow.md +30 -37
- package/assets/support/sdd-status-contract.md +7 -7
- package/contracts/review-integration/v1/schemas/transition-execution.schema.json +42 -0
- 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-provider-contract-mirror/provider-contract.lock.json +8 -7
- package/contracts/review-provider-contract-mirror/{v1.1.0 → v1.2.0}/bundle/README.md +10 -0
- package/contracts/review-provider-contract-mirror/v1.2.0/bundle/manifest.json +74 -0
- package/contracts/review-provider-contract-mirror/v1.2.0/bundle/orchestration/pi.md +53 -0
- package/contracts/review-provider-contract-mirror/v1.2.0/bundle/schemas/targeted-validator.schema.json +1 -0
- package/contracts/review-provider-contract-mirror/{v1.1.0 → v1.2.0}/generated/provider-capabilities.baseline.json +9 -2
- package/contracts/review-provider-contract-mirror/{v1.1.0 → v1.2.0}/generated/provider-roles.baseline.json +2 -2
- package/docs/native-authority-architecture.md +9 -11
- package/docs/review-integration.md +27 -373
- package/extensions/ask-user-choice.ts +151 -0
- package/extensions/gentle-ai.ts +2349 -3785
- package/extensions/quiet-tools.ts +515 -32
- package/extensions/sdd-init.ts +4 -8
- package/lib/agent-home.ts +8 -0
- package/lib/gentle-ai-renderer.ts +70 -0
- package/lib/model-routing-authority.ts +133 -0
- package/lib/native-review-cli.ts +387 -940
- package/lib/opaque-pi-reviewer-adapter.ts +284 -0
- package/lib/provider-contract-bundle.ts +88 -6
- package/lib/review-candidate-view.ts +341 -132
- package/lib/review-host-relay.ts +324 -96
- package/lib/review-integration-v2.ts +868 -307
- package/lib/review-last-event-controller.ts +35 -0
- package/lib/sdd-preflight.ts +179 -68
- package/lib/sdd-status.ts +66 -111
- package/lib/terminal-theme.ts +1 -1
- package/package.json +83 -82
- package/runtime/gentle-ai-binary.mjs +1 -1
- package/runtime/native-review-cli.mjs +337 -890
- package/runtime/review-integration-v2.mjs +816 -255
- package/runtime/review-relay-contract.mjs +1 -1
- package/scripts/{build-git-commit-transaction-runner.mjs → build-runtime-modules.mjs} +4 -5
- package/scripts/gentle-ai-installer.mjs +75 -22
- package/scripts/maintainer/provider-relay-matrix.mjs +195 -11
- package/scripts/test-packed-runner.mjs +4 -7
- package/scripts/verify-package-files.mjs +23 -23
- package/skills/_shared/review-ledger-contract.md +14 -14
- 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 +53 -93
- package/skills/judgment-day/SKILL.md +5 -7
- package/skills/rdd-defect-workflow/SKILL.md +3 -3
- 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/codegraph-tools.test.ts +3 -3
- package/tests/crosslane/cross-lane.mjs +15 -1168
- package/tests/delegated-key-learnings-contract.test.ts +8 -6
- package/tests/devbinary/native-review-parity.devtest.ts +167 -250
- package/tests/devbinary/pi-host-relay.devtest.ts +867 -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/review-acknowledged-v1.captured.json +9 -0
- package/tests/fixtures/devbinary/review-acknowledged.provenance.md +31 -0
- package/tests/fixtures/devbinary/start-v3-zero-lens-closed.captured.json +21 -0
- package/tests/fixtures/native-review-cli/v2.5.0-rc.1/PROVENANCE.txt +15 -0
- package/tests/fixtures/provider-contract-bundle/v1.2.0/README.md +22 -0
- package/{contracts/review-provider-contract-mirror/v1.1.0/bundle → tests/fixtures/provider-contract-bundle/v1.2.0}/manifest.json +11 -2
- package/tests/fixtures/provider-contract-bundle/v1.2.0/orchestration/pi.md +97 -0
- package/tests/fixtures/provider-contract-bundle/v1.2.0/schemas/lens.schema.json +16 -0
- package/tests/fixtures/provider-contract-bundle/v1.2.0/schemas/refuter.schema.json +1 -0
- package/tests/fixtures/provider-contract-bundle/v1.2.0/vectors/lens.json +1 -0
- package/tests/fixtures/provider-contract-bundle/v1.2.0/vectors/refuter.json +1 -0
- package/tests/fixtures/provider-contract-bundle/v1.2.0/vectors/targeted-validator.json +1 -0
- package/tests/gentle-ai-binary.test.ts +83 -13
- package/tests/gentle-ai-dev-binary.test.ts +51 -228
- package/tests/gentle-ai-installer.test.ts +137 -47
- package/tests/gentle-ai.test.ts +821 -131
- package/tests/gentle-theme.test.ts +133 -0
- package/tests/issue-creation-skill.test.ts +103 -0
- package/tests/maintainer/provider-relay.maintest.ts +340 -4
- package/tests/model-routing-authority.test.ts +257 -0
- package/tests/native-review-capability-contract.test.ts +45 -1
- package/tests/native-review-cli.test.ts +586 -962
- package/tests/native-review-consent.test.ts +150 -66
- package/tests/native-review-parity-runtime.test.ts +80 -359
- package/tests/native-review-parity.test.ts +674 -925
- package/tests/opaque-pi-reviewer-adapter.test.ts +266 -0
- package/tests/orchestrator-budget.test.ts +132 -88
- package/tests/orchestrator-rdd-ownership.test.ts +103 -0
- package/tests/package-manifest.test.ts +152 -36
- package/tests/provider-contract-bundle.test.ts +76 -0
- package/tests/provider-contract-mirror.test.ts +19 -0
- package/tests/provider-defect-handoff.test.ts +15 -118
- package/tests/quiet-tool-rendering.test.ts +1055 -28
- package/tests/review-agent-end-preflight.test.ts +408 -0
- package/tests/review-authority-recovery-docs.test.ts +1 -2
- package/tests/review-candidate-view.test.ts +409 -3
- package/tests/review-compact-contract.test.ts +4 -30
- package/tests/review-contract-prompt.test.ts +139 -0
- package/tests/review-controller-lock-status.test.ts +2 -2
- package/tests/review-controller-native-recovery.test.ts +363 -1450
- package/tests/review-controller-native-routing.test.ts +1251 -5642
- package/tests/review-controller-retired-ops.test.ts +1 -1
- package/tests/review-controller-workspace-root.test.ts +222 -71
- package/tests/review-controller.test.ts +26 -816
- package/tests/review-corrected-finalize-binding.test.ts +112 -153
- package/tests/review-dispatch-hydration-gap.test.ts +1 -53
- 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 +328 -91
- package/tests/review-host-relay.test.ts +436 -14
- package/tests/review-integration-v2-forward.test.ts +623 -553
- package/tests/review-integration-v2.test.ts +239 -165
- package/tests/review-last-event-closure.test.ts +408 -0
- package/tests/review-ledger-contract.test.ts +97 -35
- package/tests/review-recovered-lineage-routing.test.ts +0 -47
- package/tests/review-relay-transport-agent.test.ts +119 -46
- package/tests/review-snapshot.test.ts +3 -2
- package/tests/runtime-harness.mjs +362 -196
- package/tests/sdd-agent-tools.test.ts +36 -0
- package/tests/sdd-preflight.test.ts +81 -15
- package/tests/sdd-status.test.ts +109 -110
- package/tests/skill-collision-prefixes.test.ts +5 -8
- package/tests/writer-edit-surface-scope.test.ts +366 -0
- package/themes/Gentleman-Cute.json +94 -0
- package/themes/Gentleman-Sexy.json +92 -0
- package/lib/git-commit-transaction.ts +0 -861
- package/runtime/git-commit-transaction.mjs +0 -862
- package/scripts/run-git-commit-transaction.mjs +0 -35
- 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 -530
- /package/contracts/review-provider-contract-mirror/{v1.1.0 → v1.2.0}/bundle/schemas/lens.schema.json +0 -0
- /package/contracts/review-provider-contract-mirror/{v1.1.0 → v1.2.0}/bundle/schemas/refuter.schema.json +0 -0
- /package/contracts/review-provider-contract-mirror/{v1.1.0 → v1.2.0}/bundle/vectors/lens.json +0 -0
- /package/contracts/review-provider-contract-mirror/{v1.1.0 → v1.2.0}/bundle/vectors/refuter.json +0 -0
- /package/contracts/review-provider-contract-mirror/{v1.1.0 → v1.2.0}/bundle/vectors/targeted-validator.json +0 -0
- /package/{contracts/review-provider-contract-mirror/v1.1.0/bundle → tests/fixtures/provider-contract-bundle/v1.2.0}/schemas/targeted-validator.schema.json +0 -0
package/lib/sdd-status.ts
CHANGED
|
@@ -6,7 +6,10 @@ import {
|
|
|
6
6
|
type DomainCollision,
|
|
7
7
|
} from "./openspec-guardrails.ts";
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
// Canonical names match gentle-ai, which owns this contract. The dual-store
|
|
10
|
+
// mode was called "both" here; "hybrid" is the provider's name for the same
|
|
11
|
+
// thing, and normalizeSddArtifactStore keeps already-persisted "both" loading.
|
|
12
|
+
export type SddArtifactStore = "openspec" | "engram" | "hybrid" | "none";
|
|
10
13
|
export type ArtifactState = "missing" | "done" | "partial";
|
|
11
14
|
export type DependencyState = "blocked" | "ready" | "all_done" | "not_applicable";
|
|
12
15
|
export type ApplyState = "blocked" | "ready" | "all_done" | "not_applicable";
|
|
@@ -98,6 +101,12 @@ export interface SddStatus {
|
|
|
98
101
|
relationships: SddRelationships;
|
|
99
102
|
collisions: SddDomainCollisionReport[];
|
|
100
103
|
legacyFlatSpec?: { path: string; hasDomainSpecs: boolean };
|
|
104
|
+
/**
|
|
105
|
+
* Positive terminal projection: the change was archived. `path` is the
|
|
106
|
+
* repo-relative archive folder (openspec/changes/archive/YYYY-MM-DD-<change>).
|
|
107
|
+
* When set, `nextRecommended` is "archived" and no further phase is recommended.
|
|
108
|
+
*/
|
|
109
|
+
archived?: { path: string };
|
|
101
110
|
nextRecommended: string;
|
|
102
111
|
instructions?: SddPhaseInstructions;
|
|
103
112
|
blockedReasons: string[];
|
|
@@ -111,36 +120,12 @@ export interface SddStatus {
|
|
|
111
120
|
isNonAuthoritative: boolean;
|
|
112
121
|
}
|
|
113
122
|
|
|
114
|
-
export interface ValidatedReviewAuthorityResolution {
|
|
115
|
-
activeAuthorityId: string;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* Optional controller-owned recovery overlay. Status never infers authority from
|
|
120
|
-
* OpenSpec artifacts: callers opt in only when a repository review binding exists.
|
|
121
|
-
*/
|
|
122
|
-
export interface SddReviewAuthorityOverlay {
|
|
123
|
-
expected: boolean;
|
|
124
|
-
resolve: () => ValidatedReviewAuthorityResolution | undefined;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
/** Read-only native bound-change evidence supplied by the controller. */
|
|
128
|
-
export interface NativeReviewReadinessOverlay {
|
|
129
|
-
expected: boolean;
|
|
130
|
-
ready: boolean;
|
|
131
|
-
lineageId?: string;
|
|
132
|
-
bindingRevision?: string;
|
|
133
|
-
reason?: string;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
123
|
export interface ResolveSddStatusOptions {
|
|
137
124
|
cwd: string;
|
|
138
125
|
changeName?: string;
|
|
139
126
|
includeInstructions?: boolean;
|
|
140
127
|
workspaceRoot?: string;
|
|
141
128
|
artifactStore?: SddArtifactStore;
|
|
142
|
-
reviewAuthority?: SddReviewAuthorityOverlay;
|
|
143
|
-
nativeReviewReadiness?: NativeReviewReadinessOverlay;
|
|
144
129
|
}
|
|
145
130
|
|
|
146
131
|
const EMPTY_PATHS: SddArtifactPaths = {
|
|
@@ -273,43 +258,7 @@ function reportIsClearlyPassing(path: string | undefined): boolean {
|
|
|
273
258
|
return hasPassSignal && !hasBlocker;
|
|
274
259
|
}
|
|
275
260
|
|
|
276
|
-
function
|
|
277
|
-
if (nativeReviewReadiness?.expected && !nativeReviewReadiness.ready) {
|
|
278
|
-
const reason = `resolve-review: ${nativeReviewReadiness.reason ?? "native bound review readiness is unavailable."}`;
|
|
279
|
-
return {
|
|
280
|
-
...status,
|
|
281
|
-
applyState: "blocked",
|
|
282
|
-
dependencies: { apply: "blocked", verify: "blocked", sync: "blocked", archive: "blocked" },
|
|
283
|
-
nextRecommended: "resolve-review",
|
|
284
|
-
blockedReasons: status.blockedReasons.includes(reason) ? status.blockedReasons : [...status.blockedReasons, reason],
|
|
285
|
-
};
|
|
286
|
-
}
|
|
287
|
-
if (!reviewAuthority?.expected) return status;
|
|
288
|
-
try {
|
|
289
|
-
const resolved = reviewAuthority.resolve();
|
|
290
|
-
if (resolved?.activeAuthorityId) return status;
|
|
291
|
-
} catch (error) {
|
|
292
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
293
|
-
const reason = `resolve-review: ${message}`;
|
|
294
|
-
return {
|
|
295
|
-
...status,
|
|
296
|
-
applyState: "blocked",
|
|
297
|
-
dependencies: { apply: "blocked", verify: "blocked", sync: "blocked", archive: "blocked" },
|
|
298
|
-
nextRecommended: "resolve-review",
|
|
299
|
-
blockedReasons: status.blockedReasons.includes(reason) ? status.blockedReasons : [...status.blockedReasons, reason],
|
|
300
|
-
};
|
|
301
|
-
}
|
|
302
|
-
const reason = "resolve-review: validated active review authority is missing.";
|
|
303
|
-
return {
|
|
304
|
-
...status,
|
|
305
|
-
applyState: "blocked",
|
|
306
|
-
dependencies: { apply: "blocked", verify: "blocked", sync: "blocked", archive: "blocked" },
|
|
307
|
-
nextRecommended: "resolve-review",
|
|
308
|
-
blockedReasons: status.blockedReasons.includes(reason) ? status.blockedReasons : [...status.blockedReasons, reason],
|
|
309
|
-
};
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
function emptyStatus(cwd: string, changeName: string | null, blockedReasons: string[], artifactStore: SddArtifactStore = "openspec", isNonAuthoritative = false, reviewAuthority?: SddReviewAuthorityOverlay): SddStatus {
|
|
261
|
+
function emptyStatus(cwd: string, changeName: string | null, blockedReasons: string[], artifactStore: SddArtifactStore = "openspec", isNonAuthoritative = false): SddStatus {
|
|
313
262
|
const root = resolve(cwd);
|
|
314
263
|
const changesDir = join(root, "openspec", "changes");
|
|
315
264
|
const actionContext: SddActionContext = {
|
|
@@ -318,7 +267,7 @@ function emptyStatus(cwd: string, changeName: string | null, blockedReasons: str
|
|
|
318
267
|
allowedEditRoots: [root],
|
|
319
268
|
warnings: [],
|
|
320
269
|
};
|
|
321
|
-
return
|
|
270
|
+
return {
|
|
322
271
|
schemaName: "gentle-pi.sdd-status",
|
|
323
272
|
schemaVersion: 1,
|
|
324
273
|
changeName,
|
|
@@ -353,7 +302,32 @@ function emptyStatus(cwd: string, changeName: string | null, blockedReasons: str
|
|
|
353
302
|
nextRecommended: blockedReasons[0] ?? "Start an SDD change.",
|
|
354
303
|
blockedReasons,
|
|
355
304
|
isNonAuthoritative,
|
|
356
|
-
}
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Find the newest archive entry for a change. Archive folders are named
|
|
310
|
+
* `YYYY-MM-DD-<change>`; only an exact `-<change>` suffix after a full date
|
|
311
|
+
* prefix matches (change "foo-bar" never matches "2026-01-01-foo-bar-baz").
|
|
312
|
+
* safeDirectories sorts lexicographically, so the last match is the newest date.
|
|
313
|
+
*/
|
|
314
|
+
function findArchivedChangeEntry(root: string, changeName: string): string | undefined {
|
|
315
|
+
return safeDirectories(join(root, "openspec", "changes", "archive"))
|
|
316
|
+
.filter(
|
|
317
|
+
(entry) =>
|
|
318
|
+
/^\d{4}-\d{2}-\d{2}-$/.test(entry.slice(0, 11)) && entry.slice(11) === changeName,
|
|
319
|
+
)
|
|
320
|
+
.at(-1);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/** Positive terminal projection for a change whose folder moved to the archive. */
|
|
324
|
+
function archivedStatus(cwd: string, changeName: string, archiveEntry: string, artifactStore: SddArtifactStore): SddStatus {
|
|
325
|
+
const status = emptyStatus(cwd, changeName, [], artifactStore);
|
|
326
|
+
status.applyState = "all_done";
|
|
327
|
+
status.dependencies = { apply: "all_done", verify: "all_done", sync: "all_done", archive: "all_done" };
|
|
328
|
+
status.archived = { path: join("openspec", "changes", "archive", archiveEntry) };
|
|
329
|
+
status.nextRecommended = "archived";
|
|
330
|
+
return status;
|
|
357
331
|
}
|
|
358
332
|
|
|
359
333
|
export function listActiveOpenSpecChanges(cwd: string): string[] {
|
|
@@ -482,7 +456,7 @@ export function resolveSddStatus(options: ResolveSddStatusOptions): SddStatus {
|
|
|
482
456
|
// - store engram or none: always non-authoritative (no disk backing)
|
|
483
457
|
// - store both, no openspec/ dir: non-authoritative (no disk to scan)
|
|
484
458
|
// The both-with-openspec cases are handled below after listing active changes.
|
|
485
|
-
if (store === "engram" || store === "none" || (store === "
|
|
459
|
+
if (store === "engram" || store === "none" || (store === "hybrid" && !hasOpenSpecDir)) {
|
|
486
460
|
const changeName = options.changeName?.trim() || null;
|
|
487
461
|
return nonAuthoritativeStatus(options.cwd, changeName, store, options.includeInstructions);
|
|
488
462
|
}
|
|
@@ -500,16 +474,16 @@ export function resolveSddStatus(options: ResolveSddStatusOptions): SddStatus {
|
|
|
500
474
|
// store both + openspec/ present + zero active changes + no changeName:
|
|
501
475
|
// The change may live only in Engram — non-authoritative, not a false block.
|
|
502
476
|
// Pure openspec with zero changes is a real block (run sdd-new).
|
|
503
|
-
if (store === "
|
|
477
|
+
if (store === "hybrid") {
|
|
504
478
|
return nonAuthoritativeStatus(options.cwd, null, store, options.includeInstructions);
|
|
505
479
|
}
|
|
506
|
-
return emptyStatus(root, null, ["No active SDD changes found."], store
|
|
480
|
+
return emptyStatus(root, null, ["No active SDD changes found."], store);
|
|
507
481
|
} else {
|
|
508
482
|
// Multiple active changes and no changeName: legit selection prompt (changes DO exist
|
|
509
483
|
// on disk). Keep the existing authoritative ambiguous-selection behavior for both stores.
|
|
510
484
|
return emptyStatus(root, null, [
|
|
511
485
|
`Change selection is ambiguous: ${activeChanges.join(", ")}.`,
|
|
512
|
-
], store
|
|
486
|
+
], store);
|
|
513
487
|
}
|
|
514
488
|
}
|
|
515
489
|
|
|
@@ -517,10 +491,16 @@ export function resolveSddStatus(options: ResolveSddStatusOptions): SddStatus {
|
|
|
517
491
|
// store both + openspec/ present + named change NOT found on disk:
|
|
518
492
|
// The change may live only in Engram — non-authoritative.
|
|
519
493
|
// Pure openspec still blocks (legit "run sdd-new").
|
|
520
|
-
if (store === "
|
|
494
|
+
if (store === "hybrid") {
|
|
521
495
|
return nonAuthoritativeStatus(options.cwd, changeName, store, options.includeInstructions);
|
|
522
496
|
}
|
|
523
|
-
|
|
497
|
+
// Issue #535: an absent active folder may mean the change was archived.
|
|
498
|
+
// Project explicit completion instead of a false "run sdd-new" block.
|
|
499
|
+
const archiveEntry = findArchivedChangeEntry(root, changeName);
|
|
500
|
+
if (archiveEntry) {
|
|
501
|
+
return archivedStatus(root, changeName, archiveEntry, store);
|
|
502
|
+
}
|
|
503
|
+
return emptyStatus(root, changeName, [`Active change not found: ${changeName}.`], store);
|
|
524
504
|
}
|
|
525
505
|
|
|
526
506
|
const changeRoot = join(changesDir, changeName);
|
|
@@ -587,33 +567,13 @@ export function resolveSddStatus(options: ResolveSddStatusOptions): SddStatus {
|
|
|
587
567
|
blockedReasons.push(`Legacy flat spec is present without domain specs: ${legacyFlatSpec.path}.`);
|
|
588
568
|
}
|
|
589
569
|
|
|
590
|
-
// Planning-only status remains filesystem-read-only: do not invoke a resolver
|
|
591
|
-
// unless the controller has established that review authority is expected.
|
|
592
|
-
if (options.reviewAuthority?.expected) {
|
|
593
|
-
try {
|
|
594
|
-
const resolved = options.reviewAuthority.resolve();
|
|
595
|
-
if (!resolved || typeof resolved.activeAuthorityId !== "string" || resolved.activeAuthorityId.length === 0) {
|
|
596
|
-
blockedReasons.push("resolve-review: validated active review authority is missing.");
|
|
597
|
-
}
|
|
598
|
-
} catch (error) {
|
|
599
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
600
|
-
blockedReasons.push(`resolve-review: ${message}`);
|
|
601
|
-
}
|
|
602
|
-
}
|
|
603
|
-
if (options.nativeReviewReadiness?.expected && !options.nativeReviewReadiness.ready) {
|
|
604
|
-
blockedReasons.push(`resolve-review: ${options.nativeReviewReadiness.reason ?? "native bound review readiness is unavailable."}`);
|
|
605
|
-
}
|
|
606
|
-
|
|
607
570
|
const coreArtifactsReady = artifacts.proposal === "done" && artifacts.specs === "done" && artifacts.design === "done" && artifacts.tasks === "done" && taskProgress.total > 0 && !flatOnly;
|
|
608
|
-
const reviewBlocked = blockedReasons.some((reason) => reason.startsWith("resolve-review:"));
|
|
609
571
|
const taskArtifactBlocked = taskAccounting.errors.length > 0;
|
|
610
|
-
const
|
|
611
|
-
const applyState: ApplyState = !coreArtifactsReady || reviewBlocked || taskArtifactBlocked
|
|
572
|
+
const applyState: ApplyState = !coreArtifactsReady || taskArtifactBlocked
|
|
612
573
|
? "blocked"
|
|
613
574
|
: taskProgress.remaining === 0
|
|
614
575
|
? "all_done"
|
|
615
576
|
: "ready";
|
|
616
|
-
const parentLifecycleRequired = applyState === "all_done" && !reviewApproved;
|
|
617
577
|
const verifyClean = reportIsClearlyPassing(artifactPaths.verifyReport[0]);
|
|
618
578
|
const syncClean = reportIsClearlyPassing(artifactPaths.syncReport[0]);
|
|
619
579
|
const syncPrerequisitesReady = coreArtifactsReady && verifyClean && collisions.length === 0 && !flatOnly;
|
|
@@ -624,31 +584,27 @@ export function resolveSddStatus(options: ResolveSddStatusOptions): SddStatus {
|
|
|
624
584
|
: "blocked";
|
|
625
585
|
const verifyState: DependencyState = verifyClean
|
|
626
586
|
? "all_done"
|
|
627
|
-
:
|
|
587
|
+
: artifacts.tasks === "done" && taskProgress.total > 0 && (artifacts.applyProgress === "done" || applyState === "all_done")
|
|
628
588
|
? "ready"
|
|
629
589
|
: "blocked";
|
|
630
590
|
const dependencies: SddStatus["dependencies"] = {
|
|
631
591
|
apply: applyState === "blocked" ? "blocked" : applyState,
|
|
632
592
|
verify: verifyState,
|
|
633
593
|
sync: syncState,
|
|
634
|
-
archive: coreArtifactsReady &&
|
|
594
|
+
archive: coreArtifactsReady && verifyClean && syncClean && taskProgress.remaining === 0 && !taskArtifactBlocked ? "ready" : "blocked",
|
|
635
595
|
};
|
|
636
596
|
const archiveReady = dependencies.archive === "ready";
|
|
637
|
-
const nextRecommended =
|
|
638
|
-
? "
|
|
639
|
-
:
|
|
640
|
-
? "
|
|
641
|
-
:
|
|
642
|
-
? "
|
|
643
|
-
: dependencies.
|
|
644
|
-
? "sdd-
|
|
645
|
-
:
|
|
646
|
-
? "sdd-
|
|
647
|
-
:
|
|
648
|
-
? "sdd-sync"
|
|
649
|
-
: archiveReady
|
|
650
|
-
? "sdd-archive"
|
|
651
|
-
: blockedReasons[0] ?? "Resolve blockers.";
|
|
597
|
+
const nextRecommended = taskArtifactBlocked
|
|
598
|
+
? "fix-task-ownership-marker"
|
|
599
|
+
: dependencies.apply === "ready"
|
|
600
|
+
? "sdd-apply"
|
|
601
|
+
: dependencies.verify === "ready"
|
|
602
|
+
? "sdd-verify"
|
|
603
|
+
: dependencies.sync === "ready"
|
|
604
|
+
? "sdd-sync"
|
|
605
|
+
: archiveReady
|
|
606
|
+
? "sdd-archive"
|
|
607
|
+
: blockedReasons[0] ?? "Resolve blockers.";
|
|
652
608
|
|
|
653
609
|
const status: SddStatus = {
|
|
654
610
|
schemaName: "gentle-pi.sdd-status",
|
|
@@ -681,9 +637,8 @@ export function resolveSddStatus(options: ResolveSddStatusOptions): SddStatus {
|
|
|
681
637
|
blockedReasons,
|
|
682
638
|
isNonAuthoritative: false,
|
|
683
639
|
};
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
return resolvedStatus;
|
|
640
|
+
if (options.includeInstructions) status.instructions = renderPhaseInstructions(status);
|
|
641
|
+
return status;
|
|
687
642
|
}
|
|
688
643
|
|
|
689
644
|
export function isNonAuthoritativeStatus(status: SddStatus): boolean {
|
package/lib/terminal-theme.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const NON_OSC_ANSI_ESCAPE_PATTERN =
|
|
2
2
|
/\x1B\[[0-?]*[ -/]*[@-~]|\x1B[@-Z\\-_]|\x9B[0-?]*[ -/]*[@-~]/g;
|
|
3
|
-
const CONTROL_CHAR_PATTERN = /[\u0000-\u0008\u000b\
|
|
3
|
+
const CONTROL_CHAR_PATTERN = /[\u0000-\u0008\u000b-\u000d\u000e-\u001f\u007f-\u009f]/g;
|
|
4
4
|
const OSC_ESCAPE_PATTERN = /(?:\x1B\]|\x9D)[\s\S]*?(?:\x07|\x1B\\|\x9C|$)/g;
|
|
5
5
|
|
|
6
6
|
export function stripAnsi(value: string): string {
|
package/package.json
CHANGED
|
@@ -1,84 +1,85 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
2
|
+
"name": "gentle-pi",
|
|
3
|
+
"version": "2.4.0",
|
|
4
|
+
"description": "Turn Pi into el Gentleman: a senior-architect development harness with SDD/OpenSpec, subagents, strict TDD evidence, review guardrails, and skill discovery.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"pi-package",
|
|
9
|
+
"pi",
|
|
10
|
+
"pi-coding-agent",
|
|
11
|
+
"gentle-pi",
|
|
12
|
+
"gentle-ai",
|
|
13
|
+
"sdd",
|
|
14
|
+
"openspec",
|
|
15
|
+
"subagents",
|
|
16
|
+
"tdd",
|
|
17
|
+
"code-review",
|
|
18
|
+
"ai-coding-agent",
|
|
19
|
+
"agent-harness"
|
|
20
|
+
],
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "git+https://github.com/Gentleman-Programming/gentle-pi.git"
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"assets/",
|
|
27
|
+
"contracts/",
|
|
28
|
+
"docs/",
|
|
29
|
+
"extensions/",
|
|
30
|
+
"lib/",
|
|
31
|
+
"prompts/",
|
|
32
|
+
"runtime/",
|
|
33
|
+
"skills/",
|
|
34
|
+
"scripts/",
|
|
35
|
+
"tests/",
|
|
36
|
+
"themes/",
|
|
37
|
+
"README.md"
|
|
38
|
+
],
|
|
39
|
+
"scripts": {
|
|
40
|
+
"check:provider-contract": "node scripts/check-provider-contract.mjs",
|
|
41
|
+
"postinstall": "node scripts/install-gentle-ai.mjs",
|
|
42
|
+
"test": "node --experimental-strip-types --test tests/*.test.ts && pnpm run check:provider-contract && pnpm run test:harness",
|
|
43
|
+
"test:harness": "node --experimental-strip-types tests/runtime-harness.mjs",
|
|
44
|
+
"test:dev-binary": "node --experimental-strip-types --test tests/devbinary/*.devtest.ts",
|
|
45
|
+
"test:cross-lane": "node tests/crosslane/cross-lane.mjs",
|
|
46
|
+
"test:maintainer": "node --experimental-strip-types --test tests/maintainer/*.maintest.ts",
|
|
47
|
+
"build:runtime-modules": "node scripts/build-runtime-modules.mjs --write",
|
|
48
|
+
"check:runtime-modules": "node scripts/build-runtime-modules.mjs --check",
|
|
49
|
+
"test:packed-package": "node scripts/test-packed-runner.mjs",
|
|
50
|
+
"prepack": "pnpm test && pnpm run check:runtime-modules && node scripts/verify-package-files.mjs",
|
|
51
|
+
"prepublishOnly": "pnpm test && pnpm run check:runtime-modules && node scripts/verify-package-files.mjs && pnpm run test:packed-package"
|
|
52
|
+
},
|
|
53
|
+
"pi": {
|
|
54
|
+
"image": "https://cdn.jsdelivr.net/npm/gentle-pi/assets/gentle-logo-only.png",
|
|
55
|
+
"extensions": [
|
|
56
|
+
"./extensions"
|
|
57
|
+
],
|
|
58
|
+
"themes": [
|
|
59
|
+
"./themes"
|
|
60
|
+
],
|
|
61
|
+
"prompts": [
|
|
62
|
+
"./prompts"
|
|
63
|
+
],
|
|
64
|
+
"skills": [
|
|
65
|
+
"./skills"
|
|
66
|
+
]
|
|
67
|
+
},
|
|
68
|
+
"dependencies": {
|
|
69
|
+
"@earendil-works/pi-tui": "*",
|
|
70
|
+
"@heyhuynhgiabuu/pi-pretty": "0.6.14"
|
|
71
|
+
},
|
|
72
|
+
"peerDependencies": {
|
|
73
|
+
"@earendil-works/pi-coding-agent": "*",
|
|
74
|
+
"typebox": "*"
|
|
75
|
+
},
|
|
76
|
+
"peerDependenciesMeta": {
|
|
77
|
+
"@earendil-works/pi-coding-agent": {
|
|
78
|
+
"optional": true
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
"devDependencies": {
|
|
82
|
+
"@earendil-works/pi-coding-agent": "*"
|
|
83
|
+
},
|
|
84
|
+
"packageManager": "pnpm@11.1.1"
|
|
84
85
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Generated by scripts/build-
|
|
1
|
+
// Generated by scripts/build-runtime-modules.mjs. Do not edit.
|
|
2
2
|
import { createHash } from "node:crypto";
|
|
3
3
|
import { existsSync, lstatSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
4
4
|
import { homedir } from "node:os";
|