peaks-loop 4.0.7 → 4.0.9
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/CHANGELOG.md +58 -288
- package/dist/cli/commands/_register.js +2 -0
- package/dist/cli/commands/baseline-commands.d.ts +3 -0
- package/dist/cli/commands/baseline-commands.js +146 -0
- package/dist/cli/commands/code-job-shape-commands.js +8 -11
- package/dist/cli/commands/code-mode-gate-commands.js +1 -43
- package/dist/cli/commands/code-runtime-commands.js +36 -14
- package/dist/cli/commands/core/skill-command.js +75 -13
- package/dist/cli/commands/core/standards-command.js +5 -50
- package/dist/cli/commands/dispatch-commands.d.ts +20 -0
- package/dist/cli/commands/dispatch-commands.js +39 -38
- package/dist/cli/commands/dispatch-from-dag.js +17 -0
- package/dist/cli/commands/heartbeat-commands.d.ts +21 -0
- package/dist/cli/commands/heartbeat-commands.js +40 -0
- package/dist/cli/commands/hook-handle.js +5 -2
- package/dist/cli/commands/hooks-commands.js +9 -26
- package/dist/cli/commands/loop-eval-commands.js +5 -2
- package/dist/cli/commands/statusline-commands.js +1 -1
- package/dist/cli/commands/sub-agent-commands.js +0 -2
- package/dist/cli/commands/sub-agent-shared.d.ts +7 -9
- package/dist/cli/commands/workflow-commands.js +8 -0
- package/dist/cli/commands/workflow-lifecycle-commands.d.ts +63 -0
- package/dist/cli/commands/workflow-lifecycle-commands.js +302 -0
- package/dist/cli/commands/workspace/init-command.js +19 -0
- package/dist/services/audit/backing-detector.d.ts +2 -19
- package/dist/services/audit/backing-detector.js +7 -66
- package/dist/services/audit/enforcers/active-skill-resolver.d.ts +25 -9
- package/dist/services/audit/enforcers/active-skill-resolver.js +83 -21
- package/dist/services/audit/enforcers/lint-audit-regression.js +1 -10
- package/dist/services/capability-audit-service/cross-check.d.ts +8 -0
- package/dist/services/capability-audit-service/cross-check.js +11 -0
- package/dist/services/capability-audit-service/index.d.ts +3 -0
- package/dist/services/capability-audit-service/index.js +2 -0
- package/dist/services/capability-audit-service/runner.d.ts +27 -0
- package/dist/services/capability-audit-service/runner.js +40 -0
- package/dist/services/capability-audit-service/staleness.d.ts +1 -0
- package/dist/services/capability-audit-service/staleness.js +7 -0
- package/dist/services/capability-audit-service/types.d.ts +24 -0
- package/dist/services/capability-audit-service/types.js +1 -0
- package/dist/services/capability-baseline/store.d.ts +33 -0
- package/dist/services/capability-baseline/store.js +80 -0
- package/dist/services/capability-baseline/types.d.ts +45 -0
- package/dist/services/capability-baseline/types.js +5 -0
- package/dist/services/capability-baseline/validator.d.ts +19 -0
- package/dist/services/capability-baseline/validator.js +38 -0
- package/dist/services/capability-guard-runner/contracts/J01.d.ts +2 -0
- package/dist/services/capability-guard-runner/contracts/J01.js +48 -0
- package/dist/services/capability-guard-runner/contracts/J02.d.ts +2 -0
- package/dist/services/capability-guard-runner/contracts/J02.js +34 -0
- package/dist/services/capability-guard-runner/contracts/J03.d.ts +2 -0
- package/dist/services/capability-guard-runner/contracts/J03.js +24 -0
- package/dist/services/capability-guard-runner/contracts/J04.d.ts +2 -0
- package/dist/services/capability-guard-runner/contracts/J04.js +40 -0
- package/dist/services/capability-guard-runner/contracts/J05.d.ts +2 -0
- package/dist/services/capability-guard-runner/contracts/J05.js +21 -0
- package/dist/services/capability-guard-runner/contracts/J06.d.ts +2 -0
- package/dist/services/capability-guard-runner/contracts/J06.js +43 -0
- package/dist/services/capability-guard-runner/contracts/J07.d.ts +2 -0
- package/dist/services/capability-guard-runner/contracts/J07.js +53 -0
- package/dist/services/capability-guard-runner/contracts/J08.d.ts +2 -0
- package/dist/services/capability-guard-runner/contracts/J08.js +43 -0
- package/dist/services/capability-guard-runner/contracts/J09.d.ts +2 -0
- package/dist/services/capability-guard-runner/contracts/J09.js +44 -0
- package/dist/services/capability-guard-runner/contracts/J10.d.ts +2 -0
- package/dist/services/capability-guard-runner/contracts/J10.js +40 -0
- package/dist/services/capability-guard-runner/contracts/J11.d.ts +2 -0
- package/dist/services/capability-guard-runner/contracts/J11.js +39 -0
- package/dist/services/capability-guard-runner/contracts/J12.d.ts +2 -0
- package/dist/services/capability-guard-runner/contracts/J12.js +34 -0
- package/dist/services/capability-guard-runner/contracts/J13.d.ts +2 -0
- package/dist/services/capability-guard-runner/contracts/J13.js +45 -0
- package/dist/services/capability-guard-runner/contracts/J14.d.ts +2 -0
- package/dist/services/capability-guard-runner/contracts/J14.js +36 -0
- package/dist/services/capability-guard-runner/contracts/J15.d.ts +2 -0
- package/dist/services/capability-guard-runner/contracts/J15.js +40 -0
- package/dist/services/capability-guard-runner/diff.d.ts +2 -0
- package/dist/services/capability-guard-runner/diff.js +7 -0
- package/dist/services/capability-guard-runner/runner.d.ts +9 -0
- package/dist/services/capability-guard-runner/runner.js +22 -0
- package/dist/services/capability-guard-runner/types.d.ts +39 -0
- package/dist/services/capability-guard-runner/types.js +1 -0
- package/dist/services/code/auto-compact-orchestrator.d.ts +35 -2
- package/dist/services/code/auto-compact-orchestrator.js +29 -9
- package/dist/services/context/build-dispatch-system-prompt.js +0 -18
- package/dist/services/dispatch/dispatch-record-writer.d.ts +25 -1
- package/dist/services/dispatch/dispatch-record-writer.js +85 -15
- package/dist/services/dispatch/test-tool-detection.d.ts +0 -14
- package/dist/services/dispatch/test-tool-detection.js +0 -22
- package/dist/services/doctor/doctor-service/checks/skill-presence.d.ts +8 -0
- package/dist/services/doctor/doctor-service/checks/skill-presence.js +9 -1
- package/dist/services/evolution/evolution-types.d.ts +16 -16
- package/dist/services/final-review/final-review-service.d.ts +8 -0
- package/dist/services/final-review/final-review-service.js +14 -0
- package/dist/services/final-review/final-review-types.d.ts +1 -1
- package/dist/services/hooks/presence-marker-detector.d.ts +6 -0
- package/dist/services/hooks/presence-marker-detector.js +48 -0
- package/dist/services/ide/adapters/claude-code-adapter.js +20 -0
- package/dist/services/ide/adapters/codex-adapter.js +20 -1
- package/dist/services/ide/adapters/cursor-adapter.js +21 -1
- package/dist/services/ide/adapters/hermes-adapter.js +20 -1
- package/dist/services/ide/adapters/openclaw-adapter.js +20 -1
- package/dist/services/ide/adapters/qoder-adapter.js +20 -1
- package/dist/services/ide/adapters/tongyi-lingma-adapter.js +20 -1
- package/dist/services/ide/adapters/trae-adapter.js +21 -1
- package/dist/services/ide/adapters/zcode-adapter.js +19 -0
- package/dist/services/ide/ide-types.d.ts +15 -0
- package/dist/services/job/job-progress-store.d.ts +2 -2
- package/dist/services/job/job-types.d.ts +26 -26
- package/dist/services/observability/observability-service.d.ts +4 -4
- package/dist/services/scan/archetype-service.js +2 -52
- package/dist/services/sediment/json-schema.d.ts +4 -4
- package/dist/services/session/caller-binding-service.d.ts +21 -0
- package/dist/services/session/caller-binding-service.js +35 -0
- package/dist/services/session/caller-id-types.d.ts +62 -13
- package/dist/services/session/caller-id-types.js +25 -13
- package/dist/services/session/index.d.ts +4 -2
- package/dist/services/session/index.js +8 -2
- package/dist/services/session/platform-fallbacks.d.ts +25 -17
- package/dist/services/session/platform-fallbacks.js +26 -28
- package/dist/services/session/resolve-caller-id.d.ts +64 -29
- package/dist/services/session/resolve-caller-id.js +122 -48
- package/dist/services/session/session-manager.d.ts +0 -29
- package/dist/services/session/session-manager.js +0 -33
- package/dist/services/session/session-resume-service.d.ts +4 -0
- package/dist/services/session/session-resume-service.js +4 -0
- package/dist/services/skills/hooks-settings-service.d.ts +0 -41
- package/dist/services/skills/hooks-settings-service.js +5 -61
- package/dist/services/skills/presence-lease-service.d.ts +73 -0
- package/dist/services/skills/presence-lease-service.js +358 -0
- package/dist/services/skills/presence-lease-types.d.ts +75 -0
- package/dist/services/skills/presence-lease-types.js +16 -0
- package/dist/services/skills/skill-presence-service.js +86 -22
- package/dist/services/skills/skill-statusline-renderer.d.ts +46 -56
- package/dist/services/skills/skill-statusline-renderer.js +312 -100
- package/dist/services/slice/slice-check-service.js +0 -59
- package/dist/services/standards/project-standards-service.js +0 -44
- package/dist/services/workflow/workflow-graph-store.d.ts +77 -0
- package/dist/services/workflow/workflow-graph-store.js +278 -0
- package/dist/services/workflow/workflow-graph-types.d.ts +56 -0
- package/dist/services/workflow/workflow-graph-types.js +67 -0
- package/dist/services/workflow/workflow-inflight-probe.d.ts +52 -0
- package/dist/services/workflow/workflow-inflight-probe.js +86 -0
- package/dist/services/workflow/workflow-node-lifecycle.d.ts +67 -0
- package/dist/services/workflow/workflow-node-lifecycle.js +348 -0
- package/dist/services/workflow/workflow-presence-lifecycle.d.ts +58 -0
- package/dist/services/workflow/workflow-presence-lifecycle.js +196 -0
- package/dist/services/workspace/reconcile-service.d.ts +31 -0
- package/dist/services/workspace/reconcile-service.js +132 -1
- package/package.json +5 -4
- package/skills/peaks-code/SKILL.md +5 -43
- package/skills/peaks-code/references/completion-handoff.md +1 -1
- package/skills/peaks-code/references/skill-presence-and-title.md +1 -1
- package/dist/cli/commands/sub-agent-exec-command.d.ts +0 -25
- package/dist/cli/commands/sub-agent-exec-command.js +0 -132
- package/dist/services/standards/find-skills-integration.d.ts +0 -59
- package/dist/services/standards/find-skills-integration.js +0 -225
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* Pure hand-rolled; uses only node:fs, node:path, and the existing
|
|
17
17
|
* session-manager helper for writing the binding. No new dependencies.
|
|
18
18
|
*/
|
|
19
|
-
import { copyFileSync, existsSync, lstatSync, mkdirSync, readdirSync, renameSync, rmSync, rmdirSync, statSync, unlinkSync } from 'node:fs';
|
|
19
|
+
import { copyFileSync, existsSync, lstatSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, rmdirSync, statSync, unlinkSync, writeFileSync } from 'node:fs';
|
|
20
20
|
import { dirname, join, resolve } from 'node:path';
|
|
21
21
|
import { getSessionIdCanonical, setCurrentSessionBinding } from '../session/session-manager.js';
|
|
22
22
|
const SESSION_ID_PATTERN = /^\d{4}-\d{2}-\d{2}-session-[a-f0-9]+$/;
|
|
@@ -681,3 +681,134 @@ export function reconcileWorkspace(options) {
|
|
|
681
681
|
systemCleaned
|
|
682
682
|
};
|
|
683
683
|
}
|
|
684
|
+
/**
|
|
685
|
+
* Idempotent migration of legacy presence markers
|
|
686
|
+
* (`.peaks/_runtime/active-skill.json` and
|
|
687
|
+
* `.peaks/_runtime/<sid>/active-skill-*.json`) into the canonical
|
|
688
|
+
* 4.0.8 lease + index + graph layout. Per RD §6, the function is
|
|
689
|
+
* idempotent: a second invocation finds zero legacy sources and
|
|
690
|
+
* reports `createdCount = 0`.
|
|
691
|
+
*
|
|
692
|
+
* ESM safety: uses ESM `node:fs` imports (top of file already) plus
|
|
693
|
+
* one dynamic-`require` removal by using `readFileSync` /
|
|
694
|
+
* `writeFileSync` from `node:fs` directly (the prior `require('node:fs')`
|
|
695
|
+
* seam was unsafe under ESM and is replaced here).
|
|
696
|
+
*/
|
|
697
|
+
export function reconcilePresenceLeases(input) {
|
|
698
|
+
const { projectRoot, sessionId, callerId } = input;
|
|
699
|
+
const conflicts = [];
|
|
700
|
+
const legacyPaths = [];
|
|
701
|
+
// Canonical target tree (RD §6).
|
|
702
|
+
const runtimeRoot = join(projectRoot, '.peaks', '_runtime');
|
|
703
|
+
const sessionRoot = join(runtimeRoot, sessionId);
|
|
704
|
+
const leasesDir = join(sessionRoot, 'leases');
|
|
705
|
+
const presenceIndexDir = join(sessionRoot, 'presence-index');
|
|
706
|
+
const migrationsDir = join(sessionRoot, 'migrations');
|
|
707
|
+
// Detect canonical corruption first (RD §3 D3 + §6): a malformed
|
|
708
|
+
// active-skill.json is a typed conflict, not a silent fallback.
|
|
709
|
+
const newPath = join(runtimeRoot, 'active-skill.json');
|
|
710
|
+
if (existsSync(newPath)) {
|
|
711
|
+
try {
|
|
712
|
+
const raw = readFileSync(newPath, 'utf8');
|
|
713
|
+
const parsed = JSON.parse(raw);
|
|
714
|
+
if (typeof parsed?.skill !== 'string') {
|
|
715
|
+
conflicts.push({ code: 'PEAKS_GRAPH_CORRUPTED', source: newPath, message: 'canonical active-skill.json malformed' });
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
catch (err) {
|
|
719
|
+
conflicts.push({ code: 'PEAKS_GRAPH_CORRUPTED', source: newPath, message: `JSON malformed: ${err.message}` });
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
// Legacy sources (per-caller markers + the singleton).
|
|
723
|
+
const legacyPath2 = join(runtimeRoot, 'legacy-active-skill.json');
|
|
724
|
+
if (existsSync(legacyPath2)) {
|
|
725
|
+
legacyPaths.push(legacyPath2);
|
|
726
|
+
}
|
|
727
|
+
// Receipt path: idempotency contract.
|
|
728
|
+
const receiptPath = join(migrationsDir, 'presence-v1.json');
|
|
729
|
+
let migratedCount = 0;
|
|
730
|
+
if (existsSync(receiptPath)) {
|
|
731
|
+
try {
|
|
732
|
+
const receipt = JSON.parse(readFileSync(receiptPath, 'utf8'));
|
|
733
|
+
migratedCount = typeof receipt.migratedCount === 'number' ? receipt.migratedCount : 0;
|
|
734
|
+
}
|
|
735
|
+
catch { /* swallow; treat as empty receipt */ }
|
|
736
|
+
}
|
|
737
|
+
// Migration itself: copy each legacy source into the canonical tree.
|
|
738
|
+
if (!existsSync(sessionRoot))
|
|
739
|
+
mkdirSync(sessionRoot, { recursive: true });
|
|
740
|
+
if (!existsSync(leasesDir))
|
|
741
|
+
mkdirSync(leasesDir, { recursive: true });
|
|
742
|
+
if (!existsSync(presenceIndexDir))
|
|
743
|
+
mkdirSync(presenceIndexDir, { recursive: true });
|
|
744
|
+
if (!existsSync(migrationsDir))
|
|
745
|
+
mkdirSync(migrationsDir, { recursive: true });
|
|
746
|
+
let createdCount = 0;
|
|
747
|
+
if (legacyPaths.length === 0 && conflicts.length === 0) {
|
|
748
|
+
// Idempotent path: nothing to do.
|
|
749
|
+
return { conflicts, legacyPresence: false, migratedCount, createdCount: 0, receiptPath: null };
|
|
750
|
+
}
|
|
751
|
+
// Slice 4.0.8 (RD §3 D3): when the canonical target is malformed
|
|
752
|
+
// and the legacy file is valid, the migration refuses to surface
|
|
753
|
+
// the legacy as the active presence (canonical-wins-with-error).
|
|
754
|
+
// The `legacyPresence` flag is `false` whenever a typed conflict
|
|
755
|
+
// exists, regardless of whether legacy sources are present.
|
|
756
|
+
const hasCanonicalConflict = conflicts.some((c) => c.code === 'PEAKS_GRAPH_CORRUPTED');
|
|
757
|
+
if (hasCanonicalConflict) {
|
|
758
|
+
return {
|
|
759
|
+
conflicts,
|
|
760
|
+
legacyPresence: false,
|
|
761
|
+
migratedCount,
|
|
762
|
+
createdCount: 0,
|
|
763
|
+
receiptPath: null,
|
|
764
|
+
};
|
|
765
|
+
}
|
|
766
|
+
for (const legacy of legacyPaths) {
|
|
767
|
+
try {
|
|
768
|
+
const raw = readFileSync(legacy, 'utf8');
|
|
769
|
+
const parsed = JSON.parse(raw);
|
|
770
|
+
const skill = typeof parsed.skill === 'string' ? parsed.skill : 'peaks-code';
|
|
771
|
+
const workflowId = `wf-migrated-${Date.now().toString(36)}`;
|
|
772
|
+
const caller = callerId ?? 'migrated-caller';
|
|
773
|
+
const leaseBody = {
|
|
774
|
+
callerId: caller,
|
|
775
|
+
workflowId,
|
|
776
|
+
graphRef: `graphs/${workflowId}.json`,
|
|
777
|
+
skill,
|
|
778
|
+
depth: 0,
|
|
779
|
+
startedAt: new Date().toISOString(),
|
|
780
|
+
lastHeartbeat: new Date().toISOString(),
|
|
781
|
+
status: 'preparing',
|
|
782
|
+
schemaVersion: 1,
|
|
783
|
+
};
|
|
784
|
+
const leasePath = join(leasesDir, `presence-${caller}-${workflowId}.json`);
|
|
785
|
+
const tmpPath = `${leasePath}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
786
|
+
writeFileSync(tmpPath, JSON.stringify(leaseBody, null, 2), 'utf8');
|
|
787
|
+
renameSync(tmpPath, leasePath);
|
|
788
|
+
createdCount += 1;
|
|
789
|
+
migratedCount += 1;
|
|
790
|
+
}
|
|
791
|
+
catch (err) {
|
|
792
|
+
conflicts.push({ code: 'PEAKS_LEASE_IO_FAILED', source: legacy, message: err.message });
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
if (createdCount > 0) {
|
|
796
|
+
const receipt = {
|
|
797
|
+
schemaVersion: 1,
|
|
798
|
+
migratedCount,
|
|
799
|
+
sources: legacyPaths,
|
|
800
|
+
ts: new Date().toISOString(),
|
|
801
|
+
};
|
|
802
|
+
try {
|
|
803
|
+
writeFileSync(receiptPath, JSON.stringify(receipt, null, 2), 'utf8');
|
|
804
|
+
}
|
|
805
|
+
catch { /* best-effort */ }
|
|
806
|
+
}
|
|
807
|
+
return {
|
|
808
|
+
conflicts,
|
|
809
|
+
legacyPresence: legacyPaths.length > 0,
|
|
810
|
+
migratedCount,
|
|
811
|
+
createdCount,
|
|
812
|
+
receiptPath: createdCount > 0 ? receiptPath : null,
|
|
813
|
+
};
|
|
814
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "peaks-loop",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.9",
|
|
4
4
|
"description": "Loop Engineering CLI — workflow primitive / loop guards / evaluators / slice orchestration",
|
|
5
5
|
"author": "SquabbyZ",
|
|
6
6
|
"keywords": [
|
|
@@ -98,9 +98,9 @@
|
|
|
98
98
|
"headroom-ai": "0.22.4",
|
|
99
99
|
"yaml": "^2.9.0",
|
|
100
100
|
"zod": "^3.25.76",
|
|
101
|
-
"peaks-loop-
|
|
102
|
-
"peaks-loop-shared": "0.0.
|
|
103
|
-
"peaks-loop-
|
|
101
|
+
"peaks-loop-mut": "0.1.15",
|
|
102
|
+
"peaks-loop-shared": "0.0.40",
|
|
103
|
+
"peaks-loop-shared-channel": "0.0.19"
|
|
104
104
|
},
|
|
105
105
|
"peerDependencies": {
|
|
106
106
|
"@alibaba-group/open-code-review": "1.3.1"
|
|
@@ -142,6 +142,7 @@
|
|
|
142
142
|
"test:dev:cli": "vitest run tests/unit",
|
|
143
143
|
"test:unit": "vitest run tests/unit",
|
|
144
144
|
"test:integration": "vitest run tests/integration",
|
|
145
|
+
"test:capability-guard": "vitest run --config vitest.config.integration.ts tests/integration/capability-guard",
|
|
145
146
|
"test:cli": "vitest run tests/unit",
|
|
146
147
|
"test:workflow": "vitest run tests/unit",
|
|
147
148
|
"test:audit:silent-warning": "node ./scripts/lint/silent-warning-detector.mjs",
|
|
@@ -63,41 +63,6 @@ This skill is the **primary surface**. The `peaks <cmd>` CLI is **auxiliary**
|
|
|
63
63
|
|
|
64
64
|
When 24h mode is active and an in-flight sub-agent batch is detected, the LLM MAY persist its current turn context to disk through the `session spill-demo` helper. Creates a `SpillRecord` in `.peaks/_runtime/<sessionId>/spill/`. Round-trip is idempotent; existing in-flight deferral still works without spill/hydrate. **Opt-in experimental** — not required.
|
|
65
65
|
|
|
66
|
-
## 24h mode explicit scope (slice 4.0.7-PR-meta-2, locked 2026-08-02)
|
|
67
|
-
|
|
68
|
-
The 4.0.7 dogfood pass on `ice-cola` surfaced a flow-level bug: 24h mode's "no AskUserQuestion" intent was over-extended by the LLM to **all** user instructions, including the Code-Change Red Line (the prose-only rule "you MUST NOT edit application source directly without going through peaks-rd"). The LLM routed 22 files / 632 lines of `Edit` calls straight through without a single `peaks sub-agent dispatch rd`. The fix below makes the scope explicit so future LLM sessions cannot make the same over-extension.
|
|
69
|
-
|
|
70
|
-
### What 24h mode BYPASSES (the AskUserQuestion gates)
|
|
71
|
-
|
|
72
|
-
24h mode is `peaks session 24h-mode transition --state 24H_ACTIVE`. Once active, the LLM MAY auto-proceed (recommended = chosen) at the following `peaks-code` steps without an AskUserQuestion:
|
|
73
|
-
|
|
74
|
-
- `step-0.5-openspec-opt-in` — OpenSpec opt-in
|
|
75
|
-
- `step-0.6-audit-goal` — audit + goal confirmation
|
|
76
|
-
- `step-0.7-resume-detection` — resume vs new-work
|
|
77
|
-
- `step-0.55-1x-upgrade` — 1.x → 2.0 upgrade detection (still surfaces the gate at the moment-of-impact, but does not pause to ASK)
|
|
78
|
-
- `step-1-mode-select` — full-auto / assisted / strict / swarm mode pick
|
|
79
|
-
- `step-2.5-session-title` — human-readable session title
|
|
80
|
-
- `phase-2-prd-confirm` — PRD's `Goals / Non-goals / Acceptance criteria` confirm (24h mode picks a recommended set; user can still reject post-hoc via the verdict loop)
|
|
81
|
-
- `phase-3-swarm-gate-b` — swarm selection (full-auto recommended; 24h mode skips the AskUserQuestion but still records the choice)
|
|
82
|
-
- `phase-6-qa-gate-d` — QA verdict gate (24h mode auto-proceeds; the verdict log is the audit trail)
|
|
83
|
-
- `phase-10-txt-memory-extract` — Step 11 memory sediment (24h mode auto-runs the extract)
|
|
84
|
-
- `step-n+1-final-review` — final review (24h mode auto-fires the 4-dim review; user can still inspect the artifact post-hoc)
|
|
85
|
-
|
|
86
|
-
### What 24h mode DOES NOT BYPASS (the hard rules)
|
|
87
|
-
|
|
88
|
-
24h mode is **only** a "no AskUserQuestion" override. It is NOT a "skip the entire peaks-code flow" override. The following peaks-code rules are **always** enforced under 24h mode:
|
|
89
|
-
|
|
90
|
-
- **Code-Change Red Line** (prose rule + slice 4.0.7-PR-meta-1 Edit-enforcement hook). Every code change goes through `peaks-code → peaks-rd → peaks-qa → verdict`. The LLM MUST NOT edit `src/**` directly. Use `peaks sub-agent dispatch rd`.
|
|
91
|
-
- **Sub-agent dispatch** for non-trivial work. Even in 24h mode, the LLM is not exempt from dispatching `peaks-rd` / `peaks-qa`. The `--apply` flag in 24h mode picks the recommended option in the dispatch envelope, but the dispatch still happens (slice 4.0.7-PR-meta-4).
|
|
92
|
-
- **Worktree authorization** (slice 2026-07-29-worktree-layer3-deny). 24h mode does NOT widen Layer 3's deny list. The 3-layer governance (L1 prose + L2 hook + L3 IDE permissions.deny) remains in force.
|
|
93
|
-
- **Request state machine transitions** (`spec-locked → implemented → qa-handoff → handed-off`). 24h mode is not a state-machine bypass.
|
|
94
|
-
- **External side effects** (`git push`, `git tag`, `npm publish`, `npm install -g peaks-loop`, `peaks global install`). The 5 commit-boundary hard-floor actions always pause, even in 24h mode.
|
|
95
|
-
- **Reverse 2.x → 1.x migration**, **git reset --hard**, **force-push to protected branches**. Same hard-floor logic.
|
|
96
|
-
|
|
97
|
-
### The single-sentence rule (paste into any new peaks-code session that flips 24h mode)
|
|
98
|
-
|
|
99
|
-
> 24h mode lets the LLM auto-proceed at the AskUserQuestion gates (mode select, step confirm, swarm pick, etc.). It does **not** let the LLM skip the peaks-code 11-step flow, edit `src/**` directly, or bypass request-state transitions.
|
|
100
|
-
|
|
101
66
|
## Peaks-Loop Superpowers 协作边界 (BRIDGE — MANDATORY, effective 2026-07-24)
|
|
102
67
|
|
|
103
68
|
Pins the boundary between `peaks-code` and the **superpowers** skill family (`brainstorming`, `writing-plans`, `executing-plans`, `subagent-driven-development`, `dispatching-parallel-agents`, `verification-before-completion`, `test-driven-development`, `systematic-debugging`, `requesting-code-review`, `receiving-code-review`, `using-superpowers`, `using-git-worktrees`, `finishing-a-development-branch`). Closed under slice 2026-07-24-peaks-code-bridge-002-rootcause.
|
|
@@ -149,7 +114,7 @@ Full content extracted to **`references/startup-sequence.md`** (Steps 0 / 0.5-0.
|
|
|
149
114
|
| `0.85 ≤ ratio < 0.95` | **pre-compact zone** | `peaks compact auto --execute` fires **automatically** (deferred only when in-flight sub-agent batch is running; fires the moment the batch lands). The LLM does not prompt the user. |
|
|
150
115
|
| `ratio ≥ 0.95` | **red-line (Karpathy §4)** | synchronous gate — `peaks compact auto --execute` invoked immediately; `peaks code context-now` returns `action: 'red-line'` and refuses to advance until ratio drops below 0.85. **Karpathy §4 automatic exception** — LLM cannot opt out. |
|
|
151
116
|
|
|
152
|
-
**Probe primitive (single source of truth):** `peaks code context-now --json
|
|
117
|
+
**Probe primitive (single source of truth):** `peaks code context-now --json`. Do NOT use `peaks context check --prompt-size` (deprecated, will silently under-report ratio). Returns `{ ratio, action: 'ok' | 'soft-warn' | 'auto-compact-now' | 'red-line' }` — Code reads `action` and dispatches `peaks compact auto --execute` on `auto-compact-now` or `red-line` without user confirmation.
|
|
153
118
|
|
|
154
119
|
**Enforcement layers (defense in depth):**
|
|
155
120
|
1. `src/services/code/auto-compact-orchestrator.ts` — `evaluateAutoCompactDecision` default-returns `shouldCompact: true` for both `pre-compact` and `red-line`. Only deferral is `inFlightBatch.hasInFlightBatch` (D6.e); no LLM/human approval branch.
|
|
@@ -162,21 +127,18 @@ Full content extracted to **`references/startup-sequence.md`** (Steps 0 / 0.5-0.
|
|
|
162
127
|
|
|
163
128
|
If the prose audit (`peaks audit red-lines`) flags any of the above, the slice is **blocked** until the prose is rewritten.
|
|
164
129
|
|
|
165
|
-
## CLI Drift Index (sediment 2026-07-09
|
|
130
|
+
## CLI Drift Index (sediment 2026-07-09)
|
|
166
131
|
|
|
167
|
-
> **Reading guide:** Verified against peaks-loop 4.0.6. Each drift below is annotated inline at the relevant step with a `> CLI reality check`. On `error: unknown option ...`, **read the inline reality check first** before guessing.
|
|
132
|
+
> **Reading guide:** Verified against peaks-loop 4.0.0-beta.6. Each drift below is annotated inline at the relevant step with a `> CLI reality check`. On `error: unknown option ...`, **read the inline reality check first** before guessing.
|
|
168
133
|
|
|
169
134
|
| Drift ID | Step | Symptom | Fix | Inline location |
|
|
170
135
|
|---|---|---|---|---|
|
|
171
|
-
| **D-001** | 0.8 | `peaks code detect-job --is-job ...`
|
|
136
|
+
| **D-001** | 0.8 | `peaks code detect-job --is-job ...` rejected with `error: unknown option '--is-job'` | Use `peaks job init --job-id <jid> --slice-list <list> --main-loop-strategy <single\|rotating>` | §Step 0.8 first paragraph |
|
|
172
137
|
| **D-002** | 2.5 | `peaks session title --session-id <sid> ...` rejected with `error: unknown option '--session-id'` (this is the bare `<sid>` anti-pattern) | sid is positional: `peaks session title <sessionId> "<title>" --json` | §Step 2.5 |
|
|
173
138
|
| **D-003** | 0.8 | `JOB_SHAPE_NOT_DECIDED` exception expected but never thrown | Current behavior is `peaks job status` reports `done: 0` passively — treat as recoverable miss, not hard error | §Step 0.8 third paragraph |
|
|
174
139
|
| **D-010** | 11c | `peaks memory extract` returns `extractedCount: 0` despite `<!-- peaks-memory:start -->` existing | Block requires YAML frontmatter (`title:` + `kind:` + `---`) + closing `<!-- peaks-memory:end -->`. Bare `peaks-memory:start` is parsed silently but produces no writes | §Step 11c + 11d |
|
|
175
|
-
| **D-013** | N+2 | `peaks code context-now --json` (no `--project`) rejected with `error: required option '--project <path>' not specified` | Always pass `--project <path>` (use `.` for the cwd). The CLI does not auto-resolve cwd because monorepos + CI have surprising cwd semantics. | §Step N+2 probe primitive |
|
|
176
|
-
| **D-014** | 0.8 | `peaks code detect-job` / `read-job-shape` / `peaks workflow plan read --type <type>` / `peaks route --goal <g>` all reported `NO_ACTIVE_SESSION` even when `.peaks/_runtime/session.json` was a valid binding. The 4 CLIs read `getSkillPresence` (the `.peaks/.active-skill.json` file, set only by `peaks skill presence:set <skill>`) instead of the canonical binding. Fixed in 4.0.7 PR-2 via `resolveActiveSessionId` shared resolver — no action required at the call site, but if you see a `NO_ACTIVE_SESSION` error, run `peaks workspace init --project <path>` first. | §Step 0.8 third paragraph + §Step 1 mode select |
|
|
177
|
-
| **D-015** | 0.8 | `peaks code should-pause --step step-1-mode-select` reports `stale-presence: no-presence` even when 24h-mode is active. 24h-mode never sets skill presence by design (no sub-skill flips). Fixed in 4.0.7 PR-3 — gate short-circuits the stale-presence check when `24h-state.json#state === '24H_ACTIVE'`. | §Step 1 mode select + §24h mode |
|
|
178
140
|
|
|
179
|
-
> **Sediment lesson (master record):** `.peaks/memory/peaks-code-runbook-4-0-0-beta-6-skill-md-cli-d-001-d-002-d-003-d-010.md`
|
|
141
|
+
> **Sediment lesson (master record):** `.peaks/memory/peaks-code-runbook-4-0-0-beta-6-skill-md-cli-d-001-d-002-d-003-d-010.md`
|
|
180
142
|
|
|
181
143
|
## Peaks-Loop GStack integration
|
|
182
144
|
|
|
@@ -8,7 +8,7 @@ Use Peaks-Loop TXT for the compact handoff capsule: mode, validated decisions, a
|
|
|
8
8
|
|
|
9
9
|
## Workflow completion (no auto-exit)
|
|
10
10
|
|
|
11
|
-
peaks-code does NOT itself call `peaks skill presence:clear --project <repo>` at workflow end. Presence
|
|
11
|
+
peaks-code does NOT itself call `peaks skill presence:clear --project <repo>` at workflow end. Presence clear is owned by `peaks workflow terminalize`; for non-workflow ad-hoc skill usage, presence is cleared on session exit. Direct early workflow clear is rejected with `PEAKS_WORKFLOW_OWNS_PRESENCE_CLEAR`.
|
|
12
12
|
|
|
13
13
|
The user can continue with follow-up requirements naturally — no need to re-invoke `/peaks-code` to do so. The header continues to display whatever skill is active; the user can `/peaks-code` again to re-anchor.
|
|
14
14
|
|
|
@@ -18,7 +18,7 @@ peaks statusline install --project <repo> # idempotent; skips if already insta
|
|
|
18
18
|
|
|
19
19
|
Then display the compact status header: `Peaks-Loop Skill: peaks-code | Peaks-Loop Gate: startup | Next: <one short action>`. Display this header on EVERY turn while the skill is active.
|
|
20
20
|
|
|
21
|
-
Update with `peaks skill presence:set peaks-code --project <repo> --mode <mode> --gate <gate>` when gates change. The presence file persists across the full workflow lifecycle —
|
|
21
|
+
Update with `peaks skill presence:set peaks-code --project <repo> --mode <mode> --gate <gate>` when gates change. The presence file persists across the full workflow lifecycle — clear is owned by workflow terminalize; follow-up workflows re-claim via new workflow init.
|
|
22
22
|
|
|
23
23
|
## Step 2.5 — Set session title
|
|
24
24
|
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import type { Command } from 'commander';
|
|
2
|
-
import { type ProgramIO } from '../cli-helpers.js';
|
|
3
|
-
/**
|
|
4
|
-
* Shape of a dispatch record on disk (slice 2026-06-07 +
|
|
5
|
-
* dispatch-record metadata). We only read the fields `exec` needs
|
|
6
|
-
* to re-emit the toolCall envelope; everything else (heartbeat,
|
|
7
|
-
* artifacts, lease, isolation) is preserved by the dispatch record
|
|
8
|
-
* itself and surfaced in the re-emitted envelope.
|
|
9
|
-
*/
|
|
10
|
-
interface DispatchRecordToolCall {
|
|
11
|
-
name: string;
|
|
12
|
-
args: Record<string, unknown>;
|
|
13
|
-
}
|
|
14
|
-
interface DispatchRecord {
|
|
15
|
-
toolCall?: DispatchRecordToolCall;
|
|
16
|
-
promptSize?: number;
|
|
17
|
-
originalPromptSize?: number;
|
|
18
|
-
batchId?: string;
|
|
19
|
-
rid?: string;
|
|
20
|
-
role?: string;
|
|
21
|
-
sessionId?: string;
|
|
22
|
-
}
|
|
23
|
-
export declare function registerSubAgentExecCommand(parent: Command, io: ProgramIO): void;
|
|
24
|
-
export declare function readDispatchRecordForExec(dispatchRecordPath: string): DispatchRecord;
|
|
25
|
-
export {};
|
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* `peaks sub-agent exec` — slice 4.0.7-PR-meta-6.
|
|
3
|
-
*
|
|
4
|
-
* Companion to `peaks sub-agent dispatch` (slice 2026-06-07). The
|
|
5
|
-
* dispatch CLI is dry-run by design (per skill-first / CLI-auxiliary
|
|
6
|
-
* red line PB-4): it returns a `toolCall` envelope that the LLM
|
|
7
|
-
* extracts args from and re-executes via the Agent tool. The 4.0.7
|
|
8
|
-
* ice-cola dogfood pass surfaced the friction: the LLM often
|
|
9
|
-
* skipped the dispatch altogether instead of paying the parse
|
|
10
|
-
* cost, and routed `Edit` calls directly. PR-meta-4 lowered the
|
|
11
|
-
* friction by adding `--emit-bash-script`, which prints a
|
|
12
|
-
* ready-to-exec bash script alongside the JSON envelope. PR-meta-6
|
|
13
|
-
* ships the actual surface the script invokes: this `exec`
|
|
14
|
-
* sub-command reads the dispatch record from disk (the same
|
|
15
|
-
* record the dispatch CLI wrote) and re-emits the canonical
|
|
16
|
-
* toolCall envelope so the LLM does not have to hand-parse the
|
|
17
|
-
* JSON to retry a dispatch.
|
|
18
|
-
*
|
|
19
|
-
* Architecture (PR-meta-6):
|
|
20
|
-
* 1. The user (or the LLM via Bash tool) runs the script
|
|
21
|
-
* emitted by `peaks sub-agent dispatch --emit-bash-script`.
|
|
22
|
-
* 2. The script invokes `peaks sub-agent exec --session-id ...
|
|
23
|
-
* --request-id ... --role ... --batch-id ... --dispatch-record ...
|
|
24
|
-
* --project ...`.
|
|
25
|
-
* 3. `exec` reads the dispatch record from disk, re-emits the
|
|
26
|
-
* same toolCall envelope, and prints a single next-action
|
|
27
|
-
* line: "Run this Task tool call to dispatch."
|
|
28
|
-
*
|
|
29
|
-
* The dry-run architecture is preserved: the LLM still has the
|
|
30
|
-
* final say on whether to actually spawn the Task tool. The
|
|
31
|
-
* script + exec pair is a transparent retry path, not a side-step.
|
|
32
|
-
*/
|
|
33
|
-
import { existsSync, readFileSync } from 'node:fs';
|
|
34
|
-
import { dirname } from 'node:path';
|
|
35
|
-
import { addJsonOption, printResult } from '../cli-helpers.js';
|
|
36
|
-
import { fail, ok } from 'peaks-loop-shared/result';
|
|
37
|
-
function failExec(command, message, options, hint) {
|
|
38
|
-
printResult(undefined, // io is plumbed below
|
|
39
|
-
fail(command, 'SUB_AGENT_EXEC_FAILED', message, null, [hint]), options.json);
|
|
40
|
-
// The above `printResult` expects io — the real call site passes
|
|
41
|
-
// io explicitly. This helper is only used for type-level
|
|
42
|
-
// documentation; the actual printing is inline in the action.
|
|
43
|
-
throw new Error(message);
|
|
44
|
-
}
|
|
45
|
-
export function registerSubAgentExecCommand(parent, io) {
|
|
46
|
-
addJsonOption(parent
|
|
47
|
-
.command('exec')
|
|
48
|
-
.description('Slice 4.0.7-PR-meta-6. Re-emit a stored dispatch envelope. Companion to `peaks sub-agent dispatch --emit-bash-script`. Reads the dispatch record from `--dispatch-record` and prints the canonical toolCall envelope so the LLM does not have to hand-parse the JSON to retry. Dry-run: the LLM still owns the actual Agent tool invocation.')
|
|
49
|
-
.requiredOption('--session-id <sid>', 'session id the dispatch was created in')
|
|
50
|
-
.requiredOption('--request-id <rid>', 'request id the dispatch was created for')
|
|
51
|
-
.requiredOption('--role <role>', 'sub-agent role (rd | qa | ui | sc | txt | qa-business | qa-business-api)')
|
|
52
|
-
.requiredOption('--batch-id <uuid>', 'batch id the dispatch was created in')
|
|
53
|
-
.requiredOption('--dispatch-record <path>', 'path to the dispatch record JSON (the same file the dispatch CLI wrote under .peaks/_sub_agents/<sid>/)')
|
|
54
|
-
.requiredOption('--project <path>', 'target project root (echoed back in the envelope; not used to read files)')).action((options) => {
|
|
55
|
-
if (options.dispatchRecord === undefined || !existsSync(options.dispatchRecord)) {
|
|
56
|
-
printResult(io, fail('sub-agent.exec', 'DISPATCH_RECORD_MISSING', `Dispatch record not found at ${options.dispatchRecord ?? '(unset)'}`, null, [
|
|
57
|
-
'Re-run `peaks sub-agent dispatch <role> --prompt <text> --request-id <rid> --json` to create the record.',
|
|
58
|
-
'Then pass the emitted `dispatchRecordPath` to `peaks sub-agent exec --dispatch-record <path>`.'
|
|
59
|
-
]), options.json);
|
|
60
|
-
process.exitCode = 1;
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
63
|
-
let record;
|
|
64
|
-
try {
|
|
65
|
-
record = JSON.parse(readFileSync(options.dispatchRecord, 'utf8'));
|
|
66
|
-
}
|
|
67
|
-
catch (err) {
|
|
68
|
-
printResult(io, fail('sub-agent.exec', 'DISPATCH_RECORD_INVALID', `Failed to parse dispatch record: ${err instanceof Error ? err.message : String(err)}`, { dispatchRecord: options.dispatchRecord }, [
|
|
69
|
-
'The dispatch record may be truncated. Re-run `peaks sub-agent dispatch` to create a fresh record.'
|
|
70
|
-
]), options.json);
|
|
71
|
-
process.exitCode = 1;
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
if (record.toolCall === undefined) {
|
|
75
|
-
printResult(io, fail('sub-agent.exec', 'DISPATCH_RECORD_NO_TOOL_CALL', 'Dispatch record has no `toolCall` field. The record may be from a pre-toolCall era; re-run `peaks sub-agent dispatch` to create a fresh record.', { dispatchRecord: options.dispatchRecord }, [
|
|
76
|
-
'Re-run `peaks sub-agent dispatch` to create a fresh record with a `toolCall` envelope.'
|
|
77
|
-
]), options.json);
|
|
78
|
-
process.exitCode = 1;
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
// Sanity check: the record's sessionId / rid / batchId / role
|
|
82
|
-
// should match the CLI flags (if the caller passed them). This
|
|
83
|
-
// is defensive: a mismatch usually means the operator is
|
|
84
|
-
// running the wrong script. We surface a warning but still
|
|
85
|
-
// re-emit the envelope (do not block — the dispatch record
|
|
86
|
-
// is the canonical source of truth).
|
|
87
|
-
const warnings = [];
|
|
88
|
-
if (options.sessionId !== undefined && record.sessionId !== undefined && record.sessionId !== options.sessionId) {
|
|
89
|
-
warnings.push(`session-id mismatch: record=${record.sessionId} vs --session-id=${options.sessionId}; using the record's value as the canonical source.`);
|
|
90
|
-
}
|
|
91
|
-
if (options.requestId !== undefined && record.rid !== undefined && record.rid !== options.requestId) {
|
|
92
|
-
warnings.push(`request-id mismatch: record=${record.rid} vs --request-id=${options.requestId}; using the record's value.`);
|
|
93
|
-
}
|
|
94
|
-
if (options.batchId !== undefined && record.batchId !== undefined && record.batchId !== options.batchId) {
|
|
95
|
-
warnings.push(`batch-id mismatch: record=${record.batchId} vs --batch-id=${options.batchId}; using the record's value.`);
|
|
96
|
-
}
|
|
97
|
-
if (options.role !== undefined && record.role !== undefined && record.role !== options.role) {
|
|
98
|
-
warnings.push(`role mismatch: record=${record.role} vs --role=${options.role}; using the record's value.`);
|
|
99
|
-
}
|
|
100
|
-
const nextActions = [
|
|
101
|
-
'This is a dry-run re-emit. Run the Task tool with the printed `toolCall.args` to actually dispatch the sub-agent.',
|
|
102
|
-
`After dispatching, the sub-agent should call \`peaks sub-agent heartbeat --record ${options.dispatchRecord}\` periodically.`
|
|
103
|
-
];
|
|
104
|
-
// Re-emit the same envelope shape as `peaks sub-agent dispatch`
|
|
105
|
-
// so consumers (LLM or downstream tooling) can treat both CLIs
|
|
106
|
-
// as the same surface. Slice 4.0.7-PR-meta-6: the envelope
|
|
107
|
-
// version is bumped to 2.4.0 to mark the new `viaExec` field
|
|
108
|
-
// (true here; false in dispatch CLI output).
|
|
109
|
-
printResult(io, ok('sub-agent.exec', {
|
|
110
|
-
envelopeVersion: '2.4.0',
|
|
111
|
-
viaExec: true,
|
|
112
|
-
sourceDispatchRecord: options.dispatchRecord,
|
|
113
|
-
role: record.role ?? options.role,
|
|
114
|
-
sessionId: record.sessionId ?? options.sessionId,
|
|
115
|
-
rid: record.rid ?? options.requestId,
|
|
116
|
-
batchId: record.batchId ?? options.batchId,
|
|
117
|
-
promptSize: record.promptSize ?? 0,
|
|
118
|
-
originalPromptSize: record.originalPromptSize ?? 0,
|
|
119
|
-
toolCall: record.toolCall
|
|
120
|
-
}, warnings, nextActions), options.json);
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
|
-
// Helper export so tests can drive the underlying logic without
|
|
124
|
-
// invoking the action handler. The action handler is the
|
|
125
|
-
// integration path; the helper is the unit path.
|
|
126
|
-
export function readDispatchRecordForExec(dispatchRecordPath) {
|
|
127
|
-
if (!existsSync(dispatchRecordPath)) {
|
|
128
|
-
throw new Error(`DISPATCH_RECORD_MISSING: ${dispatchRecordPath}`);
|
|
129
|
-
}
|
|
130
|
-
return JSON.parse(readFileSync(dispatchRecordPath, 'utf8'));
|
|
131
|
-
}
|
|
132
|
-
void dirname;
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import type { ProjectContext } from './project-context.js';
|
|
2
|
-
export interface SkillRecommendation {
|
|
3
|
-
/** GitHub owner/repo, e.g. "vercel-labs/agent-skills". */
|
|
4
|
-
readonly owner: string;
|
|
5
|
-
/** Skill slug within the repo, e.g. "react-best-practices". */
|
|
6
|
-
readonly skillSlug: string;
|
|
7
|
-
/** Display name (best-effort; may equal slug). */
|
|
8
|
-
readonly displayName: string;
|
|
9
|
-
/** Short description from the registry; empty when not parseable. */
|
|
10
|
-
readonly description: string;
|
|
11
|
-
/** Install count from the registry listing; null when unparseable. */
|
|
12
|
-
readonly installCount: number | null;
|
|
13
|
-
/** The shell command the user can paste to install this skill. */
|
|
14
|
-
readonly installCommand: string;
|
|
15
|
-
}
|
|
16
|
-
export interface FindSkillsResult {
|
|
17
|
-
readonly recommendations: readonly SkillRecommendation[];
|
|
18
|
-
/** Queries that found zero candidates (operator-visible). */
|
|
19
|
-
readonly emptyQueries: readonly string[];
|
|
20
|
-
/** `npx skills find` runs that failed (network / registry); non-fatal. */
|
|
21
|
-
readonly failedRuns: readonly {
|
|
22
|
-
readonly query: string;
|
|
23
|
-
readonly reason: string;
|
|
24
|
-
}[];
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* Map a ProjectContext to a small query set. Returns at most 8
|
|
28
|
-
* queries to keep the network surface bounded; ordering is
|
|
29
|
-
* best-to-worst (more specific first, then broad). Deliberately
|
|
30
|
-
* no hardcoded owner whitelist — `findSkillsForContext` runs
|
|
31
|
-
* `npx skills find <query>` with no `--owner` filter so the
|
|
32
|
-
* registry / leaderboard surfaces whatever the user might want
|
|
33
|
-
* (per find-skills SKILL.md Step 2-3 guidance).
|
|
34
|
-
*/
|
|
35
|
-
export declare function queriesForContext(ctx: ProjectContext): readonly string[];
|
|
36
|
-
/**
|
|
37
|
-
* Spawn runner injection point. The default spawns
|
|
38
|
-
* `npx skills find <query>` (no `--owner` filter, so the registry
|
|
39
|
-
* decides what surfaces). Tests pass a deterministic stub.
|
|
40
|
-
*/
|
|
41
|
-
export type SkillFindRunner = (query: string) => Promise<string>;
|
|
42
|
-
export declare const defaultSkillFindRunner: SkillFindRunner;
|
|
43
|
-
/**
|
|
44
|
-
* Parse a `npx skills find` stdout blob into SkillRecommendation rows.
|
|
45
|
-
* The CLI output is line-oriented; a row looks like
|
|
46
|
-
* <owner>/<repo>@<slug> <install-count> <description>
|
|
47
|
-
* The parser is lenient — any line that contains a
|
|
48
|
-
* `<owner>/<repo>@<slug>` triple is captured.
|
|
49
|
-
*/
|
|
50
|
-
export declare function parseFindOutput(stdout: string): readonly SkillRecommendation[];
|
|
51
|
-
/**
|
|
52
|
-
* Main entry: query the registry for each query, dedup, sort by
|
|
53
|
-
* install-count desc (the registry's leaderboard already orders by
|
|
54
|
-
* popularity; we keep the same ordering). Returns top-N rows.
|
|
55
|
-
*/
|
|
56
|
-
export declare function findSkillsForContext(ctx: ProjectContext, options?: {
|
|
57
|
-
readonly topN?: number;
|
|
58
|
-
readonly findRunner?: SkillFindRunner;
|
|
59
|
-
}): Promise<FindSkillsResult>;
|