@chopin-ai/core 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/dist/evidence/classify.d.ts +31 -0
  2. package/dist/evidence/classify.js +87 -0
  3. package/dist/evidence/classify.js.map +1 -0
  4. package/dist/evidence/corrections.d.ts +14 -0
  5. package/dist/evidence/corrections.js +61 -0
  6. package/dist/evidence/corrections.js.map +1 -0
  7. package/dist/evidence/failures.d.ts +44 -0
  8. package/dist/evidence/failures.js +91 -0
  9. package/dist/evidence/failures.js.map +1 -0
  10. package/dist/evidence/messages-jsonl.d.ts +7 -0
  11. package/dist/evidence/messages-jsonl.js +97 -0
  12. package/dist/evidence/messages-jsonl.js.map +1 -0
  13. package/dist/evidence/points.d.ts +26 -0
  14. package/dist/evidence/points.js +72 -0
  15. package/dist/evidence/points.js.map +1 -0
  16. package/dist/evidence/sanitize.d.ts +16 -0
  17. package/dist/evidence/sanitize.js +70 -0
  18. package/dist/evidence/sanitize.js.map +1 -0
  19. package/dist/evidence/signals.d.ts +25 -0
  20. package/dist/evidence/signals.js +28 -0
  21. package/dist/evidence/signals.js.map +1 -0
  22. package/dist/evidence/usage.d.ts +12 -0
  23. package/dist/evidence/usage.js +24 -0
  24. package/dist/evidence/usage.js.map +1 -0
  25. package/dist/fault.d.ts +3 -0
  26. package/dist/fault.js +4 -0
  27. package/dist/fault.js.map +1 -0
  28. package/dist/gate/admission.d.ts +34 -0
  29. package/dist/gate/admission.js +2 -0
  30. package/dist/gate/admission.js.map +1 -0
  31. package/dist/gate/daily.d.ts +92 -0
  32. package/dist/gate/daily.js +136 -0
  33. package/dist/gate/daily.js.map +1 -0
  34. package/dist/gate/ledger.d.ts +29 -0
  35. package/dist/gate/ledger.js +88 -0
  36. package/dist/gate/ledger.js.map +1 -0
  37. package/dist/gate/sequential.d.ts +39 -0
  38. package/dist/gate/sequential.js +84 -0
  39. package/dist/gate/sequential.js.map +1 -0
  40. package/dist/index.d.ts +38 -1
  41. package/dist/index.js +21 -1
  42. package/dist/index.js.map +1 -1
  43. package/dist/judge/audit.d.ts +45 -0
  44. package/dist/judge/audit.js +55 -0
  45. package/dist/judge/audit.js.map +1 -0
  46. package/dist/judge/calibration.d.ts +70 -0
  47. package/dist/judge/calibration.js +128 -0
  48. package/dist/judge/calibration.js.map +1 -0
  49. package/dist/judge/continuation.d.ts +16 -0
  50. package/dist/judge/continuation.js +48 -0
  51. package/dist/judge/continuation.js.map +1 -0
  52. package/dist/layer/versions.d.ts +71 -0
  53. package/dist/layer/versions.js +154 -0
  54. package/dist/layer/versions.js.map +1 -0
  55. package/dist/meta.d.ts +4 -0
  56. package/dist/meta.js.map +1 -1
  57. package/dist/propose/brief.d.ts +31 -0
  58. package/dist/propose/brief.js +52 -0
  59. package/dist/propose/brief.js.map +1 -0
  60. package/dist/propose/candidate.d.ts +15 -0
  61. package/dist/propose/candidate.js +30 -0
  62. package/dist/propose/candidate.js.map +1 -0
  63. package/dist/propose/rejections.d.ts +35 -0
  64. package/dist/propose/rejections.js +35 -0
  65. package/dist/propose/rejections.js.map +1 -0
  66. package/dist/propose/skill.d.ts +4 -0
  67. package/dist/propose/skill.js +34 -0
  68. package/dist/propose/skill.js.map +1 -0
  69. package/package.json +2 -2
