toolroll 0.9.92 → 0.9.94
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 +87 -0
- package/dist/activity-line.d.ts +7 -4
- package/dist/activity-line.js +9 -7
- package/dist/agent-fence.d.ts +4 -0
- package/dist/agent-fence.js +4 -1
- package/dist/approval-authority.d.ts +7 -1
- package/dist/approval-authority.js +11 -2
- package/dist/approval-password.d.ts +31 -0
- package/dist/approval-password.js +26 -0
- package/dist/assignment-status.d.ts +1 -1
- package/dist/assignment-ui.js +3 -3
- package/dist/assignment.js +16 -3
- package/dist/boot-identity.d.ts +2 -1
- package/dist/boot-identity.js +6 -4
- package/dist/bounded-spawn.d.ts +57 -0
- package/dist/bounded-spawn.js +220 -0
- package/dist/browser/terminal.js +42 -42
- package/dist/browser/workspace.css +2 -2
- package/dist/browser/workspace.js +26 -26
- package/dist/browser-crew.js +2 -2
- package/dist/browser-shell.d.ts +1 -1
- package/dist/browser-shell.js +2 -2
- package/dist/browser-workspace.d.ts +48 -7
- package/dist/browser-workspace.js +3 -3
- package/dist/builder-restart.d.ts +21 -0
- package/dist/builder-restart.js +50 -0
- package/dist/builder.d.ts +4 -0
- package/dist/builder.js +73 -25
- package/dist/chat-acceptance.js +1 -1
- package/dist/chat-actions.d.ts +12 -2
- package/dist/chat-actions.js +25 -2
- package/dist/chat-channel.js +11 -0
- package/dist/chat-decide.d.ts +7 -2
- package/dist/chat-decide.js +37 -9
- package/dist/chat-quiet.js +3 -3
- package/dist/chat-voice.d.ts +1 -1
- package/dist/chat-voice.js +2 -2
- package/dist/check-facts.d.ts +126 -0
- package/dist/check-facts.js +318 -0
- package/dist/check-failure.d.ts +22 -3
- package/dist/check-failure.js +57 -13
- package/dist/check-levels-ui.d.ts +4 -0
- package/dist/check-levels-ui.js +10 -1
- package/dist/check-load.d.ts +85 -0
- package/dist/check-load.js +147 -0
- package/dist/check-only-standing.d.ts +36 -0
- package/dist/check-only-standing.js +39 -0
- package/dist/check-only.d.ts +15 -0
- package/dist/check-only.js +99 -0
- package/dist/check-report.d.ts +7 -0
- package/dist/check-report.js +4 -3
- package/dist/check-stamp.d.ts +46 -0
- package/dist/check-stamp.js +93 -0
- package/dist/checkout-cleanup.d.ts +36 -5
- package/dist/checkout-cleanup.js +166 -14
- package/dist/cli-help.d.ts +4 -1
- package/dist/cli-help.js +47 -30
- package/dist/cli.js +16 -1
- package/dist/code-extract.d.ts +44 -0
- package/dist/code-extract.js +88 -0
- package/dist/code-map-acts.d.ts +24 -0
- package/dist/code-map-acts.js +53 -0
- package/dist/code-map-admission.d.ts +52 -0
- package/dist/code-map-admission.js +295 -0
- package/dist/code-map-build.d.ts +63 -0
- package/dist/code-map-build.js +415 -0
- package/dist/code-map-cli.d.ts +153 -0
- package/dist/code-map-cli.js +103 -0
- package/dist/code-map-main.d.ts +1 -0
- package/dist/code-map-main.js +48 -0
- package/dist/code-map-read.d.ts +106 -0
- package/dist/code-map-read.js +171 -0
- package/dist/code-map-report.d.ts +37 -0
- package/dist/code-map-report.js +95 -0
- package/dist/code-map-shape.d.ts +172 -0
- package/dist/code-map-shape.js +327 -0
- package/dist/code-map-store.d.ts +136 -0
- package/dist/code-map-store.js +233 -0
- package/dist/coding-provider.d.ts +2 -0
- package/dist/coding-provider.js +3 -2
- package/dist/coding-update.js +3 -2
- package/dist/coding-workspace.js +4 -4
- package/dist/console-chrome.js +2 -2
- package/dist/containment.d.ts +5 -0
- package/dist/containment.js +14 -1
- package/dist/contracts/chat-actions.d.ts +9 -0
- package/dist/contracts/chat-actions.js +2 -0
- package/dist/contracts/cli.d.ts +52 -0
- package/dist/contracts/cli.js +4 -0
- package/dist/contracts/console-api.d.ts +12 -5
- package/dist/contracts/console-api.js +12 -5
- package/dist/contracts/gateway-tools.d.ts +17 -0
- package/dist/contracts/gateway-tools.js +3 -1
- package/dist/contracts/lead-tools.d.ts +61 -0
- package/dist/contracts/lead-tools.js +10 -1
- package/dist/contracts/project-knowledge.d.ts +38 -5
- package/dist/contracts/project-knowledge.js +11 -5
- package/dist/contracts/project-memory.d.ts +3 -1
- package/dist/contracts/project-memory.js +3 -2
- package/dist/contracts/release-check.d.ts +25 -1
- package/dist/contracts/release-check.js +19 -0
- package/dist/contracts/storage.d.ts +14 -0
- package/dist/contracts/storage.js +3 -1
- package/dist/contracts/store-json.d.ts +2 -0
- package/dist/contracts/youiyoux-request.d.ts +1 -1
- package/dist/contracts/youiyoux-request.js +1 -1
- package/dist/desktop-access.js +6 -2
- package/dist/desktop-update.d.ts +2 -2
- package/dist/desktop-update.js +13 -9
- package/dist/dispatch.js +18 -15
- package/dist/dispose.js +8 -2
- package/dist/easy-start.js +2 -3
- package/dist/eval-hooks.d.ts +55 -0
- package/dist/eval-hooks.js +227 -4
- package/dist/evals.js +2 -1
- package/dist/fast-start.d.ts +136 -0
- package/dist/fast-start.js +431 -0
- package/dist/fast-terms.d.ts +9 -0
- package/dist/fast-terms.js +23 -0
- package/dist/fenced-check-coverage.d.ts +62 -0
- package/dist/fenced-check-coverage.js +54 -0
- package/dist/first-run.js +1 -1
- package/dist/flaky-ci.d.ts +31 -0
- package/dist/flaky-ci.js +149 -0
- package/dist/flaky-cli.d.ts +60 -0
- package/dist/flaky-cli.js +60 -0
- package/dist/flaky.d.ts +83 -0
- package/dist/flaky.js +264 -0
- package/dist/flow-card-task.js +3 -0
- package/dist/flow-triggers.d.ts +1 -1
- package/dist/flow-triggers.js +1 -1
- package/dist/github-import.d.ts +62 -0
- package/dist/github-import.js +146 -0
- package/dist/guides.js +15 -10
- package/dist/invoke.d.ts +5 -1
- package/dist/invoke.js +49 -14
- package/dist/job-object-helper.ps1 +10 -3
- package/dist/keymap.d.ts +41 -0
- package/dist/keymap.js +51 -0
- package/dist/knowledge-cli.js +1 -1
- package/dist/knowledge-ui.d.ts +21 -4
- package/dist/knowledge-ui.js +75 -7
- package/dist/laptop-background.d.ts +16 -0
- package/dist/laptop-background.js +108 -2
- package/dist/lead-context.js +1 -1
- package/dist/lead-contract.d.ts +1 -1
- package/dist/lead-contract.js +2 -2
- package/dist/lead-progress.js +3 -0
- package/dist/lead-status.d.ts +2 -0
- package/dist/lead-status.js +6 -2
- package/dist/lead-tools.js +51 -2
- package/dist/lead.js +1 -1
- package/dist/lesson-notes.d.ts +81 -0
- package/dist/lesson-notes.js +336 -0
- package/dist/limits-ui.js +1 -1
- package/dist/local-owner.d.ts +1 -1
- package/dist/local-owner.js +11 -0
- package/dist/machine-check.d.ts +16 -0
- package/dist/machine-check.js +26 -0
- package/dist/machine-identity.d.ts +75 -0
- package/dist/machine-identity.js +170 -0
- package/dist/mcp-core.js +11 -1
- package/dist/memory-cli.d.ts +300 -1
- package/dist/memory-cli.js +62 -9
- package/dist/memory-pass.d.ts +16 -0
- package/dist/memory-pass.js +67 -3
- package/dist/memory-tidy.d.ts +181 -0
- package/dist/memory-tidy.js +523 -0
- package/dist/memory-use.d.ts +35 -0
- package/dist/memory-use.js +109 -0
- package/dist/merge-checklist.d.ts +55 -0
- package/dist/merge-checklist.js +182 -0
- package/dist/needs-you.d.ts +32 -13
- package/dist/needs-you.js +108 -49
- package/dist/nightly-github.d.ts +2 -0
- package/dist/nightly-github.js +4 -4
- package/dist/operate-remote-arguments.js +6 -1
- package/dist/operate-remote.js +3 -1
- package/dist/operate.d.ts +6 -1
- package/dist/operate.js +540 -70
- package/dist/phase-routing.js +2 -2
- package/dist/plain-schema.d.ts +23 -0
- package/dist/plain-schema.js +94 -0
- package/dist/plain-words.d.ts +20 -0
- package/dist/plain-words.js +66 -0
- package/dist/planner.js +2 -1
- package/dist/process-liveness.d.ts +2 -0
- package/dist/process-liveness.js +61 -17
- package/dist/project-delete-ui.d.ts +7 -2
- package/dist/project-delete-ui.js +12 -1
- package/dist/project-delete.js +13 -2
- package/dist/project-knowledge.d.ts +18 -11
- package/dist/project-knowledge.js +39 -9
- package/dist/project-learning.d.ts +2 -1
- package/dist/project-learning.js +15 -45
- package/dist/project-memory.d.ts +5 -0
- package/dist/project-memory.js +22 -2
- package/dist/proof.js +30 -5
- package/dist/provider-auth.js +1 -1
- package/dist/publish.js +9 -1
- package/dist/pull-request-flow.js +5 -0
- package/dist/push.d.ts +26 -3
- package/dist/push.js +55 -15
- package/dist/release-adapters.d.ts +9 -0
- package/dist/release-adapters.js +87 -1
- package/dist/release-approval.d.ts +191 -0
- package/dist/release-approval.js +382 -0
- package/dist/release-auto.js +26 -17
- package/dist/release-card.d.ts +74 -6
- package/dist/release-card.js +179 -23
- package/dist/release-carry.d.ts +7 -2
- package/dist/release-carry.js +39 -9
- package/dist/release-cli.d.ts +4 -0
- package/dist/release-cli.js +38 -23
- package/dist/release-coverage.js +1 -1
- package/dist/release-next.d.ts +48 -0
- package/dist/release-next.js +161 -0
- package/dist/release.d.ts +50 -1
- package/dist/release.js +118 -11
- package/dist/remote-destination.d.ts +36 -0
- package/dist/remote-destination.js +217 -0
- package/dist/remote-main.d.ts +48 -0
- package/dist/remote-main.js +84 -5
- package/dist/repository-context.d.ts +3 -2
- package/dist/repository-context.js +112 -70
- package/dist/restart-certification.d.ts +1 -0
- package/dist/restart-certification.js +8 -6
- package/dist/result-acts.d.ts +29 -21
- package/dist/result-acts.js +36 -25
- package/dist/result-follow-ups.d.ts +2 -2
- package/dist/result-follow-ups.js +18 -4
- package/dist/result-review.d.ts +1 -1
- package/dist/route-change-check.d.ts +4 -0
- package/dist/route-change-check.js +13 -0
- package/dist/route-change.d.ts +22 -0
- package/dist/route-change.js +89 -0
- package/dist/route-hooks.js +3 -2
- package/dist/route-results.d.ts +6 -1
- package/dist/route-results.js +14 -5
- package/dist/run-closeout.d.ts +1 -1
- package/dist/run-closeout.js +7 -5
- package/dist/runner-process.js +3 -2
- package/dist/runner.js +2 -1
- package/dist/scope.d.ts +6 -1
- package/dist/scope.js +22 -9
- package/dist/serve.d.ts +1 -1
- package/dist/serve.js +24 -18
- package/dist/server/chat.js +14 -12
- package/dist/server/chrome.d.ts +1 -1
- package/dist/server/chrome.js +26 -35
- package/dist/server/console.css +23 -0
- package/dist/server/guards.js +4 -0
- package/dist/server/home.d.ts +6 -0
- package/dist/server/home.js +21 -13
- package/dist/server/http.js +1 -1
- package/dist/server/kit.js +1 -1
- package/dist/server/merge-ready-view.d.ts +10 -0
- package/dist/server/merge-ready-view.js +30 -0
- package/dist/server/pages-assets.d.ts +1 -0
- package/dist/server/pages-assets.js +8 -5
- package/dist/server/pages.js +103 -82
- package/dist/server/render-chat.js +2 -2
- package/dist/server/render-code-map.d.ts +30 -0
- package/dist/server/render-code-map.js +137 -0
- package/dist/server/render-flaky.d.ts +20 -0
- package/dist/server/render-flaky.js +59 -0
- package/dist/server/render-history.js +1 -1
- package/dist/server/render-new-task.d.ts +26 -1
- package/dist/server/render-new-task.js +30 -5
- package/dist/server/render-pages.d.ts +1 -175
- package/dist/server/render-pages.js +38 -313
- package/dist/server/render-projects.d.ts +2 -1
- package/dist/server/render-projects.js +9 -7
- package/dist/server/render-release.d.ts +19 -0
- package/dist/server/render-release.js +84 -0
- package/dist/server/render-results.d.ts +2 -2
- package/dist/server/render-results.js +71 -73
- package/dist/server/render-tasks.d.ts +13 -2
- package/dist/server/render-tasks.js +156 -139
- package/dist/server/retired-routes.d.ts +17 -0
- package/dist/server/retired-routes.js +53 -0
- package/dist/server/route-table.d.ts +4 -1
- package/dist/server/route-table.js +52 -13
- package/dist/server/settings.js +129 -22
- package/dist/server/task-views.js +61 -26
- package/dist/server/tasks.d.ts +17 -6
- package/dist/server/tasks.js +273 -338
- package/dist/server/welcome.js +1 -1
- package/dist/settings-groups-ui.js +1 -1
- package/dist/setup-guide.d.ts +2 -2
- package/dist/stop-proof.d.ts +67 -0
- package/dist/stop-proof.js +295 -0
- package/dist/storage-sweep-process.js +1 -1
- package/dist/storage-sweep.d.ts +5 -3
- package/dist/storage-sweep.js +30 -9
- package/dist/storage-ui.js +28 -17
- package/dist/storage.d.ts +27 -2
- package/dist/storage.js +39 -2
- package/dist/store.d.ts +148 -34
- package/dist/store.js +626 -177
- package/dist/surface.js +46 -5
- package/dist/sweep-quarantine.d.ts +1 -0
- package/dist/sweep-quarantine.js +6 -4
- package/dist/tamper-scan.d.ts +4 -0
- package/dist/tamper-scan.js +90 -0
- package/dist/task-aliases.d.ts +5 -0
- package/dist/task-aliases.js +9 -0
- package/dist/task-control.js +4 -1
- package/dist/task-outcome-cli.d.ts +2 -0
- package/dist/task-outcome-cli.js +36 -17
- package/dist/task-sizing.d.ts +5 -0
- package/dist/task-sizing.js +2 -0
- package/dist/task-source.d.ts +7 -0
- package/dist/task-source.js +14 -0
- package/dist/task-status.d.ts +9 -0
- package/dist/task-status.js +40 -49
- package/dist/teardown-git.d.ts +16 -0
- package/dist/teardown-git.js +63 -5
- package/dist/telegram-progress.js +5 -3
- package/dist/telegram-status.js +6 -4
- package/dist/test-infra.d.ts +8 -0
- package/dist/test-infra.js +18 -0
- package/dist/tidy.js +1 -1
- package/dist/toolroll-update-ui.js +2 -2
- package/dist/toolroll-update.js +18 -5
- package/dist/tui-contract.d.ts +24 -0
- package/dist/tui-source.js +67 -8
- package/dist/tui.js +51 -51
- package/dist/vanished-retry.d.ts +30 -0
- package/dist/vanished-retry.js +174 -0
- package/dist/work-index.d.ts +2 -0
- package/dist/work-index.js +82 -70
- package/dist/work-summary.d.ts +2 -2
- package/dist/work-summary.js +2 -0
- package/dist/workspace-ui.d.ts +4 -2
- package/dist/workspace-ui.js +28 -22
- package/dist/worktree.d.ts +12 -3
- package/dist/worktree.js +68 -13
- package/package.json +1 -1
- package/dist/server/render-next.d.ts +0 -63
- package/dist/server/render-next.js +0 -109
package/dist/memory-cli.js
CHANGED
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
* record who did them. Nothing here starts a model. */
|
|
4
4
|
import { envelopeJson } from './envelope.js';
|
|
5
5
|
import { decisionHistory, getDecision, listDecisions, recordDecision, retireDecision, searchMemory } from './project-memory.js';
|
|
6
|
-
import { decideProposal, defaultAnalyzer, listProposals, memoryStatus, runMemoryPass } from './memory-pass.js';
|
|
6
|
+
import { decideProposal, defaultAnalyzer, defaultTidyAnalyzer, listProposals, memoryStatus, runMemoryPass } from './memory-pass.js';
|
|
7
|
+
import { afterwardsWords, noteAfterwards, NOTE_SURFACE } from './lesson-notes.js';
|
|
8
|
+
import { decideTidy, listTidy, proposeTidy, restoreDecision, restoreLesson, restoreReference, unmergeDecisions } from './memory-tidy.js';
|
|
7
9
|
const flags = [
|
|
8
10
|
{ name: 'repo', takesValue: true, meaning: 'admitted project checkout root' },
|
|
9
11
|
{ name: 'why', takesValue: true, meaning: 'the reason behind a decision' },
|
|
@@ -14,6 +16,9 @@ const flags = [
|
|
|
14
16
|
{ name: 'json', takesValue: false, meaning: 'versioned structured response' },
|
|
15
17
|
{ name: 'db', takesValue: true, meaning: 'local Toolroll database' },
|
|
16
18
|
{ name: 'decision', takesValue: true, meaning: 'accept or reject, for memory apply' },
|
|
19
|
+
{ name: 'claim', takesValue: true, meaning: 'your own words for a lesson note or a clean-up, for memory apply' },
|
|
20
|
+
{ name: 'choice', takesValue: true, meaning: 'what a clean-up does: keep:<id>, both or new; rewrite or retire; for a restore, retire or keep' },
|
|
21
|
+
{ name: 'revision', takesValue: true, meaning: 'the saved knowledge version a reference comes back from, for memory restore' },
|
|
17
22
|
{ name: 'sessions', takesValue: true, meaning: 'at most this many newest sessions for one pass (default 100)' },
|
|
18
23
|
{ name: 'no-local', takesValue: false, meaning: 'read only the plane\'s own transcripts, not local Claude Code or Codex session files' },
|
|
19
24
|
];
|
|
@@ -25,17 +30,24 @@ export const MEMORY_DESCRIPTORS = [
|
|
|
25
30
|
{ action: 'retire', synopsis: 'retire a decision that no longer holds: memory retire <id> --reason "<why>"', mutation: 'unkeyed', takesQuery: true, flags, audience: 'operator' },
|
|
26
31
|
{ action: 'propose', synopsis: 'the backward pass: read recent sessions, keep a ledger of evidenced gaps, propose a few edits (writes nothing to memory)', mutation: 'unkeyed', takesQuery: false, flags },
|
|
27
32
|
{ action: 'review', synopsis: 'list pending memory proposals with their evidence', mutation: 'none', takesQuery: false, flags },
|
|
28
|
-
{ action: 'apply', synopsis: 'decide one proposal: memory apply <id> --decision accept|reject — the only writer', mutation: 'unkeyed', takesQuery: true, flags, audience: 'operator' },
|
|
33
|
+
{ action: 'apply', synopsis: 'decide one proposal: memory apply <id> --decision accept|reject [--claim "<your words>"] — the only writer', mutation: 'unkeyed', takesQuery: true, flags, audience: 'operator' },
|
|
34
|
+
{ action: 'tidy', synopsis: 'propose retiring, merging or settling memory entries; a person accepts each (writes nothing to memory)', mutation: 'unkeyed', takesQuery: false, flags, audience: 'operator' },
|
|
35
|
+
{ action: 'restore', synopsis: 'bring back a decision: memory restore <id>, lesson:<id>, or reference:<id> --revision <version>', mutation: 'unkeyed', takesQuery: true, flags, audience: 'operator' },
|
|
36
|
+
{ action: 'unmerge', synopsis: 'undo a merge of decisions: memory unmerge <merge>', mutation: 'unkeyed', takesQuery: true, flags, audience: 'operator' },
|
|
29
37
|
{ action: 'status', synopsis: 'surface version, instruction budget, sessions analysed, open gaps and pending proposals', mutation: 'none', takesQuery: false, flags },
|
|
30
38
|
];
|
|
31
39
|
const line = (d) => `#${d.id} ${d.claim} — ${d.decidedBy}, ${d.decidedAt.slice(0, 10)}${d.status === 'active' ? '' : ` (${d.status})`}`;
|
|
40
|
+
const TIDY_WORDS = { retire: 'Retire unused', merge: 'Merge duplicates', contradiction: 'Contradiction', 'note-failing': 'Note keeps failing', restore: 'Restore', unmerge: 'Undo merge' };
|
|
41
|
+
const itemWords = (p, item) => item.kind === 'decision' ? `decision #${item.id} (version ${item.revision}, ${item.status}) ${p.titles[`decision:${item.id}`] ?? ''}`.trim()
|
|
42
|
+
: item.kind === 'lesson' ? `lesson #${item.id} (version ${item.version})` : `reference ${item.id} (knowledge version ${item.revision})`;
|
|
43
|
+
const tidyLine = (p) => `t${p.id} ${TIDY_WORDS[p.kind]}${p.status === 'pending' ? '' : ` (${p.status})`}\n ${p.rationale}${p.afterText ? `\n → ${p.afterText}` : ''}\n${p.items.map(item => ` - ${itemWords(p, item)}`).join('\n')}`;
|
|
32
44
|
export async function runMemoryCommand(positional, options, context) {
|
|
33
45
|
const action = positional[0];
|
|
34
46
|
const command = action ? `memory ${action}` : 'memory';
|
|
35
47
|
const fail = (reason, message) => { context.write(context.json ? envelopeJson({ ok: false, command, reason, message }) : message); return reason === 'usage' ? 2 : 1; };
|
|
36
48
|
const ok = (result, lines) => { context.write(context.json ? envelopeJson({ ok: true, command, ...result }) : lines.join('\n')); return 0; };
|
|
37
49
|
if (!MEMORY_DESCRIPTORS.some(d => d.action === action))
|
|
38
|
-
return fail('usage', 'Use memory search <query> | decisions | show <id> | decide "<choice>" --why "<reason>" | retire <id> --reason "<why>" | propose | review | apply <id> --decision accept|reject | status, with --repo PATH.');
|
|
50
|
+
return fail('usage', 'Use memory search <query> | decisions | show <id> | decide "<choice>" --why "<reason>" | retire <id> --reason "<why>" | tidy | restore <id> | unmerge <id> | propose | review | apply <id> --decision accept|reject | status, with --repo PATH.');
|
|
39
51
|
if (context.actor === null)
|
|
40
52
|
return fail('unauthenticated', 'Sign in first: the remembered local login drives memory commands.');
|
|
41
53
|
const text = (key) => { const v = options.get(key); return typeof v === 'string' ? v : null; };
|
|
@@ -51,6 +63,7 @@ export async function runMemoryCommand(positional, options, context) {
|
|
|
51
63
|
return fail('usage', 'Use --repo with the project checkout root.');
|
|
52
64
|
if (!context.repos.includes(repo))
|
|
53
65
|
return fail('not-found', 'That project is outside your access.');
|
|
66
|
+
const expanded = (done, words) => done.restored ? ok({ done }, [words]) : ok({ done }, [`Nothing changed yet: this reaches past what replaced it. Review t${done.proposal} (memory review) and apply it with --choice retire or --choice keep.`]);
|
|
54
67
|
try {
|
|
55
68
|
if (action === 'decisions') {
|
|
56
69
|
const decisions = listDecisions(context.store, repo, context.actor, { status: options.has('all') ? 'all' : 'active', limit: 100 });
|
|
@@ -64,7 +77,8 @@ export async function runMemoryCommand(positional, options, context) {
|
|
|
64
77
|
if (decision === null)
|
|
65
78
|
return fail('not-found', 'No such decision in this project.');
|
|
66
79
|
const history = decisionHistory(context.store, repo, context.actor, id);
|
|
67
|
-
|
|
80
|
+
const after = noteAfterwards(context.store, decision);
|
|
81
|
+
return ok({ decision, history, ...(after === null ? {} : { afterwards: after }) }, [line(decision), `Why: ${decision.why}`, `Source: ${decision.sourceKind}${decision.sourceRef ? ` · ${decision.sourceRef}` : ''}`, ...history.map(h => ` v${h.revision} ${h.action} by ${h.actor} at ${h.at.slice(0, 16).replace('T', ' ')}`), ...(after === null ? [] : [afterwardsWords(after)])]);
|
|
68
82
|
}
|
|
69
83
|
if (action === 'decide') {
|
|
70
84
|
const claim = positional.slice(1).join(' ').trim(), why = text('why') ?? '';
|
|
@@ -76,12 +90,44 @@ export async function runMemoryCommand(positional, options, context) {
|
|
|
76
90
|
}
|
|
77
91
|
if (action === 'status') {
|
|
78
92
|
const status = memoryStatus(context.store, repo, context.actor);
|
|
79
|
-
return ok({ status }, [`Surface ${status.surface} · instructions ${status.instructionBytes}/${status.budgetBytes} bytes`, `Sessions: ${status.sessions.total} seen, ${status.sessions.analyzed} analysed, ${status.sessions.failed} failed`, `Open gaps: ${status.openGaps} · pending proposals: ${status.pending}`]);
|
|
93
|
+
return ok({ status }, [`Surface ${status.surface} · instructions ${status.instructionBytes}/${status.budgetBytes} bytes`, `Sessions: ${status.sessions.total} seen, ${status.sessions.analyzed} analysed, ${status.sessions.failed} failed`, `Open gaps: ${status.openGaps} · pending proposals: ${status.pending}`, ...status.included.map(one => `${one.kind} ${one.title}: ${one.words}`), ...(status.included.length === 0 ? [] : ['Last included is counted in runs; lead chats aren\'t counted.'])]);
|
|
80
94
|
}
|
|
81
|
-
const proposalLine = (p) => `#${p.id} ${p.kind} · ${p.title} (${p.sessions} sessions${p.status === 'pending' ? '' : `, ${p.status}`})\n ${p.rationale}${p.afterText ? `\n → ${p.afterText}` : ''}${p.beforeText ? `\n ← ${p.beforeText}` : ''}${p.evidence.map(e => `\n "${e.quote.slice(0, 160)}" — ${e.session.split(':')[0]}`).join('')}`;
|
|
95
|
+
const proposalLine = (p) => p.surface === NOTE_SURFACE ? `#${p.id} ${p.title}${p.status === 'pending' ? '' : ` (${p.status})`}\n ${p.rationale}\n Draft: ${p.afterText}\n Accept with your own words: memory apply ${p.id} --decision accept --claim "…"` : `#${p.id} ${p.kind} · ${p.title} (${p.sessions} sessions${p.status === 'pending' ? '' : `, ${p.status}`})\n ${p.rationale}${p.afterText ? `\n → ${p.afterText}` : ''}${p.beforeText ? `\n ← ${p.beforeText}` : ''}${p.evidence.map(e => `\n "${e.quote.slice(0, 160)}" — ${e.session.split(':')[0]}`).join('')}`;
|
|
96
|
+
const proof = 'cli-login';
|
|
82
97
|
if (action === 'review') {
|
|
83
98
|
const proposals = listProposals(context.store, repo, options.has('all') ? 'all' : 'pending');
|
|
84
|
-
|
|
99
|
+
const cleanups = listTidy(context.store, repo, options.has('all') ? 'all' : 'pending');
|
|
100
|
+
return ok({ proposals, cleanups }, proposals.length + cleanups.length === 0 ? ['No proposals waiting. Run memory propose after more sessions.'] : [...proposals.map(proposalLine), ...cleanups.map(tidyLine)]);
|
|
101
|
+
}
|
|
102
|
+
if (action === 'tidy') {
|
|
103
|
+
const analyzer = context.tidyAnalyzer ?? defaultTidyAnalyzer(context.store, { ...(context.configDir === undefined ? {} : { configDir: context.configDir }) });
|
|
104
|
+
const report = await proposeTidy(context.store, { repo, actor: context.actor, analyzer }, context.now);
|
|
105
|
+
return ok({ report }, [`New clean-up suggestions: ${report.made}`, ...(report.problem === null ? [] : [report.problem]), 'Review them with memory review.']);
|
|
106
|
+
}
|
|
107
|
+
if (action === 'restore') {
|
|
108
|
+
const target = positional[1] ?? '';
|
|
109
|
+
const lesson = /^lesson:(\d+)$/.exec(target), reference = /^reference:([a-f0-9]{20})$/.exec(target);
|
|
110
|
+
if (lesson !== null) {
|
|
111
|
+
restoreLesson(context.store, context.evidenceRoot ?? '', { repo, actor: context.actor, id: Number(lesson[1]), proof }, context.now);
|
|
112
|
+
return ok({ lesson: Number(lesson[1]) }, [`Lesson #${lesson[1]} is in use again.`]);
|
|
113
|
+
}
|
|
114
|
+
if (reference !== null) {
|
|
115
|
+
const revision = Number(text('revision'));
|
|
116
|
+
if (!Number.isSafeInteger(revision) || revision < 1)
|
|
117
|
+
return fail('usage', 'memory restore reference:<id> --revision <saved version>');
|
|
118
|
+
restoreReference(context.store, { repo, actor: context.actor, id: reference[1], fromRevision: revision, proof }, context.now);
|
|
119
|
+
return ok({ reference: reference[1] }, ['Reference added back as a new version.']);
|
|
120
|
+
}
|
|
121
|
+
const id = Number(target);
|
|
122
|
+
if (!Number.isSafeInteger(id) || id < 1)
|
|
123
|
+
return fail('usage', 'memory restore <decision id> | lesson:<id> | reference:<id> --revision <version>');
|
|
124
|
+
return expanded(restoreDecision(context.store, { repo, actor: context.actor, id, proof }, context.now), `Restored decision #${id}.`);
|
|
125
|
+
}
|
|
126
|
+
if (action === 'unmerge') {
|
|
127
|
+
const merge = Number(positional[1]);
|
|
128
|
+
if (!Number.isSafeInteger(merge) || merge < 1)
|
|
129
|
+
return fail('usage', 'memory unmerge <merge id>');
|
|
130
|
+
return expanded(unmergeDecisions(context.store, { repo, actor: context.actor, merge, proof }, context.now), `Undid merge ${merge}.`);
|
|
85
131
|
}
|
|
86
132
|
if (action === 'propose') {
|
|
87
133
|
const sessions = text('sessions');
|
|
@@ -93,10 +139,17 @@ export async function runMemoryCommand(positional, options, context) {
|
|
|
93
139
|
return ok({ report }, [`Sessions: ${report.sessions} found, ${report.analyzed} analysed now, ${report.cached} already analysed, ${report.failed} failed`, `Open gaps: ${report.gaps} · new proposals: ${report.proposals}`, ...report.problems.slice(0, 5).map(p => ` problem: ${p}`), report.proposals > 0 ? 'Review them with memory review, then memory apply <id> --decision accept|reject.' : 'Nothing to propose yet: a gap needs the same mistake in two distinct sessions.']);
|
|
94
140
|
}
|
|
95
141
|
if (action === 'apply') {
|
|
96
|
-
const
|
|
142
|
+
const cleanup = /^t(\d+)$/.exec(positional[1] ?? '');
|
|
143
|
+
const id = cleanup === null ? Number(positional[1]) : Number(cleanup[1]), decision = text('decision');
|
|
97
144
|
if (!Number.isSafeInteger(id) || id < 1 || (decision !== 'accept' && decision !== 'reject'))
|
|
98
145
|
return fail('usage', 'memory apply <proposal id> --decision accept|reject');
|
|
99
|
-
|
|
146
|
+
if (cleanup !== null) {
|
|
147
|
+
const choice = text('choice'), said = text('claim'), why = text('why');
|
|
148
|
+
const decided = decideTidy(context.store, context.evidenceRoot ?? '', { repo, actor: context.actor, id, decision, proof, ...(choice === null ? {} : { choice }), ...(said === null ? {} : { claim: said }), ...(why === null ? {} : { why }) }, context.now);
|
|
149
|
+
return ok({ cleanup: decided }, [`${decision === 'accept' ? 'Applied' : 'Rejected'} ${tidyLine(decided)}`]);
|
|
150
|
+
}
|
|
151
|
+
const claim = text('claim');
|
|
152
|
+
const proposal = decideProposal(context.store, { repo, actor: context.actor, id, decision, ...(claim === null ? {} : { claim }) }, context.now);
|
|
100
153
|
return ok({ proposal }, [`${decision === 'accept' ? 'Applied' : 'Rejected'} ${proposalLine(proposal)}`]);
|
|
101
154
|
}
|
|
102
155
|
const id = Number(positional[1]), reason = text('reason') ?? '';
|
package/dist/memory-pass.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Store } from './store.js';
|
|
2
2
|
import { performSubscriptionLeadRequest } from './subscription-chat.js';
|
|
3
|
+
import { type TidyAnalyzer } from './memory-tidy.js';
|
|
3
4
|
import { type MemoryProposal, type Verdict } from './contracts/memory-pass.js';
|
|
4
5
|
export type { MemoryProposal, Verdict };
|
|
5
6
|
/** One session's trace, in characters (TEXT_LIMITS.memoryTrace). */
|
|
@@ -68,6 +69,14 @@ export declare function defaultAnalyzer(store: Store, options: {
|
|
|
68
69
|
timeoutMs?: number;
|
|
69
70
|
runner?: Parameters<typeof performSubscriptionLeadRequest>[1];
|
|
70
71
|
}): MemoryAnalyzer;
|
|
72
|
+
/** The clean-up's question to the chat model, asked only on a person's request (memory-tidy.ts proposeTidy). */
|
|
73
|
+
export declare function defaultTidyAnalyzer(store: Store, options?: {
|
|
74
|
+
env?: NodeJS.ProcessEnv;
|
|
75
|
+
configDir?: string;
|
|
76
|
+
fetcher?: typeof fetch;
|
|
77
|
+
runner?: Parameters<typeof performSubscriptionLeadRequest>[1];
|
|
78
|
+
timeoutMs?: number;
|
|
79
|
+
}): TidyAnalyzer;
|
|
71
80
|
/**
|
|
72
81
|
* Read the analyser's answer with the tolerant parse-side schema, then keep only claims whose quote
|
|
73
82
|
* is really in the trace and, for an instruction's effect, whose id is on the surface audited.
|
|
@@ -120,6 +129,7 @@ export declare function decideProposal(store: Store, args: {
|
|
|
120
129
|
actor: string;
|
|
121
130
|
id: number;
|
|
122
131
|
decision: 'accept' | 'reject';
|
|
132
|
+
claim?: string;
|
|
123
133
|
}, now?: Date): MemoryProposal;
|
|
124
134
|
export declare function memoryStatus(store: Store, repo: string, actor: string): {
|
|
125
135
|
surface: string;
|
|
@@ -132,4 +142,10 @@ export declare function memoryStatus(store: Store, repo: string, actor: string):
|
|
|
132
142
|
};
|
|
133
143
|
openGaps: number;
|
|
134
144
|
pending: number;
|
|
145
|
+
included: {
|
|
146
|
+
kind: string;
|
|
147
|
+
item: string;
|
|
148
|
+
title: string;
|
|
149
|
+
words: string;
|
|
150
|
+
}[];
|
|
135
151
|
};
|
package/dist/memory-pass.js
CHANGED
|
@@ -21,6 +21,10 @@ import { listDecisions, recordDecision, refuseLeadMemoryWrite } from './project-
|
|
|
21
21
|
import { composeLeadRequest, performLeadRequest, isDirectChatProvider, CHAT_KEY_ENV } from './converse.js';
|
|
22
22
|
import { performSubscriptionLeadRequest } from './subscription-chat.js';
|
|
23
23
|
import { TEXT_LIMITS } from './text-limits.js';
|
|
24
|
+
import { lastIncludedWords, memoryUseOf } from './memory-use.js';
|
|
25
|
+
import { lessonNoteOf, lessonNoteSourceRef, NOTE_SURFACE, watchNote } from './lesson-notes.js';
|
|
26
|
+
import { currentLocalOwner } from './local-owner.js';
|
|
27
|
+
import { CONTRADICTION_SCHEMA } from './memory-tidy.js';
|
|
24
28
|
import { contractError, parseContract } from './contracts/contract.js';
|
|
25
29
|
import { MEMORY_VERDICT_MODEL_SCHEMA, MEMORY_VERDICT_VERSION, memoryEvidenceSchema, memoryProposalSchema, memoryVerdictReadSchema, readSavedVerdict, savedVerdictSchema } from './contracts/memory-pass.js';
|
|
26
30
|
/** One session's trace, in characters (TEXT_LIMITS.memoryTrace). */
|
|
@@ -220,6 +224,36 @@ export function defaultAnalyzer(store, options) {
|
|
|
220
224
|
return answer.ok ? { ok: true, text: answer.answer.text } : { ok: false, problem: answer.problem };
|
|
221
225
|
};
|
|
222
226
|
}
|
|
227
|
+
/** The clean-up's question to the chat model, asked only on a person's request (memory-tidy.ts proposeTidy). */
|
|
228
|
+
export function defaultTidyAnalyzer(store, options = {}) {
|
|
229
|
+
return async (input) => {
|
|
230
|
+
if (inEvalWorld())
|
|
231
|
+
return { ok: false, problem: 'Clean up makes no provider call in an eval world.' };
|
|
232
|
+
const config = store.getChatConfig();
|
|
233
|
+
if (config === null)
|
|
234
|
+
return { ok: false, problem: 'Chat is not configured, so contradictions were not looked for.' };
|
|
235
|
+
const history = [{ role: 'operator', text: 'Read the decisions above and return the JSON object.' }];
|
|
236
|
+
if (isDirectChatProvider(config.provider)) {
|
|
237
|
+
const env = options.env ?? process.env;
|
|
238
|
+
let key = env[CHAT_KEY_ENV[config.provider]] ?? '';
|
|
239
|
+
if (!key && options.configDir !== undefined) {
|
|
240
|
+
try {
|
|
241
|
+
key = readFileSync(join(options.configDir, `chat-key-${config.provider}`), 'utf8').trim();
|
|
242
|
+
}
|
|
243
|
+
catch {
|
|
244
|
+
key = '';
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
if (!key)
|
|
248
|
+
return { ok: false, problem: `No ${config.provider} key is available, so contradictions were not looked for.` };
|
|
249
|
+
const request = composeLeadRequest({ provider: config.provider, model: config.model, key, system: input.system, dataDocument: input.data, history, tools: [] });
|
|
250
|
+
const answer = await performLeadRequest(request, config.provider, AbortSignal.timeout(options.timeoutMs ?? 120_000), options.fetcher);
|
|
251
|
+
return answer.ok ? { ok: true, text: answer.answer.text } : { ok: false, problem: answer.problem };
|
|
252
|
+
}
|
|
253
|
+
const answer = await performSubscriptionLeadRequest({ provider: config.provider, model: config.model, system: input.system, dataDocument: input.data, history, tools: [], outputSchema: CONTRADICTION_SCHEMA, timeoutMs: options.timeoutMs ?? 180_000 }, options.runner);
|
|
254
|
+
return answer.ok ? { ok: true, text: answer.answer.text } : { ok: false, problem: answer.problem };
|
|
255
|
+
};
|
|
256
|
+
}
|
|
223
257
|
const UNREADABLE = 'The analysis was not a readable verdict.';
|
|
224
258
|
/**
|
|
225
259
|
* Read the analyser's answer with the tolerant parse-side schema, then keep only claims whose quote
|
|
@@ -336,7 +370,8 @@ export function synthesizeProposals(store, repo, actor, surface, now = new Date(
|
|
|
336
370
|
const budgetLeft = INSTRUCTION_BUDGET_BYTES - Buffer.byteLength(view.knowledge.instructions);
|
|
337
371
|
let made = 0;
|
|
338
372
|
store.transact(() => {
|
|
339
|
-
|
|
373
|
+
// A lesson note is bound to its own recorded facts, not to the surface.
|
|
374
|
+
store.handle.prepare("UPDATE memory_proposal SET status='stale' WHERE repo=? AND status='pending' AND surface<>? AND surface<>?").run(repo, surface.version, NOTE_SURFACE);
|
|
340
375
|
const pendingFingerprints = new Set(store.handle.prepare("SELECT fingerprint FROM memory_proposal WHERE repo=? AND status='pending'").all(repo).map(row => String(row['fingerprint'])));
|
|
341
376
|
const rejected = new Map(store.handle.prepare('SELECT fingerprint, sessions FROM memory_rejection WHERE repo=?').all(repo).map(row => [String(row['fingerprint']), Number(row['sessions'])]));
|
|
342
377
|
const consider = (kind, fingerprint, title, rationale, beforeText, afterText, evidence) => {
|
|
@@ -401,6 +436,7 @@ export function listProposals(store, repo, status = 'pending') {
|
|
|
401
436
|
export function decideProposal(store, args, now = new Date()) {
|
|
402
437
|
refuseLeadMemoryWrite();
|
|
403
438
|
return store.transact(() => {
|
|
439
|
+
refuseLeadMemoryWrite();
|
|
404
440
|
// A person who may change this project's memory, read inside the write (a revoked account or lost access refuses).
|
|
405
441
|
if (!store.accountCanAccess(args.actor, args.repo) || store.accountOf(args.actor)?.role !== 'approver')
|
|
406
442
|
throw Error('Project memory is outside your access.');
|
|
@@ -410,8 +446,13 @@ export function decideProposal(store, args, now = new Date()) {
|
|
|
410
446
|
const proposal = proposalOf(row);
|
|
411
447
|
if (proposal.status !== 'pending')
|
|
412
448
|
throw Error('That proposal was already decided.');
|
|
449
|
+
const note = lessonNoteOf(store, proposal.id);
|
|
450
|
+
// The laptop's local owner may decide lesson notes and clean-ups, nothing else here (D3): the act says which.
|
|
451
|
+
const local = currentLocalOwner();
|
|
452
|
+
if (local !== null && (note === null || local.act !== 'memory-review'))
|
|
453
|
+
throw Error('Sign in with your password to do this.');
|
|
413
454
|
const surface = memorySurface(store, args.repo, args.actor);
|
|
414
|
-
if (surface.version !== proposal.surface) {
|
|
455
|
+
if (note === null && surface.version !== proposal.surface) {
|
|
415
456
|
store.handle.prepare("UPDATE memory_proposal SET status='stale' WHERE id=?").run(proposal.id);
|
|
416
457
|
throw Error('Project memory changed since this was proposed. Run the pass again.');
|
|
417
458
|
}
|
|
@@ -419,6 +460,14 @@ export function decideProposal(store, args, now = new Date()) {
|
|
|
419
460
|
store.handle.prepare('INSERT INTO memory_rejection(repo,fingerprint,rejected_at,rejected_by,sessions) VALUES (?,?,?,?,?) ON CONFLICT(repo,fingerprint) DO UPDATE SET rejected_at=excluded.rejected_at, rejected_by=excluded.rejected_by, sessions=excluded.sessions')
|
|
420
461
|
.run(args.repo, proposal.fingerprint, now.toISOString(), args.actor, proposal.sessions);
|
|
421
462
|
}
|
|
463
|
+
else if (note !== null) {
|
|
464
|
+
// A person's words, not the draft: "failed then passed" is what Toolroll recorded; what it means is theirs to say.
|
|
465
|
+
const claim = (args.claim ?? '').trim();
|
|
466
|
+
if (claim === '' || claim === proposal.afterText.trim())
|
|
467
|
+
throw Error('Write the note in your own words before accepting it.');
|
|
468
|
+
recordDecision(store, { repo: args.repo, actor: args.actor, draft: { claim, why: clip(proposal.rationale, 1500), sourceKind: 'result', sourceRef: lessonNoteSourceRef(proposal.id) } }, now);
|
|
469
|
+
watchNote(store, { repo: args.repo, proposal: proposal.id, identities: note.identities, now });
|
|
470
|
+
}
|
|
422
471
|
else {
|
|
423
472
|
const view = knowledgeView(store, args.repo, args.actor);
|
|
424
473
|
if (proposal.kind === 'instruction-add')
|
|
@@ -441,5 +490,20 @@ export function memoryStatus(store, repo, actor) {
|
|
|
441
490
|
return { surface: surface.version, instructionBytes: Buffer.byteLength(view.knowledge.instructions), budgetBytes: INSTRUCTION_BUDGET_BYTES,
|
|
442
491
|
sessions: { total: Number(counts['total'] ?? 0), analyzed: Number(counts['analyzed'] ?? 0), failed: Number(counts['failed'] ?? 0) },
|
|
443
492
|
openGaps: Number(store.handle.prepare('SELECT COUNT(*) AS n FROM memory_gap WHERE repo=? AND retired_at IS NULL').get(repo)?.['n'] ?? 0),
|
|
444
|
-
pending: Number(store.handle.prepare("SELECT COUNT(*) AS n FROM memory_proposal WHERE repo=? AND status='pending'").get(repo)?.['n'] ?? 0)
|
|
493
|
+
pending: Number(store.handle.prepare("SELECT COUNT(*) AS n FROM memory_proposal WHERE repo=? AND status='pending'").get(repo)?.['n'] ?? 0),
|
|
494
|
+
included: includedLines(store, repo, actor, view.knowledge.references) };
|
|
495
|
+
}
|
|
496
|
+
/** "Last included" for every decision, reference and adopted lesson, in the order they're listed elsewhere. */
|
|
497
|
+
function includedLines(store, repo, actor, references) {
|
|
498
|
+
const use = memoryUseOf(store, repo);
|
|
499
|
+
const line = (kind, item, title) => ({ kind, item, title, words: lastIncludedWords(use.get(`${kind}:${item}`)) });
|
|
500
|
+
const lessons = store.handle.prepare("SELECT id, payload FROM project_lesson WHERE repo=? AND status='adopted' ORDER BY id DESC LIMIT 50").all(repo).flatMap(row => {
|
|
501
|
+
try {
|
|
502
|
+
return [line('lesson', String(row['id']), clip(String(JSON.parse(String(row['payload'])).observation ?? ''), 80))];
|
|
503
|
+
}
|
|
504
|
+
catch {
|
|
505
|
+
return [];
|
|
506
|
+
}
|
|
507
|
+
});
|
|
508
|
+
return [...listDecisions(store, repo, actor, { limit: 50 }).map(d => line('decision', String(d.id), clip(d.claim, 80))), ...references.map(ref => line('reference', ref.id, clip(ref.title, 80))), ...lessons];
|
|
445
509
|
}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { type Decision } from "./project-memory.js";
|
|
2
|
+
import type { Store } from "./store.js";
|
|
3
|
+
export declare const UNUSED_DAYS = 60, UNUSED_RUNS = 20, FAILING_NOTE = 3, TIDY_MIN_ENTRIES = 10;
|
|
4
|
+
export declare const TIDY_EVERY_MS: number, TIDY_QUIET_MS = 86400000;
|
|
5
|
+
/** What a stale proposal says. */
|
|
6
|
+
export declare const TIDY_STALE = "Changed since proposed. Run Clean up again.";
|
|
7
|
+
export type TidyItem = {
|
|
8
|
+
kind: "decision";
|
|
9
|
+
id: number;
|
|
10
|
+
revision: number;
|
|
11
|
+
status: string;
|
|
12
|
+
sha: string;
|
|
13
|
+
} | {
|
|
14
|
+
kind: "reference";
|
|
15
|
+
id: string;
|
|
16
|
+
revision: number;
|
|
17
|
+
sha: string;
|
|
18
|
+
} | {
|
|
19
|
+
kind: "lesson";
|
|
20
|
+
id: number;
|
|
21
|
+
version: number;
|
|
22
|
+
sha: string;
|
|
23
|
+
};
|
|
24
|
+
export type TidyKind = "retire" | "merge" | "contradiction" | "note-failing" | "restore" | "unmerge";
|
|
25
|
+
export type TidyProposal = {
|
|
26
|
+
id: number;
|
|
27
|
+
repo: string;
|
|
28
|
+
kind: TidyKind;
|
|
29
|
+
items: TidyItem[];
|
|
30
|
+
afterText: string | null;
|
|
31
|
+
rationale: string;
|
|
32
|
+
evidence: Record<string, unknown>;
|
|
33
|
+
source: string;
|
|
34
|
+
status: string;
|
|
35
|
+
createdAt: string;
|
|
36
|
+
decidedBy: string | null;
|
|
37
|
+
titles: Record<string, string>;
|
|
38
|
+
};
|
|
39
|
+
export declare function listTidy(store: Store, repo: string, status?: "pending" | "all"): TidyProposal[];
|
|
40
|
+
/**
|
|
41
|
+
* The scheduled pass: deterministic, no analyzer in reach. Runs when the project has been quiet for a day, at most
|
|
42
|
+
* weekly, with at least 10 entries. Proposes only.
|
|
43
|
+
*/
|
|
44
|
+
export declare function scheduledTidy(store: Store, repo: string, now: Date): number;
|
|
45
|
+
export type TidyAnalyzer = (input: {
|
|
46
|
+
system: string;
|
|
47
|
+
data: string;
|
|
48
|
+
}) => Promise<{
|
|
49
|
+
ok: true;
|
|
50
|
+
text: string;
|
|
51
|
+
} | {
|
|
52
|
+
ok: false;
|
|
53
|
+
problem: string;
|
|
54
|
+
}>;
|
|
55
|
+
export declare const CONTRADICTION_SCHEMA: {
|
|
56
|
+
readonly type: "object";
|
|
57
|
+
readonly additionalProperties: false;
|
|
58
|
+
readonly required: readonly ["contradictions"];
|
|
59
|
+
readonly properties: {
|
|
60
|
+
readonly contradictions: {
|
|
61
|
+
readonly type: "array";
|
|
62
|
+
readonly items: {
|
|
63
|
+
readonly type: "object";
|
|
64
|
+
readonly additionalProperties: false;
|
|
65
|
+
readonly required: readonly ["a", "b", "why"];
|
|
66
|
+
readonly properties: {
|
|
67
|
+
readonly a: {
|
|
68
|
+
readonly type: "integer";
|
|
69
|
+
};
|
|
70
|
+
readonly b: {
|
|
71
|
+
readonly type: "integer";
|
|
72
|
+
};
|
|
73
|
+
readonly why: {
|
|
74
|
+
readonly type: "string";
|
|
75
|
+
};
|
|
76
|
+
};
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
/** Read a model's pairs: ids of active decisions only, a clean reason, each pair once. Everything else is dropped. */
|
|
82
|
+
export declare function parseContradictions(text: string, active: readonly number[]): {
|
|
83
|
+
a: number;
|
|
84
|
+
b: number;
|
|
85
|
+
why: string;
|
|
86
|
+
}[];
|
|
87
|
+
/** Clean up, on a person's request: the deterministic pass with no quiet gate, and contradictions when an analyzer is given. */
|
|
88
|
+
export declare function proposeTidy(store: Store, args: {
|
|
89
|
+
repo: string;
|
|
90
|
+
actor: string;
|
|
91
|
+
analyzer?: TidyAnalyzer;
|
|
92
|
+
}, now: Date): Promise<{
|
|
93
|
+
made: number;
|
|
94
|
+
problem: string | null;
|
|
95
|
+
}>;
|
|
96
|
+
/** Every decision reachable from `id` through ordinary supersession and not-undone merges, transitively (never `id`). */
|
|
97
|
+
export declare function successorChain(store: Store, repo: string, id: number): number[];
|
|
98
|
+
/** The active decisions in `id`'s chain. */
|
|
99
|
+
export declare function activeTail(store: Store, repo: string, id: number): number[];
|
|
100
|
+
/** One new decision from several; each old one superseded with a "merged into" history row; every member listed. */
|
|
101
|
+
export declare function mergeDecisions(store: Store, args: {
|
|
102
|
+
repo: string;
|
|
103
|
+
actor: string;
|
|
104
|
+
ids: readonly number[];
|
|
105
|
+
claim: string;
|
|
106
|
+
why: string;
|
|
107
|
+
proof: string;
|
|
108
|
+
}, now: Date): Decision;
|
|
109
|
+
export type ExpandedChange = {
|
|
110
|
+
restored: false;
|
|
111
|
+
proposal: number;
|
|
112
|
+
items: TidyItem[];
|
|
113
|
+
};
|
|
114
|
+
/**
|
|
115
|
+
* Restore a retired or superseded decision. With no active tail it goes straight back to active. With one, nothing
|
|
116
|
+
* changes: a proposal names every affected item, and a person chooses what happens to the tail.
|
|
117
|
+
*/
|
|
118
|
+
export declare function restoreDecision(store: Store, args: {
|
|
119
|
+
repo: string;
|
|
120
|
+
actor: string;
|
|
121
|
+
id: number;
|
|
122
|
+
proof: string;
|
|
123
|
+
}, now: Date): {
|
|
124
|
+
restored: true;
|
|
125
|
+
decision: Decision;
|
|
126
|
+
} | ExpandedChange;
|
|
127
|
+
/**
|
|
128
|
+
* Undo a merge. Direct only while its successor is active, at the revision recorded at the merge, and not merged on.
|
|
129
|
+
* Otherwise nothing changes: a proposal names every affected item, the later merge included. A merge already undone is
|
|
130
|
+
* refused and changes nothing.
|
|
131
|
+
*/
|
|
132
|
+
export declare function unmergeDecisions(store: Store, args: {
|
|
133
|
+
repo: string;
|
|
134
|
+
actor: string;
|
|
135
|
+
merge: number;
|
|
136
|
+
proof: string;
|
|
137
|
+
}, now: Date): {
|
|
138
|
+
restored: true;
|
|
139
|
+
successor: number;
|
|
140
|
+
} | ExpandedChange;
|
|
141
|
+
/** A disabled lesson back in use (re-checks its support, bound to its version and sha). */
|
|
142
|
+
export declare function restoreLesson(store: Store, root: string, args: {
|
|
143
|
+
repo: string;
|
|
144
|
+
actor: string;
|
|
145
|
+
id: number;
|
|
146
|
+
proof: string;
|
|
147
|
+
}, now: Date): void;
|
|
148
|
+
/** A reference back from history, as a new knowledge revision bound to the current one. */
|
|
149
|
+
export declare function restoreReference(store: Store, args: {
|
|
150
|
+
repo: string;
|
|
151
|
+
actor: string;
|
|
152
|
+
id: string;
|
|
153
|
+
fromRevision: number;
|
|
154
|
+
proof: string;
|
|
155
|
+
}, now: Date): void;
|
|
156
|
+
export type TidyDecision = {
|
|
157
|
+
repo: string;
|
|
158
|
+
actor: string;
|
|
159
|
+
id: number;
|
|
160
|
+
decision: "accept" | "reject";
|
|
161
|
+
choice?: string;
|
|
162
|
+
claim?: string;
|
|
163
|
+
why?: string;
|
|
164
|
+
proof: string;
|
|
165
|
+
};
|
|
166
|
+
/**
|
|
167
|
+
* Accept or reject one proposal: the one writer of a proposal's outcome. In one transaction, a person's standing, the
|
|
168
|
+
* proposal's state and every bound item are re-read; any difference marks it stale and changes nothing.
|
|
169
|
+
*/
|
|
170
|
+
export declare function decideTidy(store: Store, root: string, args: TidyDecision, now: Date): TidyProposal;
|
|
171
|
+
/** Merges that can still be undone, for the page. */
|
|
172
|
+
export declare function undoableMerges(store: Store, repo: string): {
|
|
173
|
+
merge: number;
|
|
174
|
+
successor: number;
|
|
175
|
+
predecessors: number[];
|
|
176
|
+
}[];
|
|
177
|
+
/** Lessons that were disabled and can be used again, for the page. */
|
|
178
|
+
export declare function disabledLessons(store: Store, repo: string): {
|
|
179
|
+
id: number;
|
|
180
|
+
observation: string;
|
|
181
|
+
}[];
|