@wirecat/cli-core 0.517.0 → 0.519.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.
- package/CHANGELOG.md +24 -0
- package/dist/cli/index.d.ts +2 -1
- package/dist/cli/index.js +1 -1
- package/dist/cli/messenger/schedule-command.d.ts +11 -0
- package/dist/cli/messenger/schedule-command.js +3 -3
- package/dist/cli/shared-command-exports.d.ts +1 -0
- package/dist/cli/shared-command-exports.js +2 -1
- package/dist/entities/fact.d.ts +2 -0
- package/dist/entities/fact.js +2 -0
- package/dist/entities/index.d.ts +3 -0
- package/dist/entities/memory.d.ts +3 -0
- package/dist/entities/memory.js +3 -0
- package/dist/store/evidence-findings.d.ts +3 -0
- package/dist/store/sqlite/evidence-findings.js +3 -1
- package/dist/store/sqlite/evidence-sources.d.ts +2 -0
- package/dist/store/sqlite/evidence-sources.js +35 -11
- package/dist/store/sqlite/facts.d.ts +1 -0
- package/dist/store/sqlite/facts.js +2 -2
- package/dist/store/sqlite/manifest.js +1 -0
- package/dist/store/sqlite/meeting-findings.js +1 -1
- package/dist/store/sqlite/memories.d.ts +19 -0
- package/dist/store/sqlite/memories.js +28 -4
- package/dist/store/sqlite/migrations.generated.js +7 -0
- package/dist/store/sqlite/proposed-actions.js +10 -4
- package/dist/store/sqlite/schema.d.ts +16 -0
- package/dist/store/sqlite/schema.js +2 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,30 @@ shape of this file.
|
|
|
7
7
|
|
|
8
8
|
## Unreleased
|
|
9
9
|
|
|
10
|
+
## 0.519.0 — 01.11.2026
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **`scheduleCommandFor(host)`** mounts the `schedule` command on a CLI that is not a messenger (mail-cli): the host
|
|
15
|
+
gives its identity and a context with the environment, the profile and the output. `scheduleCommand(messenger)`
|
|
16
|
+
is the same command, unchanged.
|
|
17
|
+
|
|
18
|
+
## 0.518.0 — 01.11.2026
|
|
19
|
+
|
|
20
|
+
### Added
|
|
21
|
+
|
|
22
|
+
- **A memory names its project (store version 43)**: `memories.add({ project })`, `memories.list({ project })` and
|
|
23
|
+
`memories.update(ref, { project })`, which moves a memory to another project or to none with `null`. A memory and a
|
|
24
|
+
fact carry `project` and `projectName` (`project` and `project_name` in the `memory` and `fact` entities), so a reader
|
|
25
|
+
needs no second lookup for the name.
|
|
26
|
+
- **`evidenceFindings.sources(id)`** reads each reference a findings batch cites back once, in the shape of
|
|
27
|
+
`memories.sources`: `kind`, `title`, `sender`, `at`, an excerpt of at most 280 characters, `tool` and `missing`.
|
|
28
|
+
|
|
29
|
+
### Fixed
|
|
30
|
+
|
|
31
|
+
- **A findings batch closed with nothing accepted reads as `rejected`** in `proposedActions.get` and `list`, and
|
|
32
|
+
`list({ status: "rejected" })` finds it. The store still writes it `approved`, so older builds read it as before.
|
|
33
|
+
|
|
10
34
|
## 0.517.0 — 01.11.2026
|
|
11
35
|
|
|
12
36
|
### Added
|
package/dist/cli/index.d.ts
CHANGED
|
@@ -96,6 +96,7 @@ export { httpTokenFile, type McpEnvironment, type McpHost, serverEntry } from ".
|
|
|
96
96
|
export { type MessageItem, messageItem, type ReadMessage } from "./messenger/message-items.js";
|
|
97
97
|
export { type ModeProblem, type PrivateFiles, privateFiles, withSqliteSidecars } from "./messenger/private-files.js";
|
|
98
98
|
export { buildReport as buildDoctorReport, type Report as DoctorReport, type ReportContext as DoctorReportContext, reportFileName as doctorReportFileName, } from "./messenger/report.js";
|
|
99
|
+
export type { ScheduleHost } from "./messenger/schedule-command.js";
|
|
99
100
|
export { allAnswer, allHitItem, coverageGaps, type HitItem, type MessageHitItem, messageHitItem, type NoteHitItem, noteHitItem, shownOf, } from "./messenger/search-answers.js";
|
|
100
101
|
export { SEARCHES_QUERY } from "./messenger/searches-command.js";
|
|
101
102
|
export { servingProfiles } from "./messenger/serve-command.js";
|
|
@@ -114,7 +115,7 @@ export { fieldsOf, projectFields } from "./result-fields.js";
|
|
|
114
115
|
export { type Config, type Configuration, count, first, flag, fromFile, type GlobalFlags, NONE_NAMED, namedProfile, type ProfileKind, plain, type ResolveOptions, type Settings, type SettingsExtension, type SettingsExtensionContext, type Source, settingsFor, } from "./settings.js";
|
|
115
116
|
export { type PermissionAnswer, readSetupAnswers, type SetupAnswers, setupPermissionCeiling } from "./setup-answers.js";
|
|
116
117
|
export { AGENTS, type Agent, agentFor, screenFor } from "./setup-screen.js";
|
|
117
|
-
export { accountCommand, addMeetingBatchCommand, addMeetingPreparationCommand, addMeetingProjectCandidatesCommand, addMeetingSeriesInventoryCommand, appDoctorCommand, appMcpCommand, attachmentsCommand, botAdminsCommand, botCommand, botMcpCommand, botMembersCommand, botMessagesCommand, callsCommand, chatsCommand, commandsCommand, completeCommand, configCommand, contactsCommand, conversationsCommand, deleteCommand, doctorCommand, editCommand, floodCommand, forwardCommand, generatedApiCommand, guideCommand, imagesCommand, inboxCommand, markReadCommand, mcpCommand, mentionsCommand, messagesCommand, metadataCommand, modelCatalogueCommand, modelsCommand, pinCommand, pollsCommand, projectsCommand, reactionsCommand, recipientsCommand, repliesCommand, reviewCommand, runsCommand, scheduleCommand, searchCommand, searchesCommand, sendCommand, sendsCommand, serveCommand, serverCommand, skillCommand, starCommands, statsCommand, stickersCommand, storeCommand, tagsCommand, tasksCommand, tasksStatsCommand, topicsCommand, unpinCommand, upgradeCommand, watchCommand, } from "./shared-command-exports.js";
|
|
118
|
+
export { accountCommand, addMeetingBatchCommand, addMeetingPreparationCommand, addMeetingProjectCandidatesCommand, addMeetingSeriesInventoryCommand, appDoctorCommand, appMcpCommand, attachmentsCommand, botAdminsCommand, botCommand, botMcpCommand, botMembersCommand, botMessagesCommand, callsCommand, chatsCommand, commandsCommand, completeCommand, configCommand, contactsCommand, conversationsCommand, deleteCommand, doctorCommand, editCommand, floodCommand, forwardCommand, generatedApiCommand, guideCommand, imagesCommand, inboxCommand, markReadCommand, mcpCommand, mentionsCommand, messagesCommand, metadataCommand, modelCatalogueCommand, modelsCommand, pinCommand, pollsCommand, projectsCommand, reactionsCommand, recipientsCommand, repliesCommand, reviewCommand, runsCommand, scheduleCommand, scheduleCommandFor, searchCommand, searchesCommand, sendCommand, sendsCommand, serveCommand, serverCommand, skillCommand, starCommands, statsCommand, stickersCommand, storeCommand, tagsCommand, tasksCommand, tasksStatsCommand, topicsCommand, unpinCommand, upgradeCommand, watchCommand, } from "./shared-command-exports.js";
|
|
118
119
|
export { assertSharedContracts, customizeSharedCommand, hasSharedContract, overrideSharedContract, type SharedContractOverride, sharedContractOverrides, sharedContracts, } from "./shared-contracts.js";
|
|
119
120
|
export { runnable, withSafety } from "./steps.js";
|
|
120
121
|
export { type StoreInfo, sharedStoreCommand, storeInfo, storeInfoCommand } from "./store-info.js";
|
package/dist/cli/index.js
CHANGED
|
@@ -104,7 +104,7 @@ export { fieldsOf, projectFields } from "./result-fields.js";
|
|
|
104
104
|
export { count, first, flag, fromFile, NONE_NAMED, namedProfile, plain, settingsFor, } from "./settings.js";
|
|
105
105
|
export { readSetupAnswers, setupPermissionCeiling } from "./setup-answers.js";
|
|
106
106
|
export { AGENTS, agentFor, screenFor } from "./setup-screen.js";
|
|
107
|
-
export { accountCommand, addMeetingBatchCommand, addMeetingPreparationCommand, addMeetingProjectCandidatesCommand, addMeetingSeriesInventoryCommand, appDoctorCommand, appMcpCommand, attachmentsCommand, botAdminsCommand, botCommand, botMcpCommand, botMembersCommand, botMessagesCommand, callsCommand, chatsCommand, commandsCommand, completeCommand, configCommand, contactsCommand, conversationsCommand, deleteCommand, doctorCommand, editCommand, floodCommand, forwardCommand, generatedApiCommand, guideCommand, imagesCommand, inboxCommand, markReadCommand, mcpCommand, mentionsCommand, messagesCommand, metadataCommand, modelCatalogueCommand, modelsCommand, pinCommand, pollsCommand, projectsCommand, reactionsCommand, recipientsCommand, repliesCommand, reviewCommand, runsCommand, scheduleCommand, searchCommand, searchesCommand, sendCommand, sendsCommand, serveCommand, serverCommand, skillCommand, starCommands, statsCommand, stickersCommand, storeCommand, tagsCommand, tasksCommand, tasksStatsCommand, topicsCommand, unpinCommand, upgradeCommand, watchCommand, } from "./shared-command-exports.js";
|
|
107
|
+
export { accountCommand, addMeetingBatchCommand, addMeetingPreparationCommand, addMeetingProjectCandidatesCommand, addMeetingSeriesInventoryCommand, appDoctorCommand, appMcpCommand, attachmentsCommand, botAdminsCommand, botCommand, botMcpCommand, botMembersCommand, botMessagesCommand, callsCommand, chatsCommand, commandsCommand, completeCommand, configCommand, contactsCommand, conversationsCommand, deleteCommand, doctorCommand, editCommand, floodCommand, forwardCommand, generatedApiCommand, guideCommand, imagesCommand, inboxCommand, markReadCommand, mcpCommand, mentionsCommand, messagesCommand, metadataCommand, modelCatalogueCommand, modelsCommand, pinCommand, pollsCommand, projectsCommand, reactionsCommand, recipientsCommand, repliesCommand, reviewCommand, runsCommand, scheduleCommand, scheduleCommandFor, searchCommand, searchesCommand, sendCommand, sendsCommand, serveCommand, serverCommand, skillCommand, starCommands, statsCommand, stickersCommand, storeCommand, tagsCommand, tasksCommand, tasksStatsCommand, topicsCommand, unpinCommand, upgradeCommand, watchCommand, } from "./shared-command-exports.js";
|
|
108
108
|
export { assertSharedContracts, customizeSharedCommand, hasSharedContract, overrideSharedContract, sharedContractOverrides, sharedContracts, } from "./shared-contracts.js";
|
|
109
109
|
export { runnable, withSafety } from "./steps.js";
|
|
110
110
|
export { sharedStoreCommand, storeInfo, storeInfoCommand } from "./store-info.js";
|
|
@@ -1,8 +1,19 @@
|
|
|
1
1
|
import { Command } from "commander";
|
|
2
|
+
import { type AppIdentity } from "../../ports/app.js";
|
|
3
|
+
import { type AnswerOutput } from "../envelope.js";
|
|
2
4
|
import { type Messenger } from "./context.js";
|
|
5
|
+
/** What the schedule command needs of a CLI: who it is and, per command, where it prints and which profile runs. */
|
|
6
|
+
export interface ScheduleHost {
|
|
7
|
+
app: AppIdentity;
|
|
8
|
+
context(command: Command): AnswerOutput & {
|
|
9
|
+
env: NodeJS.ProcessEnv;
|
|
10
|
+
profile: string;
|
|
11
|
+
};
|
|
12
|
+
}
|
|
3
13
|
/**
|
|
4
14
|
* Runs the CLI's own commands, or an agent, later or on a timer — through systemd (Linux), launchd
|
|
5
15
|
* (macOS) or Task Scheduler (Windows). Every timer runs `schedule exec <file>`; the schedule file holds
|
|
6
16
|
* the rest, so what runs and with which variables is the same on all three.
|
|
7
17
|
*/
|
|
18
|
+
export declare const scheduleCommandFor: ({ app, context: contextOf }: ScheduleHost) => Command;
|
|
8
19
|
export declare const scheduleCommand: (messenger: Messenger) => Command;
|
|
@@ -61,11 +61,10 @@ const withWhen = (command) => command
|
|
|
61
61
|
* (macOS) or Task Scheduler (Windows). Every timer runs `schedule exec <file>`; the schedule file holds
|
|
62
62
|
* the rest, so what runs and with which variables is the same on all three.
|
|
63
63
|
*/
|
|
64
|
-
export const
|
|
65
|
-
const { app } = messenger;
|
|
64
|
+
export const scheduleCommandFor = ({ app, context: contextOf }) => {
|
|
66
65
|
const command = new Command("schedule").description(`run a ${app.command} command or an agent later or on a timer (systemd, launchd, Task Scheduler); an agent cannot send`);
|
|
67
66
|
const prepare = (self) => {
|
|
68
|
-
const context =
|
|
67
|
+
const context = contextOf(self);
|
|
69
68
|
const system = environmentOf(self).system ?? thisMachine();
|
|
70
69
|
const state = resolvePaths({ appName: app.appName, prefix: app.envPrefix, env: context.env }).state;
|
|
71
70
|
const say = (value, lines) => renderAnswer(self, context, itemOf(value), () => lines.join("\n"));
|
|
@@ -230,3 +229,4 @@ export const scheduleCommand = (messenger) => {
|
|
|
230
229
|
});
|
|
231
230
|
return command;
|
|
232
231
|
};
|
|
232
|
+
export const scheduleCommand = (messenger) => scheduleCommandFor({ app: messenger.app, context: (command) => messengerContext(command, messenger) });
|
|
@@ -764,6 +764,7 @@ export declare const stickersCommand: (messenger: import("./index.js").Messenger
|
|
|
764
764
|
export declare const repliesCommand: (messenger: import("./index.js").Messenger) => import("commander").Command;
|
|
765
765
|
export declare const reviewCommand: (messenger: import("./index.js").Messenger) => import("commander").Command;
|
|
766
766
|
export declare const scheduleCommand: (messenger: import("./index.js").Messenger) => import("commander").Command;
|
|
767
|
+
export declare const scheduleCommandFor: (args_0: import("./messenger/schedule-command.js").ScheduleHost) => import("commander").Command;
|
|
767
768
|
export declare const searchCommand: (messenger: import("./index.js").Messenger, args_1?: {
|
|
768
769
|
topics?: boolean;
|
|
769
770
|
} | undefined) => import("commander").Command;
|
|
@@ -41,7 +41,7 @@ import { reactionsCommand as reactionsCommandDefinition } from "./messenger/reac
|
|
|
41
41
|
import { callsCommand as callsCommandDefinition, stickersCommand as stickersCommandDefinition, } from "./messenger/records-command.js";
|
|
42
42
|
import { repliesCommand as repliesCommandDefinition } from "./messenger/replies-command.js";
|
|
43
43
|
import { reviewCommand as reviewCommandDefinition } from "./messenger/review.js";
|
|
44
|
-
import { scheduleCommand as scheduleCommandDefinition } from "./messenger/schedule-command.js";
|
|
44
|
+
import { scheduleCommand as scheduleCommandDefinition, scheduleCommandFor as scheduleCommandForDefinition, } from "./messenger/schedule-command.js";
|
|
45
45
|
import { searchCommand as searchCommandDefinition } from "./messenger/search-command.js";
|
|
46
46
|
import { searchesCommand as searchesCommandDefinition } from "./messenger/searches-command.js";
|
|
47
47
|
import { serveCommand as serveCommandDefinition } from "./messenger/serve-command.js";
|
|
@@ -104,6 +104,7 @@ export const stickersCommand = sharedCommand(stickersCommandDefinition);
|
|
|
104
104
|
export const repliesCommand = sharedCommand(repliesCommandDefinition);
|
|
105
105
|
export const reviewCommand = sharedCommand(reviewCommandDefinition);
|
|
106
106
|
export const scheduleCommand = sharedCommand(scheduleCommandDefinition);
|
|
107
|
+
export const scheduleCommandFor = sharedCommand(scheduleCommandForDefinition);
|
|
107
108
|
export const searchCommand = sharedCommand(searchCommandDefinition);
|
|
108
109
|
export const searchesCommand = sharedCommand(searchesCommandDefinition);
|
|
109
110
|
export const serveCommand = sharedCommand(serveCommandDefinition);
|
package/dist/entities/fact.d.ts
CHANGED
|
@@ -6,6 +6,8 @@ export declare const fact: v.StrictObjectSchema<{
|
|
|
6
6
|
readonly text: v.StringSchema<undefined>;
|
|
7
7
|
readonly status: v.PicklistSchema<readonly ["proposed", "accepted", "superseded", "reversed", "rejected"], undefined>;
|
|
8
8
|
readonly project: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
9
|
+
/** What the project is called. */
|
|
10
|
+
readonly project_name: v.OptionalSchema<v.NullableSchema<v.StringSchema<undefined>, undefined>, undefined>;
|
|
9
11
|
readonly subject: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "a reference such as `note:42`">]>, undefined>;
|
|
10
12
|
/** What the subject is called; `null` for the owner and for a row with no name. */
|
|
11
13
|
readonly subject_name: v.OptionalSchema<v.NullableSchema<v.StringSchema<undefined>, undefined>, undefined>;
|
package/dist/entities/fact.js
CHANGED
|
@@ -8,6 +8,8 @@ export const fact = v.strictObject({
|
|
|
8
8
|
text,
|
|
9
9
|
status: v.picklist(FACT_STATUSES),
|
|
10
10
|
project: v.nullable(text),
|
|
11
|
+
/** What the project is called. */
|
|
12
|
+
project_name: v.optional(v.nullable(text)),
|
|
11
13
|
subject: v.nullable(reference),
|
|
12
14
|
/** What the subject is called; `null` for the owner and for a row with no name. */
|
|
13
15
|
subject_name: v.optional(v.nullable(text)),
|
package/dist/entities/index.d.ts
CHANGED
|
@@ -5369,6 +5369,7 @@ export declare const ENTITIES: {
|
|
|
5369
5369
|
readonly text: v.StringSchema<undefined>;
|
|
5370
5370
|
readonly status: v.PicklistSchema<readonly ["proposed", "accepted", "superseded", "reversed", "rejected"], undefined>;
|
|
5371
5371
|
readonly project: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
5372
|
+
readonly project_name: v.OptionalSchema<v.NullableSchema<v.StringSchema<undefined>, undefined>, undefined>;
|
|
5372
5373
|
readonly subject: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "a reference such as `note:42`">]>, undefined>;
|
|
5373
5374
|
readonly subject_name: v.OptionalSchema<v.NullableSchema<v.StringSchema<undefined>, undefined>, undefined>;
|
|
5374
5375
|
readonly subject_is_owner: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
|
|
@@ -5408,6 +5409,8 @@ export declare const ENTITIES: {
|
|
|
5408
5409
|
readonly subject: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "a reference such as `note:42`">]>, undefined>;
|
|
5409
5410
|
readonly subject_name: v.OptionalSchema<v.NullableSchema<v.StringSchema<undefined>, undefined>, undefined>;
|
|
5410
5411
|
readonly subject_is_owner: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
|
|
5412
|
+
readonly project: v.OptionalSchema<v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "a reference such as `note:42`">]>, undefined>, undefined>;
|
|
5413
|
+
readonly project_name: v.OptionalSchema<v.NullableSchema<v.StringSchema<undefined>, undefined>, undefined>;
|
|
5411
5414
|
readonly author: v.StrictObjectSchema<{
|
|
5412
5415
|
readonly type: v.PicklistSchema<["person", "bot"], undefined>;
|
|
5413
5416
|
readonly id: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
|
|
@@ -8,6 +8,9 @@ export declare const memory: v.StrictObjectSchema<{
|
|
|
8
8
|
/** What the subject is called; `null` for the owner and for a row with no name. */
|
|
9
9
|
readonly subject_name: v.OptionalSchema<v.NullableSchema<v.StringSchema<undefined>, undefined>, undefined>;
|
|
10
10
|
readonly subject_is_owner: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
|
|
11
|
+
/** The project it belongs to, and what that project is called. */
|
|
12
|
+
readonly project: v.OptionalSchema<v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "a reference such as `note:42`">]>, undefined>, undefined>;
|
|
13
|
+
readonly project_name: v.OptionalSchema<v.NullableSchema<v.StringSchema<undefined>, undefined>, undefined>;
|
|
11
14
|
readonly author: v.StrictObjectSchema<{
|
|
12
15
|
readonly type: v.PicklistSchema<["person", "bot"], undefined>;
|
|
13
16
|
readonly id: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
|
package/dist/entities/memory.js
CHANGED
|
@@ -10,6 +10,9 @@ export const memory = v.strictObject({
|
|
|
10
10
|
/** What the subject is called; `null` for the owner and for a row with no name. */
|
|
11
11
|
subject_name: v.optional(v.nullable(text)),
|
|
12
12
|
subject_is_owner: v.optional(v.boolean()),
|
|
13
|
+
/** The project it belongs to, and what that project is called. */
|
|
14
|
+
project: v.optional(v.nullable(reference)),
|
|
15
|
+
project_name: v.optional(v.nullable(text)),
|
|
13
16
|
author,
|
|
14
17
|
model: v.nullable(text),
|
|
15
18
|
confidence: v.nullable(v.number()),
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type FindingOutcome, type FindingsInput, type FindingsReceipt } from "../meetings/index.js";
|
|
2
|
+
import type { EvidenceSource } from "./sqlite/evidence-sources.js";
|
|
2
3
|
export declare const EVIDENCE_FINDINGS_KIND = "evidence_findings";
|
|
3
4
|
export declare const validateEvidenceFindings: (input: FindingsInput) => FindingsInput;
|
|
4
5
|
/** Who decided: the owner, or an agent the host let decide for the owner, with its reason. */
|
|
@@ -60,4 +61,6 @@ export interface EvidenceFindingsStore {
|
|
|
60
61
|
accept: string[];
|
|
61
62
|
by?: EvidenceFindingsDecider;
|
|
62
63
|
}): Promise<EvidenceFindingsBatch>;
|
|
64
|
+
/** Each reference the batch cites, read back once; one gone from the store since is `missing`. */
|
|
65
|
+
sources(id: string): Promise<EvidenceSource[]>;
|
|
63
66
|
}
|
|
@@ -3,6 +3,7 @@ import { contextEvidenceFingerprint } from "../../context/evidence.js";
|
|
|
3
3
|
import { findingFingerprint, findingHash } from "../../meetings/index.js";
|
|
4
4
|
import { EVIDENCE_FINDINGS_KIND, validateEvidenceFindings, } from "../evidence-findings.js";
|
|
5
5
|
import { contextRecordOf } from "./context-evidence.js";
|
|
6
|
+
import { sourcesOfReferences } from "./evidence-sources.js";
|
|
6
7
|
import { findingsAgent, findingsCoreOver } from "./findings-core.js";
|
|
7
8
|
import { authorActor } from "./memories.js";
|
|
8
9
|
import { proposalOperationsOver } from "./proposed-actions.js";
|
|
@@ -34,7 +35,7 @@ export const evidenceFindingsStoreOver = (context) => {
|
|
|
34
35
|
};
|
|
35
36
|
const view = (proposal) => {
|
|
36
37
|
const input = proposal.payload;
|
|
37
|
-
if (!input || !proposal.target || !["proposed", "approved"].includes(proposal.status))
|
|
38
|
+
if (!input || !proposal.target || !["proposed", "approved", "rejected"].includes(proposal.status))
|
|
38
39
|
return invalid("invalid stored findings batch");
|
|
39
40
|
return {
|
|
40
41
|
id: proposal.id,
|
|
@@ -123,6 +124,7 @@ export const evidenceFindingsStoreOver = (context) => {
|
|
|
123
124
|
});
|
|
124
125
|
},
|
|
125
126
|
get: async (id) => view(load(id)),
|
|
127
|
+
sources: async (id) => sourcesOfReferences(database, view(load(id)).input.findings.flatMap((finding) => finding.evidence.map((one) => one.reference))),
|
|
126
128
|
list: async ({ project, limit = 20, offset = 0, status } = {}) => {
|
|
127
129
|
if (status !== undefined && status !== "proposed" && status !== "reviewed")
|
|
128
130
|
return invalid("finding status is proposed or reviewed");
|
|
@@ -21,3 +21,5 @@ export declare const evidenceSourcesOf: (database: CacheDatabase, from: {
|
|
|
21
21
|
type: string;
|
|
22
22
|
id: number;
|
|
23
23
|
}) => EvidenceSource[];
|
|
24
|
+
/** Each distinct reference read back, in order; one the store no longer resolves keeps its reference, `missing`. */
|
|
25
|
+
export declare const sourcesOfReferences: (database: CacheDatabase, references: readonly string[]) => EvidenceSource[];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { linkKind } from "./link-kinds.js";
|
|
2
|
-
import { referenceOfThing, stateOfThing, storedThing } from "./things.js";
|
|
2
|
+
import { canonicalThingReference, referenceOfThing, stateOfThing, storedThing, thingOf } from "./things.js";
|
|
3
3
|
const EXCERPT_CHARS = 280;
|
|
4
4
|
const excerptOf = (text) => {
|
|
5
5
|
if (text == null)
|
|
@@ -32,16 +32,7 @@ const KIND = {
|
|
|
32
32
|
meeting_transcript: "meeting",
|
|
33
33
|
meeting_transcript_row: "meeting",
|
|
34
34
|
};
|
|
35
|
-
|
|
36
|
-
* Every `evidence` link from a memory or fact, in the order they were written, including one whose target was
|
|
37
|
-
* deleted since: `evidenceOf` drops those, so a reader would never learn the record lost a source.
|
|
38
|
-
*/
|
|
39
|
-
export const evidenceSourcesOf = (database, from) => database
|
|
40
|
-
.prepare(`SELECT to_type, to_id FROM links WHERE from_type = ? AND from_id = ? AND kind = ${linkKind("evidence")} ` +
|
|
41
|
-
"AND to_id IS NOT NULL ORDER BY id")
|
|
42
|
-
.all(from.type, from.id)
|
|
43
|
-
.map((link) => {
|
|
44
|
-
const thing = storedThing(link.to_type, link.to_id);
|
|
35
|
+
const sourceOf = (database, thing) => {
|
|
45
36
|
const state = stateOfThing(database, thing);
|
|
46
37
|
const read = READS[thing.type];
|
|
47
38
|
const row = read === undefined || state === "unavailable" ? undefined : database.prepare(read).get(thing.id);
|
|
@@ -56,4 +47,37 @@ export const evidenceSourcesOf = (database, from) => database
|
|
|
56
47
|
tool: textOf(row?.tool),
|
|
57
48
|
missing: gone,
|
|
58
49
|
};
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Every `evidence` link from a memory or fact, in the order they were written, including one whose target was
|
|
53
|
+
* deleted since: `evidenceOf` drops those, so a reader would never learn the record lost a source.
|
|
54
|
+
*/
|
|
55
|
+
export const evidenceSourcesOf = (database, from) => database
|
|
56
|
+
.prepare(`SELECT to_type, to_id FROM links WHERE from_type = ? AND from_id = ? AND kind = ${linkKind("evidence")} ` +
|
|
57
|
+
"AND to_id IS NOT NULL ORDER BY id")
|
|
58
|
+
.all(from.type, from.id)
|
|
59
|
+
.map((link) => sourceOf(database, storedThing(link.to_type, link.to_id)));
|
|
60
|
+
const thingNamed = (database, reference) => {
|
|
61
|
+
try {
|
|
62
|
+
return thingOf(database, canonicalThingReference(reference));
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
return undefined;
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
/** Each distinct reference read back, in order; one the store no longer resolves keeps its reference, `missing`. */
|
|
69
|
+
export const sourcesOfReferences = (database, references) => [...new Set(references)].map((reference) => {
|
|
70
|
+
const thing = thingNamed(database, reference);
|
|
71
|
+
if (thing)
|
|
72
|
+
return { ...sourceOf(database, thing), ref: reference };
|
|
73
|
+
return {
|
|
74
|
+
ref: reference,
|
|
75
|
+
kind: reference.startsWith("msg:") ? "message" : reference.split(":")[0] || "unknown",
|
|
76
|
+
title: null,
|
|
77
|
+
sender: null,
|
|
78
|
+
at: null,
|
|
79
|
+
excerpt: null,
|
|
80
|
+
tool: null,
|
|
81
|
+
missing: true,
|
|
82
|
+
};
|
|
59
83
|
});
|
|
@@ -12,6 +12,7 @@ export interface Fact {
|
|
|
12
12
|
/** Proposed, then accepted or rejected; a correction supersedes it; only a decision is reversed. */
|
|
13
13
|
status: (typeof FACT_STATUSES)[number];
|
|
14
14
|
project: string | null;
|
|
15
|
+
projectName: string | null;
|
|
15
16
|
subject: string | null;
|
|
16
17
|
subjectName: string | null;
|
|
17
18
|
subjectIsOwner: boolean;
|
|
@@ -3,7 +3,7 @@ import { FACT_TYPES, MEMORY_SCOPES } from "../../domain/knowledge.js";
|
|
|
3
3
|
import { calendarMoment } from "../../domain/moment.js";
|
|
4
4
|
import { evidenceSourcesOf } from "./evidence-sources.js";
|
|
5
5
|
import { linkKind } from "./link-kinds.js";
|
|
6
|
-
import { authorActor, authorOf, dropLinksOf, erase, evidenceOf, keepHighestId, linkEvidence, nextId, subjectOf, } from "./memories.js";
|
|
6
|
+
import { authorActor, authorOf, dropLinksOf, erase, evidenceOf, keepHighestId, linkEvidence, nextId, projectOf, subjectOf, } from "./memories.js";
|
|
7
7
|
import { requiredThing } from "./notes.js";
|
|
8
8
|
import { write } from "./transaction.js";
|
|
9
9
|
const NAMED = "SELECT f.*, b.name AS author_name FROM facts f LEFT JOIN bots b ON f.author_type = 'bot' AND b.id = f.author_id";
|
|
@@ -21,7 +21,7 @@ export const factOperationsOver = (context) => {
|
|
|
21
21
|
type: row.type,
|
|
22
22
|
statement: String(row.statement),
|
|
23
23
|
status: row.status,
|
|
24
|
-
|
|
24
|
+
...projectOf(database, row),
|
|
25
25
|
...subjectOf(database, row),
|
|
26
26
|
occurredAt: row.occurred_at == null ? null : iso(row.occurred_at),
|
|
27
27
|
supersedes: row.supersedes_id == null ? null : `fact:${row.supersedes_id}`,
|
|
@@ -56,6 +56,7 @@ export const MANIFEST = [
|
|
|
56
56
|
{ name: "20261030225520_version-40-note-trigrams", version: 40, minCompatible: 34 },
|
|
57
57
|
{ name: "20261031230945_version-41-task-fields", version: 41, minCompatible: 34 },
|
|
58
58
|
{ name: "20261101002523_version-42-task-revision", version: 42, minCompatible: 34 },
|
|
59
|
+
{ name: "20261101011859_version-43-memory-project", version: 43, minCompatible: 34 },
|
|
59
60
|
];
|
|
60
61
|
export const generatedMigrations = (manifest = MANIFEST, generated = GENERATED) => {
|
|
61
62
|
const migrations = [];
|
|
@@ -43,7 +43,7 @@ export const meetingFindingsStoreOver = (context) => {
|
|
|
43
43
|
};
|
|
44
44
|
const view = (proposal) => {
|
|
45
45
|
const input = proposal.payload;
|
|
46
|
-
if (!input || !proposal.account || !["proposed", "approved"].includes(proposal.status))
|
|
46
|
+
if (!input || !proposal.account || !["proposed", "approved", "rejected"].includes(proposal.status))
|
|
47
47
|
return invalid("invalid stored findings batch");
|
|
48
48
|
return {
|
|
49
49
|
id: proposal.id,
|
|
@@ -19,6 +19,9 @@ export interface Memory {
|
|
|
19
19
|
subjectName: string | null;
|
|
20
20
|
/** The subject is the owner. */
|
|
21
21
|
subjectIsOwner: boolean;
|
|
22
|
+
/** The project it belongs to, as `project:<id>`. */
|
|
23
|
+
project: string | null;
|
|
24
|
+
projectName: string | null;
|
|
22
25
|
/** `name` is a bot's handle; `null` for a person. */
|
|
23
26
|
author: {
|
|
24
27
|
type: Actor["type"];
|
|
@@ -45,6 +48,7 @@ export interface MemoryInput {
|
|
|
45
48
|
evidence: string[];
|
|
46
49
|
author: Author;
|
|
47
50
|
subject?: string;
|
|
51
|
+
project?: string;
|
|
48
52
|
confidence?: number;
|
|
49
53
|
status?: "proposed" | "confirmed";
|
|
50
54
|
/** The memory this one replaces; it becomes `superseded`. */
|
|
@@ -55,11 +59,16 @@ export interface MemoriesStore {
|
|
|
55
59
|
get(reference: string): Promise<Memory>;
|
|
56
60
|
list(options?: {
|
|
57
61
|
subject?: string;
|
|
62
|
+
project?: string;
|
|
58
63
|
kind?: Memory["kind"];
|
|
59
64
|
status?: Memory["status"];
|
|
60
65
|
scope?: Memory["scope"];
|
|
61
66
|
limit?: number;
|
|
62
67
|
}): Promise<Memory[]>;
|
|
68
|
+
/** Moves it to another project, or to none with `null`. */
|
|
69
|
+
update(reference: string, change: {
|
|
70
|
+
project: string | null;
|
|
71
|
+
}): Promise<Memory>;
|
|
63
72
|
/** The owner stands behind it; its evidence was checked now. */
|
|
64
73
|
confirm(reference: string): Promise<Memory>;
|
|
65
74
|
/** Its evidence no longer holds. */
|
|
@@ -100,6 +109,16 @@ export declare const evidenceOf: (context: StoreContext, from: {
|
|
|
100
109
|
}) => string[];
|
|
101
110
|
/** What a memory's or fact's subject is called, for a reader who should not have to look the reference up. */
|
|
102
111
|
export declare const subjectOf: (database: StoreContext["database"], row: Row) => Pick<Memory, "subject" | "subjectName" | "subjectIsOwner">;
|
|
112
|
+
/** A memory's or fact's project, with its name, so a reader does not look the project up. */
|
|
113
|
+
export declare const projectOf: (database: StoreContext["database"], row: Row) => {
|
|
114
|
+
project: null;
|
|
115
|
+
projectName: null;
|
|
116
|
+
} | {
|
|
117
|
+
project: string;
|
|
118
|
+
projectName: string | null;
|
|
119
|
+
};
|
|
120
|
+
/** A `project:<id>` the store holds, as its row id. */
|
|
121
|
+
export declare const projectId: (database: StoreContext["database"], reference: string) => number;
|
|
103
122
|
type Numbered = "memories" | "facts";
|
|
104
123
|
/**
|
|
105
124
|
* The id the next row takes: above every row there is and every one forgotten. SQLite hands out the highest id + 1,
|
|
@@ -64,6 +64,20 @@ export const subjectOf = (database, row) => {
|
|
|
64
64
|
subjectIsOwner: Number(named?.owner) === 1,
|
|
65
65
|
};
|
|
66
66
|
};
|
|
67
|
+
/** A memory's or fact's project, with its name, so a reader does not look the project up. */
|
|
68
|
+
export const projectOf = (database, row) => {
|
|
69
|
+
if (row.project_id == null)
|
|
70
|
+
return { project: null, projectName: null };
|
|
71
|
+
const named = database.prepare(SUBJECT_NAMES.project).get(Number(row.project_id));
|
|
72
|
+
return { project: `project:${row.project_id}`, projectName: named?.name == null ? null : String(named.name) };
|
|
73
|
+
};
|
|
74
|
+
/** A `project:<id>` the store holds, as its row id. */
|
|
75
|
+
export const projectId = (database, reference) => {
|
|
76
|
+
const project = requiredThing(database, reference, "the project");
|
|
77
|
+
if (project.type !== "project")
|
|
78
|
+
throw new CliError("validation_error", `${reference} is not a project`);
|
|
79
|
+
return project.id;
|
|
80
|
+
};
|
|
67
81
|
const highestKey = (table) => `ids.${table}.highest`;
|
|
68
82
|
/**
|
|
69
83
|
* The id the next row takes: above every row there is and every one forgotten. SQLite hands out the highest id + 1,
|
|
@@ -118,6 +132,7 @@ export const memoriesStoreOver = (context) => {
|
|
|
118
132
|
kind: row.kind,
|
|
119
133
|
body: String(row.body),
|
|
120
134
|
...subjectOf(database, row),
|
|
135
|
+
...projectOf(database, row),
|
|
121
136
|
author: authorOf(row),
|
|
122
137
|
model: row.model == null ? null : String(row.model),
|
|
123
138
|
confidence: row.confidence == null ? null : Number(row.confidence),
|
|
@@ -167,12 +182,14 @@ export const memoriesStoreOver = (context) => {
|
|
|
167
182
|
const id = write(database, () => {
|
|
168
183
|
const { actor, model } = authorActor(context, input.author);
|
|
169
184
|
const subject = input.subject === undefined ? undefined : requiredThing(database, input.subject, "the subject");
|
|
185
|
+
const project = input.project === undefined ? null : projectId(database, input.project);
|
|
170
186
|
const replaced = input.supersedes === undefined ? undefined : Number(rowOf(input.supersedes).id);
|
|
171
187
|
const at = now();
|
|
172
188
|
const made = Number(database
|
|
173
189
|
.prepare("INSERT INTO memories (id, kind, body, subject_type, subject_id, author_type, author_id, model, confidence, status, " +
|
|
174
|
-
"last_verified_at, supersedes_id, scope, created_at, updated_at)
|
|
175
|
-
|
|
190
|
+
"last_verified_at, supersedes_id, scope, project_id, created_at, updated_at) " +
|
|
191
|
+
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING id")
|
|
192
|
+
.get(nextId(database, "memories"), kind, body, subject?.type ?? null, subject?.id ?? null, actor.type, actor.id, model, input.confidence ?? null, status, status === "confirmed" ? at : null, replaced ?? null, scope, project, at, at)?.id);
|
|
176
193
|
linkEvidence(context, { type: "memory", id: made }, input.evidence, input.author === "owner" ? "owner" : "agent");
|
|
177
194
|
if (replaced !== undefined)
|
|
178
195
|
database.prepare("UPDATE memories SET status = 'superseded', updated_at = ? WHERE id = ?").run(at, replaced);
|
|
@@ -183,13 +200,20 @@ export const memoriesStoreOver = (context) => {
|
|
|
183
200
|
get: async (reference) => memoryOf(rowOf(reference)),
|
|
184
201
|
list: async (options = {}) => {
|
|
185
202
|
const subject = options.subject === undefined ? undefined : requiredThing(database, options.subject);
|
|
203
|
+
const project = options.project === undefined ? null : projectId(database, options.project);
|
|
186
204
|
return database
|
|
187
205
|
.prepare(`${NAMED} WHERE m.deleted_at IS NULL AND (? IS NULL OR (m.subject_type = ? AND m.subject_id = ?)) ` +
|
|
188
|
-
"AND (? IS NULL OR m.kind = ?) AND (? IS NULL OR m.status = ?) AND (? IS NULL OR m.scope = ?) " +
|
|
206
|
+
"AND (? IS NULL OR m.project_id = ?) AND (? IS NULL OR m.kind = ?) AND (? IS NULL OR m.status = ?) AND (? IS NULL OR m.scope = ?) " +
|
|
189
207
|
"ORDER BY m.created_at DESC, m.id DESC LIMIT ?")
|
|
190
|
-
.all(subject?.type ?? null, subject?.type ?? null, subject?.id ?? null, options.kind ?? null, options.kind ?? null, options.status ?? null, options.status ?? null, options.scope ?? null, options.scope ?? null, Math.min(Math.max(options.limit ?? 100, 1), 500))
|
|
208
|
+
.all(subject?.type ?? null, subject?.type ?? null, subject?.id ?? null, project, project, options.kind ?? null, options.kind ?? null, options.status ?? null, options.status ?? null, options.scope ?? null, options.scope ?? null, Math.min(Math.max(options.limit ?? 100, 1), 500))
|
|
191
209
|
.map(memoryOf);
|
|
192
210
|
},
|
|
211
|
+
update: async (reference, change) => write(database, () => {
|
|
212
|
+
const id = Number(rowOf(reference).id);
|
|
213
|
+
const project = change.project === null ? null : projectId(database, change.project);
|
|
214
|
+
database.prepare("UPDATE memories SET project_id = ?, updated_at = ? WHERE id = ?").run(project, now(), id);
|
|
215
|
+
return memoryOf(rowOf(`memory:${id}`));
|
|
216
|
+
}),
|
|
193
217
|
confirm: async (reference) => setStatus(reference, "confirmed", true),
|
|
194
218
|
markStale: async (reference) => setStatus(reference, "stale", false),
|
|
195
219
|
remove: async (reference) => {
|
|
@@ -870,5 +870,12 @@ export const GENERATED = [
|
|
|
870
870
|
"CREATE TRIGGER tasks_revision_tagging_ai AFTER INSERT ON taggings WHEN new.taggable_type = 'task' BEGIN\n UPDATE tasks SET revision = revision + 1 WHERE id = new.taggable_id;\nEND;",
|
|
871
871
|
"CREATE TRIGGER tasks_revision_tagging_ad AFTER DELETE ON taggings WHEN old.taggable_type = 'task' BEGIN\n UPDATE tasks SET revision = revision + 1 WHERE id = old.taggable_id;\nEND;"
|
|
872
872
|
]
|
|
873
|
+
},
|
|
874
|
+
{
|
|
875
|
+
"name": "20261101011859_version-43-memory-project",
|
|
876
|
+
"statements": [
|
|
877
|
+
"ALTER TABLE `memories` ADD `project_id` integer REFERENCES projects(id);",
|
|
878
|
+
"CREATE INDEX `memories_by_project_id` ON `memories` (`project_id`);"
|
|
879
|
+
]
|
|
873
880
|
}
|
|
874
881
|
];
|
|
@@ -8,9 +8,15 @@ import { write } from "./transaction.js";
|
|
|
8
8
|
export const PROPOSAL_STATUSES = ["proposed", "approved", "rejected", "executed", "failed"];
|
|
9
9
|
export const PROPOSAL_VERDICTS = ["useful", "not_useful"];
|
|
10
10
|
const iso = (value) => (value == null ? null : new Date(Number(value)).toISOString());
|
|
11
|
-
const NAMED = "SELECT p.*, b.name AS proposer_name FROM proposed_actions p " +
|
|
12
|
-
"LEFT JOIN bots b ON p.proposed_by_type = 'bot' AND b.id = p.proposed_by_id";
|
|
13
11
|
const json = (value) => (value == null ? null : JSON.parse(String(value)));
|
|
12
|
+
/**
|
|
13
|
+
* A findings batch closed with nothing accepted is stored `approved`, as older builds read it; it reads as
|
|
14
|
+
* `rejected`, the decision the owner made.
|
|
15
|
+
*/
|
|
16
|
+
const STATUS = `CASE WHEN p.status = 'approved' AND p.kind IN ('${MEETING_FINDINGS_KIND}', '${EVIDENCE_FINDINGS_KIND}') ` +
|
|
17
|
+
"AND json_array_length(p.result, '$.accepted') = 0 THEN 'rejected' ELSE p.status END";
|
|
18
|
+
const NAMED = `SELECT p.*, ${STATUS} AS shown_status, b.name AS proposer_name FROM proposed_actions p ` +
|
|
19
|
+
"LEFT JOIN bots b ON p.proposed_by_type = 'bot' AND b.id = p.proposed_by_id";
|
|
14
20
|
export const proposalOperationsOver = (context) => {
|
|
15
21
|
const { database, now } = context;
|
|
16
22
|
const actionOf = (row) => {
|
|
@@ -26,7 +32,7 @@ export const proposalOperationsOver = (context) => {
|
|
|
26
32
|
: (referenceOfThing(database, storedThing(row.target_type, row.target_id)) ?? null),
|
|
27
33
|
payload: json(row.payload),
|
|
28
34
|
reason: row.reason == null ? null : String(row.reason),
|
|
29
|
-
status: row.
|
|
35
|
+
status: row.shown_status,
|
|
30
36
|
proposedBy: {
|
|
31
37
|
type: row.proposed_by_type,
|
|
32
38
|
id: String(row.proposed_by_id),
|
|
@@ -106,7 +112,7 @@ export const proposalOperationsOver = (context) => {
|
|
|
106
112
|
if (status !== undefined && !PROPOSAL_STATUSES.includes(status))
|
|
107
113
|
throw new CliError("validation_error", `a status is one of ${PROPOSAL_STATUSES.join(", ")}`);
|
|
108
114
|
return database
|
|
109
|
-
.prepare(`${NAMED} WHERE (? IS NULL OR
|
|
115
|
+
.prepare(`${NAMED} WHERE (? IS NULL OR ${STATUS} = ?) ORDER BY p.created_at DESC, p.id DESC LIMIT ?`)
|
|
110
116
|
.all(status ?? null, status ?? null, Math.min(Math.max(limit, 1), 500))
|
|
111
117
|
.map(actionOf);
|
|
112
118
|
},
|
|
@@ -8226,6 +8226,22 @@ export declare const memories: import("drizzle-orm/sqlite-core").SQLiteTableWith
|
|
|
8226
8226
|
identity: undefined;
|
|
8227
8227
|
generated: undefined;
|
|
8228
8228
|
}, {}>;
|
|
8229
|
+
projectId: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
8230
|
+
name: string;
|
|
8231
|
+
tableName: "memories";
|
|
8232
|
+
dataType: "number int53";
|
|
8233
|
+
data: number;
|
|
8234
|
+
driverParam: number;
|
|
8235
|
+
notNull: false;
|
|
8236
|
+
hasDefault: false;
|
|
8237
|
+
isPrimaryKey: false;
|
|
8238
|
+
isAutoincrement: false;
|
|
8239
|
+
hasRuntimeDefault: false;
|
|
8240
|
+
enumValues: undefined;
|
|
8241
|
+
baseColumn: never;
|
|
8242
|
+
identity: undefined;
|
|
8243
|
+
generated: undefined;
|
|
8244
|
+
}, {}>;
|
|
8229
8245
|
};
|
|
8230
8246
|
dialect: 'sqlite';
|
|
8231
8247
|
isAlias: false;
|
|
@@ -872,10 +872,12 @@ export const memories = sqliteTable("memories", {
|
|
|
872
872
|
createdAt: integer("created_at").notNull(),
|
|
873
873
|
updatedAt: integer("updated_at").notNull(),
|
|
874
874
|
deletedAt: integer("deleted_at"),
|
|
875
|
+
projectId: integer("project_id").references(() => projects.id),
|
|
875
876
|
}, (table) => [
|
|
876
877
|
index("memories_by_subject_type_subject_id").on(table.subjectType, table.subjectId),
|
|
877
878
|
index("memories_by_author_type_author_id").on(table.authorType, table.authorId),
|
|
878
879
|
index("memories_by_supersedes_id").on(table.supersedesId),
|
|
880
|
+
index("memories_by_project_id").on(table.projectId),
|
|
879
881
|
]);
|
|
880
882
|
export const memoryIndexPending = sqliteTable("memory_index_pending", {
|
|
881
883
|
id: integer("id").notNull(),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wirecat/cli-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.519.0",
|
|
4
4
|
"description": "The messenger-neutral half of a messaging CLI: domain model, message locators, rendering, name resolution, the SQLite seam, the command skeleton and shared read commands, the send guard, run records and the message store",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Viacheslav Ptsarev",
|