@@ -0,0 +1,71 @@
1
+ import type { Layer } from "./layer.js";
2
+ /** One thing the loop added to the layer, with where it came from and where it has passed the gate. */
3
+ export interface LayerItem {
4
+ /** Stable across versions. */
5
+ id: string;
6
+ kind: "instruction" | "skill";
7
+ /** An instruction's text. */
8
+ text?: string;
9
+ /** A skill's name; its files are under `skills/<name>/` in the version. */
10
+ skill?: string;
11
+ /** Where it passed the gate: model references such as `provider/id`, and harness names. */
12
+ validated: {
13
+ models: string[];
14
+ harnesses: string[];
15
+ };
16
+ /** The kind of failure it answers and the certificate that admitted it. */
17
+ source: {
18
+ failure?: string;
19
+ certificate?: string;
20
+ };
21
+ pinned: boolean;
22
+ archived: boolean;
23
+ added: string;
24
+ }
25
+ /** What a session runs with, for choosing the items that apply to it. */
26
+ export interface Runner {
27
+ model: string;
28
+ harness: string;
29
+ /** When true, an item applies on every model, not only those it passed the gate on. */
30
+ anyModel?: boolean;
31
+ }
32
+ /** Limits on what every session carries, so the layer cannot grow without bound. */
33
+ export declare const LAYER_LIMITS: {
34
+ readonly residentTokens: 4000;
35
+ readonly skills: 30;
36
+ };
37
+ /**
38
+ * The loop's versions of the layer under one directory: each version is a whole directory written beside the others
39
+ * and published by renaming it into place, so a crash never leaves a half-written one, and `current` names the one
40
+ * in use. Every change, including archiving and pinning, is a new version.
41
+ */
42
+ export declare class LayerVersions {
43
+ readonly root: string;
44
+ constructor(root: string);
45
+ /** The version in use; 0 is the empty one. */
46
+ current(): Promise<number>;
47
+ items(version: number): Promise<LayerItem[]>;
48
+ directory(version: number): string;
49
+ /**
50
+ * A new version made from the current one: `edit` gives its items, and `files` writes (a string) or removes
51
+ * (`null`) files by their path in the version. The new version becomes current.
52
+ */
53
+ commit(edit: (items: LayerItem[]) => LayerItem[], files?: Readonly<Record<string, string | null>>): Promise<number>;
54
+ /** Makes `version` the one in use, by an atomic replace of the pointer. */
55
+ use(version: number): Promise<void>;
56
+ /** Whether `version` still holds exactly what was written when it was made. */
57
+ intact(version: number): Promise<boolean>;
58
+ /**
59
+ * When the version in use was changed after it was made, goes back to the newest earlier version that was not, and
60
+ * says which versions it moved between.
61
+ */
62
+ recover(): Promise<{
63
+ from: number;
64
+ to: number;
65
+ } | undefined>;
66
+ private versions;
67
+ }
68
+ /** The layer a session runs with: the hand-written `base`, then the loop's items that apply to `runner`. */
69
+ export declare function effectiveLayer(base: Layer, versions: LayerVersions, version: number, runner: Runner): Promise<Layer>;
70
+ /** What in `layer` exceeds the limits on what every session carries; empty when within them. */
71
+ export declare function overLimits(layer: Layer): string[];
@@ -0,0 +1,154 @@
1
+ import { createHash } from "node:crypto";
2
+ import { cp, mkdir, mkdtemp, readdir, readFile, rename, rm, writeFile } from "node:fs/promises";
3
+ import { dirname, join, relative } from "node:path";
4
+ import { loadSkills } from "./skills.js";
5
+ /** Limits on what every session carries, so the layer cannot grow without bound. */
6
+ export const LAYER_LIMITS = { residentTokens: 4000, skills: 30 };
7
+ const ITEMS = "items.json";
8
+ const CHECKSUM = "SHA256";
9
+ const CURRENT = "current";
10
+ /**
11
+ * The loop's versions of the layer under one directory: each version is a whole directory written beside the others
12
+ * and published by renaming it into place, so a crash never leaves a half-written one, and `current` names the one
13
+ * in use. Every change, including archiving and pinning, is a new version.
14
+ */
15
+ export class LayerVersions {
16
+ root;
17
+ constructor(root) {
18
+ this.root = root;
19
+ }
20
+ /** The version in use; 0 is the empty one. */
21
+ async current() {
22
+ const text = await readFile(join(this.root, CURRENT), "utf8").catch(absent);
23
+ return text === undefined ? 0 : Number(text.trim());
24
+ }
25
+ async items(version) {
26
+ if (version === 0)
27
+ return [];
28
+ return JSON.parse(await readFile(join(this.directory(version), ITEMS), "utf8"));
29
+ }
30
+ directory(version) {
31
+ return join(this.root, `v${version}`);
32
+ }
33
+ /**
34
+ * A new version made from the current one: `edit` gives its items, and `files` writes (a string) or removes
35
+ * (`null`) files by their path in the version. The new version becomes current.
36
+ */
37
+ async commit(edit, files = {}) {
38
+ await mkdir(this.root, { recursive: true });
39
+ const from = await this.current();
40
+ const next = (await this.versions()).reduce((max, v) => Math.max(max, v), from) + 1;
41
+ const staging = await mkdtemp(join(this.root, ".staging-"));
42
+ try {
43
+ if (from !== 0)
44
+ await cp(this.directory(from), staging, { recursive: true });
45
+ for (const [path, text] of Object.entries(files)) {
46
+ const target = join(staging, path);
47
+ if (relative(staging, target).startsWith(".."))
48
+ throw new Error(`${path} is outside the layer`);
49
+ if (text === null)
50
+ await rm(target, { recursive: true, force: true });
51
+ else {
52
+ await mkdir(dirname(target), { recursive: true });
53
+ await writeFile(target, text);
54
+ }
55
+ }
56
+ await writeFile(join(staging, ITEMS), JSON.stringify(edit(await this.items(from)), null, 2));
57
+ await writeFile(join(staging, CHECKSUM), await checksum(staging));
58
+ await rename(staging, this.directory(next));
59
+ }
60
+ catch (error) {
61
+ await rm(staging, { recursive: true, force: true });
62
+ throw error;
63
+ }
64
+ await this.use(next);
65
+ return next;
66
+ }
67
+ /** Makes `version` the one in use, by an atomic replace of the pointer. */
68
+ async use(version) {
69
+ const temporary = join(this.root, `.${CURRENT}-${process.pid}`);
70
+ await writeFile(temporary, `${version}\n`);
71
+ await rename(temporary, join(this.root, CURRENT));
72
+ }
73
+ /** Whether `version` still holds exactly what was written when it was made. */
74
+ async intact(version) {
75
+ if (version === 0)
76
+ return true;
77
+ const recorded = await readFile(join(this.directory(version), CHECKSUM), "utf8").catch(absent);
78
+ return recorded !== undefined && recorded === (await checksum(this.directory(version)).catch(() => undefined));
79
+ }
80
+ /**
81
+ * When the version in use was changed after it was made, goes back to the newest earlier version that was not, and
82
+ * says which versions it moved between.
83
+ */
84
+ async recover() {
85
+ const from = await this.current();
86
+ if (await this.intact(from))
87
+ return undefined;
88
+ const earlier = (await this.versions()).filter((v) => v < from).sort((a, b) => b - a);
89
+ let to = 0;
90
+ for (const version of earlier) {
91
+ if (await this.intact(version)) {
92
+ to = version;
93
+ break;
94
+ }
95
+ }
96
+ await this.use(to);
97
+ return { from, to };
98
+ }
99
+ async versions() {
100
+ const names = await readdir(this.root).catch((error) => {
101
+ if (error.code === "ENOENT")
102
+ return [];
103
+ throw error;
104
+ });
105
+ return names.flatMap((name) => (/^v\d+$/.test(name) ? [Number(name.slice(1))] : []));
106
+ }
107
+ }
108
+ /** The layer a session runs with: the hand-written `base`, then the loop's items that apply to `runner`. */
109
+ export async function effectiveLayer(base, versions, version, runner) {
110
+ const applies = (item) => !item.archived && item.validated.harnesses.includes(runner.harness) &&
111
+ (runner.anyModel === true || item.validated.models.includes(runner.model));
112
+ const items = (await versions.items(version)).filter(applies);
113
+ const texts = items.flatMap((item) => (item.kind === "instruction" && item.text !== undefined ? [item.text] : []));
114
+ const instructions = [base.instructions, ...texts].filter((text) => text !== undefined && text !== "").join("\n\n");
115
+ const names = new Set(items.flatMap((item) => (item.kind === "skill" && item.skill !== undefined ? [item.skill] : [])));
116
+ const problems = [];
117
+ const added = (await loadSkills(join(versions.directory(version), "skills"), problems)).filter((skill) => names.has(skill.name));
118
+ if (problems.length > 0)
119
+ throw new Error(`layer version ${version}: ${problems.join("; ")}`);
120
+ const skills = [...base.skills.filter((skill) => !names.has(skill.name)), ...added];
121
+ return { ...base, instructions: instructions === "" ? undefined : instructions, skills };
122
+ }
123
+ /** What in `layer` exceeds the limits on what every session carries; empty when within them. */
124
+ export function overLimits(layer) {
125
+ const resident = (layer.instructions ?? "").length + layer.skills.reduce((n, s) => n + s.name.length + s.description.length + 4, 0);
126
+ const tokens = Math.ceil(resident / 4);
127
+ return [
128
+ ...(tokens > LAYER_LIMITS.residentTokens ? [`resident context is about ${tokens} tokens, over ${LAYER_LIMITS.residentTokens}`] : []),
129
+ ...(layer.skills.length > LAYER_LIMITS.skills ? [`${layer.skills.length} skills, over ${LAYER_LIMITS.skills}`] : []),
130
+ ];
131
+ }
132
+ async function checksum(directory) {
133
+ const hash = createHash("sha256");
134
+ for (const file of (await files(directory)).sort()) {
135
+ if (file === CHECKSUM)
136
+ continue;
137
+ hash.update(`${file}\0`).update(await readFile(join(directory, file))).update("\0");
138
+ }
139
+ return hash.digest("hex");
140
+ }
141
+ async function files(directory, prefix = "") {
142
+ const entries = await readdir(join(directory, prefix), { withFileTypes: true });
143
+ const nested = await Promise.all(entries.map((entry) => {
144
+ const path = prefix === "" ? entry.name : `${prefix}/${entry.name}`;
145
+ return entry.isDirectory() ? files(directory, path) : Promise.resolve([path]);
146
+ }));
147
+ return nested.flat();
148
+ }
149
+ function absent(error) {
150
+ if (error.code === "ENOENT")
151
+ return undefined;
152
+ throw error;
153
+ }
154
+ //# sourceMappingURL=versions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"versions.js","sourceRoot":"","sources":["../../src/layer/versions.ts"],"names":[],"mappings":"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"}
package/dist/meta.d.ts CHANGED
@@ -13,6 +13,10 @@ export interface ChopinMeta {
13
13
  };
