opencode-matrixx 2.6.11 → 2.6.12
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/agents/architect/default.d.ts +1 -1
- package/dist/agents/architect/gpt.d.ts +1 -1
- package/dist/agents/oracle/plan-template.d.ts +1 -7
- package/dist/agents/oracle/system-prompt.d.ts +1 -1
- package/dist/cli.js +0 -10
- package/dist/config/schema/hooks.d.ts +0 -2
- package/dist/config/schema/matrixx-config.d.ts +0 -7
- package/dist/config/schema.d.ts +0 -1
- package/dist/create-hooks.d.ts +0 -2
- package/dist/features/builtin-commands/templates/evolution.d.ts +1 -1
- package/dist/features/builtin-commands/templates/start-work.d.ts +1 -1
- package/dist/features/evolution/compressor/index.d.ts +2 -2
- package/dist/features/evolution/compressor/interface.d.ts +9 -4
- package/dist/features/evolution/compressor/llm.d.ts +14 -4
- package/dist/features/evolution/evaluator.d.ts +10 -0
- package/dist/features/evolution/pipeline.d.ts +3 -1
- package/dist/features/evolution/schema.d.ts +46 -0
- package/dist/features/evolution/store/budget-ledger.d.ts +46 -0
- package/dist/features/evolution/store/index.d.ts +5 -0
- package/dist/features/evolution/store/lifecycle.d.ts +52 -0
- package/dist/features/evolution/store/project-identity.d.ts +27 -0
- package/dist/features/evolution/store/query.d.ts +23 -0
- package/dist/features/evolution/{store.d.ts → store/trace-store.d.ts} +1 -1
- package/dist/features/evolution/types.d.ts +34 -1
- package/dist/features/evolution/writer-emit.d.ts +17 -0
- package/dist/features/evolution/writer-frontmatter.d.ts +23 -0
- package/dist/features/evolution/writer-supersede.d.ts +20 -0
- package/dist/features/evolution/writer.d.ts +4 -0
- package/dist/features/plan-contract/appendix.d.ts +14 -0
- package/dist/features/plan-contract/constants.d.ts +16 -0
- package/dist/features/plan-contract/front-matter.d.ts +34 -0
- package/dist/features/plan-contract/index.d.ts +14 -0
- package/dist/features/plan-contract/migration.d.ts +36 -0
- package/dist/features/plan-contract/schema.d.ts +32 -0
- package/dist/features/plan-contract/skeleton.d.ts +5 -0
- package/dist/features/plan-contract/types.d.ts +56 -0
- package/dist/features/plan-contract/validate.d.ts +9 -0
- package/dist/features/session-state/state.d.ts +0 -11
- package/dist/hooks/evolution-compressor/host-llm-call.d.ts +17 -0
- package/dist/hooks/index.d.ts +0 -2
- package/dist/hooks/task-continuation-enforcer/constants.d.ts +0 -5
- package/dist/index.js +2875 -1587
- package/dist/matrixx.schema.json +0 -27
- package/dist/plugin/hooks/create-core-hooks.d.ts +0 -2
- package/dist/plugin/hooks/create-session-hooks.d.ts +1 -2
- package/dist/plugin/hooks/create-tool-guard-hooks.d.ts +1 -2
- package/dist/plugin/tool-gating.d.ts +2 -0
- package/dist/tools/evolution/constants.d.ts +24 -0
- package/dist/tools/evolution/index.d.ts +3 -0
- package/dist/tools/evolution/query-actions.d.ts +3 -0
- package/dist/tools/evolution/tools.d.ts +16 -0
- package/dist/tools/evolution/types.d.ts +20 -0
- package/dist/tools/index.d.ts +1 -0
- package/dist/tools/plan/constants.d.ts +1 -0
- package/dist/tools/plan/index.d.ts +1 -0
- package/dist/tools/plan/plan-tasks.d.ts +3 -0
- package/dist/tools/plan/types.d.ts +10 -0
- package/package.json +1 -1
- package/dist/config/schema/failure-counter.d.ts +0 -7
- package/dist/hooks/failure-counter/counter.d.ts +0 -7
- package/dist/hooks/failure-counter/hook.d.ts +0 -18
- package/dist/hooks/failure-counter/index.d.ts +0 -3
- package/dist/hooks/failure-counter/patterns.d.ts +0 -6
- package/dist/hooks/hashline-edit-diff-enhancer/hook.d.ts +0 -28
- package/dist/hooks/hashline-edit-diff-enhancer/index.d.ts +0 -1
- /package/dist/{hooks/failure-counter/counter.test.d.ts → tools/evolution/query-actions.test.d.ts} +0 -0
- /package/dist/{hooks/failure-counter/patterns.test.d.ts → tools/evolution/tools.test.d.ts} +0 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { KnowledgeKind } from "./types";
|
|
3
|
+
/**
|
|
4
|
+
* D5 typed knowledge kinds — DATA schemas (not config knobs).
|
|
5
|
+
*
|
|
6
|
+
* The `KnowledgeKind` union lives in `./types` (single source); this module
|
|
7
|
+
* owns the Zod runtime schema plus the fail-open normalizer used on every
|
|
8
|
+
* read path (LLM output, stored JSON, legacy meta.json without `kind`).
|
|
9
|
+
*/
|
|
10
|
+
export declare const KNOWLEDGE_KINDS: readonly ["workflow", "correction", "debugging_pattern", "gotcha", "convention"];
|
|
11
|
+
export declare const KnowledgeKindSchema: z.ZodEnum<{
|
|
12
|
+
workflow: "workflow";
|
|
13
|
+
correction: "correction";
|
|
14
|
+
debugging_pattern: "debugging_pattern";
|
|
15
|
+
gotcha: "gotcha";
|
|
16
|
+
convention: "convention";
|
|
17
|
+
}>;
|
|
18
|
+
export declare const DEFAULT_KNOWLEDGE_KIND: KnowledgeKind;
|
|
19
|
+
/**
|
|
20
|
+
* Fail-open normalizer: valid kinds pass through, missing/unknown values
|
|
21
|
+
* become `convention` instead of throwing (back-compat for stored JSON).
|
|
22
|
+
*/
|
|
23
|
+
export declare function normalizeKnowledgeKind(value: unknown): KnowledgeKind;
|
|
24
|
+
/** Data-shape schema for distilled knowledge (stored/LLM JSON, not config). */
|
|
25
|
+
export declare const DistilledKnowledgeDataSchema: z.ZodObject<{
|
|
26
|
+
title: z.ZodString;
|
|
27
|
+
summary: z.ZodString;
|
|
28
|
+
patterns: z.ZodArray<z.ZodString>;
|
|
29
|
+
pitfalls: z.ZodArray<z.ZodString>;
|
|
30
|
+
prerequisites: z.ZodArray<z.ZodString>;
|
|
31
|
+
skillDraft: z.ZodOptional<z.ZodString>;
|
|
32
|
+
confidence: z.ZodNumber;
|
|
33
|
+
sourceSessionIDs: z.ZodArray<z.ZodString>;
|
|
34
|
+
kind: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
35
|
+
workflow: "workflow";
|
|
36
|
+
correction: "correction";
|
|
37
|
+
debugging_pattern: "debugging_pattern";
|
|
38
|
+
gotcha: "gotcha";
|
|
39
|
+
convention: "convention";
|
|
40
|
+
}>>>;
|
|
41
|
+
projectId: z.ZodOptional<z.ZodString>;
|
|
42
|
+
sourceTraceIDs: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString>>>;
|
|
43
|
+
distilledAt: z.ZodOptional<z.ZodString>;
|
|
44
|
+
superseded_by: z.ZodOptional<z.ZodString>;
|
|
45
|
+
}, z.core.$strip>;
|
|
46
|
+
export type DistilledKnowledgeData = z.infer<typeof DistilledKnowledgeDataSchema>;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { CompressionUsage } from "../types";
|
|
2
|
+
export declare const BUDGET_FILE = ".matrixx/evolution/budget.json";
|
|
3
|
+
/** Typed capacity breach for the writer's pending queue. */
|
|
4
|
+
export declare class MaxPendingError extends Error {
|
|
5
|
+
readonly pending: number;
|
|
6
|
+
readonly maxPending: number;
|
|
7
|
+
constructor(pending: number, maxPending: number);
|
|
8
|
+
}
|
|
9
|
+
/** One recorded compression charge. */
|
|
10
|
+
export type BudgetEvent = {
|
|
11
|
+
at: string;
|
|
12
|
+
inputTokens: number;
|
|
13
|
+
outputTokens: number;
|
|
14
|
+
costCents: number;
|
|
15
|
+
};
|
|
16
|
+
/** Persisted per-day ledger shape for `.matrixx/evolution/budget.json`. */
|
|
17
|
+
export type BudgetLedger = {
|
|
18
|
+
day: string;
|
|
19
|
+
spendCents: number;
|
|
20
|
+
events: BudgetEvent[];
|
|
21
|
+
};
|
|
22
|
+
/** UTC calendar-day key (`YYYY-MM-DD`) for an instant. Pure. */
|
|
23
|
+
export declare function utcDayKey(at: Date): string;
|
|
24
|
+
/** Absolute ledger path for an evolution dir. */
|
|
25
|
+
export declare function budgetPath(evolutionDir: string): string;
|
|
26
|
+
export declare function emptyLedger(day: string): BudgetLedger;
|
|
27
|
+
/** Reset a ledger when the UTC day rolls over. Pure. */
|
|
28
|
+
export declare function rollLedger(ledger: BudgetLedger, day: string): BudgetLedger;
|
|
29
|
+
/** Include-inclusive cap check for one more charge. Pure. */
|
|
30
|
+
export declare function withinDailyCap(ledger: BudgetLedger, usage: CompressionUsage, maxCostCentsPerDay: number): boolean;
|
|
31
|
+
/** Append a charge to the ledger, rolling the day first. Pure (caller persists). */
|
|
32
|
+
export declare function recordUsage(ledger: BudgetLedger, usage: CompressionUsage, at: Date): BudgetLedger;
|
|
33
|
+
/** True once recorded spend meets or exceeds the daily cap. */
|
|
34
|
+
export declare function isOverDailyCap(ledger: BudgetLedger, maxCostCentsPerDay: number): boolean;
|
|
35
|
+
/** Throw MaxPendingError when the pending queue is full. */
|
|
36
|
+
export declare function checkPendingCapacity(pendingCount: number, maxPending: number): void;
|
|
37
|
+
/** Read the persisted ledger, rolling to `now`'s UTC day; fail-open on any error. */
|
|
38
|
+
export declare function loadLedger(evolutionDir: string, now?: Date): BudgetLedger;
|
|
39
|
+
/** Persist the ledger atomically (tmp + rename), mirroring the repo convention. */
|
|
40
|
+
export declare function saveLedger(evolutionDir: string, ledger: BudgetLedger): void;
|
|
41
|
+
/**
|
|
42
|
+
* Load-modify-write a charge. Not locked across processes: concurrent writers
|
|
43
|
+
* follow last-write-wins (a lost charge is acceptable for a single-process
|
|
44
|
+
* plugin). Sequential callers accumulate correctly.
|
|
45
|
+
*/
|
|
46
|
+
export declare function recordUsageToDisk(evolutionDir: string, usage: CompressionUsage, at?: Date): BudgetLedger;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { KnowledgeKind } from "../types";
|
|
2
|
+
export declare const QUARANTINE_SEGMENT = "quarantine";
|
|
3
|
+
export type ProposalStatus = "pending" | "approved" | "rejected" | "quarantined" | "superseded";
|
|
4
|
+
export type RetrievalMeta = {
|
|
5
|
+
status: ProposalStatus;
|
|
6
|
+
quarantined?: boolean;
|
|
7
|
+
superseded?: boolean;
|
|
8
|
+
projectId?: string;
|
|
9
|
+
kind?: KnowledgeKind;
|
|
10
|
+
tokenCost?: number;
|
|
11
|
+
};
|
|
12
|
+
export type RetrievalScope = {
|
|
13
|
+
projectId?: string;
|
|
14
|
+
kinds?: KnowledgeKind[];
|
|
15
|
+
tokenCap?: number;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Normative retrieval contract: approved && !quarantined && !superseded &&
|
|
19
|
+
* projectScope match && kind match && tokenCap.
|
|
20
|
+
*/
|
|
21
|
+
export declare function isRetrievable(meta: RetrievalMeta, scope: RetrievalScope): boolean;
|
|
22
|
+
export type QuarantineOptions = {
|
|
23
|
+
projectRoot?: string;
|
|
24
|
+
sourceDir?: string;
|
|
25
|
+
reason?: string;
|
|
26
|
+
};
|
|
27
|
+
export type QuarantineResult = {
|
|
28
|
+
quarantined: boolean;
|
|
29
|
+
slug: string;
|
|
30
|
+
quarantinePath: string;
|
|
31
|
+
reason?: string;
|
|
32
|
+
};
|
|
33
|
+
export declare function promotedDirFor(slug: string, projectRoot?: string): string;
|
|
34
|
+
export declare function quarantineDirFor(slug: string, projectRoot?: string): string;
|
|
35
|
+
/** MOVE a promoted skill under `<evolutionDir>/quarantine/<slug>/` and audit it (instead of rm -rf). */
|
|
36
|
+
export declare function quarantineSkill(slug: string, opts?: QuarantineOptions): Promise<QuarantineResult>;
|
|
37
|
+
/** Restore a previously quarantined skill back to the promoted dir. Owned by T6. */
|
|
38
|
+
export declare function restoreFromQuarantine(slug: string, opts?: {
|
|
39
|
+
projectRoot?: string;
|
|
40
|
+
destDir?: string;
|
|
41
|
+
}): Promise<boolean>;
|
|
42
|
+
export type SupersedeOptions = {
|
|
43
|
+
projectRoot?: string;
|
|
44
|
+
supersededBy: string;
|
|
45
|
+
};
|
|
46
|
+
export type SupersedeResult = {
|
|
47
|
+
slug: string;
|
|
48
|
+
supersededBy: string;
|
|
49
|
+
superseded: boolean;
|
|
50
|
+
};
|
|
51
|
+
/** Point an old artifact at its live head. Updates meta atomically, audits, never unlinks. */
|
|
52
|
+
export declare function supersedeSkill(slug: string, opts: SupersedeOptions): Promise<SupersedeResult>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type DistilledKnowledge, UNSCOPED_LEGACY } from "../types";
|
|
2
|
+
export { UNSCOPED_LEGACY };
|
|
3
|
+
export type ProjectIdentity = {
|
|
4
|
+
projectId: string;
|
|
5
|
+
root: string;
|
|
6
|
+
remote?: string;
|
|
7
|
+
};
|
|
8
|
+
/** Injectable git runner: returns trimmed stdout, or null when the command fails. */
|
|
9
|
+
export type GitRunner = (args: string[], cwd: string) => string | null;
|
|
10
|
+
/** Normalize a missing/empty project id to the unscoped sentinel. Pure. */
|
|
11
|
+
export declare function normalizeProjectId(projectId: string | undefined): string;
|
|
12
|
+
/** Lowercase, trim, collapse runs of non-alphanumerics to a single dash. Pure. */
|
|
13
|
+
export declare function normalizeTitle(title: string): string;
|
|
14
|
+
/** Drop the memoized identities (test hook + explicit invalidation). */
|
|
15
|
+
export declare function clearProjectIdentityCache(): void;
|
|
16
|
+
/** Short, stable project suffix used to disambiguate cross-project slugs. Pure. */
|
|
17
|
+
export declare function projectSlugSuffix(projectId: string): string;
|
|
18
|
+
/**
|
|
19
|
+
* Resolve the git identity for a project root. The id is `sha256:<hex>` of the
|
|
20
|
+
* git remote URL when one exists, otherwise of the canonical repo-root path.
|
|
21
|
+
* Results are memoized per canonical root: a second resolve for the same root
|
|
22
|
+
* spawns no git. `remote` is returned for in-memory use only — callers MUST NOT
|
|
23
|
+
* persist or log it.
|
|
24
|
+
*/
|
|
25
|
+
export declare function resolveProjectIdentity(root: string, runner?: GitRunner): ProjectIdentity;
|
|
26
|
+
/** Scoped dedup key: projectId + kind + normalized title. Owned by T5. */
|
|
27
|
+
export declare function dedupKey(identity: ProjectIdentity, knowledge: DistilledKnowledge): string;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type RetrievalMeta, type RetrievalScope } from "./lifecycle";
|
|
2
|
+
/** Appended when `get_context` output is cut at the char cap. */
|
|
3
|
+
export declare const CONTEXT_TRUNCATION_MARKER = "\n...[context truncated]";
|
|
4
|
+
/** One read-only retrieval candidate: normalized meta + searchable body. */
|
|
5
|
+
export type RetrievalRecord = {
|
|
6
|
+
id: string;
|
|
7
|
+
meta: RetrievalMeta;
|
|
8
|
+
text: string;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Enumerate retrieval candidates from the staged skill store and the pending
|
|
12
|
+
* queue. Staged entries win on slug collisions. Read-only; missing dirs → [].
|
|
13
|
+
*/
|
|
14
|
+
export declare function readRetrievalRecords(projectRoot: string): RetrievalRecord[];
|
|
15
|
+
export type SearchOptions = {
|
|
16
|
+
/** Case-insensitive substring match against id + body. Absent matches all. */
|
|
17
|
+
query?: string;
|
|
18
|
+
scope: RetrievalScope;
|
|
19
|
+
};
|
|
20
|
+
/** Filter records through the T4a predicate, then narrow by text match. */
|
|
21
|
+
export declare function searchRecords(records: RetrievalRecord[], options: SearchOptions): RetrievalRecord[];
|
|
22
|
+
/** Cut text at `cap` chars, appending the marker only when truncation happens. */
|
|
23
|
+
export declare function truncateContext(text: string, cap: number): string;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { EvolutionState, TraceRecord } from "
|
|
1
|
+
import type { EvolutionState, TraceRecord } from "../types";
|
|
2
2
|
export declare const EVOLUTION_DIR = ".matrixx/evolution";
|
|
3
3
|
export declare const TRACES_DIR = ".matrixx/evolution/traces";
|
|
4
4
|
export declare const DISTILLED_DIR = ".matrixx/evolution/distilled";
|
|
@@ -12,6 +12,9 @@ export type TraceRecord = {
|
|
|
12
12
|
errorType?: string;
|
|
13
13
|
model?: string;
|
|
14
14
|
};
|
|
15
|
+
export type KnowledgeKind = "workflow" | "correction" | "debugging_pattern" | "gotcha" | "convention";
|
|
16
|
+
/** Project scope used when git identity is unknown (T4a contract; populated by T5). */
|
|
17
|
+
export declare const UNSCOPED_LEGACY = "unscoped-legacy";
|
|
15
18
|
export type DistilledKnowledge = {
|
|
16
19
|
title: string;
|
|
17
20
|
summary: string;
|
|
@@ -21,6 +24,27 @@ export type DistilledKnowledge = {
|
|
|
21
24
|
skillDraft?: string;
|
|
22
25
|
confidence: number;
|
|
23
26
|
sourceSessionIDs: string[];
|
|
27
|
+
kind: KnowledgeKind;
|
|
28
|
+
/** Git-derived project scope; absent normalizes to UNSCOPED_LEGACY. Populated by T5. */
|
|
29
|
+
projectId?: string;
|
|
30
|
+
/** Trace ids backing this distillation; absent defaults to []. */
|
|
31
|
+
sourceTraceIDs: string[];
|
|
32
|
+
/** ISO timestamp of distillation; absent is back-filled at parse time. */
|
|
33
|
+
distilledAt: string;
|
|
34
|
+
};
|
|
35
|
+
export type CompressionUsage = {
|
|
36
|
+
inputTokens: number;
|
|
37
|
+
outputTokens: number;
|
|
38
|
+
costCents: number;
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Cost/usage channel (T4a): `compress()` resolves to `{ knowledge, usage? }` with
|
|
42
|
+
* `usage = { inputTokens, outputTokens, costCents }`. T1 emits it, T3 (budget-ledger)
|
|
43
|
+
* consumes it, T8 provenance cites it. No separate store-appended ledger event.
|
|
44
|
+
*/
|
|
45
|
+
export type CompressResult = {
|
|
46
|
+
knowledge: DistilledKnowledge;
|
|
47
|
+
usage?: CompressionUsage;
|
|
24
48
|
};
|
|
25
49
|
export type CompressionInput = {
|
|
26
50
|
sessionID: string;
|
|
@@ -31,7 +55,7 @@ export type CompressionInput = {
|
|
|
31
55
|
taskHistory?: unknown[];
|
|
32
56
|
};
|
|
33
57
|
export interface Compressor {
|
|
34
|
-
compress(input: CompressionInput): Promise<
|
|
58
|
+
compress(input: CompressionInput): Promise<CompressResult>;
|
|
35
59
|
}
|
|
36
60
|
export type EvolutionState = {
|
|
37
61
|
totalTraces: number;
|
|
@@ -45,7 +69,16 @@ export type SkillMeta = {
|
|
|
45
69
|
derived_from: string[];
|
|
46
70
|
created_at: string;
|
|
47
71
|
confidence: number;
|
|
72
|
+
kind?: KnowledgeKind;
|
|
73
|
+
/** Git-derived project scope; absent/failing back-compat normalizes to unscoped. */
|
|
74
|
+
projectId?: string;
|
|
48
75
|
eval_score?: number | null;
|
|
49
76
|
tags?: string[];
|
|
50
77
|
prerequisites?: string[];
|
|
78
|
+
/** Live-head pointer set on an old artifact when a later re-distill replaces it. */
|
|
79
|
+
superseded_by?: string;
|
|
80
|
+
/** Canonical title slug shared across a supersede chain (old + new coexist). */
|
|
81
|
+
base_slug?: string;
|
|
82
|
+
/** Content hash used to detect byte-identical re-distills (idempotent suppression). */
|
|
83
|
+
content_hash?: string;
|
|
51
84
|
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { DistilledKnowledge, KnowledgeKind } from "./types";
|
|
2
|
+
export declare function slugify(title: string): string;
|
|
3
|
+
export type EmitInput = {
|
|
4
|
+
pendingDir: string;
|
|
5
|
+
skillsDir: string;
|
|
6
|
+
slug: string;
|
|
7
|
+
knowledge: DistilledKnowledge;
|
|
8
|
+
projectId: string;
|
|
9
|
+
kind: KnowledgeKind;
|
|
10
|
+
contentHash: string;
|
|
11
|
+
baseSlug: string;
|
|
12
|
+
};
|
|
13
|
+
export declare function emitArtifact(input: EmitInput): Promise<{
|
|
14
|
+
slug: string;
|
|
15
|
+
pendingPath: string;
|
|
16
|
+
metaPath: string;
|
|
17
|
+
}>;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type KnowledgeKind, type SkillMeta } from "./types";
|
|
2
|
+
/**
|
|
3
|
+
* Provenance (T8) is the evidence trail behind a generated skill: which
|
|
4
|
+
* sessions and trace rows it was distilled from, and when. It is emitted both
|
|
5
|
+
* as SKILL.md YAML frontmatter and mirrored into meta.json.
|
|
6
|
+
*/
|
|
7
|
+
export type ProvenanceMeta = SkillMeta & {
|
|
8
|
+
session_ids: string[];
|
|
9
|
+
trace_ids: string[];
|
|
10
|
+
distilled_at: string;
|
|
11
|
+
};
|
|
12
|
+
export type Provenance = {
|
|
13
|
+
session_ids: string[];
|
|
14
|
+
trace_ids: string[];
|
|
15
|
+
project_id: string;
|
|
16
|
+
kind: KnowledgeKind;
|
|
17
|
+
confidence: number;
|
|
18
|
+
distilled_at: string;
|
|
19
|
+
};
|
|
20
|
+
/** Legacy artifacts predate provenance; loading them must never throw. */
|
|
21
|
+
export declare function hasProvenance(meta: unknown): boolean;
|
|
22
|
+
export declare function provenanceOf(meta: ProvenanceMeta): Provenance;
|
|
23
|
+
export declare function toFrontmatter(meta: ProvenanceMeta): string;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { DistilledKnowledge, KnowledgeKind, SkillMeta } from "./types";
|
|
2
|
+
export type SupersedeKey = {
|
|
3
|
+
baseSlug: string;
|
|
4
|
+
projectId: string;
|
|
5
|
+
kind: KnowledgeKind;
|
|
6
|
+
};
|
|
7
|
+
/** Stable hash of the distillable payload, ignoring volatile timestamps/provenance. */
|
|
8
|
+
export declare function contentHashFor(knowledge: DistilledKnowledge): string;
|
|
9
|
+
/** Distinct, deterministic slug for a chain entry so old and new coexist on disk. */
|
|
10
|
+
export declare function chainSlug(baseSlug: string, contentHash: string): string;
|
|
11
|
+
/** Return `desired`, or the first free `desired-N` when it is already taken. */
|
|
12
|
+
export declare function uniqueSlug(taken: ReadonlySet<string>, desired: string): string;
|
|
13
|
+
/** Read every pending `*.meta.json`; malformed files are skipped, missing dirs yield []. */
|
|
14
|
+
export declare function listPendingMetas(pendingDir: string): SkillMeta[];
|
|
15
|
+
/** Whether a meta shares the (projectId, kind, normalized title) key of a candidate. */
|
|
16
|
+
export declare function knowledgeKeyMatches(meta: SkillMeta, key: SupersedeKey): boolean;
|
|
17
|
+
/** The live artifact for a key: newest matching meta without `superseded_by`. */
|
|
18
|
+
export declare function findLiveHead(metas: SkillMeta[], key: SupersedeKey): SkillMeta | null;
|
|
19
|
+
/** Follow `superseded_by` from `startSlug` to the chain end; fail-open on breaks/cycles. */
|
|
20
|
+
export declare function resolveHeadSlug(metas: SkillMeta[], startSlug: string): string;
|
|
@@ -5,11 +5,15 @@ export declare class EvolutionWriter {
|
|
|
5
5
|
private skillsDir;
|
|
6
6
|
private promotedBase;
|
|
7
7
|
private globalBase?;
|
|
8
|
+
private projectRoot;
|
|
8
9
|
constructor(config: EvolutionWriterConfig, projectRoot?: string);
|
|
10
|
+
private readMeta;
|
|
11
|
+
private emit;
|
|
9
12
|
stage(knowledge: DistilledKnowledge): Promise<{
|
|
10
13
|
slug: string;
|
|
11
14
|
pendingPath: string;
|
|
12
15
|
metaPath: string;
|
|
16
|
+
deduped?: boolean;
|
|
13
17
|
}>;
|
|
14
18
|
promote(slug: string): Promise<{
|
|
15
19
|
promotedPath: string;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plan Contract — Appendix Boundary
|
|
3
|
+
*
|
|
4
|
+
* Locates the designated appendix region of a plan. The region begins at the
|
|
5
|
+
* first H2 whose normalized text is exactly `Appendix` and extends to EOF.
|
|
6
|
+
* H2s at/after it are exempt from canonical-section and ordering checks.
|
|
7
|
+
*
|
|
8
|
+
* Pure content-level helper — accepts a string only, never touches the file system.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Return the ZERO-BASED line index of the first `## Appendix` H2, or `-1` when
|
|
12
|
+
* the plan has no appendix. "Normalized" means the heading text is trimmed.
|
|
13
|
+
*/
|
|
14
|
+
export declare function findAppendixStart(content: string): number;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plan Contract Constants
|
|
3
|
+
*
|
|
4
|
+
* Canonical structure of an Oracle work plan: the ordered H2 sections and the
|
|
5
|
+
* required per-task grammar. Checkbox regexes are the single source of truth in
|
|
6
|
+
* mission-state — re-exported here, never re-declared.
|
|
7
|
+
*/
|
|
8
|
+
export { NUMBERED_CHECKED_RE, NUMBERED_UNCHECKED_RE, TOP_CHECKED_RE, TOP_UNCHECKED_RE, } from "../../features/mission-state/constants";
|
|
9
|
+
/** Ordered H2 section titles, exactly as emitted by the Oracle plan template. */
|
|
10
|
+
export declare const CANONICAL_SECTIONS: readonly ["TL;DR", "Context", "Work Objectives", "Verification Strategy (MANDATORY)", "Execution Strategy", "TODOs", "Commit Strategy", "Success Criteria"];
|
|
11
|
+
/** Ordered labels that every TODO task block must declare. */
|
|
12
|
+
export declare const REQUIRED_TASK_SUBFIELDS: readonly ["What to do", "Must NOT do", "Recommended Agent Profile", "Parallelization", "References", "Acceptance Criteria", "Agent-Executed QA Scenarios"];
|
|
13
|
+
/** Canonical section title union derived from {@link CANONICAL_SECTIONS}. */
|
|
14
|
+
export type PlanSection = (typeof CANONICAL_SECTIONS)[number];
|
|
15
|
+
/** Canonical task subfield label union derived from {@link REQUIRED_TASK_SUBFIELDS}. */
|
|
16
|
+
export type PlanTaskSubfield = (typeof REQUIRED_TASK_SUBFIELDS)[number];
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plan Front-Matter
|
|
3
|
+
*
|
|
4
|
+
* Structured YAML front-matter (a leading `---` fenced block) for Oracle plan
|
|
5
|
+
* files, parsed with `js-yaml`.
|
|
6
|
+
*
|
|
7
|
+
* PRECEDENCE: when a front-matter block is present it is authoritative for
|
|
8
|
+
* `status` and `revision`. The legacy `<!-- plan-persister: {...} -->` comment
|
|
9
|
+
* (see mission-state `plan-storage.ts`) remains authoritative for `todoTotal`,
|
|
10
|
+
* `todoCompleted`, `updatedAt` and `sessionId`, and is NEVER removed. Front-matter
|
|
11
|
+
* is ADDITIVE over that comment, not a replacement.
|
|
12
|
+
*
|
|
13
|
+
* Serialization is IDEMPOTENT: `parse(serialize(parse(content)))` equals
|
|
14
|
+
* `parse(content)`, and `serialize(parse(serialize(fm)))` equals
|
|
15
|
+
* `serialize(fm)`. On disagreement `status` comes from the front-matter while
|
|
16
|
+
* the legacy comment is left untouched.
|
|
17
|
+
*/
|
|
18
|
+
import type { PlanFrontMatter } from "./types";
|
|
19
|
+
/**
|
|
20
|
+
* Parse the leading YAML front-matter block.
|
|
21
|
+
*
|
|
22
|
+
* Returns `null` when the block is absent, malformed, or fails the
|
|
23
|
+
* {@link PlanFrontMatter} shape (e.g. missing `status`/`revision` or an
|
|
24
|
+
* out-of-vocabulary status).
|
|
25
|
+
*/
|
|
26
|
+
export declare function parsePlanFrontMatter(content: string): PlanFrontMatter | null;
|
|
27
|
+
/**
|
|
28
|
+
* Serialize front-matter to a `---` fenced YAML block.
|
|
29
|
+
*
|
|
30
|
+
* Optional fields are omitted when `undefined`; array fields are emitted even
|
|
31
|
+
* when empty. The returned block ends with a trailing newline so it can be
|
|
32
|
+
* prepended to plan content additively.
|
|
33
|
+
*/
|
|
34
|
+
export declare function serializePlanFrontMatter(fm: PlanFrontMatter): string;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plan Contract — barrel
|
|
3
|
+
*
|
|
4
|
+
* Foundation module for the plan contract: canonical sections, task grammar,
|
|
5
|
+
* and the Zod schema for the structured plan view.
|
|
6
|
+
*/
|
|
7
|
+
export { findAppendixStart } from "./appendix";
|
|
8
|
+
export { CANONICAL_SECTIONS, NUMBERED_CHECKED_RE, NUMBERED_UNCHECKED_RE, type PlanSection, type PlanTaskSubfield, REQUIRED_TASK_SUBFIELDS, TOP_CHECKED_RE, TOP_UNCHECKED_RE, } from "./constants";
|
|
9
|
+
export { parsePlanFrontMatter, serializePlanFrontMatter } from "./front-matter";
|
|
10
|
+
export { isGrandfathered, shouldMigrate } from "./migration";
|
|
11
|
+
export { type PlanContract, PlanContractSchema } from "./schema";
|
|
12
|
+
export { renderPlanSkeleton } from "./skeleton";
|
|
13
|
+
export type { PlanContractResult, PlanContractWarning, PlanFrontMatter, PlanStatus, PlanTask, } from "./types";
|
|
14
|
+
export { parsePlanContract, parsePlanTasks, validatePlanContract } from "./validate";
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plan Front-Matter Migration & Grandfathering
|
|
3
|
+
*
|
|
4
|
+
* Front-matter is ADDITIVE over the legacy `<!-- plan-persister: {...} -->`
|
|
5
|
+
* comment (`mission-state/plan-storage.ts`) — it does not replace it. Migration
|
|
6
|
+
* is apply-on-next-edit ONLY: no `plan_migrate` tool is shipped and no plan is
|
|
7
|
+
* rewritten automatically.
|
|
8
|
+
*
|
|
9
|
+
* Grandfathering protects the pre-existing plan corpus from retro-breaking: a
|
|
10
|
+
* plan that lacks front-matter is only exempt when its id is on the frozen
|
|
11
|
+
* {@link GRANDFATHER_ALLOWLIST}. A brand-new plan lacking front-matter is NOT
|
|
12
|
+
* grandfathered.
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Frozen allowlist of plan ids (filename without `.md`) that predate the
|
|
16
|
+
* front-matter requirement — captured from the live `.matrixx/plans` corpus
|
|
17
|
+
* (23 files) at planning time.
|
|
18
|
+
*
|
|
19
|
+
* Grandfathered plans never emit a front-matter warning and are exempt from any
|
|
20
|
+
* future FAIL-mode front-matter requirement. The exemption clears as soon as
|
|
21
|
+
* the plan gains a front-matter block.
|
|
22
|
+
*/
|
|
23
|
+
export declare const GRANDFATHER_ALLOWLIST: readonly string[];
|
|
24
|
+
/**
|
|
25
|
+
* True IFF the plan has no front-matter AND its id is on the frozen allowlist.
|
|
26
|
+
*
|
|
27
|
+
* This is deliberately narrower than "any plan lacking front-matter": a new
|
|
28
|
+
* non-allowlisted plan returns `false`.
|
|
29
|
+
*/
|
|
30
|
+
export declare function isGrandfathered(filePath: string, content: string): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* True IFF front-matter is absent, for ANY plan (grandfathered included),
|
|
33
|
+
* because injection is additive. Idempotent: once front-matter is present this
|
|
34
|
+
* returns `false`.
|
|
35
|
+
*/
|
|
36
|
+
export declare function shouldMigrate(content: string): boolean;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plan Contract Schema
|
|
3
|
+
*
|
|
4
|
+
* Zod v4 schema for the STRUCTURED view of an Oracle plan. The Markdown grammar
|
|
5
|
+
* itself is parsed elsewhere; this validates the parsed shape.
|
|
6
|
+
*/
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
export declare const PlanContractSchema: z.ZodObject<{
|
|
9
|
+
frontMatter: z.ZodOptional<z.ZodObject<{
|
|
10
|
+
status: z.ZodEnum<{
|
|
11
|
+
pending: "pending";
|
|
12
|
+
completed: "completed";
|
|
13
|
+
in_progress: "in_progress";
|
|
14
|
+
}>;
|
|
15
|
+
revision: z.ZodNumber;
|
|
16
|
+
phase: z.ZodOptional<z.ZodString>;
|
|
17
|
+
wave: z.ZodOptional<z.ZodString>;
|
|
18
|
+
deps: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
19
|
+
blockedBy: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
20
|
+
}, z.core.$strip>>;
|
|
21
|
+
sections: z.ZodArray<z.ZodString>;
|
|
22
|
+
tasks: z.ZodArray<z.ZodObject<{
|
|
23
|
+
n: z.ZodNumber;
|
|
24
|
+
title: z.ZodString;
|
|
25
|
+
checked: z.ZodBoolean;
|
|
26
|
+
line: z.ZodNumber;
|
|
27
|
+
anchor: z.ZodString;
|
|
28
|
+
}, z.core.$strip>>;
|
|
29
|
+
dod: z.ZodArray<z.ZodString>;
|
|
30
|
+
}, z.core.$strip>;
|
|
31
|
+
/** Parsed, validated structured view of a plan. */
|
|
32
|
+
export type PlanContract = z.infer<typeof PlanContractSchema>;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plan Contract Types
|
|
3
|
+
*
|
|
4
|
+
* Structured view of an Oracle work plan: parsed sections, numbered tasks,
|
|
5
|
+
* definition-of-done lines, and optional YAML front-matter.
|
|
6
|
+
*/
|
|
7
|
+
import type { PlanSection } from "./constants";
|
|
8
|
+
export type { PlanSection };
|
|
9
|
+
/** A single numbered TODO task parsed from a plan. */
|
|
10
|
+
export interface PlanTask {
|
|
11
|
+
/** Task number as written in the plan (e.g. `1` in `- [ ] 1. ...`). */
|
|
12
|
+
n: number;
|
|
13
|
+
/** Task title text following the number. */
|
|
14
|
+
title: string;
|
|
15
|
+
/** Whether the task checkbox is checked. */
|
|
16
|
+
checked: boolean;
|
|
17
|
+
/** 1-based line number of the task within the plan file. */
|
|
18
|
+
line: number;
|
|
19
|
+
/** Stable LINE#ID anchor for hashline-scoped edits. */
|
|
20
|
+
anchor: string;
|
|
21
|
+
}
|
|
22
|
+
/** Severity-neutral diagnostic emitted while validating a plan contract. */
|
|
23
|
+
export interface PlanContractWarning {
|
|
24
|
+
/** Machine-readable warning code. */
|
|
25
|
+
code: string;
|
|
26
|
+
/** Human-readable explanation. */
|
|
27
|
+
message: string;
|
|
28
|
+
/** 1-based line the warning refers to, when known. */
|
|
29
|
+
line?: number;
|
|
30
|
+
}
|
|
31
|
+
/** Outcome of validating a plan against the contract. */
|
|
32
|
+
export interface PlanContractResult {
|
|
33
|
+
/** True when no errors were produced (warnings may still be present). */
|
|
34
|
+
ok: boolean;
|
|
35
|
+
/** Non-fatal contract deviations. */
|
|
36
|
+
warnings: PlanContractWarning[];
|
|
37
|
+
/** Fatal contract violations. */
|
|
38
|
+
errors: string[];
|
|
39
|
+
}
|
|
40
|
+
/** Lifecycle status carried by a plan's YAML front-matter. */
|
|
41
|
+
export type PlanStatus = "pending" | "in_progress" | "completed";
|
|
42
|
+
/** Structured YAML front-matter block parsed from a plan file. */
|
|
43
|
+
export interface PlanFrontMatter {
|
|
44
|
+
/** Current plan lifecycle status. */
|
|
45
|
+
status: PlanStatus;
|
|
46
|
+
/** Monotonic revision counter. */
|
|
47
|
+
revision: number;
|
|
48
|
+
/** Execution phase label, when present. */
|
|
49
|
+
phase?: string;
|
|
50
|
+
/** Execution wave label, when present. */
|
|
51
|
+
wave?: string;
|
|
52
|
+
/** Task ids this plan depends on. */
|
|
53
|
+
deps?: string[];
|
|
54
|
+
/** Task ids blocked by this plan. */
|
|
55
|
+
blockedBy?: string[];
|
|
56
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { PlanContract } from "./schema";
|
|
2
|
+
import type { PlanContractResult, PlanTask } from "./types";
|
|
3
|
+
/** Optional caller-supplied LINE#ID anchors keyed by 1-based line number. */
|
|
4
|
+
export type HashlineAnchors = ReadonlyMap<number, string> | Readonly<Record<number, string>>;
|
|
5
|
+
export declare function parsePlanTasks(content: string, hashlineAnchors?: HashlineAnchors): PlanTask[];
|
|
6
|
+
export declare function parsePlanContract(content: string): PlanContract;
|
|
7
|
+
export declare function validatePlanContract(content: string, options?: {
|
|
8
|
+
mode?: "warn" | "fail";
|
|
9
|
+
}): PlanContractResult;
|
|
@@ -28,14 +28,3 @@ export declare function setSessionAgent(sessionID: string, agent: string): void;
|
|
|
28
28
|
export declare function updateSessionAgent(sessionID: string, agent: string): void;
|
|
29
29
|
export declare function getSessionAgent(sessionID: string): string | undefined;
|
|
30
30
|
export declare function clearSessionAgent(sessionID: string): void;
|
|
31
|
-
export declare function incFailureCounter(sessionID: string): number;
|
|
32
|
-
export declare function resetFailureCounter(sessionID: string): void;
|
|
33
|
-
export declare function getFailureCount(sessionID: string): number;
|
|
34
|
-
export declare function getFailureState(sessionID: string): {
|
|
35
|
-
count: number;
|
|
36
|
-
lastFailedAt: number;
|
|
37
|
-
} | undefined;
|
|
38
|
-
export declare function clearFailureCounter(sessionID: string): void;
|
|
39
|
-
/** @internal For testing only */
|
|
40
|
-
export declare function _resetFailureCountersForTesting(): void;
|
|
41
|
-
export declare function isThresholdReached(sessionID: string, threshold: number): boolean;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { createOpencodeClient } from "@opencode-ai/sdk";
|
|
2
|
+
import type { LlmUsage } from "../../features/evolution/compressor/interface";
|
|
3
|
+
type Client = ReturnType<typeof createOpencodeClient>;
|
|
4
|
+
export declare function parseModelOverride(model: string | undefined): {
|
|
5
|
+
providerID: string;
|
|
6
|
+
modelID: string;
|
|
7
|
+
} | undefined;
|
|
8
|
+
export declare function createHostLlmCall(options: {
|
|
9
|
+
client: Client;
|
|
10
|
+
directory: string;
|
|
11
|
+
agent?: string;
|
|
12
|
+
model?: string;
|
|
13
|
+
}): (prompt: string, model?: string) => Promise<{
|
|
14
|
+
text: string;
|
|
15
|
+
usage?: LlmUsage;
|
|
16
|
+
}>;
|
|
17
|
+
export {};
|
package/dist/hooks/index.d.ts
CHANGED
|
@@ -24,8 +24,6 @@ export { createEvolutionCompressorHook } from "./evolution-compressor";
|
|
|
24
24
|
export { createEvolutionHitlHook } from "./evolution-hitl";
|
|
25
25
|
export { passesQualityGate } from "./evolution-quality-gate";
|
|
26
26
|
export { createEvolutionWatcherHook } from "./evolution-watcher";
|
|
27
|
-
export { createFailureCounterHook } from "./failure-counter";
|
|
28
|
-
export { createHashlineEditDiffEnhancerHook } from "./hashline-edit-diff-enhancer";
|
|
29
27
|
export { createHashlineReadEnhancerHook } from "./hashline-read-enhancer";
|
|
30
28
|
export { createInputSecretGuardHook } from "./input-secret-guard";
|
|
31
29
|
export { createInteractiveBashSessionHook } from "./interactive-bash-session";
|
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
export declare const HOOK_NAME = "task-continuation-enforcer";
|
|
2
2
|
export declare const DEFAULT_SKIP_AGENTS: string[];
|
|
3
|
-
export declare const EXPLORER_AGENTS: string[];
|
|
4
|
-
export declare function hasNonExplorerBgTasks(tasks: Array<{
|
|
5
|
-
agent?: string;
|
|
6
|
-
}>): boolean;
|
|
7
3
|
export declare const CONTINUATION_PROMPT: string;
|
|
8
|
-
export declare const BOOTSTRAP_PROMPT: string;
|
|
9
4
|
export declare const COUNTDOWN_SECONDS = 2;
|
|
10
5
|
export declare const TOAST_DURATION_MS = 900;
|
|
11
6
|
export declare const COUNTDOWN_GRACE_PERIOD_MS = 500;
|