@gitroll/tacitt-cli 0.6.13 → 0.6.14
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-setup-Doy_AnPY.mjs → agent-setup-CEPQfjBv.mjs} +2 -2
- package/dist/agent-setup-worker.mjs +5 -5
- package/dist/cli.mjs +6 -6
- package/dist/codex-title-worker.mjs +1 -1
- package/dist/configured-preview-worker.mjs +5 -5
- package/dist/configured-session-worker.mjs +5 -5
- package/dist/{frame-BPbypzmt.mjs → frame-CRm99088.mjs} +1 -1
- package/dist/{heap-DCS_WXIA.mjs → heap-Bh9tySJp.mjs} +8 -7
- package/dist/inspection-worker.mjs +4 -4
- package/dist/{job--zxwgaPy.mjs → job-CsWKWcM4.mjs} +4 -4
- package/dist/{locate-PLEyLYW-.mjs → locate-CP2t26j2.mjs} +173 -19
- package/dist/{model-CyXvsWLz.mjs → model-ChHuVKoB.mjs} +1 -1
- package/dist/operation-executor.mjs +3 -3
- package/dist/preview-worker.mjs +1 -1
- package/dist/privacy-validator.mjs +1 -1
- package/dist/{query-BC7MIaWc.mjs → query-D28k3XOr.mjs} +5822 -5704
- package/dist/{run-Dod7Vykp.mjs → run-CiJmV__5.mjs} +4 -4
- package/dist/{src-CttNuxOn.mjs → src-B3il9x5F.mjs} +37 -13
- package/dist/{src-dL6y2mcu.mjs → src-CWMrGXJK.mjs} +4 -4
- package/dist/{src-CP-K2PBv.mjs → src-CmvEJj46.mjs} +31 -8
- package/dist/store-database-worker.mjs +1 -1
- package/dist/web/assets/index-XdWDOC5H.js +172 -0
- package/dist/web/index.html +1 -1
- package/package.json +1 -1
- package/skills/tacitt/INDEX.md +1 -1
- package/skills/tacitt/SKILL.md +2 -0
- package/skills/tacitt/references/INDEX.md +2 -2
- package/skills/tacitt/references/commands.md +13 -0
- package/skills/tacitt/references/journey.md +2 -0
- package/skills/tacitt/scripts/INDEX.md +1 -1
- package/skills/tacitt/scripts/journey-classification-tasks.mjs +2 -0
- package/skills/tacitt/scripts/journey-state.d.mts +3 -0
- package/skills/tacitt/scripts/journey-state.mjs +8 -1
- package/skills/tacitt/scripts/journey.mjs +30 -0
- package/skills/tacitt/scripts/privacy-validator.mjs +76 -7
- package/dist/web/assets/index-BgDdPL1c.js +0 -172
package/dist/web/index.html
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
7
|
<meta name="referrer" content="no-referrer" />
|
|
8
8
|
<title>tacitt · Local session collection</title>
|
|
9
|
-
<script type="module" crossorigin src="./assets/index-
|
|
9
|
+
<script type="module" crossorigin src="./assets/index-XdWDOC5H.js"></script>
|
|
10
10
|
<link rel="stylesheet" crossorigin href="./assets/index-DzOozqms.css">
|
|
11
11
|
</head>
|
|
12
12
|
<body>
|
package/package.json
CHANGED
package/skills/tacitt/INDEX.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
<!-- index-entries
|
|
7
7
|
./ | Shipped skill | Workspace-scoped instructions for direct CLI and optional Web collaboration.
|
|
8
8
|
INDEX.md | Documentation | Directory navigation.
|
|
9
|
-
SKILL.md | Agent instructions | Supplies the managed release template, explicit fast/low worker policy and phase routing into classification, paired CLI scan reruns, consent gates, account-seeded access, person-only Public choices, privacy review and approved export.
|
|
9
|
+
SKILL.md | Agent instructions | Supplies the managed release template, explicit fast/low worker policy and phase routing into classification, paired CLI scan reruns, consent gates, Retry-only formation account stop, account-seeded access, person-only Public choices, privacy review and approved export.
|
|
10
10
|
-->
|
|
11
11
|
|
|
12
12
|
The entry table is not committed: run `pnpm run write:indexes`, then open `INDEX.local.md` in this directory.
|
package/skills/tacitt/SKILL.md
CHANGED
|
@@ -22,6 +22,8 @@ The agent invoking this Skill is its Main coordinator, including when another ag
|
|
|
22
22
|
|
|
23
23
|
## Required order
|
|
24
24
|
|
|
25
|
+
Before first Work formation, `journey.prepare` reads the account inventory once, across all pages, with `include=title,removedFromWork,unitAccess` and the shared 30-second bound. A failed or partial read stops before classification and forms no Work. On `ACCOUNT_WORKS_UNAVAILABLE`, say "Tacitt could not read your profile, so it cannot tell which Works are already Private there." On `ACCOUNT_SIGNED_OUT`, ask the person to sign in. The helper's `accountReadRecovery` offers Retry only: get the current journey revision and submit `{kind:"account-read"}` once, then wait if the read still fails. For the first formation of a journey, never continue classification without a successful read or offer to group without the profile. A journey that already has a formed snapshot from an earlier build continues under its existing rules with no formation read. Consent without a subject keeps the existing signed-out exception. A successful read stores account facts for the later rebuild slice; it does not yet change Work ids, titles, grouping, access or Send.
|
|
26
|
+
|
|
25
27
|
For scan starts and reruns after scope confirmation, follow the [paired CLI background preparation, restart budget and prepare-outcome rules](references/commands.md#scan-results).
|
|
26
28
|
|
|
27
29
|
The person decides in the panel; you keep the journey moving. Never ask the person to return to chat to confirm or continue, except for the explicit [remote-worker host consent](references/remote-workers.md) before classification freezes. Until Ready to send, while the next step is theirs, [wait inside this turn](references/journey.md#waiting-for-the-person); at Ready to send your turn ends.
|
|
@@ -9,8 +9,8 @@ INDEX.md | Directory index | Locates the shipped native journey references.
|
|
|
9
9
|
b-method.md | Method reference | Defines the dictionary method: analysed scope, the child answer, the ten term types and how the hidden set is applied.
|
|
10
10
|
bootstrap.md | Skill reference | Verifies the exact paired CLI release and preserves installation boundaries.
|
|
11
11
|
classification.md | Skill reference | Owns priority dispatch of unresolved/evidence tasks, authoritative task-pointer prompts, semantic evidence safeguards, bounded reconciliation, final metadata and full-coverage publication and unconfirmed Public suggestions.
|
|
12
|
-
commands.md | Command reference | Supplies classification assignment and answer-publication, session review, decision-card, final-resolution, phase-helper, batched reader lifecycle events, explicit paired-CLI scan reruns, account inheritance, person-only Public choices and Send contracts.
|
|
13
|
-
journey.md | Skill reference | Guides explicit consent, row-assigned classification, CLI-owned answer publication and same-child recovery, account-seeded scan scope, explicit Public choices, contextual cards, final resolution, preview and approved packaging.
|
|
12
|
+
commands.md | Command reference | Supplies classification assignment and answer-publication, session review, decision-card, final-resolution, phase-helper, batched reader lifecycle events, explicit paired-CLI scan reruns, Retry-only formation reads, account inheritance, person-only Public choices and Send contracts.
|
|
13
|
+
journey.md | Skill reference | Guides explicit consent, row-assigned classification, CLI-owned answer publication and same-child recovery, Retry-only formation reads, account-seeded scan scope, explicit Public choices, contextual cards, final resolution, preview and approved packaging.
|
|
14
14
|
parallel-review.md | Review protocol | Runs the review helper loop: bounded current-provider analysis agents, CLI-published drafts, same-child repair, batched launches and exits, busy slots, durable replay and recovery.
|
|
15
15
|
remote-workers.md | Collection protocol | Owns per-Send host consent, bounded remote worker import before freeze and disclosure of unreadable dispatch lines or collection failures.
|
|
16
16
|
send.md | Send reference | Owns browser Send, owner login, scope confirmation, incremental session intent, concurrent transfers with serialized commits, narrow pre-upload access blocking, upload-bound completion, background assessment, fresh review recovery and deliberate upgrades.
|
|
@@ -25,6 +25,7 @@ Consent arrives from the panel's Continue button (or, after an explicit chat agr
|
|
|
25
25
|
- `journey.classificationSubmit`: `{journeyId,expectedRevision,idempotencyKey,items}`. Each item is `{projectName,description,projectType,rootSessionIds,recommendation:{access,reason}}`. Types are `work`, `side`, `coursework`, `personal`, `scratch`, `other`; access is `public`, `private`, `drop`. Cover every root exactly once, preserve families and merge matching project identities; matching names alone are not identity. Recommendations do not change access by themselves.
|
|
26
26
|
- Apply explicit visibility using `{kind:"work-access",workId,access}` or `{kind:"works-access",workIds,access}`. Browser choices are already committed; never overwrite them with an older recommendation.
|
|
27
27
|
- Before `scope-confirm`, an unchosen Work may store a placeholder `access`; the panel shows its recommendation. Scope confirmation preserves confirmed person choices and a delegate's Private choice. It seeds account access while signed in (`accessOrigin:"account"`): all Private confirms, every root held Public confirms with account proof, partial Public history stays a suggestion, and mixed starts Private with a visible conflict. No account history uses the model path. Model Public also stays `accessConfirmed:false`; model Private may confirm. The panel asks the person for every suggested-Public Work. A suggested Public Work requires that person's explicit visibility choice, including choosing the same displayed Public value. Never use delegation to confirm Public.
|
|
28
|
+
- Before first formation, `journey.prepare` performs the all-or-nothing account read. `ACCOUNT_WORKS_UNAVAILABLE` or `ACCOUNT_SIGNED_OUT` stops before classification with no Work formed. Get the current revision and submit `{kind:"account-read"}` once as Retry; the helper returns this sole choice in `accountReadRecovery`. If Retry still fails, wait for the profile read (or sign-in) to recover; never continue without the profile. A successful formation read changes no Work grouping or visibility in slice A.
|
|
28
29
|
- As soon as the known Works (an `ingest` result with `partial: true`) or the complete proposal is ingested, record `{kind:"scope-confirm"}` for scan scope. This does not confirm suggested Public (a Work whose every root session is already Public on the account is confirmed by that account history and needs no question); name each suggested-Public Work and ask the person to choose Public or Private, in the panel or conversation. `scope-confirm` reads the account inventory first (30 s bound). A failed read refuses it with `ACCOUNT_ACCESS_UNAVAILABLE`, and a signed-out read with `ACCOUNT_SIGNED_OUT`; each records `accountRead` and changes no Work, and only a later `scope-confirm` that reads the account confirms the scope (Retry; it decides nothing, so run it once without asking). A signed-out `scope-confirm` continues on the model path only when this journey has recorded consent without an account subject. That covers consent given before sign-in was required or in a build with no sign-in client. A calling process with no sign-in client cannot exempt consent that records a subject. After confirmation, `{kind:"account-read"}` reads the account again from the panel or chat: on a read it re-applies account access to Public Works while preserving confirmed person choices, every Private Work and every left-out Work; on a failure it records the status only. The view's `accountReadCurrent` is true only for a `read` under the account signed in now; while it is false and an included Work is suggested Public or Public by account proof, the panel shows a stop with Retry or Sign in in place of the Send button. Then `journey.prepare` runs selected Work static scans and, while grouping continues, waits for and prepares the Works the complete proposal publishes or extends. `journey.classificationSubmit` takes optional `pendingRootSessionIds` (roots still being grouped, kept in one unread Work) and, after confirmation, `expectedClassificationRevision` (the classification it completes) instead of a current `expectedRevision`. Visibility stays open until Send: Drop stops that Work's scan, and a Work moved out of Drop needs `journey.prepare` again.
|
|
29
30
|
|
|
30
31
|
## Remote worker collection
|
|
@@ -57,6 +58,18 @@ Ingest and `next-packs` list `blockedWorks[]` only while one exists.
|
|
|
57
58
|
Phase-helper `status` and `await` also print `leftOutSessions`, the number of root sessions in
|
|
58
59
|
those Works, only when it is above zero; say it in chat before the review is complete, Ready
|
|
59
60
|
to send or nothing is left to send.
|
|
61
|
+
They also print `accountFormation: {leftOutSessions, heldBackSessions}` when formation kept
|
|
62
|
+
sessions out of every Work because of the person's profile (ADR 0276). Say each nonzero count
|
|
63
|
+
once in the journey, never a session or Work name: "N sessions are left out because you
|
|
64
|
+
removed their Work on your profile." and "N sessions stay in their Works on your profile and
|
|
65
|
+
are not sent this time." (singular: "1 session is left out because you removed its Work on
|
|
66
|
+
your profile.", "1 session stays in its Work on your profile and is not sent this time.").
|
|
67
|
+
When every session is already on the profile, left out or held back, `journey.prepare` fails with
|
|
68
|
+
`ACCOUNT_NOTHING_TO_SEND` and the helper phase is `nothing-to-send` with `accountFormation`: say
|
|
69
|
+
the counts once and that nothing is left to send this time, then end the turn. Running `/tacitt`
|
|
70
|
+
again reads the profile again.
|
|
71
|
+
Works with `accountWork: true` are the person's profile Works rebuilt with their profile title;
|
|
72
|
+
classification never groups or describes them.
|
|
60
73
|
When no selected Work is left (every one skipped or Dropped), the helper phase is
|
|
61
74
|
`nothing-to-send`: there is no Send, and `await` waits for a Retry or a move out of Drop.
|
|
62
75
|
When the person asks to retry, respond
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Classification-first native journey
|
|
2
2
|
|
|
3
|
+
Before first Work formation, `journey.prepare` reads the account inventory once, across all pages, with `include=title,removedFromWork,unitAccess` and the shared 30-second bound. A failed or partial read stops before classification and forms no Work. On `ACCOUNT_WORKS_UNAVAILABLE`, say "Tacitt could not read your profile, so it cannot tell which Works are already Private there." On `ACCOUNT_SIGNED_OUT`, ask the person to sign in. The helper's `accountReadRecovery` offers Retry only: get the current journey revision and submit `{kind:"account-read"}` once, then wait if the read still fails. For the first formation of a journey, never continue classification without a successful read or offer to group without the profile. A journey that already has a formed snapshot from an earlier build continues under its existing rules with no formation read. Consent without a subject keeps the existing signed-out exception. A successful read stores account facts for the later rebuild slice; it does not yet change Work ids, titles, grouping, access or Send.
|
|
4
|
+
|
|
3
5
|
> Audience: native Codex and Claude Code agents
|
|
4
6
|
> Ownership: Tacitt CLI maintainers
|
|
5
7
|
|
|
@@ -32,7 +32,7 @@ journey-state.mjs | Runtime state | Pending-Public-choice, confirmed-answer and
|
|
|
32
32
|
journey-tasks.d.mts | Declaration | Types task creation, rendered-token sizing, canonical answer metadata and batch answer reads.
|
|
33
33
|
journey-tasks.mjs | Task builder | Exact rendered-token budgets, private drafts, a 200-value cap (ADR 0234), compact existing policies with bounded overhead (ADR 0251), and one-term-per-line card/resolution payloads with complete bounded read ranges.
|
|
34
34
|
journey.d.mts | Declaration | Phase helper contract for integration tests.
|
|
35
|
-
journey.mjs | Runtime |
|
|
35
|
+
journey.mjs | Runtime | Retry-only formation failure/status projection and phase tasks with compact existing-card identity snapshots, durable exact batch writes, the person-decision `await` that hands off at Ready to send, the late placed-Work check before the classification commit (its stderr names only item indexes and Work ids) and shared CLI transport.
|
|
36
36
|
local-cli.d.mts | Type declarations | Defines the shared installed-package binding used by the CLI and standalone verifier.
|
|
37
37
|
local-cli.mjs | Read-only package verifier | Validates an explicit installed CLI identity and aggregate artifact digest without network or application-state access.
|
|
38
38
|
review-stream-client.d.mts | Type declarations | Types the fixed request/shutdown limits, private lifecycle callbacks and review-stream client methods.
|
|
@@ -21,6 +21,8 @@ const projectInstruction =
|
|
|
21
21
|
const rootUniverse = (view) => {
|
|
22
22
|
const result = []
|
|
23
23
|
for (const work of view.works) {
|
|
24
|
+
// Rebuilt account Works are not classified (ADR 0276 D1).
|
|
25
|
+
if (work.accountWork) continue
|
|
24
26
|
for (const rootSessionId of work.rootSessionIds) {
|
|
25
27
|
result.push({ rootSessionId, workId: work.id })
|
|
26
28
|
}
|
|
@@ -44,6 +44,9 @@ export function isSkipped(
|
|
|
44
44
|
work: Pick<SkipRuleWork, 'status' | 'blockedCodes' | 'inputRevision' | 'reviewInterruptions'>,
|
|
45
45
|
): boolean
|
|
46
46
|
export function isIncluded(work: SkipRuleWork): boolean
|
|
47
|
+
export function accountFormationField(view: {
|
|
48
|
+
accountWorks?: { status: string; leftOut?: number; heldBack?: number }
|
|
49
|
+
}): { accountFormation?: { leftOutSessions: number; heldBackSessions: number } }
|
|
47
50
|
export function leftOutField(view: { works: readonly SkipRuleWork[] }): {
|
|
48
51
|
leftOutSessions?: number
|
|
49
52
|
}
|
|
@@ -69,6 +69,13 @@ export const isSkipped = (work) =>
|
|
|
69
69
|
* Issue #59: the sessions (roots) of every skipped, not Dropped Work, which the agent says in chat
|
|
70
70
|
* before Ready to send. One number, printed only when above zero (issue #55).
|
|
71
71
|
*/
|
|
72
|
+
/** ADR 0276 D1 formation counts, as `accountFormationLines` of the panel; tell the person once. */
|
|
73
|
+
export const accountFormationField = (view) => {
|
|
74
|
+
const read = view.accountWorks?.status === 'read' ? view.accountWorks : null
|
|
75
|
+
return read && (read.leftOut || read.heldBack)
|
|
76
|
+
? { accountFormation: { leftOutSessions: read.leftOut, heldBackSessions: read.heldBack } }
|
|
77
|
+
: {}
|
|
78
|
+
}
|
|
72
79
|
export const leftOutField = (view) => {
|
|
73
80
|
const sessions = view.works
|
|
74
81
|
.filter((work) => work.access !== 'drop' && isSkipped(work))
|
|
@@ -120,7 +127,7 @@ export function phaseOf(view, drainedRevision) {
|
|
|
120
127
|
if (view.phase === 'paused') return 'paused'
|
|
121
128
|
if (view.phase === 'completed') return 'completed'
|
|
122
129
|
if (view.phase === 'sending') return 'sending'
|
|
123
|
-
if (!view.snapshotId) return 'freeze'
|
|
130
|
+
if (!view.snapshotId) return view.accountWorks?.nothingToSend ? 'nothing-to-send' : 'freeze'
|
|
124
131
|
if (view.classificationRevision === null) return 'classification'
|
|
125
132
|
if (view.scope.status !== 'confirmed') return 'classification-confirmation'
|
|
126
133
|
// A pending Hide needs journey.prepare to recover it before anything else (ADR 0236).
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
interruptedReviews,
|
|
13
13
|
isIncluded,
|
|
14
14
|
leftOutField,
|
|
15
|
+
accountFormationField,
|
|
15
16
|
activeTerms,
|
|
16
17
|
stageFingerprint,
|
|
17
18
|
procedureFor,
|
|
@@ -87,6 +88,27 @@ async function prepareInitialFreeze(run, journeyId, call, view) {
|
|
|
87
88
|
} catch (error) {
|
|
88
89
|
// A large first freeze can outlast one helper command; captured roots persist for the rerun.
|
|
89
90
|
if (error?.code === 'CLI_UNAVAILABLE') return { stage: 'freeze', status: 'running', startedAt }
|
|
91
|
+
// Every session is already on the profile or left out (ADR 0276): there is no Send.
|
|
92
|
+
if (error?.code === 'ACCOUNT_NOTHING_TO_SEND') {
|
|
93
|
+
const stopped = await call('journey.get', { journeyId })
|
|
94
|
+
return {
|
|
95
|
+
stage: 'freeze',
|
|
96
|
+
status: 'nothing-to-send',
|
|
97
|
+
startedAt,
|
|
98
|
+
...accountFormationField(stopped),
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
if (['ACCOUNT_WORKS_UNAVAILABLE', 'ACCOUNT_SIGNED_OUT'].includes(error?.code)) {
|
|
102
|
+
const stopped = await call('journey.get', { journeyId })
|
|
103
|
+
if (stopped.accountReadRecovery)
|
|
104
|
+
return {
|
|
105
|
+
stage: 'freeze',
|
|
106
|
+
status: 'blocked',
|
|
107
|
+
startedAt,
|
|
108
|
+
accountReadRecovery: stopped.accountReadRecovery,
|
|
109
|
+
next: 'journey.prepare',
|
|
110
|
+
}
|
|
111
|
+
}
|
|
90
112
|
throw error
|
|
91
113
|
}
|
|
92
114
|
const completed = await call('journey.get', { journeyId })
|
|
@@ -194,12 +216,16 @@ async function awaitDecision(run, journeyId, waitMs, call, sleep, ensureHost) {
|
|
|
194
216
|
command: 'await',
|
|
195
217
|
from,
|
|
196
218
|
phase,
|
|
219
|
+
...(view.accountReadRecovery
|
|
220
|
+
? { accountReadRecovery: view.accountReadRecovery, next: 'journey.prepare' }
|
|
221
|
+
: {}),
|
|
197
222
|
changed,
|
|
198
223
|
waitedMs: Date.now() - started,
|
|
199
224
|
revision: view.revision,
|
|
200
225
|
blockedWorks: blocked,
|
|
201
226
|
...(held.length ? { interruptedReviews: held } : {}),
|
|
202
227
|
...leftOutField(view),
|
|
228
|
+
...accountFormationField(view),
|
|
203
229
|
...(retried.length ? { retriedWorks: retried, next: 'journey.prepare' } : {}),
|
|
204
230
|
...(handoff ? { handoff: { panel: await ensureHost(), next: 'end-turn' } } : {}),
|
|
205
231
|
}
|
|
@@ -264,12 +290,16 @@ async function runPhaseCore(
|
|
|
264
290
|
? { classification: await classificationProgress(manifest) }
|
|
265
291
|
: {}),
|
|
266
292
|
phase: await currentPhase(run, view),
|
|
293
|
+
...(view.accountReadRecovery
|
|
294
|
+
? { accountReadRecovery: view.accountReadRecovery, next: 'journey.prepare' }
|
|
295
|
+
: {}),
|
|
267
296
|
revision: view.revision,
|
|
268
297
|
readingComplete: view.readingComplete,
|
|
269
298
|
pending: activeTerms(view).filter((term) => term.disposition === 'pending').length,
|
|
270
299
|
blockedWorks: blockedWorks(view),
|
|
271
300
|
...(interruptions.length ? { interruptedReviews: interruptions } : {}),
|
|
272
301
|
...leftOutField(view),
|
|
302
|
+
...accountFormationField(view),
|
|
273
303
|
answersRevision: view.privacy.answersRevision,
|
|
274
304
|
...packagingProgress(view),
|
|
275
305
|
coldElapsedMs,
|
|
@@ -5112,6 +5112,14 @@ function object(shape, params) {
|
|
|
5112
5112
|
};
|
|
5113
5113
|
return new ZodObject(def);
|
|
5114
5114
|
}
|
|
5115
|
+
function strictObject(shape, params) {
|
|
5116
|
+
return new ZodObject({
|
|
5117
|
+
type: "object",
|
|
5118
|
+
shape,
|
|
5119
|
+
catchall: never(),
|
|
5120
|
+
...normalizeParams(params)
|
|
5121
|
+
});
|
|
5122
|
+
}
|
|
5115
5123
|
function looseObject(shape, params) {
|
|
5116
5124
|
return new ZodObject({
|
|
5117
5125
|
type: "object",
|
|
@@ -5400,7 +5408,7 @@ const range = object({
|
|
|
5400
5408
|
start: number().int().nonnegative(),
|
|
5401
5409
|
end: number().int().nonnegative()
|
|
5402
5410
|
}).strict();
|
|
5403
|
-
const digest$
|
|
5411
|
+
const digest$4 = string().regex(/^[a-f0-9]{64}$/u);
|
|
5404
5412
|
/** Original static title mask provenance for keyword-only preview/packaging. */
|
|
5405
5413
|
const classificationTitleMaskSchema = object({
|
|
5406
5414
|
inputRange: range,
|
|
@@ -5417,14 +5425,66 @@ const classificationTitleMaskSchema = object({
|
|
|
5417
5425
|
originalPointer: string().nullable(),
|
|
5418
5426
|
outputPointer: string().nullable(),
|
|
5419
5427
|
sourceRange: range.nullable(),
|
|
5420
|
-
inputSha256: digest$
|
|
5421
|
-
outputSha256: digest$
|
|
5428
|
+
inputSha256: digest$4,
|
|
5429
|
+
outputSha256: digest$4,
|
|
5422
5430
|
context: object({
|
|
5423
5431
|
start: number().int().nonnegative(),
|
|
5424
5432
|
text: string()
|
|
5425
5433
|
}).strict()
|
|
5426
5434
|
}).strict();
|
|
5427
5435
|
//#endregion
|
|
5436
|
+
//#region packages/application/src/journey/account-works.ts
|
|
5437
|
+
const digest$3 = string().regex(/^[0-9a-f]{64}$/u);
|
|
5438
|
+
const stored = object({
|
|
5439
|
+
/** Wire field from issue #131; a formation reply without it is read as no stored metadata. */
|
|
5440
|
+
metadataSha256: digest$3.nullish().transform((value) => value ?? null),
|
|
5441
|
+
key: digest$3,
|
|
5442
|
+
sessionKey: string().regex(/^sess-pilot\/[^/]+\/[^/]+\/[^/]+$/u).nullable(),
|
|
5443
|
+
sha256: digest$3,
|
|
5444
|
+
byteLength: number().int().positive(),
|
|
5445
|
+
lastAt: datetime()
|
|
5446
|
+
});
|
|
5447
|
+
const access = _enum([
|
|
5448
|
+
"public",
|
|
5449
|
+
"private",
|
|
5450
|
+
"removed"
|
|
5451
|
+
]);
|
|
5452
|
+
const accountWorksInventorySchema = object({
|
|
5453
|
+
works: array(object({
|
|
5454
|
+
logicalWorkId: uuid(),
|
|
5455
|
+
title: string().min(1).max(300),
|
|
5456
|
+
access,
|
|
5457
|
+
unitAccess: access,
|
|
5458
|
+
sessions: array(stored)
|
|
5459
|
+
})),
|
|
5460
|
+
unassigned: array(stored.extend({ removedFromWork: uuid().nullish().transform((value) => value ?? null) }))
|
|
5461
|
+
});
|
|
5462
|
+
const accountWorksSchema = discriminatedUnion("status", [
|
|
5463
|
+
strictObject({
|
|
5464
|
+
status: literal("read"),
|
|
5465
|
+
subject: string().min(1).max(128),
|
|
5466
|
+
at: datetime(),
|
|
5467
|
+
inventory: accountWorksInventorySchema,
|
|
5468
|
+
/** Families with a key unassigned after its Work's removal: no Work, not sent (D4). */
|
|
5469
|
+
leftOut: array(strictObject({
|
|
5470
|
+
rootSessionId: string().min(1).max(128),
|
|
5471
|
+
removedWorkId: uuid()
|
|
5472
|
+
})).default([]),
|
|
5473
|
+
/** Families with a held key that are not cleanly placed: no Work, not sent (D9). */
|
|
5474
|
+
heldBack: array(string().min(1).max(128)).default([]),
|
|
5475
|
+
/** Every family was left out or held back: no Work and no snapshot (#129 review). */
|
|
5476
|
+
nothingToSend: literal(true).optional()
|
|
5477
|
+
}),
|
|
5478
|
+
strictObject({
|
|
5479
|
+
status: literal("signed-out"),
|
|
5480
|
+
at: datetime()
|
|
5481
|
+
}),
|
|
5482
|
+
strictObject({
|
|
5483
|
+
status: literal("unavailable"),
|
|
5484
|
+
at: datetime()
|
|
5485
|
+
})
|
|
5486
|
+
]);
|
|
5487
|
+
//#endregion
|
|
5428
5488
|
//#region packages/application/src/journey/profile.ts
|
|
5429
5489
|
/**
|
|
5430
5490
|
* Passport's own rules (talent-platform `profile-settings.ts`): 1 to 39 letters and digits with
|
|
@@ -10167,7 +10227,8 @@ const reviewInterruptionSchema = object({
|
|
|
10167
10227
|
}).strict();
|
|
10168
10228
|
const journeyWorkSchema = object({
|
|
10169
10229
|
id: journeyIdSchema,
|
|
10170
|
-
title
|
|
10230
|
+
/** 240 characters; an `account` title holds the server's 300 (ADR 0276 D2). */
|
|
10231
|
+
title: string().trim().min(1).max(300),
|
|
10171
10232
|
/** Statically processed repository or folder name; the original stays in the private plan. */
|
|
10172
10233
|
projectName: label,
|
|
10173
10234
|
projectType: journeyWorkTypeSchema.nullable(),
|
|
@@ -10183,7 +10244,11 @@ const journeyWorkSchema = object({
|
|
|
10183
10244
|
description: string(),
|
|
10184
10245
|
reason: string()
|
|
10185
10246
|
}).strict().optional(),
|
|
10186
|
-
titleOrigin: _enum([
|
|
10247
|
+
titleOrigin: _enum([
|
|
10248
|
+
"model",
|
|
10249
|
+
"explicit",
|
|
10250
|
+
"account"
|
|
10251
|
+
]),
|
|
10187
10252
|
explicitTitleId: journeyIdSchema.nullable(),
|
|
10188
10253
|
accessOrigin: _enum([
|
|
10189
10254
|
"default",
|
|
@@ -10221,6 +10286,8 @@ const journeyWorkSchema = object({
|
|
|
10221
10286
|
inputRevision: count$1.min(1),
|
|
10222
10287
|
/** Placement created this Work (create-work or a sorting "new" decision): its name is generic. */
|
|
10223
10288
|
createdByPlacement: literal(true).optional(),
|
|
10289
|
+
/** Rebuilt at formation from the account Work with this id (ADR 0276 D1); never classified. */
|
|
10290
|
+
accountWork: literal(true).optional(),
|
|
10224
10291
|
/** Host-owned eligibility after removal-only regrouping; never authorizes output by itself. */
|
|
10225
10292
|
reviewReuseFrom: object({
|
|
10226
10293
|
inputRevision: count$1.min(1),
|
|
@@ -10276,7 +10343,7 @@ const journeyWorkSchema = object({
|
|
|
10276
10343
|
sentBundleId: journeyIdSchema.optional(),
|
|
10277
10344
|
sentAccess: _enum(["public", "private"]).optional()
|
|
10278
10345
|
}).strict().nullable()
|
|
10279
|
-
}).strict();
|
|
10346
|
+
}).strict().refine((work) => work.titleOrigin === "account" || work.title.length <= 240, { path: ["title"] });
|
|
10280
10347
|
const journeyConsentSchema = object({
|
|
10281
10348
|
provider: label,
|
|
10282
10349
|
allowedAt: datetime(),
|
|
@@ -10298,7 +10365,7 @@ const journeyExceptionSchema = object({
|
|
|
10298
10365
|
value: string().min(1).max(1024)
|
|
10299
10366
|
}).strict();
|
|
10300
10367
|
object({
|
|
10301
|
-
formatVersion: literal(10),
|
|
10368
|
+
formatVersion: literal([10, 11]),
|
|
10302
10369
|
outputVersion: number().int().positive().optional(),
|
|
10303
10370
|
classificationRevision: count$1.nullable(),
|
|
10304
10371
|
privacy: journeyPrivacySchema,
|
|
@@ -10368,6 +10435,8 @@ object({
|
|
|
10368
10435
|
* confirmation and Retry set `read`; late classification records only a failure. Absent in a
|
|
10369
10436
|
* journey of an earlier version, which reads as not `read`.
|
|
10370
10437
|
*/
|
|
10438
|
+
/** Formation read only; never establishes access proof. */
|
|
10439
|
+
accountWorks: accountWorksSchema.optional(),
|
|
10371
10440
|
accountRead: object({
|
|
10372
10441
|
status: _enum([
|
|
10373
10442
|
"read",
|