@cleocode/contracts 2026.9.15 → 2026.9.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent-registry.d.ts +11 -1
- package/dist/agent-registry.d.ts.map +1 -1
- package/dist/code-symbol.d.ts +13 -1
- package/dist/code-symbol.d.ts.map +1 -1
- package/dist/code-symbol.js +1 -1
- package/dist/config.d.ts +42 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/credential-transfer.d.ts +103 -0
- package/dist/credential-transfer.d.ts.map +1 -0
- package/dist/credential-transfer.js +21 -0
- package/dist/credential-transfer.js.map +1 -0
- package/dist/dispatch/operations-registry.d.ts.map +1 -1
- package/dist/dispatch/operations-registry.js +7 -2
- package/dist/dispatch/operations-registry.js.map +1 -1
- package/dist/doctor.d.ts +103 -0
- package/dist/doctor.d.ts.map +1 -1
- package/dist/errors.d.ts +5 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +2 -1
- package/dist/errors.js.map +1 -1
- package/dist/graph.d.ts +118 -1
- package/dist/graph.d.ts.map +1 -1
- package/dist/index.d.ts +6 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/operations/nexus-scope-map.d.ts +16 -0
- package/dist/operations/nexus-scope-map.d.ts.map +1 -1
- package/dist/operations/nexus-scope-map.js +16 -0
- package/dist/operations/nexus-scope-map.js.map +1 -1
- package/dist/operations/nexus-scope.d.ts +8 -0
- package/dist/operations/nexus-scope.d.ts.map +1 -1
- package/dist/operations/nexus.d.ts +77 -5
- package/dist/operations/nexus.d.ts.map +1 -1
- package/dist/portable-bundle.d.ts +436 -0
- package/dist/portable-bundle.d.ts.map +1 -0
- package/dist/portable-bundle.js +17 -0
- package/dist/portable-bundle.js.map +1 -0
- package/package.json +2 -2
- package/src/__tests__/__snapshots__/operations-registry.test.ts.snap +1 -1
- package/src/agent-registry.ts +11 -1
- package/src/code-symbol.ts +13 -1
- package/src/config.ts +44 -0
- package/src/credential-transfer.ts +112 -0
- package/src/dispatch/operations-registry.ts +8 -2
- package/src/doctor.ts +115 -0
- package/src/errors.ts +7 -1
- package/src/graph.ts +122 -1
- package/src/index.ts +50 -0
- package/src/operations/nexus-scope-map.ts +16 -0
- package/src/operations/nexus-scope.ts +9 -0
- package/src/operations/nexus.ts +87 -5
- package/src/portable-bundle.ts +476 -0
package/src/agent-registry.ts
CHANGED
|
@@ -35,8 +35,18 @@ export interface AgentCredential {
|
|
|
35
35
|
agentId: string;
|
|
36
36
|
/** Human-readable display name. */
|
|
37
37
|
displayName: string;
|
|
38
|
-
/**
|
|
38
|
+
/**
|
|
39
|
+
* API key for authentication (`sk_live_*`). Stored encrypted at rest (global
|
|
40
|
+
* KDF, T12352). When {@link AgentCredential.requiresReauth} is true this is
|
|
41
|
+
* NOT the real key — re-register it.
|
|
42
|
+
*/
|
|
39
43
|
apiKey: string;
|
|
44
|
+
/**
|
|
45
|
+
* True when the stored key is not recoverable (written before T12352, which
|
|
46
|
+
* stored a derived HMAC and discarded the key, or encrypted on another
|
|
47
|
+
* device). Re-register with `cleo agent register --id <id> --api-key <key>`.
|
|
48
|
+
*/
|
|
49
|
+
requiresReauth?: boolean;
|
|
40
50
|
/** Base URL of the messaging API (default: api.signaldock.io). */
|
|
41
51
|
apiBaseUrl: string;
|
|
42
52
|
/** Agent classification from the registry (e.g. 'code_dev', 'orchestrator'). */
|
package/src/code-symbol.ts
CHANGED
|
@@ -87,7 +87,7 @@ export const PARSER_WORKER_HEAP_MIN_MB = 8;
|
|
|
87
87
|
export const PARSER_WORKER_HEAP_MAX_MB = 4_096;
|
|
88
88
|
|
|
89
89
|
/** Default V8 old-space per parse worker, in MiB. */
|
|
90
|
-
export const PARSER_WORKER_HEAP_DEFAULT_MB =
|
|
90
|
+
export const PARSER_WORKER_HEAP_DEFAULT_MB = 512;
|
|
91
91
|
|
|
92
92
|
/** Bounds for one native parser invocation; cancellation is cooperative in-process. */
|
|
93
93
|
export interface ParserExecutionLimits {
|
|
@@ -111,6 +111,18 @@ export interface ParserProcessHandle {
|
|
|
111
111
|
nativeMemory: 'unverified';
|
|
112
112
|
/** Kill owned execution and wait until it has exited. */
|
|
113
113
|
stop(): Promise<void>;
|
|
114
|
+
/**
|
|
115
|
+
* The tail of the child's own standard error, bounded in size.
|
|
116
|
+
*
|
|
117
|
+
* The stream was drained and discarded so a full pipe could not block the
|
|
118
|
+
* child. Draining is right; discarding is not — it threw away the only
|
|
119
|
+
* account of why a worker died, leaving the parent to report the broken pipe
|
|
120
|
+
* it noticed afterwards. Retaining a bounded tail keeps the pipe moving and
|
|
121
|
+
* keeps the cause (T12313).
|
|
122
|
+
*
|
|
123
|
+
* @returns Captured stderr, newest content last; empty when the child said nothing.
|
|
124
|
+
*/
|
|
125
|
+
stderrTail(): string;
|
|
114
126
|
}
|
|
115
127
|
|
|
116
128
|
/** Dependency-inverted access to the existing runtime process containment service. */
|
package/src/config.ts
CHANGED
|
@@ -751,6 +751,43 @@ export interface LeadRollupConfig {
|
|
|
751
751
|
mode?: LeadRollupMode;
|
|
752
752
|
}
|
|
753
753
|
|
|
754
|
+
/**
|
|
755
|
+
* Inline refresh policy for code-graph queries (T12316).
|
|
756
|
+
*
|
|
757
|
+
* Before answering, a graph query checks how far the published index lags the
|
|
758
|
+
* working tree. When only a few files are stale it refreshes the index inline
|
|
759
|
+
* (incrementally) and discloses that it did; above these bounds it answers
|
|
760
|
+
* from the stale index with a warning instead of blocking.
|
|
761
|
+
*/
|
|
762
|
+
export interface NexusAutoRefreshConfig {
|
|
763
|
+
/**
|
|
764
|
+
* Whether queries may refresh the index inline.
|
|
765
|
+
*
|
|
766
|
+
* @defaultValue true
|
|
767
|
+
*/
|
|
768
|
+
enabled?: boolean;
|
|
769
|
+
/**
|
|
770
|
+
* Most stale files a query refreshes inline.
|
|
771
|
+
*
|
|
772
|
+
* @defaultValue 25
|
|
773
|
+
*/
|
|
774
|
+
maxFiles?: number;
|
|
775
|
+
/**
|
|
776
|
+
* Wall-clock budget in milliseconds. A refresh whose recorded-cost estimate
|
|
777
|
+
* exceeds it is not started; a started one is cancelled at the budget and
|
|
778
|
+
* leaves the previous graph intact.
|
|
779
|
+
*
|
|
780
|
+
* @defaultValue 60000
|
|
781
|
+
*/
|
|
782
|
+
budgetMs?: number;
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
/** Code-graph (`cleo nexus`) configuration. */
|
|
786
|
+
export interface NexusConfig {
|
|
787
|
+
/** Inline refresh of a slightly stale index before graph queries answer. */
|
|
788
|
+
autoRefresh?: NexusAutoRefreshConfig;
|
|
789
|
+
}
|
|
790
|
+
|
|
754
791
|
/**
|
|
755
792
|
* Daemon lifecycle configuration.
|
|
756
793
|
*
|
|
@@ -930,6 +967,13 @@ export interface CleoConfig {
|
|
|
930
967
|
* @saga T10377
|
|
931
968
|
*/
|
|
932
969
|
leadRollup?: LeadRollupConfig;
|
|
970
|
+
/**
|
|
971
|
+
* Code-graph behaviour — inline refresh bounds for stale-index queries.
|
|
972
|
+
*
|
|
973
|
+
* @defaultValue undefined (auto-refresh enabled, 25 files, 60 s)
|
|
974
|
+
* @task T12316
|
|
975
|
+
*/
|
|
976
|
+
nexus?: NexusConfig;
|
|
933
977
|
/**
|
|
934
978
|
* Daemon lifecycle settings.
|
|
935
979
|
*
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Credential transfer contracts — moving stored secrets between devices
|
|
3
|
+
* without moving the device key.
|
|
4
|
+
*
|
|
5
|
+
* CLEO encrypts stored credentials under a key derived from the local
|
|
6
|
+
* `machine-key`. That key never leaves the device (it is excluded from every
|
|
7
|
+
* backup bundle, encrypted or not). A credential therefore crosses devices in
|
|
8
|
+
* one of two ways:
|
|
9
|
+
*
|
|
10
|
+
* - **Sealed** — an encrypted backup carries the credentials re-sealed under a
|
|
11
|
+
* key derived from the user's passphrase; the importing device unseals them
|
|
12
|
+
* and re-encrypts each one under ITS OWN machine-key.
|
|
13
|
+
* - **Re-entered** — an unencrypted backup carries no usable credential
|
|
14
|
+
* material; the import lists every credential to re-enter, each with the
|
|
15
|
+
* exact command that re-enters it.
|
|
16
|
+
*
|
|
17
|
+
* @task T12326
|
|
18
|
+
* @module credential-transfer
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* The store a credential lives in.
|
|
23
|
+
*
|
|
24
|
+
* - `project-agent` — `tasks_agent_credentials.api_key_encrypted` in the
|
|
25
|
+
* project `cleo.db` (project KDF).
|
|
26
|
+
* - `service-connection` — `service_connections.credentials_enc` in the global
|
|
27
|
+
* `cleo.db` (global KDF, id `service:<provider>:<label>`).
|
|
28
|
+
* - `llm-pool` — an entry in `<cleoHome>/llm-credentials.json`.
|
|
29
|
+
* - `agent-registry` — `agent_registry_agents.api_key_encrypted` in the global
|
|
30
|
+
* `cleo.db` (global KDF, id `agent:<agentId>`, `gk1:` prefix — T12352).
|
|
31
|
+
*
|
|
32
|
+
* @task T12326
|
|
33
|
+
* @task T12352
|
|
34
|
+
*/
|
|
35
|
+
export type CredentialStoreKind =
|
|
36
|
+
| 'project-agent'
|
|
37
|
+
| 'service-connection'
|
|
38
|
+
| 'llm-pool'
|
|
39
|
+
| 'agent-registry';
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* A credential identified WITHOUT its value — safe to print, log, or write
|
|
43
|
+
* into a bundle manifest.
|
|
44
|
+
*
|
|
45
|
+
* @task T12326
|
|
46
|
+
*/
|
|
47
|
+
export interface CredentialDescriptor {
|
|
48
|
+
/** Which store holds the credential. */
|
|
49
|
+
readonly store: CredentialStoreKind;
|
|
50
|
+
/**
|
|
51
|
+
* Stable identity within the store: the agent id (`project-agent`,
|
|
52
|
+
* `agent-registry`),
|
|
53
|
+
* `<provider>:<label>` (`service-connection`, `llm-pool`).
|
|
54
|
+
*/
|
|
55
|
+
readonly id: string;
|
|
56
|
+
/** Human-readable description of the credential. */
|
|
57
|
+
readonly label: string;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* A credential the target device must re-enter, with the one command that
|
|
62
|
+
* re-enters it.
|
|
63
|
+
*
|
|
64
|
+
* @task T12326
|
|
65
|
+
*/
|
|
66
|
+
export interface CredentialReentry extends CredentialDescriptor {
|
|
67
|
+
/** Why the credential could not be carried over. */
|
|
68
|
+
readonly reason: string;
|
|
69
|
+
/** The exact CLI command that re-enters this credential (secret shown as a placeholder). */
|
|
70
|
+
readonly reentryCommand: string;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Outcome of sealing the local credentials under a passphrase.
|
|
75
|
+
*
|
|
76
|
+
* @task T12326
|
|
77
|
+
*/
|
|
78
|
+
export interface SealCredentialsResult {
|
|
79
|
+
/** Sealed payload bytes (passphrase-encrypted). Never contains machine-key material. */
|
|
80
|
+
readonly sealed: Uint8Array;
|
|
81
|
+
/** Credentials carried in the sealed payload. */
|
|
82
|
+
readonly sealedCredentials: readonly CredentialDescriptor[];
|
|
83
|
+
/** Credentials that could not be decrypted locally and must be re-entered after restore. */
|
|
84
|
+
readonly reentry: readonly CredentialReentry[];
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Outcome of unsealing a payload into the local stores.
|
|
89
|
+
*
|
|
90
|
+
* @task T12326
|
|
91
|
+
*/
|
|
92
|
+
export interface UnsealCredentialsResult {
|
|
93
|
+
/** Credentials re-encrypted under the local machine-key and written. */
|
|
94
|
+
readonly restored: readonly CredentialDescriptor[];
|
|
95
|
+
/** Credentials the operator must re-enter, each with its command. */
|
|
96
|
+
readonly reentry: readonly CredentialReentry[];
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Outcome of migrating project credentials from the legacy path-bound KDF to
|
|
101
|
+
* the project-identity KDF.
|
|
102
|
+
*
|
|
103
|
+
* @task T12326
|
|
104
|
+
*/
|
|
105
|
+
export interface ProjectCredentialMigrationResult {
|
|
106
|
+
/** Credentials re-encrypted from the legacy path KDF to the project-id KDF. */
|
|
107
|
+
readonly migrated: readonly CredentialDescriptor[];
|
|
108
|
+
/** Credentials already under the project-id KDF (untouched). */
|
|
109
|
+
readonly current: readonly CredentialDescriptor[];
|
|
110
|
+
/** Credentials no candidate key could decrypt — ciphertext left untouched. */
|
|
111
|
+
readonly reentry: readonly CredentialReentry[];
|
|
112
|
+
}
|
|
@@ -6965,7 +6965,12 @@ export const OPERATIONS: OperationDef[] = [
|
|
|
6965
6965
|
required: false,
|
|
6966
6966
|
description: 'JS regex matched against project_path',
|
|
6967
6967
|
},
|
|
6968
|
-
{
|
|
6968
|
+
{
|
|
6969
|
+
name: 'includeTemp',
|
|
6970
|
+
type: 'boolean',
|
|
6971
|
+
required: false,
|
|
6972
|
+
description: 'Match .temp/ or OS temp-directory paths',
|
|
6973
|
+
},
|
|
6969
6974
|
{
|
|
6970
6975
|
name: 'includeTests',
|
|
6971
6976
|
type: 'boolean',
|
|
@@ -7000,7 +7005,8 @@ export const OPERATIONS: OperationDef[] = [
|
|
|
7000
7005
|
name: 'vacuum',
|
|
7001
7006
|
type: 'boolean',
|
|
7002
7007
|
required: false,
|
|
7003
|
-
description:
|
|
7008
|
+
description:
|
|
7009
|
+
'After delete, VACUUM the global registry store (<cleoHome>/cleo.db) to reclaim space (T9117 · T12324)',
|
|
7004
7010
|
},
|
|
7005
7011
|
],
|
|
7006
7012
|
},
|
package/src/doctor.ts
CHANGED
|
@@ -1063,3 +1063,118 @@ export interface LegacyBackupScanResult {
|
|
|
1063
1063
|
*/
|
|
1064
1064
|
errors: Array<{ path: string; error: string }>;
|
|
1065
1065
|
}
|
|
1066
|
+
|
|
1067
|
+
// ============================================================================
|
|
1068
|
+
// Superseded-store reconcile — `cleo doctor superseded-store --reconcile` (T12319)
|
|
1069
|
+
// ============================================================================
|
|
1070
|
+
|
|
1071
|
+
/**
|
|
1072
|
+
* Per-table row accounting for one legacy source table reconciled into the
|
|
1073
|
+
* live project `cleo.db`.
|
|
1074
|
+
*
|
|
1075
|
+
* `missingInLive` counts SOURCE rows whose primary key is absent from the live
|
|
1076
|
+
* table — the rows a reconcile must still copy. It is `null` only when the key
|
|
1077
|
+
* cannot be compared (no shared primary key); such a table is judged by counts.
|
|
1078
|
+
*
|
|
1079
|
+
* @task T12319
|
|
1080
|
+
*/
|
|
1081
|
+
export interface SupersededStoreTableCount {
|
|
1082
|
+
/** Logical legacy source (`tasks`, `brain (project)`, `conduit`). */
|
|
1083
|
+
sourceDb: string;
|
|
1084
|
+
/** Table name in the legacy file. */
|
|
1085
|
+
sourceTable: string;
|
|
1086
|
+
/** Consolidated table in `cleo.db` the rows land in. */
|
|
1087
|
+
targetTable: string;
|
|
1088
|
+
/** Rows in the legacy table. */
|
|
1089
|
+
sourceRows: number;
|
|
1090
|
+
/** Rows in the live table. */
|
|
1091
|
+
liveRows: number;
|
|
1092
|
+
/** Source rows whose key is absent from the live table, or `null` if not comparable. */
|
|
1093
|
+
missingInLive: number | null;
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
/**
|
|
1097
|
+
* A legacy row set an additive reconcile did NOT copy (T12355). Every one is
|
|
1098
|
+
* listed; none is silently dropped.
|
|
1099
|
+
*
|
|
1100
|
+
* - `live-authoritative` — the table's runtime home is part of the task graph
|
|
1101
|
+
* the project has been editing on the consolidated store; a legacy row
|
|
1102
|
+
* missing there may have been deleted or rewritten since, so copying it
|
|
1103
|
+
* could resurrect or contradict live state.
|
|
1104
|
+
* - `collides-with-live` — inserting the row would violate a live key or
|
|
1105
|
+
* constraint (e.g. a `(task_id, ordinal)` slot a newer criterion now holds),
|
|
1106
|
+
* i.e. it could only land by overwriting live data.
|
|
1107
|
+
*
|
|
1108
|
+
* @task T12355
|
|
1109
|
+
*/
|
|
1110
|
+
export interface SupersededStoreConflict {
|
|
1111
|
+
/** Logical legacy source. */
|
|
1112
|
+
sourceDb: string;
|
|
1113
|
+
/** Table in the legacy file. */
|
|
1114
|
+
sourceTable: string;
|
|
1115
|
+
/** Table the runtime reads it from. */
|
|
1116
|
+
targetTable: string;
|
|
1117
|
+
/** Legacy rows left uncopied. */
|
|
1118
|
+
rows: number;
|
|
1119
|
+
/** Why they were left. */
|
|
1120
|
+
reason: 'live-authoritative' | 'collides-with-live';
|
|
1121
|
+
}
|
|
1122
|
+
|
|
1123
|
+
/**
|
|
1124
|
+
* Outcome of `cleo doctor superseded-store --reconcile`.
|
|
1125
|
+
*
|
|
1126
|
+
* - `nothing-to-reconcile` — every legacy row is already present; no write.
|
|
1127
|
+
* - `planned` — dry-run; `before` shows what an apply would copy.
|
|
1128
|
+
* - `reconciled` — rows copied and re-verified; `after` proves zero missing.
|
|
1129
|
+
* - `refused` — the post-copy verification found a mismatch; every row this
|
|
1130
|
+
* run inserted was reverted (see `rolledBack`) and the command exits non-zero.
|
|
1131
|
+
*
|
|
1132
|
+
* @task T12319
|
|
1133
|
+
*/
|
|
1134
|
+
export type SupersededStoreReconcileOutcome =
|
|
1135
|
+
| 'nothing-to-reconcile'
|
|
1136
|
+
| 'planned'
|
|
1137
|
+
| 'reconciled'
|
|
1138
|
+
| 'refused';
|
|
1139
|
+
|
|
1140
|
+
/**
|
|
1141
|
+
* Receipt of a superseded-store reconcile. Written verbatim to
|
|
1142
|
+
* `<staging>/reconcile-receipt.json` for an apply.
|
|
1143
|
+
*
|
|
1144
|
+
* @task T12319
|
|
1145
|
+
*/
|
|
1146
|
+
export interface SupersededStoreReconcileResult {
|
|
1147
|
+
/** Final outcome; `refused` is the only non-zero exit. */
|
|
1148
|
+
outcome: SupersededStoreReconcileOutcome;
|
|
1149
|
+
/**
|
|
1150
|
+
* `full` — every legacy row must end up present (stranded projects).
|
|
1151
|
+
* `additive` — for a project already running on the consolidated store:
|
|
1152
|
+
* copy only rows whose keys are absent from live history tables, never
|
|
1153
|
+
* touch the live task graph, and list everything left in `conflicts`.
|
|
1154
|
+
*/
|
|
1155
|
+
mode: 'full' | 'additive';
|
|
1156
|
+
/** Legacy rows deliberately left uncopied (additive mode); empty in full mode. */
|
|
1157
|
+
conflicts: SupersededStoreConflict[];
|
|
1158
|
+
/** `true` when nothing was written. */
|
|
1159
|
+
dryRun: boolean;
|
|
1160
|
+
/** Absolute project root. */
|
|
1161
|
+
projectRoot: string;
|
|
1162
|
+
/** Absolute path of the live project `cleo.db`. */
|
|
1163
|
+
liveStorePath: string;
|
|
1164
|
+
/** Legacy files read (never modified, moved or deleted). */
|
|
1165
|
+
sourcePaths: string[];
|
|
1166
|
+
/** Per-table accounting before any write. */
|
|
1167
|
+
before: SupersededStoreTableCount[];
|
|
1168
|
+
/** Per-table accounting after the copy; empty unless a copy ran. */
|
|
1169
|
+
after: SupersededStoreTableCount[];
|
|
1170
|
+
/** Rows inserted into `cleo.db` by this run (0 for dry-run / no-op). */
|
|
1171
|
+
rowsCopied: number;
|
|
1172
|
+
/** Rows reverted after a refused verification (0 otherwise). */
|
|
1173
|
+
rolledBack: number;
|
|
1174
|
+
/** Staging directory holding the journal, source backups and receipt, or `null`. */
|
|
1175
|
+
stagingDir: string | null;
|
|
1176
|
+
/** Absolute path of the written receipt, or `null` when none was written. */
|
|
1177
|
+
receiptPath: string | null;
|
|
1178
|
+
/** Human-readable explanation, suitable for printing verbatim. */
|
|
1179
|
+
reason: string;
|
|
1180
|
+
}
|
package/src/errors.ts
CHANGED
|
@@ -543,6 +543,11 @@ export interface ChangesetYamlInvalidDetails {
|
|
|
543
543
|
snippet?: string;
|
|
544
544
|
/** Underlying parser message, propagated verbatim for diagnostics. */
|
|
545
545
|
parserMessage: string;
|
|
546
|
+
/**
|
|
547
|
+
* Remediation naming the fix when the failure is a value starting with a
|
|
548
|
+
* YAML-reserved character, e.g. wrap it in double quotes (T12351).
|
|
549
|
+
*/
|
|
550
|
+
hint?: string;
|
|
546
551
|
}
|
|
547
552
|
|
|
548
553
|
/**
|
|
@@ -588,7 +593,8 @@ export class ChangesetYamlInvalidError extends Error {
|
|
|
588
593
|
constructor(details: ChangesetYamlInvalidDetails) {
|
|
589
594
|
const linePart = details.line !== null ? `:${details.line}` : '';
|
|
590
595
|
super(
|
|
591
|
-
`E_CHANGESET_YAML_INVALID: ${details.file}${linePart} invalid YAML frontmatter: ${details.parserMessage}
|
|
596
|
+
`E_CHANGESET_YAML_INVALID: ${details.file}${linePart} invalid YAML frontmatter: ${details.parserMessage}` +
|
|
597
|
+
(details.hint !== undefined ? `\n hint: ${details.hint}` : ''),
|
|
592
598
|
);
|
|
593
599
|
this.name = 'ChangesetYamlInvalidError';
|
|
594
600
|
this.details = details;
|
package/src/graph.ts
CHANGED
|
@@ -658,8 +658,19 @@ export interface GraphIndexAssessment {
|
|
|
658
658
|
sourceRoots?: GraphSourceRootAssessment;
|
|
659
659
|
/** Immutable publication identity allocated before extraction; absent on historical indexes. */
|
|
660
660
|
generation?: string;
|
|
661
|
-
/**
|
|
661
|
+
/**
|
|
662
|
+
* Unmodeled AST scopes remain explicit limitations instead of fabricated declarations.
|
|
663
|
+
* Absent on a summary read: the list is stored beside the assessment (T12348)
|
|
664
|
+
* and loaded only on request; {@link GraphIndexAssessment.referenceCount} still
|
|
665
|
+
* reports how many there are.
|
|
666
|
+
*/
|
|
662
667
|
references?: GraphIndexReferenceReport[];
|
|
668
|
+
/**
|
|
669
|
+
* Number of retained references, recorded whenever the list is stored
|
|
670
|
+
* separately from this summary (T12348). Absent on historical indexes, whose
|
|
671
|
+
* `references` are inline.
|
|
672
|
+
*/
|
|
673
|
+
referenceCount?: number;
|
|
663
674
|
/** Explicit nested repository/worktree scope retained for subsequent rebuilds. */
|
|
664
675
|
includedRepositories?: string[];
|
|
665
676
|
/** Canonical root whose relative file paths this graph describes. */
|
|
@@ -682,6 +693,116 @@ export interface GraphPublicationRows {
|
|
|
682
693
|
nodes: NexusNodeInsertRow[];
|
|
683
694
|
/** Complete replacement relationship generation. */
|
|
684
695
|
relations: NexusRelationInsertRow[];
|
|
696
|
+
/**
|
|
697
|
+
* Per-file extraction memo changes committed in the same transaction as the rows.
|
|
698
|
+
* Absent when the producer does not maintain a parse cache.
|
|
699
|
+
*/
|
|
700
|
+
parseCache?: GraphParseCacheUpdate;
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
/**
|
|
704
|
+
* One file's memoized extraction output, valid only for the exact bytes and extractor build.
|
|
705
|
+
*
|
|
706
|
+
* Extraction is a pure function of `(path, content, extractor build, publication generation)`;
|
|
707
|
+
* the generation token embedded in anonymous identities is rewritten on reuse, so a reused
|
|
708
|
+
* entry yields exactly what re-parsing the same bytes would.
|
|
709
|
+
*/
|
|
710
|
+
export interface GraphParseCacheEntry {
|
|
711
|
+
/** Path relative to the assessed source root. */
|
|
712
|
+
path: string;
|
|
713
|
+
/** SHA-256 of the bytes that produced this extraction. */
|
|
714
|
+
contentHash: string;
|
|
715
|
+
/** Fingerprint of the extractor build (code + grammars) that produced it. */
|
|
716
|
+
fingerprint: string;
|
|
717
|
+
/** Publication generation embedded in the stored payload's anonymous identities. */
|
|
718
|
+
generation: string;
|
|
719
|
+
/** Compressed serialized extraction; opaque to every owner except the producing pipeline. */
|
|
720
|
+
payload: Uint8Array;
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
/** Parse-cache mutation applied atomically with a graph publication. */
|
|
724
|
+
export interface GraphParseCacheUpdate {
|
|
725
|
+
/** Extractor fingerprint every retained and written entry must carry. */
|
|
726
|
+
fingerprint: string;
|
|
727
|
+
/** Delete every existing entry before applying `upserts` (full rebuilds). */
|
|
728
|
+
reset: boolean;
|
|
729
|
+
/** Entries for files parsed during this run. */
|
|
730
|
+
upserts: GraphParseCacheEntry[];
|
|
731
|
+
/** Paths whose entries no longer describe a current, successfully parsed file. */
|
|
732
|
+
deletePaths: string[];
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
/** Why and how an index run chose between reusing prior extraction and parsing everything. */
|
|
736
|
+
export interface GraphIndexRunSummary {
|
|
737
|
+
/**
|
|
738
|
+
* `incremental` parsed only files without a reusable extraction; `full` parsed every file;
|
|
739
|
+
* `unchanged` found no source difference and published nothing.
|
|
740
|
+
*/
|
|
741
|
+
mode: 'incremental' | 'full' | 'unchanged';
|
|
742
|
+
/** Human-readable reason for the mode, including every full-rebuild fallback. */
|
|
743
|
+
reason: string;
|
|
744
|
+
/** Previously indexed files whose content hash differs. */
|
|
745
|
+
changedFiles: number;
|
|
746
|
+
/** Files absent from the previous generation. */
|
|
747
|
+
addedFiles: number;
|
|
748
|
+
/** Previously indexed files no longer present. */
|
|
749
|
+
deletedFiles: number;
|
|
750
|
+
/** Files handed to the parser this run. */
|
|
751
|
+
parsedFiles: number;
|
|
752
|
+
/** Files whose extraction was reused from the parse cache instead of re-parsed. */
|
|
753
|
+
reusedFiles: number;
|
|
754
|
+
/**
|
|
755
|
+
* Files whose imports, calls, accesses and heritage were re-resolved. Resolution always runs
|
|
756
|
+
* over the complete merged symbol table, so this equals every extracted file; dependents of
|
|
757
|
+
* changed files are therefore never left pointing at stale targets.
|
|
758
|
+
*/
|
|
759
|
+
resolvedFiles: number;
|
|
760
|
+
/** Wall-clock milliseconds per pipeline phase, for cost disclosure. */
|
|
761
|
+
phaseMs: Record<string, number>;
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
/**
|
|
765
|
+
* Freshness of a published code-graph index relative to the working tree.
|
|
766
|
+
*
|
|
767
|
+
* Computed by metadata comparison (mtime + size) with a content-hash fallback on mismatch, so
|
|
768
|
+
* a touched-but-identical file is not reported stale.
|
|
769
|
+
*/
|
|
770
|
+
export interface GraphIndexFreshness {
|
|
771
|
+
/** Whether a published index exists at all. */
|
|
772
|
+
indexed: boolean;
|
|
773
|
+
/** `fresh` when no indexed file differs from disk; `stale` otherwise; `unknown` if unassessed. */
|
|
774
|
+
status: 'fresh' | 'stale' | 'unknown';
|
|
775
|
+
/** Assessment timestamp of the published generation. */
|
|
776
|
+
lastIndexedAt: string | null;
|
|
777
|
+
/** Files recorded in the published generation's assessment. */
|
|
778
|
+
fileCount: number;
|
|
779
|
+
/** Modified, added and deleted source files. */
|
|
780
|
+
staleFileCount: number;
|
|
781
|
+
/** Up to a bounded sample of stale paths, for disclosure. */
|
|
782
|
+
stalePaths: string[];
|
|
783
|
+
/** Whether the queried symbol's own file is stale; absent when no symbol file is known. */
|
|
784
|
+
symbolFileStale?: boolean;
|
|
785
|
+
/** The symbol file the `symbolFileStale` verdict describes. */
|
|
786
|
+
symbolFile?: string;
|
|
787
|
+
/** Command that refreshes the index. */
|
|
788
|
+
refreshCommand: string;
|
|
789
|
+
/** Rough cost of that refresh, for the caller to decide whether to wait for it. */
|
|
790
|
+
refreshEstimate: string;
|
|
791
|
+
/** Milliseconds spent assessing freshness. */
|
|
792
|
+
checkMs: number;
|
|
793
|
+
/** Diagnostic reason when `status` is `unknown`. */
|
|
794
|
+
reason?: string;
|
|
795
|
+
/** Present when the query attempted to refresh the index inline before answering. */
|
|
796
|
+
autoRefresh?: {
|
|
797
|
+
/** Whether the inline refresh published a new generation. */
|
|
798
|
+
refreshed: boolean;
|
|
799
|
+
/** Stale files at the time the refresh was attempted. */
|
|
800
|
+
staleFiles: number;
|
|
801
|
+
/** Milliseconds the refresh took (or ran before it was abandoned). */
|
|
802
|
+
durationMs: number;
|
|
803
|
+
/** Why the refresh ran, was skipped, or failed. */
|
|
804
|
+
reason: string;
|
|
805
|
+
};
|
|
685
806
|
}
|
|
686
807
|
|
|
687
808
|
// ---------------------------------------------------------------------------
|
package/src/index.ts
CHANGED
|
@@ -291,6 +291,8 @@ export type {
|
|
|
291
291
|
LoggingConfig,
|
|
292
292
|
LogLevel,
|
|
293
293
|
MemoryBridgeMode,
|
|
294
|
+
NexusAutoRefreshConfig,
|
|
295
|
+
NexusConfig,
|
|
294
296
|
OutputConfig,
|
|
295
297
|
OutputFormat,
|
|
296
298
|
ProviderConfig,
|
|
@@ -307,6 +309,15 @@ export type {
|
|
|
307
309
|
SystemBinding,
|
|
308
310
|
} from './config.js';
|
|
309
311
|
export type { AdapterContextMonitorProvider } from './context-monitor.js';
|
|
312
|
+
// === Credential Transfer Types (T12326 — portable credentials) ===
|
|
313
|
+
export type {
|
|
314
|
+
CredentialDescriptor,
|
|
315
|
+
CredentialReentry,
|
|
316
|
+
CredentialStoreKind,
|
|
317
|
+
ProjectCredentialMigrationResult,
|
|
318
|
+
SealCredentialsResult,
|
|
319
|
+
UnsealCredentialsResult,
|
|
320
|
+
} from './credential-transfer.js';
|
|
310
321
|
// === Claude Code credential parsing (T9307 — pure helper, no core imports) ===
|
|
311
322
|
export type {
|
|
312
323
|
ClaudeCodeOAuthBlock,
|
|
@@ -494,6 +505,10 @@ export type {
|
|
|
494
505
|
SagaAuditResult,
|
|
495
506
|
SagaAuditViolation,
|
|
496
507
|
SagaAuditViolationKind,
|
|
508
|
+
SupersededStoreConflict,
|
|
509
|
+
SupersededStoreReconcileOutcome,
|
|
510
|
+
SupersededStoreReconcileResult,
|
|
511
|
+
SupersededStoreTableCount,
|
|
497
512
|
WorktreeAnomaly,
|
|
498
513
|
WorktreeAnomalyKind,
|
|
499
514
|
} from './doctor.js';
|
|
@@ -701,9 +716,13 @@ export type {
|
|
|
701
716
|
GraphEdgeConfidenceLabel,
|
|
702
717
|
GraphIndexAssessment,
|
|
703
718
|
GraphIndexFileReport,
|
|
719
|
+
GraphIndexFreshness,
|
|
704
720
|
GraphIndexReferenceReport,
|
|
721
|
+
GraphIndexRunSummary,
|
|
705
722
|
GraphNode,
|
|
706
723
|
GraphNodeKind,
|
|
724
|
+
GraphParseCacheEntry,
|
|
725
|
+
GraphParseCacheUpdate,
|
|
707
726
|
GraphPublicationRows,
|
|
708
727
|
GraphRelation,
|
|
709
728
|
GraphRelationType,
|
|
@@ -1478,9 +1497,13 @@ export type {
|
|
|
1478
1497
|
NexusPermissionLevel,
|
|
1479
1498
|
NexusPermissionSetParams,
|
|
1480
1499
|
NexusPermissionSetResult,
|
|
1500
|
+
NexusProjectCheckout,
|
|
1481
1501
|
NexusProjectRecord,
|
|
1482
1502
|
NexusProjectStats,
|
|
1483
1503
|
NexusProjectsCleanParams,
|
|
1504
|
+
NexusProjectsCleanReason,
|
|
1505
|
+
NexusProjectsCleanReceipt,
|
|
1506
|
+
NexusProjectsCleanRemoval,
|
|
1484
1507
|
NexusProjectsCleanResult,
|
|
1485
1508
|
NexusProjectsListParams,
|
|
1486
1509
|
NexusProjectsListResult,
|
|
@@ -1498,6 +1521,7 @@ export type {
|
|
|
1498
1521
|
NexusRefreshBridgeResult,
|
|
1499
1522
|
NexusRegisterParams,
|
|
1500
1523
|
NexusRegisterResult,
|
|
1524
|
+
NexusRegistryClassification,
|
|
1501
1525
|
NexusResolveParams,
|
|
1502
1526
|
NexusResolveResult,
|
|
1503
1527
|
NexusRouteMapParams,
|
|
@@ -1950,6 +1974,32 @@ export type {
|
|
|
1950
1974
|
PlaybookRun,
|
|
1951
1975
|
PlaybookRunStatus,
|
|
1952
1976
|
} from './playbook.js';
|
|
1977
|
+
// === Portable Bundle (manifest v2) Types (T12318 — lossless machine migration) ===
|
|
1978
|
+
export type {
|
|
1979
|
+
PortableBundleManifest,
|
|
1980
|
+
PortableBundleScope,
|
|
1981
|
+
PortableDatabaseEntry,
|
|
1982
|
+
PortableDatabaseRole,
|
|
1983
|
+
PortableExclusion,
|
|
1984
|
+
PortableExportResult,
|
|
1985
|
+
PortableFileEntry,
|
|
1986
|
+
PortableGlobalSection,
|
|
1987
|
+
PortableImportResult,
|
|
1988
|
+
PortableImportSectionResult,
|
|
1989
|
+
PortableKeyCounts,
|
|
1990
|
+
PortableLegacyEvidence,
|
|
1991
|
+
PortablePathFinding,
|
|
1992
|
+
PortableProjectSection,
|
|
1993
|
+
PortableReentryItem,
|
|
1994
|
+
PortableRelocationReport,
|
|
1995
|
+
PortableSealedCredentials,
|
|
1996
|
+
PortableSectionBase,
|
|
1997
|
+
PortableSkippedProject,
|
|
1998
|
+
PortableSkipReason,
|
|
1999
|
+
PortableSymlinkEntry,
|
|
2000
|
+
PortableTableComparison,
|
|
2001
|
+
PortableUnmigratedLegacyReport,
|
|
2002
|
+
} from './portable-bundle.js';
|
|
1953
2003
|
// === PostgresDataAccessor Contracts — cloud-sync scaffold (T9062) ===
|
|
1954
2004
|
export type {
|
|
1955
2005
|
CreatePostgresDataAccessorFn,
|