gsd-pi 2.29.0-dev.77f06e2 → 2.29.0-dev.f08b4fe
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/dist/extension-registry.d.ts +63 -0
- package/dist/extension-registry.js +166 -0
- package/dist/headless.js +4 -0
- package/dist/loader.js +10 -1
- package/dist/resource-loader.js +11 -1
- package/dist/resources/extensions/async-jobs/extension-manifest.json +13 -0
- package/dist/resources/extensions/bg-shell/extension-manifest.json +14 -0
- package/dist/resources/extensions/browser-tools/extension-manifest.json +37 -0
- package/dist/resources/extensions/context7/extension-manifest.json +12 -0
- package/dist/resources/extensions/google-search/extension-manifest.json +12 -0
- package/dist/resources/extensions/gsd/auto-dashboard.ts +31 -0
- package/dist/resources/extensions/gsd/auto-dispatch.ts +32 -3
- package/dist/resources/extensions/gsd/auto-post-unit.ts +39 -10
- package/dist/resources/extensions/gsd/auto-prompts.ts +40 -17
- package/dist/resources/extensions/gsd/auto-recovery.ts +2 -1
- package/dist/resources/extensions/gsd/auto-start.ts +18 -32
- package/dist/resources/extensions/gsd/auto-worktree.ts +21 -182
- package/dist/resources/extensions/gsd/auto.ts +2 -9
- package/dist/resources/extensions/gsd/captures.ts +4 -10
- package/dist/resources/extensions/gsd/commands-extensions.ts +328 -0
- package/dist/resources/extensions/gsd/commands-handlers.ts +2 -1
- package/dist/resources/extensions/gsd/commands.ts +53 -2
- package/dist/resources/extensions/gsd/detection.ts +2 -1
- package/dist/resources/extensions/gsd/doctor-checks.ts +49 -1
- package/dist/resources/extensions/gsd/doctor-types.ts +3 -1
- package/dist/resources/extensions/gsd/extension-manifest.json +18 -0
- package/dist/resources/extensions/gsd/forensics.ts +2 -2
- package/dist/resources/extensions/gsd/git-service.ts +3 -2
- package/dist/resources/extensions/gsd/gitignore.ts +9 -63
- package/dist/resources/extensions/gsd/gsd-db.ts +1 -165
- package/dist/resources/extensions/gsd/guided-flow.ts +8 -5
- package/dist/resources/extensions/gsd/index.ts +3 -3
- package/dist/resources/extensions/gsd/md-importer.ts +3 -2
- package/dist/resources/extensions/gsd/mechanical-completion.ts +430 -0
- package/dist/resources/extensions/gsd/migrate/command.ts +3 -2
- package/dist/resources/extensions/gsd/migrate/writer.ts +2 -1
- package/dist/resources/extensions/gsd/migrate-external.ts +123 -0
- package/dist/resources/extensions/gsd/paths.ts +24 -2
- package/dist/resources/extensions/gsd/post-unit-hooks.ts +6 -5
- package/dist/resources/extensions/gsd/preferences-models.ts +7 -1
- package/dist/resources/extensions/gsd/preferences-validation.ts +2 -1
- package/dist/resources/extensions/gsd/preferences.ts +10 -5
- package/dist/resources/extensions/gsd/prompts/discuss-headless.md +4 -2
- package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/plan-milestone.md +26 -2
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +15 -1
- package/dist/resources/extensions/gsd/repo-identity.ts +148 -0
- package/dist/resources/extensions/gsd/resource-version.ts +99 -0
- package/dist/resources/extensions/gsd/session-forensics.ts +4 -3
- package/dist/resources/extensions/gsd/tests/activity-log.test.ts +2 -2
- package/dist/resources/extensions/gsd/tests/auto-recovery.test.ts +3 -3
- package/dist/resources/extensions/gsd/tests/auto-worktree.test.ts +0 -58
- package/dist/resources/extensions/gsd/tests/doctor-runtime.test.ts +3 -4
- package/dist/resources/extensions/gsd/tests/feature-branch-lifecycle-integration.test.ts +5 -18
- package/dist/resources/extensions/gsd/tests/git-service.test.ts +10 -37
- package/dist/resources/extensions/gsd/tests/knowledge.test.ts +4 -4
- package/dist/resources/extensions/gsd/tests/mechanical-completion.test.ts +356 -0
- package/dist/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +1 -0
- package/dist/resources/extensions/gsd/tests/token-profile.test.ts +14 -16
- package/dist/resources/extensions/gsd/triage-resolution.ts +2 -1
- package/dist/resources/extensions/gsd/types.ts +2 -0
- package/dist/resources/extensions/gsd/worktree-command.ts +1 -11
- package/dist/resources/extensions/gsd/worktree-manager.ts +3 -2
- package/dist/resources/extensions/gsd/worktree.ts +42 -5
- package/dist/resources/extensions/mac-tools/extension-manifest.json +16 -0
- package/dist/resources/extensions/mcporter/extension-manifest.json +12 -0
- package/dist/resources/extensions/remote-questions/extension-manifest.json +11 -0
- package/dist/resources/extensions/search-the-web/extension-manifest.json +13 -0
- package/dist/resources/extensions/slash-commands/extension-manifest.json +11 -0
- package/dist/resources/extensions/subagent/extension-manifest.json +13 -0
- package/dist/resources/extensions/ttsr/extension-manifest.json +11 -0
- package/dist/resources/extensions/universal-config/extension-manifest.json +13 -0
- package/dist/resources/extensions/voice/extension-manifest.json +12 -0
- package/dist/resources/skills/create-gsd-extension/SKILL.md +87 -0
- package/dist/resources/skills/create-gsd-extension/references/compaction-session-control.md +77 -0
- package/dist/resources/skills/create-gsd-extension/references/custom-commands.md +139 -0
- package/dist/resources/skills/create-gsd-extension/references/custom-rendering.md +108 -0
- package/dist/resources/skills/create-gsd-extension/references/custom-tools.md +183 -0
- package/dist/resources/skills/create-gsd-extension/references/custom-ui.md +490 -0
- package/dist/resources/skills/create-gsd-extension/references/events-reference.md +126 -0
- package/dist/resources/skills/create-gsd-extension/references/extension-lifecycle.md +64 -0
- package/dist/resources/skills/create-gsd-extension/references/extensionapi-reference.md +75 -0
- package/dist/resources/skills/create-gsd-extension/references/extensioncontext-reference.md +53 -0
- package/dist/resources/skills/create-gsd-extension/references/key-rules-gotchas.md +36 -0
- package/dist/resources/skills/create-gsd-extension/references/mode-behavior.md +32 -0
- package/dist/resources/skills/create-gsd-extension/references/model-provider-management.md +89 -0
- package/dist/resources/skills/create-gsd-extension/references/packaging-distribution.md +55 -0
- package/dist/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +90 -0
- package/dist/resources/skills/create-gsd-extension/references/state-management.md +70 -0
- package/dist/resources/skills/create-gsd-extension/references/system-prompt-modification.md +52 -0
- package/dist/resources/skills/create-gsd-extension/templates/extension-skeleton.ts +51 -0
- package/dist/resources/skills/create-gsd-extension/templates/stateful-tool-skeleton.ts +143 -0
- package/dist/resources/skills/create-gsd-extension/workflows/add-capability.md +57 -0
- package/dist/resources/skills/create-gsd-extension/workflows/create-extension.md +156 -0
- package/dist/resources/skills/create-gsd-extension/workflows/debug-extension.md +74 -0
- package/dist/resources/skills/create-skill/SKILL.md +184 -0
- package/dist/resources/skills/create-skill/references/api-security.md +226 -0
- package/dist/resources/skills/create-skill/references/be-clear-and-direct.md +531 -0
- package/dist/resources/skills/create-skill/references/common-patterns.md +595 -0
- package/dist/resources/skills/create-skill/references/core-principles.md +437 -0
- package/dist/resources/skills/create-skill/references/executable-code.md +175 -0
- package/dist/resources/skills/create-skill/references/gsd-skill-ecosystem.md +68 -0
- package/dist/resources/skills/create-skill/references/iteration-and-testing.md +474 -0
- package/dist/resources/skills/create-skill/references/recommended-structure.md +168 -0
- package/dist/resources/skills/create-skill/references/skill-structure.md +372 -0
- package/dist/resources/skills/create-skill/references/use-xml-tags.md +466 -0
- package/dist/resources/skills/create-skill/references/using-scripts.md +113 -0
- package/dist/resources/skills/create-skill/references/using-templates.md +112 -0
- package/dist/resources/skills/create-skill/references/workflows-and-validation.md +510 -0
- package/dist/resources/skills/create-skill/templates/router-skill.md +73 -0
- package/dist/resources/skills/create-skill/templates/simple-skill.md +33 -0
- package/dist/resources/skills/create-skill/workflows/add-reference.md +96 -0
- package/dist/resources/skills/create-skill/workflows/add-script.md +93 -0
- package/dist/resources/skills/create-skill/workflows/add-template.md +74 -0
- package/dist/resources/skills/create-skill/workflows/add-workflow.md +120 -0
- package/dist/resources/skills/create-skill/workflows/audit-skill.md +148 -0
- package/dist/resources/skills/create-skill/workflows/create-new-skill.md +196 -0
- package/dist/resources/skills/create-skill/workflows/get-guidance.md +121 -0
- package/dist/resources/skills/create-skill/workflows/upgrade-to-router.md +161 -0
- package/dist/resources/skills/create-skill/workflows/verify-skill.md +204 -0
- package/dist/resources/skills/react-best-practices/SKILL.md +1 -1
- package/package.json +1 -1
- package/packages/native/dist/native.d.ts +2 -0
- package/packages/native/dist/native.js +19 -5
- package/packages/native/src/native.ts +23 -9
- package/packages/pi-coding-agent/dist/core/lsp/client.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/client.js +3 -0
- package/packages/pi-coding-agent/dist/core/lsp/client.js.map +1 -1
- package/packages/pi-coding-agent/src/core/lsp/client.ts +3 -0
- package/src/resources/extensions/async-jobs/extension-manifest.json +13 -0
- package/src/resources/extensions/bg-shell/extension-manifest.json +14 -0
- package/src/resources/extensions/browser-tools/extension-manifest.json +37 -0
- package/src/resources/extensions/context7/extension-manifest.json +12 -0
- package/src/resources/extensions/google-search/extension-manifest.json +12 -0
- package/src/resources/extensions/gsd/auto-dashboard.ts +31 -0
- package/src/resources/extensions/gsd/auto-dispatch.ts +32 -3
- package/src/resources/extensions/gsd/auto-post-unit.ts +39 -10
- package/src/resources/extensions/gsd/auto-prompts.ts +40 -17
- package/src/resources/extensions/gsd/auto-recovery.ts +2 -1
- package/src/resources/extensions/gsd/auto-start.ts +18 -32
- package/src/resources/extensions/gsd/auto-worktree.ts +21 -182
- package/src/resources/extensions/gsd/auto.ts +2 -9
- package/src/resources/extensions/gsd/captures.ts +4 -10
- package/src/resources/extensions/gsd/commands-extensions.ts +328 -0
- package/src/resources/extensions/gsd/commands-handlers.ts +2 -1
- package/src/resources/extensions/gsd/commands.ts +53 -2
- package/src/resources/extensions/gsd/detection.ts +2 -1
- package/src/resources/extensions/gsd/doctor-checks.ts +49 -1
- package/src/resources/extensions/gsd/doctor-types.ts +3 -1
- package/src/resources/extensions/gsd/extension-manifest.json +18 -0
- package/src/resources/extensions/gsd/forensics.ts +2 -2
- package/src/resources/extensions/gsd/git-service.ts +3 -2
- package/src/resources/extensions/gsd/gitignore.ts +9 -63
- package/src/resources/extensions/gsd/gsd-db.ts +1 -165
- package/src/resources/extensions/gsd/guided-flow.ts +8 -5
- package/src/resources/extensions/gsd/index.ts +3 -3
- package/src/resources/extensions/gsd/md-importer.ts +3 -2
- package/src/resources/extensions/gsd/mechanical-completion.ts +430 -0
- package/src/resources/extensions/gsd/migrate/command.ts +3 -2
- package/src/resources/extensions/gsd/migrate/writer.ts +2 -1
- package/src/resources/extensions/gsd/migrate-external.ts +123 -0
- package/src/resources/extensions/gsd/paths.ts +24 -2
- package/src/resources/extensions/gsd/post-unit-hooks.ts +6 -5
- package/src/resources/extensions/gsd/preferences-models.ts +7 -1
- package/src/resources/extensions/gsd/preferences-validation.ts +2 -1
- package/src/resources/extensions/gsd/preferences.ts +10 -5
- package/src/resources/extensions/gsd/prompts/discuss-headless.md +4 -2
- package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/plan-milestone.md +26 -2
- package/src/resources/extensions/gsd/prompts/plan-slice.md +15 -1
- package/src/resources/extensions/gsd/repo-identity.ts +148 -0
- package/src/resources/extensions/gsd/resource-version.ts +99 -0
- package/src/resources/extensions/gsd/session-forensics.ts +4 -3
- package/src/resources/extensions/gsd/tests/activity-log.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/auto-worktree.test.ts +0 -58
- package/src/resources/extensions/gsd/tests/doctor-runtime.test.ts +3 -4
- package/src/resources/extensions/gsd/tests/feature-branch-lifecycle-integration.test.ts +5 -18
- package/src/resources/extensions/gsd/tests/git-service.test.ts +10 -37
- package/src/resources/extensions/gsd/tests/knowledge.test.ts +4 -4
- package/src/resources/extensions/gsd/tests/mechanical-completion.test.ts +356 -0
- package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/token-profile.test.ts +14 -16
- package/src/resources/extensions/gsd/triage-resolution.ts +2 -1
- package/src/resources/extensions/gsd/types.ts +2 -0
- package/src/resources/extensions/gsd/worktree-command.ts +1 -11
- package/src/resources/extensions/gsd/worktree-manager.ts +3 -2
- package/src/resources/extensions/gsd/worktree.ts +42 -5
- package/src/resources/extensions/mac-tools/extension-manifest.json +16 -0
- package/src/resources/extensions/mcporter/extension-manifest.json +12 -0
- package/src/resources/extensions/remote-questions/extension-manifest.json +11 -0
- package/src/resources/extensions/search-the-web/extension-manifest.json +13 -0
- package/src/resources/extensions/slash-commands/extension-manifest.json +11 -0
- package/src/resources/extensions/subagent/extension-manifest.json +13 -0
- package/src/resources/extensions/ttsr/extension-manifest.json +11 -0
- package/src/resources/extensions/universal-config/extension-manifest.json +13 -0
- package/src/resources/extensions/voice/extension-manifest.json +12 -0
- package/src/resources/skills/create-gsd-extension/SKILL.md +87 -0
- package/src/resources/skills/create-gsd-extension/references/compaction-session-control.md +77 -0
- package/src/resources/skills/create-gsd-extension/references/custom-commands.md +139 -0
- package/src/resources/skills/create-gsd-extension/references/custom-rendering.md +108 -0
- package/src/resources/skills/create-gsd-extension/references/custom-tools.md +183 -0
- package/src/resources/skills/create-gsd-extension/references/custom-ui.md +490 -0
- package/src/resources/skills/create-gsd-extension/references/events-reference.md +126 -0
- package/src/resources/skills/create-gsd-extension/references/extension-lifecycle.md +64 -0
- package/src/resources/skills/create-gsd-extension/references/extensionapi-reference.md +75 -0
- package/src/resources/skills/create-gsd-extension/references/extensioncontext-reference.md +53 -0
- package/src/resources/skills/create-gsd-extension/references/key-rules-gotchas.md +36 -0
- package/src/resources/skills/create-gsd-extension/references/mode-behavior.md +32 -0
- package/src/resources/skills/create-gsd-extension/references/model-provider-management.md +89 -0
- package/src/resources/skills/create-gsd-extension/references/packaging-distribution.md +55 -0
- package/src/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +90 -0
- package/src/resources/skills/create-gsd-extension/references/state-management.md +70 -0
- package/src/resources/skills/create-gsd-extension/references/system-prompt-modification.md +52 -0
- package/src/resources/skills/create-gsd-extension/templates/extension-skeleton.ts +51 -0
- package/src/resources/skills/create-gsd-extension/templates/stateful-tool-skeleton.ts +143 -0
- package/src/resources/skills/create-gsd-extension/workflows/add-capability.md +57 -0
- package/src/resources/skills/create-gsd-extension/workflows/create-extension.md +156 -0
- package/src/resources/skills/create-gsd-extension/workflows/debug-extension.md +74 -0
- package/src/resources/skills/create-skill/SKILL.md +184 -0
- package/src/resources/skills/create-skill/references/api-security.md +226 -0
- package/src/resources/skills/create-skill/references/be-clear-and-direct.md +531 -0
- package/src/resources/skills/create-skill/references/common-patterns.md +595 -0
- package/src/resources/skills/create-skill/references/core-principles.md +437 -0
- package/src/resources/skills/create-skill/references/executable-code.md +175 -0
- package/src/resources/skills/create-skill/references/gsd-skill-ecosystem.md +68 -0
- package/src/resources/skills/create-skill/references/iteration-and-testing.md +474 -0
- package/src/resources/skills/create-skill/references/recommended-structure.md +168 -0
- package/src/resources/skills/create-skill/references/skill-structure.md +372 -0
- package/src/resources/skills/create-skill/references/use-xml-tags.md +466 -0
- package/src/resources/skills/create-skill/references/using-scripts.md +113 -0
- package/src/resources/skills/create-skill/references/using-templates.md +112 -0
- package/src/resources/skills/create-skill/references/workflows-and-validation.md +510 -0
- package/src/resources/skills/create-skill/templates/router-skill.md +73 -0
- package/src/resources/skills/create-skill/templates/simple-skill.md +33 -0
- package/src/resources/skills/create-skill/workflows/add-reference.md +96 -0
- package/src/resources/skills/create-skill/workflows/add-script.md +93 -0
- package/src/resources/skills/create-skill/workflows/add-template.md +74 -0
- package/src/resources/skills/create-skill/workflows/add-workflow.md +120 -0
- package/src/resources/skills/create-skill/workflows/audit-skill.md +148 -0
- package/src/resources/skills/create-skill/workflows/create-new-skill.md +196 -0
- package/src/resources/skills/create-skill/workflows/get-guidance.md +121 -0
- package/src/resources/skills/create-skill/workflows/upgrade-to-router.md +161 -0
- package/src/resources/skills/create-skill/workflows/verify-skill.md +204 -0
- package/src/resources/skills/react-best-practices/SKILL.md +1 -1
- package/dist/resources/extensions/gsd/auto-worktree-sync.ts +0 -199
- package/dist/resources/extensions/gsd/tests/worktree-db-integration.test.ts +0 -205
- package/dist/resources/extensions/gsd/tests/worktree-db.test.ts +0 -442
- package/src/resources/extensions/gsd/auto-worktree-sync.ts +0 -199
- package/src/resources/extensions/gsd/tests/worktree-db-integration.test.ts +0 -205
- package/src/resources/extensions/gsd/tests/worktree-db.test.ts +0 -442
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extension Registry — manages manifest reading, registry persistence, and enable/disable state.
|
|
3
|
+
*
|
|
4
|
+
* Extensions without manifests always load (backwards compatible).
|
|
5
|
+
* A fresh install has an empty registry — all extensions enabled by default.
|
|
6
|
+
* The only way an extension stops loading is an explicit `gsd extensions disable <id>`.
|
|
7
|
+
*/
|
|
8
|
+
export interface ExtensionManifest {
|
|
9
|
+
id: string;
|
|
10
|
+
name: string;
|
|
11
|
+
version: string;
|
|
12
|
+
description: string;
|
|
13
|
+
tier: "core" | "bundled" | "community";
|
|
14
|
+
requires: {
|
|
15
|
+
platform: string;
|
|
16
|
+
};
|
|
17
|
+
provides?: {
|
|
18
|
+
tools?: string[];
|
|
19
|
+
commands?: string[];
|
|
20
|
+
hooks?: string[];
|
|
21
|
+
shortcuts?: string[];
|
|
22
|
+
};
|
|
23
|
+
dependencies?: {
|
|
24
|
+
extensions?: string[];
|
|
25
|
+
runtime?: string[];
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
export interface ExtensionRegistryEntry {
|
|
29
|
+
id: string;
|
|
30
|
+
enabled: boolean;
|
|
31
|
+
source: "bundled" | "user" | "project";
|
|
32
|
+
disabledAt?: string;
|
|
33
|
+
disabledReason?: string;
|
|
34
|
+
}
|
|
35
|
+
export interface ExtensionRegistry {
|
|
36
|
+
version: 1;
|
|
37
|
+
entries: Record<string, ExtensionRegistryEntry>;
|
|
38
|
+
}
|
|
39
|
+
export declare function getRegistryPath(): string;
|
|
40
|
+
export declare function loadRegistry(): ExtensionRegistry;
|
|
41
|
+
export declare function saveRegistry(registry: ExtensionRegistry): void;
|
|
42
|
+
/** Returns true if the extension is enabled (missing entries default to enabled). */
|
|
43
|
+
export declare function isExtensionEnabled(registry: ExtensionRegistry, id: string): boolean;
|
|
44
|
+
export declare function enableExtension(registry: ExtensionRegistry, id: string): void;
|
|
45
|
+
/**
|
|
46
|
+
* Disable an extension. Returns an error string if the extension is core (cannot disable),
|
|
47
|
+
* or null on success.
|
|
48
|
+
*/
|
|
49
|
+
export declare function disableExtension(registry: ExtensionRegistry, id: string, manifest: ExtensionManifest | null, reason?: string): string | null;
|
|
50
|
+
/** Read extension-manifest.json from a directory. Returns null if missing or invalid. */
|
|
51
|
+
export declare function readManifest(extensionDir: string): ExtensionManifest | null;
|
|
52
|
+
/**
|
|
53
|
+
* Given an entry path (e.g. `.../extensions/browser-tools/index.ts`),
|
|
54
|
+
* resolve the parent directory and read its manifest.
|
|
55
|
+
*/
|
|
56
|
+
export declare function readManifestFromEntryPath(entryPath: string): ExtensionManifest | null;
|
|
57
|
+
/** Scan all subdirectories of extensionsDir for manifests. Returns a Map<id, manifest>. */
|
|
58
|
+
export declare function discoverAllManifests(extensionsDir: string): Map<string, ExtensionManifest>;
|
|
59
|
+
/**
|
|
60
|
+
* Auto-populate registry entries for newly discovered extensions.
|
|
61
|
+
* Extensions already in the registry are left untouched.
|
|
62
|
+
*/
|
|
63
|
+
export declare function ensureRegistryEntries(extensionsDir: string): void;
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extension Registry — manages manifest reading, registry persistence, and enable/disable state.
|
|
3
|
+
*
|
|
4
|
+
* Extensions without manifests always load (backwards compatible).
|
|
5
|
+
* A fresh install has an empty registry — all extensions enabled by default.
|
|
6
|
+
* The only way an extension stops loading is an explicit `gsd extensions disable <id>`.
|
|
7
|
+
*/
|
|
8
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, writeFileSync } from "node:fs";
|
|
9
|
+
import { homedir } from "node:os";
|
|
10
|
+
import { dirname, join } from "node:path";
|
|
11
|
+
// ─── Validation ─────────────────────────────────────────────────────────────
|
|
12
|
+
function isRegistry(data) {
|
|
13
|
+
if (typeof data !== "object" || data === null)
|
|
14
|
+
return false;
|
|
15
|
+
const obj = data;
|
|
16
|
+
return obj.version === 1 && typeof obj.entries === "object" && obj.entries !== null;
|
|
17
|
+
}
|
|
18
|
+
function isManifest(data) {
|
|
19
|
+
if (typeof data !== "object" || data === null)
|
|
20
|
+
return false;
|
|
21
|
+
const obj = data;
|
|
22
|
+
return (typeof obj.id === "string" &&
|
|
23
|
+
typeof obj.name === "string" &&
|
|
24
|
+
typeof obj.version === "string" &&
|
|
25
|
+
typeof obj.tier === "string");
|
|
26
|
+
}
|
|
27
|
+
// ─── Registry Path ──────────────────────────────────────────────────────────
|
|
28
|
+
export function getRegistryPath() {
|
|
29
|
+
return join(homedir(), ".gsd", "extensions", "registry.json");
|
|
30
|
+
}
|
|
31
|
+
// ─── Registry I/O ───────────────────────────────────────────────────────────
|
|
32
|
+
function defaultRegistry() {
|
|
33
|
+
return { version: 1, entries: {} };
|
|
34
|
+
}
|
|
35
|
+
export function loadRegistry() {
|
|
36
|
+
const filePath = getRegistryPath();
|
|
37
|
+
try {
|
|
38
|
+
if (!existsSync(filePath))
|
|
39
|
+
return defaultRegistry();
|
|
40
|
+
const raw = readFileSync(filePath, "utf-8");
|
|
41
|
+
const parsed = JSON.parse(raw);
|
|
42
|
+
return isRegistry(parsed) ? parsed : defaultRegistry();
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return defaultRegistry();
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
export function saveRegistry(registry) {
|
|
49
|
+
const filePath = getRegistryPath();
|
|
50
|
+
try {
|
|
51
|
+
mkdirSync(dirname(filePath), { recursive: true });
|
|
52
|
+
const tmp = filePath + ".tmp";
|
|
53
|
+
writeFileSync(tmp, JSON.stringify(registry, null, 2), "utf-8");
|
|
54
|
+
renameSync(tmp, filePath);
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
// Non-fatal — don't let persistence failures break operation
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// ─── Query ──────────────────────────────────────────────────────────────────
|
|
61
|
+
/** Returns true if the extension is enabled (missing entries default to enabled). */
|
|
62
|
+
export function isExtensionEnabled(registry, id) {
|
|
63
|
+
const entry = registry.entries[id];
|
|
64
|
+
if (!entry)
|
|
65
|
+
return true;
|
|
66
|
+
return entry.enabled;
|
|
67
|
+
}
|
|
68
|
+
// ─── Mutations ──────────────────────────────────────────────────────────────
|
|
69
|
+
export function enableExtension(registry, id) {
|
|
70
|
+
const entry = registry.entries[id];
|
|
71
|
+
if (entry) {
|
|
72
|
+
entry.enabled = true;
|
|
73
|
+
delete entry.disabledAt;
|
|
74
|
+
delete entry.disabledReason;
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
registry.entries[id] = { id, enabled: true, source: "bundled" };
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Disable an extension. Returns an error string if the extension is core (cannot disable),
|
|
82
|
+
* or null on success.
|
|
83
|
+
*/
|
|
84
|
+
export function disableExtension(registry, id, manifest, reason) {
|
|
85
|
+
if (manifest?.tier === "core") {
|
|
86
|
+
return `Cannot disable "${id}" — it is a core extension.`;
|
|
87
|
+
}
|
|
88
|
+
const entry = registry.entries[id];
|
|
89
|
+
if (entry) {
|
|
90
|
+
entry.enabled = false;
|
|
91
|
+
entry.disabledAt = new Date().toISOString();
|
|
92
|
+
entry.disabledReason = reason;
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
registry.entries[id] = {
|
|
96
|
+
id,
|
|
97
|
+
enabled: false,
|
|
98
|
+
source: "bundled",
|
|
99
|
+
disabledAt: new Date().toISOString(),
|
|
100
|
+
disabledReason: reason,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
// ─── Manifest Reading ───────────────────────────────────────────────────────
|
|
106
|
+
/** Read extension-manifest.json from a directory. Returns null if missing or invalid. */
|
|
107
|
+
export function readManifest(extensionDir) {
|
|
108
|
+
const manifestPath = join(extensionDir, "extension-manifest.json");
|
|
109
|
+
if (!existsSync(manifestPath))
|
|
110
|
+
return null;
|
|
111
|
+
try {
|
|
112
|
+
const raw = JSON.parse(readFileSync(manifestPath, "utf-8"));
|
|
113
|
+
return isManifest(raw) ? raw : null;
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Given an entry path (e.g. `.../extensions/browser-tools/index.ts`),
|
|
121
|
+
* resolve the parent directory and read its manifest.
|
|
122
|
+
*/
|
|
123
|
+
export function readManifestFromEntryPath(entryPath) {
|
|
124
|
+
const dir = dirname(entryPath);
|
|
125
|
+
return readManifest(dir);
|
|
126
|
+
}
|
|
127
|
+
// ─── Discovery ──────────────────────────────────────────────────────────────
|
|
128
|
+
/** Scan all subdirectories of extensionsDir for manifests. Returns a Map<id, manifest>. */
|
|
129
|
+
export function discoverAllManifests(extensionsDir) {
|
|
130
|
+
const manifests = new Map();
|
|
131
|
+
if (!existsSync(extensionsDir))
|
|
132
|
+
return manifests;
|
|
133
|
+
for (const entry of readdirSync(extensionsDir, { withFileTypes: true })) {
|
|
134
|
+
if (!entry.isDirectory())
|
|
135
|
+
continue;
|
|
136
|
+
const manifest = readManifest(join(extensionsDir, entry.name));
|
|
137
|
+
if (manifest) {
|
|
138
|
+
manifests.set(manifest.id, manifest);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return manifests;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Auto-populate registry entries for newly discovered extensions.
|
|
145
|
+
* Extensions already in the registry are left untouched.
|
|
146
|
+
*/
|
|
147
|
+
export function ensureRegistryEntries(extensionsDir) {
|
|
148
|
+
const manifests = discoverAllManifests(extensionsDir);
|
|
149
|
+
if (manifests.size === 0)
|
|
150
|
+
return;
|
|
151
|
+
const registry = loadRegistry();
|
|
152
|
+
let changed = false;
|
|
153
|
+
for (const [id, manifest] of manifests) {
|
|
154
|
+
if (!registry.entries[id]) {
|
|
155
|
+
registry.entries[id] = {
|
|
156
|
+
id,
|
|
157
|
+
enabled: true,
|
|
158
|
+
source: "bundled",
|
|
159
|
+
};
|
|
160
|
+
changed = true;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
if (changed) {
|
|
164
|
+
saveRegistry(registry);
|
|
165
|
+
}
|
|
166
|
+
}
|
package/dist/headless.js
CHANGED
|
@@ -128,6 +128,10 @@ async function runHeadlessOnce(options, restartCount) {
|
|
|
128
128
|
let interrupted = false;
|
|
129
129
|
const startTime = Date.now();
|
|
130
130
|
const isNewMilestone = options.command === 'new-milestone';
|
|
131
|
+
// new-milestone involves codebase investigation + artifact writing — needs more time
|
|
132
|
+
if (isNewMilestone && options.timeout === 300_000) {
|
|
133
|
+
options.timeout = 600_000; // 10 minutes
|
|
134
|
+
}
|
|
131
135
|
// Supervised mode cannot share stdin with --context -
|
|
132
136
|
if (options.supervised && options.context === '-') {
|
|
133
137
|
process.stderr.write('[headless] Error: --supervised cannot be used with --context - (both require stdin)\n');
|
package/dist/loader.js
CHANGED
|
@@ -29,6 +29,7 @@ if (firstArg === '--help' || firstArg === '-h') {
|
|
|
29
29
|
import { agentDir, appRoot } from './app-paths.js';
|
|
30
30
|
import { serializeBundledExtensionPaths } from './bundled-extension-paths.js';
|
|
31
31
|
import { discoverExtensionEntryPaths } from './extension-discovery.js';
|
|
32
|
+
import { loadRegistry, readManifestFromEntryPath, isExtensionEnabled } from './extension-registry.js';
|
|
32
33
|
import { renderLogo } from './logo.js';
|
|
33
34
|
// pkg/ is a shim directory: contains gsd's piConfig (package.json) and pi's
|
|
34
35
|
// theme assets (dist/modes/interactive/theme/) without a src/ directory.
|
|
@@ -86,7 +87,15 @@ process.env.GSD_WORKFLOW_PATH = join(resourcesDir, 'GSD-WORKFLOW.md');
|
|
|
86
87
|
// where initResources() will sync them.
|
|
87
88
|
const bundledExtDir = join(resourcesDir, 'extensions');
|
|
88
89
|
const agentExtDir = join(agentDir, 'extensions');
|
|
89
|
-
const
|
|
90
|
+
const registry = loadRegistry();
|
|
91
|
+
const discoveredExtensionPaths = discoverExtensionEntryPaths(bundledExtDir)
|
|
92
|
+
.map((entryPath) => join(agentExtDir, relative(bundledExtDir, entryPath)))
|
|
93
|
+
.filter((entryPath) => {
|
|
94
|
+
const manifest = readManifestFromEntryPath(entryPath);
|
|
95
|
+
if (!manifest)
|
|
96
|
+
return true; // no manifest = always load
|
|
97
|
+
return isExtensionEnabled(registry, manifest.id);
|
|
98
|
+
});
|
|
90
99
|
process.env.GSD_BUNDLED_EXTENSION_PATHS = serializeBundledExtensionPaths(discoveredExtensionPaths);
|
|
91
100
|
// Respect HTTP_PROXY / HTTPS_PROXY / NO_PROXY env vars for all outbound requests.
|
|
92
101
|
// pi-coding-agent's cli.ts sets this, but GSD bypasses that entry point — so we
|
package/dist/resource-loader.js
CHANGED
|
@@ -6,6 +6,7 @@ import { dirname, join, relative, resolve } from 'node:path';
|
|
|
6
6
|
import { fileURLToPath } from 'node:url';
|
|
7
7
|
import { compareSemver } from './update-check.js';
|
|
8
8
|
import { discoverExtensionEntryPaths } from './extension-discovery.js';
|
|
9
|
+
import { loadRegistry, readManifestFromEntryPath, isExtensionEnabled, ensureRegistryEntries } from './extension-registry.js';
|
|
9
10
|
// Resolve resources directory — prefer dist/resources/ (stable, set at build time)
|
|
10
11
|
// over src/resources/ (live working tree, changes with git branch).
|
|
11
12
|
//
|
|
@@ -218,6 +219,7 @@ export function initResources(agentDir) {
|
|
|
218
219
|
// overwrite them (covers extensions, agents, and skills in one walk).
|
|
219
220
|
makeTreeWritable(agentDir);
|
|
220
221
|
writeManagedResourceManifest(agentDir);
|
|
222
|
+
ensureRegistryEntries(join(agentDir, 'extensions'));
|
|
221
223
|
}
|
|
222
224
|
/**
|
|
223
225
|
* Constructs a DefaultResourceLoader that loads extensions from both
|
|
@@ -234,10 +236,18 @@ function getBundledExtensionKeys() {
|
|
|
234
236
|
return _bundledExtensionKeys;
|
|
235
237
|
}
|
|
236
238
|
export function buildResourceLoader(agentDir) {
|
|
239
|
+
const registry = loadRegistry();
|
|
237
240
|
const piAgentDir = join(homedir(), '.pi', 'agent');
|
|
238
241
|
const piExtensionsDir = join(piAgentDir, 'extensions');
|
|
239
242
|
const bundledKeys = getBundledExtensionKeys();
|
|
240
|
-
const piExtensionPaths = discoverExtensionEntryPaths(piExtensionsDir)
|
|
243
|
+
const piExtensionPaths = discoverExtensionEntryPaths(piExtensionsDir)
|
|
244
|
+
.filter((entryPath) => !bundledKeys.has(getExtensionKey(entryPath, piExtensionsDir)))
|
|
245
|
+
.filter((entryPath) => {
|
|
246
|
+
const manifest = readManifestFromEntryPath(entryPath);
|
|
247
|
+
if (!manifest)
|
|
248
|
+
return true;
|
|
249
|
+
return isExtensionEnabled(registry, manifest.id);
|
|
250
|
+
});
|
|
241
251
|
return new DefaultResourceLoader({
|
|
242
252
|
agentDir,
|
|
243
253
|
additionalExtensionPaths: piExtensionPaths,
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "async-jobs",
|
|
3
|
+
"name": "Async Jobs",
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"description": "Run bash commands in the background with job tracking and cancellation",
|
|
6
|
+
"tier": "bundled",
|
|
7
|
+
"requires": { "platform": ">=2.29.0" },
|
|
8
|
+
"provides": {
|
|
9
|
+
"tools": ["async_bash", "await_job", "cancel_job"],
|
|
10
|
+
"commands": ["jobs"],
|
|
11
|
+
"hooks": ["session_start"]
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "bg-shell",
|
|
3
|
+
"name": "Background Shell",
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"description": "Run and manage background shell processes with interactive monitoring",
|
|
6
|
+
"tier": "bundled",
|
|
7
|
+
"requires": { "platform": ">=2.29.0" },
|
|
8
|
+
"provides": {
|
|
9
|
+
"tools": ["bg_shell"],
|
|
10
|
+
"commands": ["bg"],
|
|
11
|
+
"hooks": ["session_shutdown"],
|
|
12
|
+
"shortcuts": ["Ctrl+Alt+B"]
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "browser-tools",
|
|
3
|
+
"name": "Browser Tools",
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"description": "Playwright-based web automation, screenshots, and analysis",
|
|
6
|
+
"tier": "bundled",
|
|
7
|
+
"requires": { "platform": ">=2.29.0" },
|
|
8
|
+
"provides": {
|
|
9
|
+
"tools": [
|
|
10
|
+
"browser_navigate", "browser_go_back", "browser_go_forward", "browser_reload",
|
|
11
|
+
"browser_click", "browser_drag", "browser_type", "browser_upload_file",
|
|
12
|
+
"browser_scroll", "browser_hover", "browser_key_press", "browser_select_option",
|
|
13
|
+
"browser_set_checked", "browser_screenshot", "browser_wait_for",
|
|
14
|
+
"browser_get_console_logs", "browser_get_network_logs", "browser_get_dialog_logs",
|
|
15
|
+
"browser_evaluate", "browser_get_accessibility_tree", "browser_find",
|
|
16
|
+
"browser_get_page_source", "browser_close",
|
|
17
|
+
"browser_trace_start", "browser_trace_stop", "browser_export_har",
|
|
18
|
+
"browser_timeline", "browser_session_summary", "browser_debug_bundle",
|
|
19
|
+
"browser_assert", "browser_diff", "browser_batch",
|
|
20
|
+
"browser_snapshot_refs", "browser_get_ref", "browser_click_ref",
|
|
21
|
+
"browser_hover_ref", "browser_fill_ref",
|
|
22
|
+
"browser_list_pages", "browser_switch_page", "browser_close_page",
|
|
23
|
+
"browser_list_frames", "browser_select_frame",
|
|
24
|
+
"browser_analyze_form", "browser_fill_form",
|
|
25
|
+
"browser_find_best", "browser_act",
|
|
26
|
+
"browser_save_pdf", "browser_save_state", "browser_restore_state",
|
|
27
|
+
"browser_mock_route", "browser_block_urls", "browser_clear_routes",
|
|
28
|
+
"browser_emulate_device", "browser_extract",
|
|
29
|
+
"browser_visual_diff", "browser_zoom_region",
|
|
30
|
+
"browser_generate_test", "browser_action_cache", "browser_check_injection"
|
|
31
|
+
],
|
|
32
|
+
"hooks": ["session_shutdown"]
|
|
33
|
+
},
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"runtime": ["playwright"]
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "context7",
|
|
3
|
+
"name": "Context7",
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"description": "Fetch up-to-date library documentation and code examples from Context7",
|
|
6
|
+
"tier": "bundled",
|
|
7
|
+
"requires": { "platform": ">=2.29.0" },
|
|
8
|
+
"provides": {
|
|
9
|
+
"tools": ["resolve_library", "get_library_docs"],
|
|
10
|
+
"hooks": ["session_start"]
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "google-search",
|
|
3
|
+
"name": "Google Search",
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"description": "Web search via Google with AI-synthesized answers and source citations",
|
|
6
|
+
"tier": "bundled",
|
|
7
|
+
"requires": { "platform": ">=2.29.0" },
|
|
8
|
+
"provides": {
|
|
9
|
+
"tools": ["google_search"],
|
|
10
|
+
"hooks": ["session_start"]
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -11,6 +11,7 @@ import type { GSDState } from "./types.js";
|
|
|
11
11
|
import { getCurrentBranch } from "./worktree.js";
|
|
12
12
|
import { getActiveHook } from "./post-unit-hooks.js";
|
|
13
13
|
import { getLedger, getProjectTotals, formatCost, formatTokenCount, formatTierSavings } from "./metrics.js";
|
|
14
|
+
import { getHealthTrend, getConsecutiveErrorUnits } from "./doctor-proactive.js";
|
|
14
15
|
import {
|
|
15
16
|
resolveMilestoneFile,
|
|
16
17
|
resolveSliceFile,
|
|
@@ -649,6 +650,31 @@ export function updateProgressWidget(
|
|
|
649
650
|
* Build a compact string-array representation of the progress widget.
|
|
650
651
|
* Used as a fallback when the factory-based widget cannot render (RPC mode).
|
|
651
652
|
*/
|
|
653
|
+
// ─── Model Health Indicator ───────────────────────────────────────────────────
|
|
654
|
+
|
|
655
|
+
/**
|
|
656
|
+
* Compute a traffic-light health indicator from observable signals.
|
|
657
|
+
* 🟢 progressing well — no errors, trend stable/improving
|
|
658
|
+
* 🟡 struggling — some errors or degrading trend
|
|
659
|
+
* 🔴 stuck — consecutive errors, likely needs attention
|
|
660
|
+
*/
|
|
661
|
+
export function getModelHealthIndicator(): { emoji: string; label: string } {
|
|
662
|
+
const trend = getHealthTrend();
|
|
663
|
+
const consecutiveErrors = getConsecutiveErrorUnits();
|
|
664
|
+
|
|
665
|
+
if (consecutiveErrors >= 3) {
|
|
666
|
+
return { emoji: "🔴", label: "stuck" };
|
|
667
|
+
}
|
|
668
|
+
if (consecutiveErrors >= 1 || trend === "degrading") {
|
|
669
|
+
return { emoji: "🟡", label: "struggling" };
|
|
670
|
+
}
|
|
671
|
+
if (trend === "improving") {
|
|
672
|
+
return { emoji: "🟢", label: "progressing well" };
|
|
673
|
+
}
|
|
674
|
+
// stable or unknown
|
|
675
|
+
return { emoji: "🟢", label: "progressing" };
|
|
676
|
+
}
|
|
677
|
+
|
|
652
678
|
function buildProgressTextLines(
|
|
653
679
|
verb: string,
|
|
654
680
|
phaseLabel: string,
|
|
@@ -697,6 +723,11 @@ function buildProgressTextLines(
|
|
|
697
723
|
}
|
|
698
724
|
|
|
699
725
|
if (next) lines.push(` Next: ${next}`);
|
|
726
|
+
|
|
727
|
+
// Model health indicator
|
|
728
|
+
const health = getModelHealthIndicator();
|
|
729
|
+
lines.push(` Health: ${health.emoji} ${health.label}`);
|
|
730
|
+
|
|
700
731
|
lines.push(` ${widgetPwd}`);
|
|
701
732
|
|
|
702
733
|
return lines;
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
import type { GSDState } from "./types.js";
|
|
13
13
|
import type { GSDPreferences } from "./preferences.js";
|
|
14
14
|
import type { UatType } from "./files.js";
|
|
15
|
-
import { loadFile, extractUatType, loadActiveOverrides } from "./files.js";
|
|
15
|
+
import { loadFile, extractUatType, loadActiveOverrides, parseRoadmap } from "./files.js";
|
|
16
16
|
import {
|
|
17
17
|
resolveMilestoneFile, resolveMilestonePath, resolveSliceFile, resolveTaskFile,
|
|
18
18
|
relSliceFile, buildMilestoneFileName,
|
|
@@ -123,11 +123,40 @@ const DISPATCH_RULES: DispatchRule[] = [
|
|
|
123
123
|
};
|
|
124
124
|
},
|
|
125
125
|
},
|
|
126
|
+
{
|
|
127
|
+
name: "uat-verdict-gate (non-PASS blocks progression)",
|
|
128
|
+
match: async ({ mid, basePath, prefs }) => {
|
|
129
|
+
// Only applies when UAT dispatch is enabled
|
|
130
|
+
if (!prefs?.uat_dispatch) return null;
|
|
131
|
+
|
|
132
|
+
const roadmapFile = resolveMilestoneFile(basePath, mid, "ROADMAP");
|
|
133
|
+
const roadmapContent = roadmapFile ? await loadFile(roadmapFile) : null;
|
|
134
|
+
if (!roadmapContent) return null;
|
|
135
|
+
|
|
136
|
+
const roadmap = parseRoadmap(roadmapContent);
|
|
137
|
+
for (const slice of roadmap.slices.filter(s => s.done)) {
|
|
138
|
+
const resultFile = resolveSliceFile(basePath, mid, slice.id, "UAT-RESULT");
|
|
139
|
+
if (!resultFile) continue;
|
|
140
|
+
const content = await loadFile(resultFile);
|
|
141
|
+
if (!content) continue;
|
|
142
|
+
const verdictMatch = content.match(/verdict:\s*([\w-]+)/i);
|
|
143
|
+
const verdict = verdictMatch?.[1]?.toLowerCase();
|
|
144
|
+
if (verdict && verdict !== "pass" && verdict !== "passed") {
|
|
145
|
+
return {
|
|
146
|
+
action: "stop" as const,
|
|
147
|
+
reason: `UAT verdict for ${slice.id} is "${verdict}" — blocking progression until resolved.\nReview the UAT result and update the verdict to PASS, or re-run /gsd auto after fixing.`,
|
|
148
|
+
level: "warning" as const,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return null;
|
|
153
|
+
},
|
|
154
|
+
},
|
|
126
155
|
{
|
|
127
156
|
name: "reassess-roadmap (post-completion)",
|
|
128
157
|
match: async ({ state, mid, midTitle, basePath, prefs }) => {
|
|
129
|
-
//
|
|
130
|
-
if (prefs?.phases?.
|
|
158
|
+
// Reassess is opt-in: only fire when explicitly enabled
|
|
159
|
+
if (!prefs?.phases?.reassess_after_slice) return null;
|
|
131
160
|
const needsReassess = await checkNeedsReassessment(basePath, mid, state);
|
|
132
161
|
if (!needsReassess) return null;
|
|
133
162
|
return {
|
|
@@ -37,7 +37,6 @@ import { resolveAutoSupervisorConfig, loadEffectiveGSDPreferences } from "./pref
|
|
|
37
37
|
import { runGSDDoctor, rebuildState, summarizeDoctorIssues } from "./doctor.js";
|
|
38
38
|
import { COMPLETION_TRANSITION_CODES } from "./doctor-types.js";
|
|
39
39
|
import { recordHealthSnapshot, checkHealEscalation } from "./doctor-proactive.js";
|
|
40
|
-
import { syncStateToProjectRoot } from "./auto-worktree-sync.js";
|
|
41
40
|
import { resetRewriteCircuitBreaker } from "./auto-dispatch.js";
|
|
42
41
|
import { isDbAvailable } from "./gsd-db.js";
|
|
43
42
|
import { consumeSignal } from "./session-status-io.js";
|
|
@@ -213,15 +212,6 @@ export async function postUnitPreVerification(pctx: PostUnitContext): Promise<"d
|
|
|
213
212
|
// Non-fatal
|
|
214
213
|
}
|
|
215
214
|
|
|
216
|
-
// Sync worktree state back to project root
|
|
217
|
-
if (s.originalBasePath && s.originalBasePath !== s.basePath) {
|
|
218
|
-
try {
|
|
219
|
-
syncStateToProjectRoot(s.basePath, s.originalBasePath, s.currentMilestoneId);
|
|
220
|
-
} catch {
|
|
221
|
-
// Non-fatal
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
|
|
225
215
|
// Rewrite-docs completion
|
|
226
216
|
if (s.currentUnit.type === "rewrite-docs") {
|
|
227
217
|
try {
|
|
@@ -331,6 +321,45 @@ export async function postUnitPostVerification(pctx: PostUnitContext): Promise<"
|
|
|
331
321
|
}
|
|
332
322
|
}
|
|
333
323
|
|
|
324
|
+
// ── Mechanical completion (ADR-003) ──
|
|
325
|
+
// After task execution, attempt mechanical slice and milestone completion
|
|
326
|
+
// instead of dispatching LLM sessions for complete-slice / validate-milestone.
|
|
327
|
+
if (s.currentUnit?.type === "execute-task" && !s.stepMode) {
|
|
328
|
+
try {
|
|
329
|
+
const [mid, sid] = s.currentUnit.id.split("/");
|
|
330
|
+
if (mid && sid) {
|
|
331
|
+
const state = await deriveState(s.basePath);
|
|
332
|
+
if (state.phase === "summarizing" && state.activeSlice?.id === sid) {
|
|
333
|
+
const { mechanicalSliceCompletion } = await import("./mechanical-completion.js");
|
|
334
|
+
const ok = await mechanicalSliceCompletion(s.basePath, mid, sid);
|
|
335
|
+
if (ok) {
|
|
336
|
+
invalidateAllCaches();
|
|
337
|
+
autoCommitCurrentBranch(s.basePath, "mechanical-completion", `${mid}/${sid}`);
|
|
338
|
+
ctx.ui.notify(`Mechanical completion: ${sid} summary + roadmap updated.`, "info");
|
|
339
|
+
|
|
340
|
+
// Re-derive state — check if milestone is now ready for validation
|
|
341
|
+
invalidateAllCaches();
|
|
342
|
+
const postSliceState = await deriveState(s.basePath);
|
|
343
|
+
if (postSliceState.phase === "validating-milestone" || postSliceState.phase === "completing-milestone") {
|
|
344
|
+
const { aggregateMilestoneVerification, generateMilestoneSummary } = await import("./mechanical-completion.js");
|
|
345
|
+
const validation = await aggregateMilestoneVerification(s.basePath, mid);
|
|
346
|
+
if (validation.verdict !== "failed") {
|
|
347
|
+
await generateMilestoneSummary(s.basePath, mid);
|
|
348
|
+
invalidateAllCaches();
|
|
349
|
+
autoCommitCurrentBranch(s.basePath, "mechanical-milestone-completion", mid);
|
|
350
|
+
ctx.ui.notify(`Mechanical completion: ${mid} validation + summary written.`, "info");
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
// If !ok, summarizing phase persists → dispatch rule fires as LLM fallback
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
} catch (err) {
|
|
358
|
+
process.stderr.write(`gsd-mechanical: completion failed: ${(err as Error).message}\n`);
|
|
359
|
+
// Non-fatal — fall through to normal dispatch
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
|
|
334
363
|
// ── Post-unit hooks ──
|
|
335
364
|
if (s.currentUnit && !s.stepMode) {
|
|
336
365
|
const hookUnit = checkPostUnitHooks(s.currentUnit.type, s.currentUnit.id, s.basePath);
|