engineering-memory 1.11.14 → 1.11.16
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/dispatcher/sections.mjs +2 -2
- package/package.json +1 -1
- package/runtime/build.json +1 -1
- package/runtime/dist/src/mcp/questionnaire-tools.js +105 -50
- package/runtime/dist/src/mcp/worktree-tools.js +4 -3
- package/runtime/dist/src/runtime/bridge-service.js +12 -6
- package/runtime/dist/src/runtime/task-start.js +124 -0
- package/runtime/dist/src/runtime/worktree-editor.js +184 -0
- package/runtime/dist/src/runtime/worktree-gradle.js +318 -0
- package/runtime/dist/src/runtime/worktree-pool.js +181 -3
- package/runtime/dist/src/runtime/worktree-preparation.js +901 -0
- package/runtime/dist/src/runtime/worktree-readiness-types.js +18 -0
- package/skill/references/lifecycle.md +3 -1
- package/skill/references/questionnaires.md +9 -5
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export var WorktreeFileStatus;
|
|
2
|
+
(function (WorktreeFileStatus) {
|
|
3
|
+
WorktreeFileStatus["Prepared"] = "prepared";
|
|
4
|
+
WorktreeFileStatus["Attention"] = "attention";
|
|
5
|
+
WorktreeFileStatus["NotNeeded"] = "not_needed";
|
|
6
|
+
WorktreeFileStatus["Skipped"] = "skipped";
|
|
7
|
+
})(WorktreeFileStatus || (WorktreeFileStatus = {}));
|
|
8
|
+
export var WorktreeFileIssue;
|
|
9
|
+
(function (WorktreeFileIssue) {
|
|
10
|
+
WorktreeFileIssue["Missing"] = "missing";
|
|
11
|
+
WorktreeFileIssue["Conflict"] = "conflict";
|
|
12
|
+
WorktreeFileIssue["Stale"] = "stale";
|
|
13
|
+
WorktreeFileIssue["Unsafe"] = "unsafe";
|
|
14
|
+
WorktreeFileIssue["Unsupported"] = "unsupported";
|
|
15
|
+
WorktreeFileIssue["SourceChanged"] = "source_changed";
|
|
16
|
+
WorktreeFileIssue["Failed"] = "failed";
|
|
17
|
+
})(WorktreeFileIssue || (WorktreeFileIssue = {}));
|
|
18
|
+
//# sourceMappingURL=worktree-readiness-types.js.map
|
|
@@ -20,10 +20,12 @@ For a bound repository, call `session.bootstrap` before producing a plan or chan
|
|
|
20
20
|
|
|
21
21
|
Before a new write or scaffold task, read `session.entry` and the project Git preferences. If `canManage` is true, and any of development/production/test is still unanswered, ask them through one native form and save them with `project.set_git_preferences` — the tool asks every supplied role as its own question in that single form, then saves the approved roles together in one PUT. Development needs a branch; production/test may explicitly be absent. Their answered flags prevent repeated questions. Other members choose only a task-specific base and continue without changing shared preferences. A later request to change a base updates future tasks only. Branch preferences never label memory sources or change commit/tree applicability.
|
|
22
22
|
|
|
23
|
-
Start new write or scaffold work with `task.branch`, before `session.bootstrap`, passing the stable `externalTaskId` and `repoRoot`. It opens one native form
|
|
23
|
+
Start new write or scaffold work with `task.branch`, before `session.bootstrap`, passing the stable `externalTaskId` and `repoRoot`. It opens one short native form with only two questions: the starting branch and the folder. The branch name is generated automatically; a user-requested name may be supplied through `name`. Identical configured remote branches appear once. Folder choices: a separate managed worktree, this folder as a new branch when it is clean (moving out an unfinished task that holds it, which that option names), this folder on its current branch, or not now. Pass `base` or `name` when the user has already specified them; a supplied base removes that question. Do not ask a separate naming question. Keep the form concise and do not repeat its choices in a long chat introduction. Show the whole form in as few native control calls as the host allows, relay every answer together, then call `task.branch` again with the same arguments, which is the `retry` the relay returns. That call allocates exactly what was answered, fetches a remote base and pins its commit, and returns the `repoRoot` to bootstrap in. When the fetch fails it asks once whether to continue from the local commit; never select a cached branch silently. "Not now" returns `status: 'deferred'` with nothing created, reserved or saved: say so in one line, continue only read-only work, and call the returned `reconsider` exactly as given once the user asks to start it. A refusal that names a new `decisionAttempt`, such as a branch name that already exists, asks the form again under that attempt. Existing task decisions survive retries and restarts; resume a recorded branch rather than recreating or resetting it.
|
|
24
24
|
|
|
25
25
|
Use the returned `repoRoot` for **every** file read/write, terminal, context, validation and Git/delivery operation. The user-local pool is shared by Codex and Claude. Managed directories live under `engineering_memory/worktrees/<stable-project-folder>/<folder>_worktreeN`, at the root of the system drive on Windows (`C:\engineering_memory\worktrees\...`) and in the home directory elsewhere, or under the absolute directory named by `worktree-root.json` in the user-level API state directory when that file exists; `worktree.list` reports the effective root, and worktrees created by earlier clients under the Documents folder keep working where they are. Do not supply arbitrary `worktreePath` values or create ad-hoc siblings. Independent clones cannot reuse each other's worktrees. `worktree.list` explains which slots are active, inactive but protected, or safely reusable. The versioned backend policy defaults to 50 directories per project/computer, 30-second heartbeats and 10-minute inactivity. Protected inactive directories still count toward the limit. Only a global admin changes `worktree.set_policy`; it is not an environment setting.
|
|
26
26
|
|
|
27
|
+
After managed allocation, inspect `readiness.files` and `readiness.editor`. The bridge prepares supported ignored runtime files from pinned same-clone sources, preserving existing files and reporting missing, conflicting, stale or unsupported configuration. A signing key outside the source checkout remains external. File contents stay local. Repair the reported issue with the user's existing authority, then retry `task.branch` or `session.resume`; never overwrite a conflict merely to make preparation pass. The editor status `requested` records a VS Code CLI request, not verified window visibility. The CLI reuses a matching single-folder window and preserves unrelated windows; an existing multi-root membership is not verified. Headless sessions, unavailable editors and launch failures leave the task allocated. Do not repeatedly open windows yourself after a recorded request.
|
|
28
|
+
|
|
27
29
|
Renew `task.heartbeat` using the exact returned task, path and ownership generation during actual work and at approximately the cached heartbeat interval during long local commands. The bridge renews while its own task operation is running. Never run a perpetual heartbeat for an idle chat or MCP process. Inactivity never authorizes takeover of a live owner or deletion of files. Before writing after interruption, use `session.resume`; follow any returned worktree redirect and resume there. A stale generation cannot renew, release, verify or commit another owner's work.
|
|
28
30
|
|
|
29
31
|
Use `task.pause` when work stops or is handed to another client. It preserves task state and files, invalidates the old owner, and allows safe clean directories to be reused. It is not `task.abandon`. Resume reacquires the original directory when possible or uses the retained task branch in another safe directory. `worktree.reconcile` recovers interrupted allocation and validated local ownership records against Git. Never edit the registry, force checkout, stash/reset/clean, remove branches, kill a client or delete a worktree to bypass a refusal.
|
|
@@ -8,9 +8,11 @@ Use `questionnaire.ask` for a required decision. It records the question before
|
|
|
8
8
|
|
|
9
9
|
Pass `repoRoot`, `questionnaireId`, `message` and two to twelve `options`, each with an `id` and `label`. Identifiers use letters, digits, underscores or hyphens.
|
|
10
10
|
|
|
11
|
+
Order choices with the recommendation first, or label the recommended choice explicitly in the user’s language. The renderer marks the recommendation without preselecting an answer. Keep task-start questions short; for a complex decision preserve the context, a concrete example and each option’s consequences. Do not repeat option explanations in the question body.
|
|
12
|
+
|
|
11
13
|
A question has to be answerable by someone who has not followed the work. Say in `context` why it is being asked, give in `example` one concrete thing the decision changes, and give every option a `description` of what happens next if it is chosen. Show a record, a branch or a project by its title or name; an identifier or a hash in the visible text is refused, and one that really has to be shown goes inside backticks. Write all of it in the language the user is writing in and pass that language as `language`, a BCP-47 tag such as `tr`, `en` or `pt-BR`. The tag is remembered for the account and the computer, so it is asked for once: `session.entry` and every tool that opens a form take the same argument, and `questionnaire.ask` is refused while no language is known.
|
|
12
14
|
|
|
13
|
-
Every form
|
|
15
|
+
Every form lets the person write an answer or comment without selecting an option. Use the host control's own free-input area; do not add a duplicate Other choice or a second question for feedback. Standard MCP forms expose one optional free-input field. On fixed decisions, text returns `status: pending` and `reason: feedback`, including when a selection is present: a comment may qualify that selection. It is not persisted as a decision. Address the feedback, then resume the original question or use a new bound question if its choices change. A host-native free response is relayed with the internal `__other__` choice and `text`; that identifier is not a visible choice. Explicit `allowFreeText` forms retain their free-answer contract and accept a typed answer without a selection. Earlier explanation choices and checkbox replies still return `needs_explanation` without recording consent. When the person asks for more detail, explain why the question is asked, what the options lead to and one example, then resume the original question. Set `allowFreeText` only when the user needs to give an answer outside those options. `questionnaire.resume` takes the same `repoRoot` and `questionnaireId`. These tools collect decisions; they do not commit, publish, bind a project or perform the selected action. Apply the accepted answer through the relevant lifecycle tool, checking the current target and version first.
|
|
14
16
|
|
|
15
17
|
Fixed-choice answers can be replayed from the local receipt. Free text is returned only in the accepting call and is never stored. If a later receipt says the answer is unavailable, recover it from the user's actual answer in the conversation; never reconstruct it from the options. If it cannot be recovered, explain that it must be requested again using a new question identifier.
|
|
16
18
|
|
|
@@ -26,7 +28,7 @@ never enough to answer here. Resume it only in the chat working on that task.
|
|
|
26
28
|
|
|
27
29
|
Only an explicit, valid accepted response answers a question. A timeout, dismissed form, empty response, invalid response, connection loss or ended turn is not an answer. These events leave the decision pending. Never substitute the recommended choice or treat silence as consent. The form's cancel or decline button dismisses the form; if abandoning the work is a meaningful decision, offer it as an explicit answer in the question. A question left pending this way stays pending; show it again once, on the user's next message, and then wait rather than re-asking on every following turn.
|
|
28
30
|
|
|
29
|
-
State the decision and one
|
|
31
|
+
State the decision in `message` and one useful example in `example`, in the language the user is writing in. Never put a resource key, hash, task ID or other internal identifier in a question's text — it explains nothing to the person answering and only makes the question harder to read.
|
|
30
32
|
|
|
31
33
|
Never use request_user_input_async for a required decision: it does not wait for an answer. Do not end a turn while a required native form is still awaiting the user. Work that does not depend on the answer may continue. If the host removes the form or interrupts the tool call, retain the pending decision and resume that same question when the user returns. Do not automatically reopen dismissed forms in a loop, or use repeated sleeps to claim that a host timer has been disabled.
|
|
32
34
|
|
|
@@ -65,12 +67,12 @@ host: offer the MCP form again in a fresh session, since decline alone is not pr
|
|
|
65
67
|
cannot display one.
|
|
66
68
|
|
|
67
69
|
Some forms carry several related questions in one durable record. The `task.branch` start form
|
|
68
|
-
asks
|
|
70
|
+
asks only the starting branch and where to work; it names the new branch automatically. The
|
|
69
71
|
`project.set_git_preferences` form asks one question per role. Their `hostFallback` carries a
|
|
70
72
|
`questions` array instead of a single `options` array. AskUserQuestion takes at most 4
|
|
71
73
|
questions per call, so show them in as few calls as needed and relay every answer together in
|
|
72
74
|
one `questionnaire.answer_from_host` call, as `answers` keyed by each question's id. A choice
|
|
73
|
-
that needs text, such as
|
|
75
|
+
that needs text, such as another starting branch, carries it as that answer's `text`. A record can
|
|
74
76
|
also declare `terminalChoices`: picking one of those answers (for example "Not now") makes
|
|
75
77
|
every other question in that form optional.
|
|
76
78
|
|
|
@@ -180,7 +182,7 @@ Ask for the registered email and intended role. Show owner, maintainer, member,
|
|
|
180
182
|
|
|
181
183
|
## Branch
|
|
182
184
|
|
|
183
|
-
Call `task.branch` once for every new write or scaffold task, on any branch, and before a read-only task transitions to writing. Do not ask these questions yourself first: its one form asks where the task works (a separate managed worktree, this folder when it is clean, this folder after the task holding it moves out, or the branch already checked out), which branch it starts from
|
|
185
|
+
Call `task.branch` once for every new write or scaffold task, on any branch, and before a read-only task transitions to writing. Do not ask these questions yourself first: its one form asks where the task works (a separate managed worktree, this folder when it is clean, this folder after the task holding it moves out, or the branch already checked out), and which branch it starts from. The new branch name is generated automatically; never add a naming question unless the user requests it. Keep the two questions short; do not repeat all choices in the introduction. Pass the exact `externalTaskId`. Pass `name`, `base` or `keepCurrent` only when the user already stated them, so the form skips that question; never pass a `worktreePath`. A task whose branch already exists resumes its recorded task instead of starting a new one. Continue in the returned `repoRoot`. Retries and handoffs reuse the stored answer. Read-only analysis does not create a branch or consume another task's answer.
|
|
184
186
|
|
|
185
187
|
## Flow Entry and Exit
|
|
186
188
|
|
|
@@ -375,3 +377,5 @@ freed with `worktree.release` instead.
|
|
|
375
377
|
|
|
376
378
|
If the user later reconsiders a preserved legacy checkout, repeat `worktree.reconcile` with a new
|
|
377
379
|
`decisionAttempt`; never reinterpret the previous preserve answer as approval.
|
|
380
|
+
|
|
381
|
+
Codex exposes native user-input tools and MCP elicitation as separate host capabilities. Use only tools permitted in the current mode. Standard MCP fields support labels, descriptions and optional text. Codex's native question UI already supports free responses; do not mistake a restriction in our form schema for a host limitation. Do not guess an undocumented `openai/form` schema. Keep fallback questions structured rather than flattening options into one long prompt.
|