@workit-dev/core 0.0.1 → 1.0.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/LICENSE +21 -0
- package/README.md +22 -43
- package/package.json +56 -6
- package/schemas/config.json +74 -0
- package/schemas/vcs.json +79 -0
- package/schemas/workspaces.json +1029 -0
- package/schemas/youtrack.json +84 -0
- package/scripts/analyze-release-scope.ts +215 -0
- package/scripts/bundled-deps.json +131 -0
- package/scripts/fixtures/sample-plan.md +15 -0
- package/scripts/fixtures/sample-sdd/progress.md +2 -0
- package/scripts/install-codex-plugin.sh +28 -0
- package/scripts/install-cursor-plugin.sh +146 -0
- package/scripts/install-opencode-plugin.sh +79 -0
- package/scripts/install-pi-package.sh +56 -0
- package/scripts/lib/config-dir.sh +28 -0
- package/scripts/publish-changed-packages.ts +395 -0
- package/scripts/rewrite-workspace-deps.ts +53 -0
- package/scripts/run-cursor-mcp.sh +6 -0
- package/scripts/sync-release-manifests.ts +82 -0
- package/scripts/sync-runtime.sh +142 -0
- package/scripts/validate-cursor-marketplace.ts +171 -0
- package/scripts/verify-bundle-sources.ts +134 -0
- package/scripts/write-schemas.ts +16 -0
- package/skills/workit-architecture/SKILL.md +72 -0
- package/skills/workit-architecture/agents/openai.yaml +3 -0
- package/skills/workit-architecture/references/instruction-files.md +52 -0
- package/skills/workit-architecture/references/vocabulary.md +53 -0
- package/skills/workit-bdd/SKILL.md +53 -0
- package/skills/workit-continue/SKILL.md +54 -0
- package/skills/workit-debug/SKILL.md +45 -0
- package/skills/workit-deslop/SKILL.md +58 -0
- package/skills/workit-fanout/SKILL.md +71 -0
- package/skills/workit-fanout/references/brief.md +141 -0
- package/skills/workit-fanout/references/orchestration.md +169 -0
- package/skills/workit-implement/SKILL.md +71 -0
- package/skills/workit-retro/SKILL.md +72 -0
- package/skills/workit-retro/agents/openai.yaml +3 -0
- package/skills/workit-retro/references/sources.md +35 -0
- package/skills/workit-retro/references/steering.md +39 -0
- package/skills/workit-review/SKILL.md +66 -0
- package/skills/workit-review/references/impact.md +24 -0
- package/skills/workit-shape/SKILL.md +71 -0
- package/skills/workit-shape/references/diagrams.md +17 -0
- package/skills/workit-shape/references/knowledge.md +61 -0
- package/skills/workit-shape/references/mockups.md +15 -0
- package/skills/workit-shape/references/slicing.md +44 -0
- package/skills/workit-ship/SKILL.md +71 -0
- package/skills/workit-ship/references/changelog.md +44 -0
- package/skills/workit-ship/references/pr-body.md +32 -0
- package/skills/workit-ship/references/release.md +39 -0
- package/skills/workit-test-audit/SKILL.md +54 -0
- package/skills/workit-verify-app/SKILL.md +68 -0
- package/skills/workit-verify-app/references/template.md +51 -0
- package/src/autonomy.ts +910 -0
- package/src/check-config.ts +613 -0
- package/src/checks.ts +534 -0
- package/src/ci-waiter.ts +159 -0
- package/src/core/boundary.ts +55 -0
- package/src/core/branch-policy.ts +112 -0
- package/src/core/branch.ts +1192 -0
- package/src/core/changelog-gate.ts +349 -0
- package/src/core/changelog-merge.ts +214 -0
- package/src/core/changelog.ts +392 -0
- package/src/core/cleanup.ts +638 -0
- package/src/core/cli-locate.ts +173 -0
- package/src/core/commit-flavors.ts +65 -0
- package/src/core/config-schemas.ts +653 -0
- package/src/core/config.ts +351 -0
- package/src/core/context-read.ts +144 -0
- package/src/core/docs-gate.ts +69 -0
- package/src/core/finding-evidence.ts +89 -0
- package/src/core/finding-queue.ts +36 -0
- package/src/core/git.ts +73 -0
- package/src/core/gitignore.ts +52 -0
- package/src/core/heavy-eta.ts +170 -0
- package/src/core/heavy-lease.ts +290 -0
- package/src/core/heavy-rules.ts +373 -0
- package/src/core/heavy-scope.ts +131 -0
- package/src/core/heavy-words.ts +83 -0
- package/src/core/heavy.ts +535 -0
- package/src/core/hygiene.ts +149 -0
- package/src/core/init.ts +218 -0
- package/src/core/live-session.ts +333 -0
- package/src/core/logger.ts +310 -0
- package/src/core/methods.ts +185 -0
- package/src/core/model-fallback.ts +208 -0
- package/src/core/node-resolve.mjs +249 -0
- package/src/core/operation-input.ts +632 -0
- package/src/core/package-root.ts +28 -0
- package/src/core/policy/attributes.ts +97 -0
- package/src/core/policy/bookkeeping.ts +119 -0
- package/src/core/policy/carry.ts +122 -0
- package/src/core/policy/check-evidence.ts +115 -0
- package/src/core/policy/current-judgment.ts +20 -0
- package/src/core/policy/derive.ts +387 -0
- package/src/core/policy/judgment.ts +246 -0
- package/src/core/policy/lane.ts +562 -0
- package/src/core/policy/pr-lane.ts +32 -0
- package/src/core/policy/substance.ts +365 -0
- package/src/core/policy-resolver.ts +94 -0
- package/src/core/pr-create.ts +448 -0
- package/src/core/pr-template.ts +162 -0
- package/src/core/release-notes.ts +197 -0
- package/src/core/release-tracks.ts +779 -0
- package/src/core/remotes.ts +436 -0
- package/src/core/repo-context.ts +542 -0
- package/src/core/repo-paths.ts +29 -0
- package/src/core/resources.ts +1299 -0
- package/src/core/role-models.ts +603 -0
- package/src/core/route-intent.ts +305 -0
- package/src/core/rules.ts +65 -0
- package/src/core/runtime-identity.ts +63 -0
- package/src/core/safe-write.ts +87 -0
- package/src/core/scope-glob.ts +56 -0
- package/src/core/scripts.ts +6 -0
- package/src/core/skill-manifests.ts +173 -0
- package/src/core/store-lock.ts +374 -0
- package/src/core/support-matrix.ts +24 -0
- package/src/core/task-context.ts +247 -0
- package/src/core/task-contract.ts +1279 -0
- package/src/core/task-delivery.ts +109 -0
- package/src/core/task-engine.ts +2248 -0
- package/src/core/task-evaluation.ts +1147 -0
- package/src/core/task-store.ts +2649 -0
- package/src/core/task-view.ts +180 -0
- package/src/core/templates.ts +22 -0
- package/src/core/tracker-issues.ts +174 -0
- package/src/core/vcs-config.ts +540 -0
- package/src/core/workers.ts +62 -0
- package/src/core/workit-paths.mjs +242 -0
- package/src/core/workspace-branch-policy.ts +123 -0
- package/src/core/workspaces.ts +1745 -0
- package/src/core/youtrack-backend.ts +288 -0
- package/src/core/youtrack-tools.ts +260 -0
- package/src/core/youtrack-writes.ts +73 -0
- package/src/core/youtrack-ytrack.ts +217 -0
- package/src/core/youtrack.ts +454 -0
- package/src/core/ytrack-skill.ts +297 -0
- package/src/core.ts +171 -0
- package/src/deslop/lex.ts +271 -0
- package/src/deslop/scan.ts +232 -0
- package/src/duration.ts +27 -0
- package/src/fanout-brief.ts +486 -0
- package/src/fanout-check.ts +455 -0
- package/src/fanout-landed.ts +370 -0
- package/src/fanout-stack.ts +108 -0
- package/src/fanout-status.ts +362 -0
- package/src/fanout-worktree.ts +893 -0
- package/src/fanout.ts +1473 -0
- package/src/forge/exec.ts +385 -0
- package/src/forge/github.ts +831 -0
- package/src/forge/gitlab.ts +906 -0
- package/src/forge/issue-forge.ts +209 -0
- package/src/forge/issue-link.ts +468 -0
- package/src/forge/issue-ops.ts +314 -0
- package/src/forge/merge-gate-base-red.ts +72 -0
- package/src/forge/pr-body.ts +100 -0
- package/src/forge/pr-edit.ts +292 -0
- package/src/forge/pr-ops.ts +1109 -0
- package/src/forge/pr-status.ts +10 -0
- package/src/forge/redact.ts +195 -0
- package/src/forge/report.ts +994 -0
- package/src/forge/reruns.ts +132 -0
- package/src/forge/resolve.ts +509 -0
- package/src/forge/types.ts +242 -0
- package/src/forge/verify.ts +398 -0
- package/src/git/default-base.ts +130 -0
- package/src/git/env-redirect.ts +28 -0
- package/src/git/facts.ts +122 -0
- package/src/git/ops.ts +1823 -0
- package/src/git/refs-read.ts +332 -0
- package/src/git/release.ts +1020 -0
- package/src/git/rev.ts +1175 -0
- package/src/git/session-hook.ts +597 -0
- package/src/git/stage.ts +63 -0
- package/src/hooks/agent-model.ts +149 -0
- package/src/hooks/budget-signal.ts +284 -0
- package/src/hooks/context.ts +461 -0
- package/src/hooks/cwd-normalize.ts +79 -0
- package/src/hooks/deadline.ts +228 -0
- package/src/hooks/delivery-verbs.ts +182 -0
- package/src/hooks/descriptor.ts +124 -0
- package/src/hooks/handle.ts +433 -0
- package/src/hooks/heavy-gate.ts +99 -0
- package/src/hooks/hook-runs.ts +130 -0
- package/src/hooks/hosts/claude-code.ts +380 -0
- package/src/hooks/hosts/codex.ts +372 -0
- package/src/hooks/hosts/cursor.ts +419 -0
- package/src/hooks/hosts/fields.ts +98 -0
- package/src/hooks/hosts/opencode.ts +79 -0
- package/src/hooks/hosts/pi.ts +78 -0
- package/src/hooks/index.ts +60 -0
- package/src/hooks/model-limit.ts +378 -0
- package/src/hooks/model-switch.ts +35 -0
- package/src/hooks/policy.ts +29 -0
- package/src/hooks/process.ts +48 -0
- package/src/hooks/protocol.ts +135 -0
- package/src/hooks/raw-git.ts +2289 -0
- package/src/hooks/repeat-failure.ts +115 -0
- package/src/hooks/run.ts +54 -0
- package/src/hooks/session-marker.ts +151 -0
- package/src/hooks/shell-words.ts +532 -0
- package/src/hooks/skill-nudge.ts +295 -0
- package/src/hooks/spawn-gate.ts +72 -0
- package/src/hooks/standing-signal.ts +99 -0
- package/src/hooks/standing.ts +225 -0
- package/src/hooks/steering.ts +74 -0
- package/src/hooks/stop.ts +408 -0
- package/src/hooks/worktree-confine.ts +415 -0
- package/src/hooks/write-gate.ts +1174 -0
- package/src/host-session.ts +459 -0
- package/src/knowledge.ts +368 -0
- package/src/ledger.ts +2913 -0
- package/src/stack.ts +2570 -0
- package/src/store/event-log.ts +217 -0
- package/src/store/notes.ts +29 -0
- package/src/store/patch.ts +135 -0
- package/src/store/paths.ts +368 -0
- package/src/store/reduce.ts +203 -0
- package/src/test-audit-mocks.ts +309 -0
- package/src/verdict-cover.ts +151 -0
- package/src/worktree-deps.ts +142 -0
- package/templates/headers.md +3 -0
- package/templates/hygiene/.editorconfig +8 -0
- package/templates/hygiene/.gitattributes +3 -0
- package/templates/hygiene/CHANGELOG.md +14 -0
- package/templates/hygiene/CONTRIBUTING.md +3 -0
- package/templates/hygiene/LICENSE +21 -0
- package/templates/hygiene/README.md +3 -0
- package/templates/issue-update.md +5 -0
- package/templates/plan-template.md +26 -0
- package/templates/spec-template.md +64 -0
- package/templates/workit-contract.md +13 -0
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
import { isUncertainWorker } from "./workers";
|
|
2
|
+
import {
|
|
3
|
+
POLICY_VERSION,
|
|
4
|
+
failure,
|
|
5
|
+
sha256,
|
|
6
|
+
success,
|
|
7
|
+
type Candidate,
|
|
8
|
+
type Decision,
|
|
9
|
+
type Provenance,
|
|
10
|
+
type Progress,
|
|
11
|
+
type Ref,
|
|
12
|
+
type Result,
|
|
13
|
+
type TaskView,
|
|
14
|
+
type Utc,
|
|
15
|
+
} from "./task-contract";
|
|
16
|
+
import { captureCandidate, evaluateEvidence, treeFreshness } from "./task-evaluation";
|
|
17
|
+
import { selectMethods, type SelectedMethod } from "./methods";
|
|
18
|
+
import type { NativeWorkerObservation } from "./workers";
|
|
19
|
+
|
|
20
|
+
export type ResumeObservation = {
|
|
21
|
+
observation: NativeWorkerObservation;
|
|
22
|
+
authority: Provenance | null;
|
|
23
|
+
};
|
|
24
|
+
export type ResumeObservationInput = ResumeObservation | NativeWorkerObservation;
|
|
25
|
+
|
|
26
|
+
export type ResumeReconciliation = {
|
|
27
|
+
candidate: Candidate;
|
|
28
|
+
staleEvidenceIds: string[];
|
|
29
|
+
workerUpdates: NativeWorkerObservation[];
|
|
30
|
+
blockers: Progress["blockers"];
|
|
31
|
+
reassessmentRequired: boolean;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export function reconcileResume(
|
|
35
|
+
view: TaskView,
|
|
36
|
+
observations: ResumeObservationInput[] = [],
|
|
37
|
+
): Result<ResumeReconciliation> {
|
|
38
|
+
if (observations.length > 0)
|
|
39
|
+
return failure("permission_denied", "worker observations require native host verification");
|
|
40
|
+
const candidate = captureCandidate(view.workspace.root, view.task.intent.data.scope, []);
|
|
41
|
+
if (!candidate.ok) return candidate;
|
|
42
|
+
const staleEvidenceIds = evaluateEvidence(
|
|
43
|
+
view.task,
|
|
44
|
+
candidate.data,
|
|
45
|
+
treeFreshness(view.workspace.root),
|
|
46
|
+
)
|
|
47
|
+
.filter((entry) => entry.status === "stale")
|
|
48
|
+
.map((entry) => entry.evidenceId);
|
|
49
|
+
const blockers = [...view.task.progress.blockers];
|
|
50
|
+
if (view.task.workers.some((entry) => isUncertainWorker(entry.data.state)))
|
|
51
|
+
blockers.push({
|
|
52
|
+
reason: "worker state requires reconciliation",
|
|
53
|
+
dependentAction: "resume",
|
|
54
|
+
refs: [],
|
|
55
|
+
});
|
|
56
|
+
return success(null, null, {
|
|
57
|
+
candidate: candidate.data,
|
|
58
|
+
staleEvidenceIds,
|
|
59
|
+
workerUpdates: [],
|
|
60
|
+
blockers,
|
|
61
|
+
reassessmentRequired: view.task.policy?.policyVersion !== POLICY_VERSION,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
type CompactReference = { kind: Ref["kind"] } & Partial<
|
|
66
|
+
Pick<Extract<Ref, { kind: "file" }>, "path">
|
|
67
|
+
> &
|
|
68
|
+
Partial<Pick<Extract<Ref, { kind: "record" }>, "collection" | "id">>;
|
|
69
|
+
type CompactDecision = {
|
|
70
|
+
id: string;
|
|
71
|
+
purpose: Decision["purpose"];
|
|
72
|
+
status: Decision["response"];
|
|
73
|
+
digest: string;
|
|
74
|
+
choice: string;
|
|
75
|
+
references: CompactReference[];
|
|
76
|
+
/** Where an inherited decision was recorded ("branch develop"); absent for the task's own. */
|
|
77
|
+
origin?: string;
|
|
78
|
+
};
|
|
79
|
+
type CompactMethod = Pick<SelectedMethod, "id" | "assurance"> & { reason: string };
|
|
80
|
+
/** Decisions of a task the current one inherits from (its base branch's task). */
|
|
81
|
+
export type InheritedDecisions = {
|
|
82
|
+
origin: string;
|
|
83
|
+
taskId: string;
|
|
84
|
+
decisions: TaskView["task"]["decisions"];
|
|
85
|
+
};
|
|
86
|
+
export type CompactTaskContext = {
|
|
87
|
+
objective: string;
|
|
88
|
+
/** Null when the checkout has no task yet and only inherited decisions apply. */
|
|
89
|
+
status: TaskView["task"]["status"] | null;
|
|
90
|
+
decisions: CompactDecision[];
|
|
91
|
+
methods: CompactMethod[];
|
|
92
|
+
gaps: string[];
|
|
93
|
+
nextAction: string | null;
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
const COMPACT_MAX_BYTES = 4096;
|
|
97
|
+
const COMPACT_MAX_ITEMS = 8;
|
|
98
|
+
const COMPACT_TEXT_BYTES = 128;
|
|
99
|
+
const sensitiveUrl = /\bhttps?:\/\/[^/\s:@]+:[^@\s]+@/gi;
|
|
100
|
+
const sensitiveValue =
|
|
101
|
+
/(?:token|secret|password|passwd|api[-_ ]?key|private[-_ ]?key|authorization)\s*[:=]\s*(?:bearer\s+)?\S+|\bbearer\s+\S+/gi;
|
|
102
|
+
const privateKey = /-----BEGIN [^-]*PRIVATE KEY-----[\s\S]*?-----END [^-]*PRIVATE KEY-----/gi;
|
|
103
|
+
const compactText = (value: string | null, limit: number): string | null =>
|
|
104
|
+
value === null
|
|
105
|
+
? null
|
|
106
|
+
: value
|
|
107
|
+
.replace(privateKey, "<redacted-private-key>")
|
|
108
|
+
.replace(sensitiveUrl, "<redacted-url>")
|
|
109
|
+
.replace(sensitiveValue, (match) => {
|
|
110
|
+
const separator = match.search(/[:=]/u);
|
|
111
|
+
if (separator >= 0) return `${match.slice(0, separator)}=<redacted>`;
|
|
112
|
+
const space = match.search(/\s/u);
|
|
113
|
+
return `${match.slice(0, space)} <redacted>`;
|
|
114
|
+
})
|
|
115
|
+
.slice(0, limit);
|
|
116
|
+
const compactBytes = (value: string): number => new TextEncoder().encode(value).byteLength;
|
|
117
|
+
const compactTimestamp = (value: Utc): string =>
|
|
118
|
+
`${value.slice(0, 19)}.${value.slice(20, -1).padEnd(9, "0")}`;
|
|
119
|
+
const compactDecisionChoice = (entry: TaskView["task"]["decisions"][number]): string | null => {
|
|
120
|
+
const stated = entry.data.binding.statedChoice?.text;
|
|
121
|
+
const approved = entry.data.response === "approved" ? entry.data.binding.presented : "";
|
|
122
|
+
const source = stated?.trim() || approved.trim() || null;
|
|
123
|
+
return compactText(source, COMPACT_TEXT_BYTES);
|
|
124
|
+
};
|
|
125
|
+
const compactReference = (ref: Ref): CompactReference => {
|
|
126
|
+
if (ref.kind === "file")
|
|
127
|
+
return {
|
|
128
|
+
kind: "file",
|
|
129
|
+
path: compactText(ref.path, COMPACT_TEXT_BYTES) ?? "",
|
|
130
|
+
};
|
|
131
|
+
if (ref.kind === "record")
|
|
132
|
+
return {
|
|
133
|
+
kind: "record",
|
|
134
|
+
collection: ref.collection,
|
|
135
|
+
id: ref.id,
|
|
136
|
+
};
|
|
137
|
+
return { kind: ref.kind };
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
type TaskDecision = TaskView["task"]["decisions"][number];
|
|
141
|
+
const newestDecisionFirst = (left: TaskDecision, right: TaskDecision): number => {
|
|
142
|
+
const leftAt = compactTimestamp(left.recordedAt);
|
|
143
|
+
const rightAt = compactTimestamp(right.recordedAt);
|
|
144
|
+
if (leftAt !== rightAt) return leftAt > rightAt ? -1 : 1;
|
|
145
|
+
return left.id < right.id ? -1 : left.id > right.id ? 1 : 0;
|
|
146
|
+
};
|
|
147
|
+
/**
|
|
148
|
+
* The task's own decisions (newest first), then the ones it inherits (origin
|
|
149
|
+
* set; the engine passes only unrevoked ones), at most COMPACT_MAX_ITEMS.
|
|
150
|
+
*/
|
|
151
|
+
const compactDecisions = (
|
|
152
|
+
sources: Array<{ origin: string | null; taskId: string; decisions: TaskDecision[] } | null>,
|
|
153
|
+
): CompactDecision[] =>
|
|
154
|
+
sources
|
|
155
|
+
.flatMap((source) =>
|
|
156
|
+
source
|
|
157
|
+
? source.decisions.toSorted(newestDecisionFirst).map((entry) => ({
|
|
158
|
+
id: entry.id,
|
|
159
|
+
purpose: entry.data.purpose,
|
|
160
|
+
status: entry.data.response,
|
|
161
|
+
digest: entry.data.digest,
|
|
162
|
+
choice:
|
|
163
|
+
compactDecisionChoice(entry) ||
|
|
164
|
+
`task.inspect taskId=${source.taskId} view=full; decision=${entry.id}`,
|
|
165
|
+
references: entry.data.binding.contentRefs.slice(0, 1).map(compactReference),
|
|
166
|
+
// Undefined (dropped from the JSON) for the task's own decisions.
|
|
167
|
+
origin: source.origin ?? undefined,
|
|
168
|
+
}))
|
|
169
|
+
: [],
|
|
170
|
+
)
|
|
171
|
+
.slice(0, COMPACT_MAX_ITEMS);
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* The compact context of `view`'s task plus the decisions it inherits; with
|
|
175
|
+
* a null `view` (the branch has no task of its own yet) only the inherited
|
|
176
|
+
* decisions. Stale evidence is one counted gap with the command that lists it.
|
|
177
|
+
*/
|
|
178
|
+
export function compactTaskContext(
|
|
179
|
+
view: TaskView | null,
|
|
180
|
+
inherited: InheritedDecisions | null = null,
|
|
181
|
+
): string {
|
|
182
|
+
const decisions = compactDecisions([
|
|
183
|
+
view && { origin: null, taskId: view.task.id, decisions: view.task.decisions },
|
|
184
|
+
inherited,
|
|
185
|
+
]);
|
|
186
|
+
const methods: CompactMethod[] = view?.task.policy
|
|
187
|
+
? selectMethods(view.task.policy, view.capabilities).map((method) => ({
|
|
188
|
+
id: method.id,
|
|
189
|
+
assurance: method.assurance,
|
|
190
|
+
reason: compactText(method.reason, COMPACT_TEXT_BYTES) ?? "",
|
|
191
|
+
}))
|
|
192
|
+
: [];
|
|
193
|
+
const stale = view?.evidence.filter((entry) => entry.status === "stale").length;
|
|
194
|
+
const gaps = Array.from(
|
|
195
|
+
new Set([
|
|
196
|
+
...(stale
|
|
197
|
+
? [`stale evidence: ${stale}; workit task inspect --task ${view.task.id} --view full`]
|
|
198
|
+
: []),
|
|
199
|
+
...(view?.requirements ?? [])
|
|
200
|
+
.filter((entry) => entry.status !== "satisfied")
|
|
201
|
+
.map((entry) => entry.reason),
|
|
202
|
+
...(view?.task.progress.blockers ?? []).map((entry) => entry.reason),
|
|
203
|
+
]),
|
|
204
|
+
)
|
|
205
|
+
.toSorted()
|
|
206
|
+
.slice(0, COMPACT_MAX_ITEMS)
|
|
207
|
+
.map((gap) => compactText(gap, COMPACT_TEXT_BYTES)!);
|
|
208
|
+
const context: CompactTaskContext = {
|
|
209
|
+
objective: view
|
|
210
|
+
? (compactText(view.task.intent.data.objective, COMPACT_TEXT_BYTES) ?? "")
|
|
211
|
+
: "no task on this branch yet",
|
|
212
|
+
status: view?.task.status ?? null,
|
|
213
|
+
decisions,
|
|
214
|
+
methods,
|
|
215
|
+
gaps,
|
|
216
|
+
nextAction: compactText(view?.task.progress.nextAction ?? null, COMPACT_TEXT_BYTES),
|
|
217
|
+
};
|
|
218
|
+
let encoded = JSON.stringify(context);
|
|
219
|
+
while (
|
|
220
|
+
compactBytes(encoded) > COMPACT_MAX_BYTES &&
|
|
221
|
+
(context.decisions.length || context.methods.length || context.gaps.length)
|
|
222
|
+
) {
|
|
223
|
+
if (context.gaps.length) context.gaps.pop();
|
|
224
|
+
else if (context.decisions.length) context.decisions.pop();
|
|
225
|
+
else context.methods.pop();
|
|
226
|
+
encoded = JSON.stringify(context);
|
|
227
|
+
}
|
|
228
|
+
if (compactBytes(encoded) > COMPACT_MAX_BYTES) {
|
|
229
|
+
context.objective = compactText(context.objective, 64) ?? "";
|
|
230
|
+
context.nextAction = compactText(context.nextAction, 64);
|
|
231
|
+
encoded = JSON.stringify(context);
|
|
232
|
+
}
|
|
233
|
+
return encoded;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
export const exportDigest = (bundle: {
|
|
237
|
+
schemaVersion: 1;
|
|
238
|
+
exportedAt: Utc;
|
|
239
|
+
sourceWorkspaceId: string;
|
|
240
|
+
task: unknown;
|
|
241
|
+
}): string =>
|
|
242
|
+
sha256({
|
|
243
|
+
schemaVersion: bundle.schemaVersion,
|
|
244
|
+
exportedAt: bundle.exportedAt,
|
|
245
|
+
sourceWorkspaceId: bundle.sourceWorkspaceId,
|
|
246
|
+
task: bundle.task,
|
|
247
|
+
});
|