14
14
  /** Why the turn ended without an answer. */
15
15
  error?: string;
16
+ /** The harness's diagnostic codes on a tool result: `blocked` for a call a hook refused, `rejected` for one the user did. */
17
+ diagnostics?: string[];
18
+ /** A user-role message the harness added, such as a reminder or a command's output, rather than one the user wrote. */
19
+ injected?: boolean;
16
20
  }
17
21
  export declare function withChopinMeta<T extends object>(value: T, meta: ChopinMeta): T;
18
22
  export declare function chopinMeta(value: object): ChopinMeta | undefined;
package/dist/meta.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"meta.js","sourceRoot":"","sources":["../src/meta.ts"],"names":[],"mappings":"AAAA,gGAAgG;AAChG,MAAM,CAAC,MAAM,QAAQ,GAAG,WAAW,CAAC;AAapC,MAAM,UAAU,cAAc,CAAmB,KAAQ,EAAE,IAAgB;IACzE,MAAM,QAAQ,GAAI,KAA0B,CAAC,KAAK,CAAC;IACnD,OAAO,EAAE,GAAG,KAAK,EAAE,KAAK,EAAE,EAAE,GAAG,QAAQ,EAAE,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,EAAE,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,KAAa;IACtC,OAAQ,KAA0B,CAAC,KAAK,EAAE,CAAC,QAAQ,CAA2B,CAAC;AACjF,CAAC"}
1
+ {"version":3,"file":"meta.js","sourceRoot":"","sources":["../src/meta.ts"],"names":[],"mappings":"AAAA,gGAAgG;AAChG,MAAM,CAAC,MAAM,QAAQ,GAAG,WAAW,CAAC;AAiBpC,MAAM,UAAU,cAAc,CAAmB,KAAQ,EAAE,IAAgB;IACzE,MAAM,QAAQ,GAAI,KAA0B,CAAC,KAAK,CAAC;IACnD,OAAO,EAAE,GAAG,KAAK,EAAE,KAAK,EAAE,EAAE,GAAG,QAAQ,EAAE,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,EAAE,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,KAAa;IACtC,OAAQ,KAA0B,CAAC,KAAK,EAAE,CAAC,QAAQ,CAA2B,CAAC;AACjF,CAAC"}
@@ -0,0 +1,31 @@
1
+ import type { FailureClass } from "../evidence/failures.js";
2
+ import type { TranscriptEntry } from "../transcript.js";
3
+ import type { Rejection } from "./rejections.js";
4
+ /** A session the failure came from, with the lines where it happened in it. */
5
+ export interface FailureSession {
6
+ session: string;
7
+ entries: readonly TranscriptEntry[];
8
+ lines: readonly number[];
9
+ }
10
+ export interface BriefInput {
11
+ failure: FailureClass;
12
+ /** Every session the failure came from; the change is tested at each of these failures. */
13
+ sessions: readonly FailureSession[];
14
+ /** What the user said to correct a step, by `session:line`. */
15
+ corrections: ReadonlyMap<string, string>;
16
+ /** Secret values to mask, besides the common secret formats. */
17
+ secrets: readonly string[];
18
+ rejections: readonly Rejection[];
19
+ /** The layer's items as they read now, by id. */
20
+ existing: readonly {
21
+ id: string;
22
+ text: string;
23
+ }[];
24
+ }
25
+ /**
26
+ * What a proposer works from: the kind of failure and every time it happened, each with the step to change marked
27
+ * and the user's correction of it, steps that went right for contrast, what was tried before and refused, and the
28
+ * layer as it is; one session alone does not show what they have in common. Everything from the sessions is
29
+ * redacted again here, whoever redacted it before.
30
+ */
31
+ export declare function proposalBrief(input: BriefInput): string;
@@ -0,0 +1,52 @@
1
+ import { goodSteps } from "../evidence/points.js";
2
+ import { redactTranscript } from "../evidence/sanitize.js";
3
+ /** How many lines around a failure, and how many contrasting steps that went right, the proposer is shown. */
4
+ const BEFORE = 20;
5
+ const AFTER = 5;
6
+ const CONTRASTS = 3;
7
+ const ENTRY_CHARS = 2000;
8
+ /**
9
+ * What a proposer works from: the kind of failure and every time it happened, each with the step to change marked
10
+ * and the user's correction of it, steps that went right for contrast, what was tried before and refused, and the
11
+ * layer as it is; one session alone does not show what they have in common. Everything from the sessions is
12
+ * redacted again here, whoever redacted it before.
13
+ */
14
+ export function proposalBrief(input) {
15
+ const sessions = input.sessions.map((session) => ({ ...session, entries: redactTranscript(session.entries, input.secrets) }));
16
+ const clip = (entry) => {
17
+ const text = JSON.stringify(entry);
18
+ return text.length <= ENTRY_CHARS ? text : `${text.slice(0, ENTRY_CHARS)}…`;
19
+ };
20
+ const excerpt = (entries, line, before, after) => entries.slice(Math.max(0, line - before), line + after + 1).map((entry, i) => {
21
+ const at = Math.max(0, line - before) + i;
22
+ return `${at === line ? ">>> " : ""}${at}: ${clip(entry)}`;
23
+ });
24
+ const times = sessions.flatMap((session, n) => session.lines.map((line) => {
25
+ const correction = input.corrections.get(`${session.session}:${line}`);
26
+ return [
27
+ `### Session ${n + 1}, line ${line}`,
28
+ ...(correction === undefined ? [] : [`The user corrected this step: ${correction}`]),
29
+ ...excerpt(session.entries, line, BEFORE, AFTER),
30
+ ];
31
+ }));
32
+ const good = sessions.flatMap((session, n) => {
33
+ const line = goodSteps(session.entries, session.lines).filter((at) => !session.lines.includes(at)).at(-1);
34
+ return line === undefined ? [] : [[`### Session ${n + 1}, line ${line}`, ...excerpt(session.entries, line, 3, 1)]];
35
+ }).slice(0, CONTRASTS).flat();
36
+ return [
37
+ "## The failure",
38
+ JSON.stringify(input.failure.signature),
39
+ `Seen ${times.length} times in ${sessions.length} sessions, every one below; your change is tested at each.`,
40
+ "## Each time it happened",
41
+ "The step marked >>> is the one your change must alter. What follows it, such as the user's correction, had not "
42
+ + "happened when the agent took that step, so the condition your change names must be visible before it.",
43
+ ...times.flat(),
44
+ "## Steps that went right",
45
+ ...(good.length === 0 ? ["(none)"] : good),
46
+ "## Tried before and refused",
47
+ ...(input.rejections.length === 0 ? ["(nothing yet)"] : input.rejections.map((rejection) => `- ${JSON.stringify(rejection.text)}: ${rejection.reason}${rejection.prediction === undefined ? "" : ` (it predicted: ${rejection.prediction})`}`)),
48
+ "## The layer now",
49
+ ...(input.existing.length === 0 ? ["(empty)"] : input.existing.map((item) => `- ${item.id}: ${JSON.stringify(item.text)}`)),
50
+ ].join("\n");
51
+ }
52
+ //# sourceMappingURL=brief.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"brief.js","sourceRoot":"","sources":["../../src/propose/brief.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import type { TextCandidate } from "../judge/audit.js";
2
+ /** A proposal as the proposer hands it in: one change to the layer's text, where it applies, and what it should do. */
3
+ export interface Proposal {
4
+ candidate: TextCandidate;
5
+ /** A skill's name, which is also its directory; only for a skill. */
6
+ skill?: string;
7
+ scope: "global" | "project";
8
+ /** What the change should fix, and what it might break, said so it can be checked. */
9
+ prediction: string;
10
+ }
11
+ /**
12
+ * The proposal in a proposer's reply, a single JSON object; `undefined` when the reply is not exactly one well-formed
13
+ * proposal, since a proposal that has to be guessed at is not tested.
14
+ */
15
+ export declare function parseProposal(reply: string): Proposal | undefined;
@@ -0,0 +1,30 @@
1
+ const SKILL_NAME = /^[a-z0-9]+(-[a-z0-9]+)*$/;
2
+ /**
3
+ * The proposal in a proposer's reply, a single JSON object; `undefined` when the reply is not exactly one well-formed
4
+ * proposal, since a proposal that has to be guessed at is not tested.
5
+ */
6
+ export function parseProposal(reply) {
7
+ let value;
8
+ try {
9
+ value = JSON.parse(reply.slice(reply.indexOf("{"), reply.lastIndexOf("}") + 1));
10
+ }
11
+ catch {
12
+ return undefined;
13
+ }
14
+ const { kind, text, skill, scope, prediction, revises } = value;
15
+ if (kind !== "instruction" && kind !== "skill")
16
+ return undefined;
17
+ if (typeof text !== "string" || text.trim() === "")
18
+ return undefined;
19
+ if (scope !== "global" && scope !== "project")
20
+ return undefined;
21
+ if (typeof prediction !== "string" || prediction.trim() === "")
22
+ return undefined;
23
+ if (revises !== undefined && revises !== null && typeof revises !== "string")
24
+ return undefined;
25
+ if (kind === "skill" && (typeof skill !== "string" || !SKILL_NAME.test(skill) || skill.length > 64))
26
+ return undefined;
27
+ const candidate = { kind, text, ...(typeof revises === "string" && { revises }) };
28
+ return { candidate, ...(kind === "skill" && { skill: skill }), scope, prediction };
29
+ }
30
+ //# sourceMappingURL=candidate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"candidate.js","sourceRoot":"","sources":["../../src/propose/candidate.ts"],"names":[],"mappings":"AAYA,MAAM,UAAU,GAAG,0BAA0B,CAAC;AAE9C;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,KAAa;IACzC,IAAI,KAA8B,CAAC;IACnC,IAAI,CAAC;QACH,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAA4B,CAAC;IAC7G,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC;IAChE,IAAI,IAAI,KAAK,aAAa,IAAI,IAAI,KAAK,OAAO;QAAE,OAAO,SAAS,CAAC;IACjE,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE;QAAE,OAAO,SAAS,CAAC;IACrE,IAAI,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAChE,IAAI,OAAO,UAAU,KAAK,QAAQ,IAAI,UAAU,CAAC,IAAI,EAAE,KAAK,EAAE;QAAE,OAAO,SAAS,CAAC;IACjF,IAAI,OAAO,KAAK,SAAS,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IAC/F,IAAI,IAAI,KAAK,OAAO,IAAI,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,EAAE,CAAC;QAAE,OAAO,SAAS,CAAC;IACtH,MAAM,SAAS,GAAkB,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,OAAO,OAAO,KAAK,QAAQ,IAAI,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;IACjG,OAAO,EAAE,SAAS,EAAE,GAAG,CAAC,IAAI,KAAK,OAAO,IAAI,EAAE,KAAK,EAAE,KAAe,EAAE,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC;AAC/F,CAAC"}
@@ -0,0 +1,35 @@
1
+ /** After this many refusals a kind of failure is set aside for the user. */
2
+ export declare const SHELVE_AFTER = 3;
3
+ /** A proposal that was refused: the kind of failure it answered, what it changed, and why it was refused. */
4
+ export interface Rejection {
5
+ failure: string;
6
+ candidate: string;
7
+ text: string;
8
+ reason: string;
9
+ /** The prediction it made that did not hold, when one did not. */
10
+ prediction?: string;
11
+ /**
12
+ * The model on which the failure did not recur, so no change could be shown to mend it there, how many failures of
13
+ * the kind were known then, the criteria they were judged by, and how many continuations told it; more failures,
14
+ * other criteria, or fewer continuations than a full measure are reason to look again.
15
+ */
16
+ notRecurring?: {
17
+ model: string;
18
+ failures: number;
19
+ criteria?: string;
20
+ tried?: number;
21
+ };
22
+ at: string;
23
+ }
24
+ /** Refused proposals as JSON Lines, read back so the next proposal for the same failure sees what was tried. */
25
+ export declare class Rejections {
26
+ readonly path: string;
27
+ constructor(path: string);
28
+ record(rejection: Omit<Rejection, "at">): Promise<void>;
29
+ for(failure: string): Promise<Rejection[]>;
30
+ /**
31
+ * Whether the kind of failure, now with `failures` failures judged by `criteria`, is set aside on `model`: refused
32
+ * often enough, or found not to recur there while it had as many, judged the same way.
33
+ */
34
+ shelved(failure: string, model: string, failures: number, criteria?: string): Promise<boolean>;
35
+ }
@@ -0,0 +1,35 @@
1
+ import { appendFile, mkdir, readFile } from "node:fs/promises";
2
+ import { dirname } from "node:path";
3
+ import { RECURRENCE } from "../gate/daily.js";
4
+ /** After this many refusals a kind of failure is set aside for the user. */
5
+ export const SHELVE_AFTER = 3;
6
+ /** Refused proposals as JSON Lines, read back so the next proposal for the same failure sees what was tried. */
7
+ export class Rejections {
8
+ path;
9
+ constructor(path) {
10
+ this.path = path;
11
+ }
12
+ async record(rejection) {
13
+ await mkdir(dirname(this.path), { recursive: true });
14
+ await appendFile(this.path, `${JSON.stringify({ ...rejection, at: new Date().toISOString() })}\n`);
15
+ }
16
+ async for(failure) {
17
+ const text = await readFile(this.path, "utf8").catch((error) => {
18
+ if (error.code === "ENOENT")
19
+ return "";
20
+ throw error;
21
+ });
22
+ return text.split("\n").filter((line) => line !== "").map((line) => JSON.parse(line))
23
+ .filter((rejection) => rejection.failure === failure);
24
+ }
25
+ /**
26
+ * Whether the kind of failure, now with `failures` failures judged by `criteria`, is set aside on `model`: refused
27
+ * often enough, or found not to recur there while it had as many, judged the same way.
28
+ */
29
+ async shelved(failure, model, failures, criteria = "") {
30
+ const refused = await this.for(failure);
31
+ return refused.length >= SHELVE_AFTER || refused.some(({ notRecurring }) => notRecurring?.model === model && failures <= notRecurring.failures && (notRecurring.criteria ?? "") === criteria
32
+ && (notRecurring.tried ?? 0) >= RECURRENCE.tries);
33
+ }
34
+ }
35
+ //# sourceMappingURL=rejections.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rejections.js","sourceRoot":"","sources":["../../src/propose/rejections.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC/D,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,4EAA4E;AAC5E,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC;AAmB9B,gHAAgH;AAChH,MAAM,OAAO,UAAU;IACZ,IAAI,CAAS;IAEtB,YAAY,IAAY;QACtB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,SAAgC;QAC3C,MAAM,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACrD,MAAM,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,SAAS,EAAE,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC;IACrG,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,OAAe;QACvB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,KAA4B,EAAE,EAAE;YACpF,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ;gBAAE,OAAO,EAAE,CAAC;YACvC,MAAM,KAAK,CAAC;QACd,CAAC,CAAC,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAc,CAAC;aAC/F,MAAM,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,OAAO,KAAK,OAAO,CAAC,CAAC;IAC1D,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,OAAO,CAAC,OAAe,EAAE,KAAa,EAAE,QAAgB,EAAE,QAAQ,GAAG,EAAE;QAC3E,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACxC,OAAO,OAAO,CAAC,MAAM,IAAI,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,YAAY,EAAE,EAAE,EAAE,CACzE,YAAY,EAAE,KAAK,KAAK,KAAK,IAAI,QAAQ,IAAI,YAAY,CAAC,QAAQ,IAAI,CAAC,YAAY,CAAC,QAAQ,IAAI,EAAE,CAAC,KAAK,QAAQ;eAC7G,CAAC,YAAY,CAAC,KAAK,IAAI,CAAC,CAAC,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC;IACtD,CAAC;CACF"}
@@ -0,0 +1,4 @@
1
+ /** The name of the skill that teaches the proposer its method; it is part of the layer, so the loop can improve it. */
2
+ export declare const PROPOSER_SKILL = "chopin-propose";
3
+ /** The method a proposer starts with, before the loop has improved it. */
4
+ export declare const DEFAULT_PROPOSER_SKILL = "---\nname: chopin-propose\ndescription: When asked to propose a change to the agent's own instructions from a failure it keeps making.\n---\nYou are improving the agent you are, from a kind of failure it has made in more than one session.\n\n1. Read every time the failure happened. At each marked step find the decision that went wrong: what the agent knew\n then, what it did, and, from what followed, such as the user's correction, what it should have done instead.\n2. Find what the user wants in all of them, not in one alone. When the user corrected the agent, their words say\n what they want and often why.\n3. Propose one change that would have altered every marked step: a short instruction, or one skill when the fix\n needs steps or a check to run. Write it as\n - what to do, said as what to do rather than what to avoid, naming concrete commands, files or checks rather\n than giving general advice;\n - when it applies: something the agent can see before it acts, said in general terms rather than in the words\n of a request you read, and never the correction that came after;\n - when it does not apply, if there is such a case;\n - why, in the user's words when they gave a reason.\n Prefer revising an item already in the layer when one covers the same ground; never add a second item with the\n same role.\n4. Do not repeat a change that was tried and refused; learn from why it was refused.\n5. Keep it general: never name the tasks or sessions you read, never hard-code their answers, and never tell the\n agent to skip checks, force anything, delete, or widen its own permissions.\n6. Choose its scope: \"project\" when it only holds in this repository, \"global\" when it holds anywhere.\n7. Predict what it should fix and what it might break, in one or two sentences that a test could prove wrong.\n\nReply with only one JSON object:\n{\"kind\":\"instruction\" or \"skill\",\"text\":\"the instruction, or the skill's whole SKILL.md\",\"skill\":\"its name, for a\nskill\",\"scope\":\"global\" or \"project\",\"revises\":\"the id of the item it revises, or null\",\"prediction\":\"\u2026\"}\n";
@@ -0,0 +1,34 @@
1
+ /** The name of the skill that teaches the proposer its method; it is part of the layer, so the loop can improve it. */
2
+ export const PROPOSER_SKILL = "chopin-propose";
3
+ /** The method a proposer starts with, before the loop has improved it. */
4
+ export const DEFAULT_PROPOSER_SKILL = `---
5
+ name: ${PROPOSER_SKILL}
6
+ description: When asked to propose a change to the agent's own instructions from a failure it keeps making.
7
+ ---
8
+ You are improving the agent you are, from a kind of failure it has made in more than one session.
9
+
10
+ 1. Read every time the failure happened. At each marked step find the decision that went wrong: what the agent knew
11
+ then, what it did, and, from what followed, such as the user's correction, what it should have done instead.
12
+ 2. Find what the user wants in all of them, not in one alone. When the user corrected the agent, their words say
13
+ what they want and often why.
14
+ 3. Propose one change that would have altered every marked step: a short instruction, or one skill when the fix
15
+ needs steps or a check to run. Write it as
16
+ - what to do, said as what to do rather than what to avoid, naming concrete commands, files or checks rather
17
+ than giving general advice;
18
+ - when it applies: something the agent can see before it acts, said in general terms rather than in the words
19
+ of a request you read, and never the correction that came after;
20
+ - when it does not apply, if there is such a case;
21
+ - why, in the user's words when they gave a reason.
22
+ Prefer revising an item already in the layer when one covers the same ground; never add a second item with the
23
+ same role.
24
+ 4. Do not repeat a change that was tried and refused; learn from why it was refused.
25
+ 5. Keep it general: never name the tasks or sessions you read, never hard-code their answers, and never tell the
26
+ agent to skip checks, force anything, delete, or widen its own permissions.
27
+ 6. Choose its scope: "project" when it only holds in this repository, "global" when it holds anywhere.
28
+ 7. Predict what it should fix and what it might break, in one or two sentences that a test could prove wrong.
29
+
30
+ Reply with only one JSON object:
31
+ {"kind":"instruction" or "skill","text":"the instruction, or the skill's whole SKILL.md","skill":"its name, for a
32
+ skill","scope":"global" or "project","revises":"the id of the item it revises, or null","prediction":"…"}
33
+ `;
34
+ //# sourceMappingURL=skill.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill.js","sourceRoot":"","sources":["../../src/propose/skill.ts"],"names":[],"mappings":"AAAA,uHAAuH;AACvH,MAAM,CAAC,MAAM,cAAc,GAAG,gBAAgB,CAAC;AAE/C,0EAA0E;AAC1E,MAAM,CAAC,MAAM,sBAAsB,GAAG;QAC9B,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4BrB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chopin-ai/core",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Harness-agnostic core: mutable-layer formats, ACP transcripts and the chopin command registry",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -23,7 +23,7 @@
23
23
  ],
24
24
  "dependencies": {
25
25
  "@agentclientprotocol/sdk": "^1.9.0",
26
- "@chopin-ai/workspace": "^0.2.0",
26
+ "@chopin-ai/workspace": "^0.3.0",
27
27
  "yaml": "^2.9.1"
28
28
  }
29
29
  }