@tea-agent/loop-agent 0.43.0-next.17 → 0.43.0-next.19
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/AGENTS.md +1 -1
- package/CHANGELOG.md +68 -2309
- package/README.md +7 -0
- package/dist/application/dag/args.js +8 -0
- package/dist/application/task-lifecycle/advance.js +38 -7
- package/dist/build-stamp.json +3 -3
- package/dist/cli/command-definitions.js +2 -0
- package/dist/cli/program.js +3 -1
- package/dist/cli/update/init-surface-notifier.js +2 -0
- package/dist/cli/update/policy.js +2 -0
- package/dist/commands/cursor-prompt.js +2 -0
- package/dist/commands/dag-approve.js +2 -0
- package/dist/commands/dag-final-verification.js +2 -0
- package/dist/commands/dag-init-hybrid.js +2 -0
- package/dist/commands/dag-reconcile-tasks.js +2 -0
- package/dist/commands/dag-reject.js +2 -0
- package/dist/commands/dag-report.js +2 -0
- package/dist/commands/dag-rerun.js +2 -0
- package/dist/commands/dag-resume.js +2 -0
- package/dist/commands/dag-workflow-compile.js +2 -0
- package/dist/commands/dag-workflow-plan.js +2 -0
- package/dist/commands/dag-workflow-validate.js +2 -0
- package/dist/commands/delegate.js +2 -0
- package/dist/commands/examples.js +2 -0
- package/dist/commands/import-prd.js +2 -0
- package/dist/commands/init-model-catalog.js +2 -0
- package/dist/commands/init.js +19 -13
- package/dist/commands/instructions.js +2 -0
- package/dist/commands/knowledge.js +2 -0
- package/dist/commands/loop-benchmark.js +2 -0
- package/dist/commands/pi-prompt.js +2 -0
- package/dist/commands/pi-reuse-benchmark.js +2 -0
- package/dist/commands/promote-run.js +2 -0
- package/dist/commands/stats.js +1 -1
- package/dist/commands/study-init.js +2 -0
- package/dist/commands/task-advance.js +34 -0
- package/dist/commands/task-source-prepare.js +2 -0
- package/dist/commands/worktree-create.js +2 -0
- package/dist/commands/worktree-remove.js +2 -0
- package/dist/executors/dag-pi-executor.js +1640 -194
- package/dist/executors/pi-executor.js +85 -3
- package/dist/executors/pi-sdk-executor.js +18 -0
- package/dist/executors/shell-executor.js +92 -7
- package/dist/executors/shell-verification.js +3 -0
- package/dist/governance/exec-plans.js +6 -3
- package/dist/infrastructure/console/app-data.js +6 -0
- package/dist/shared/artifacts-core.js +2 -0
- package/dist/shared/backend-dogfood-preflight.js +47 -0
- package/dist/shared/dag-failure-category.js +3 -0
- package/dist/shared/git-progress.js +2 -0
- package/dist/shared/one-shot-prompt-args.js +2 -0
- package/dist/shared/operator/capabilities.js +180 -0
- package/dist/shared/package-metadata.js +6 -4
- package/dist/shared/pi-context-pressure/sift-bridge.js +1 -1
- package/dist/shared/reference-context.js +2 -0
- package/dist/task/config-types.js +29 -0
- package/dist/task/contract/project.js +9 -0
- package/dist/task/contract/recover.js +6 -0
- package/dist/task/contract/schema.js +17 -0
- package/dist/task/source-prepare/artifact-meta.js +9 -2
- package/dist/task/source-prepare/build-draft.js +60 -0
- package/dist/task/source-prepare/fragment-inventory.js +4 -1
- package/dist/task/source-prepare/parse-intent.js +36 -11
- package/dist/task/task-demand-routing.js +5 -2
- package/dist/worker/console/chat/browser-automation.js +468 -308
- package/dist/worker/console/chat/browser-routes.js +175 -57
- package/dist/worker/console/chat/explore-tools.js +5 -2
- package/dist/worker/console/chat/pi-mode-loop-isolation.js +155 -0
- package/dist/worker/console/chat/pi-runtime/custom-tools/browser-tools.js +115 -20
- package/dist/worker/console/chat/pi-runtime/custom-tools/operator-tools.js +24 -16
- package/dist/worker/console/chat/pi-runtime/custom-tools/scheduled-goal-tools.js +22 -0
- package/dist/worker/console/chat/pi-runtime/progressive-tools.js +195 -0
- package/dist/worker/console/chat/pi-runtime.js +95 -28
- package/dist/worker/console/chat/routes.js +20 -1
- package/dist/worker/console/chat/scheduled-goal-booking.js +59 -0
- package/dist/worker/console/chat/scheduled-goal-delivery.js +27 -0
- package/dist/worker/console/chat/scheduled-goal-request.js +190 -0
- package/dist/worker/console/chat/sdd-data-alignment.js +1 -1
- package/dist/worker/console/chat/session-mode.js +8 -4
- package/dist/worker/console/chat/session-store.js +42 -9
- package/dist/worker/console/chat/tool-preview.js +115 -0
- package/dist/worker/console/chat/tools.js +7 -1
- package/dist/worker/console/chat/turn-order.js +13 -0
- package/dist/worker/console/chat/turn-process.js +32 -30
- package/dist/worker/console/operator-actions.js +50 -0
- package/dist/worker/console/prd-intake-bridge.js +54 -1
- package/dist/worker/console/scheduled-goal-host.js +98 -0
- package/dist/worker/console/scheduled-goal-operation-adapter.js +127 -0
- package/dist/worker/console/server.js +15 -0
- package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-C4NXyedy.js → abnfDiagram-N423BO3Z-8-j6y-sd.js} +1 -1
- package/dist/worker/console/static/assets/{arc-NZ3qXvBI.js → arc-eoQiMvuk.js} +1 -1
- package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-COZSRvml.js → architectureDiagram-T3A2C74G-C4A3uMcI.js} +1 -1
- package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-Ck0Gxi9C.js → blockDiagram-VBNYF7ZC-D4zD2F-Q.js} +1 -1
- package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-BX5HQ4Ox.js → c4Diagram-5PPSVZJV-j1RkJziL.js} +1 -1
- package/dist/worker/console/static/assets/channel-ChE7y-cx.js +1 -0
- package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-CoviemSL.js → chunk-2GRJ4B5K-YBHmhik1.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-DbOdOkbZ.js → chunk-2Q5K7J3B-COfWyo9P.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5RXB4S5H-BsG2pmdQ.js → chunk-5RXB4S5H-I99OUkHY.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5VM5RSS4-DGdvrNm8.js → chunk-5VM5RSS4-XKxoJNJ4.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-BAy7Yd6y.js → chunk-6Q2QTUOP-DLT_cYx1.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-GF5L2VYU-D9UA7hUb.js → chunk-GF5L2VYU-CxcKZ9mV.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-JWPE2WC7-DPz7SZ8V.js → chunk-JWPE2WC7-V1EqXdjY.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-KBJHAD2P-BmuEOIh7.js → chunk-KBJHAD2P-DebTtdFp.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-RYQCIY6F-CIhBWnd8.js → chunk-RYQCIY6F-B-ivNRDf.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-XXDRQBXY-CScR6mDD.js → chunk-XXDRQBXY-DC_Ds11b.js} +1 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-C01TCf2X.js +1 -0
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-C01TCf2X.js +1 -0
- package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-BjpfWaUr.js → cose-bilkent-JH36ORCC-sWEqKwIb.js} +1 -1
- package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-BFQohJgT.js → cynefin-VYW2F7L2-BXa_dcu4.js} +1 -1
- package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-D3gzRJnS.js → cynefinDiagram-MW4NZA55-C-Mle84F.js} +1 -1
- package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-5eojkhoA.js → dagre-VZM6K2ZE-CXPDBITe.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-7IWD3JNH-CpD8LWu_.js → diagram-7IWD3JNH-CC-WJQfa.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-B8_4qJ2a.js → diagram-B4RE2ZJO-CDAV5Vs4.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-LBJQPF4R-HOsXf0eu.js → diagram-LBJQPF4R-CmFiAcNz.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-Q27KOJAE-BqwRwiWP.js → diagram-Q27KOJAE-DPBZHuyn.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-UB23O5K3-BRVCNZe1.js → diagram-UB23O5K3-jUlm_Ds3.js} +1 -1
- package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-Cvb1TgGh.js → ebnfDiagram-BXEA7PRR-DWhQ3mfY.js} +1 -1
- package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-DS0O0qG9.js → erDiagram-JOGREHBK-Tr2gMqet.js} +1 -1
- package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-BHIRvRr3.js → flowDiagram-UKHOOZJN-DJjVQHPA.js} +1 -1
- package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-DcCJ1JWx.js → ganttDiagram-PKOTCBZU-D74dQ4u0.js} +1 -1
- package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-B9ia5ony.js → gitGraphDiagram-DS77QQ5N-DwW0tZ0X.js} +1 -1
- package/dist/worker/console/static/assets/index-BWkIfcrK.css +1 -0
- package/dist/worker/console/static/assets/{index-wXlQohNs.js → index-Cdkvw_H6.js} +97 -97
- package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-3ogpgegn.js → infoDiagram-6WML65LV-ILCbxJyb.js} +1 -1
- package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-4tgpQ5SL.js → ishikawaDiagram-WSZJBQD7-DeuWBQ89.js} +1 -1
- package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-DNfgHqFx.js → journeyDiagram-NVQOT4AX-CF5ih8Fk.js} +1 -1
- package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-Dz7ngC8z.js → kanban-definition-27J2QSJJ-C7yOSuRO.js} +1 -1
- package/dist/worker/console/static/assets/{linear-DI7Jv62E.js → linear-BDZ9riWi.js} +1 -1
- package/dist/worker/console/static/assets/{mermaid.core-CQA4Nzmo.js → mermaid.core-7pKqYtpZ.js} +5 -5
- package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-CtsMc8Mf.js → mindmap-definition-FAOFIHXS-LeJDybSU.js} +1 -1
- package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-ByppE9yH.js → pegDiagram-VL7TDLO6-BJvT3pMD.js} +1 -1
- package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-B5PtgFgt.js → pieDiagram-7S7Q4E2Y-_rGqpMan.js} +1 -1
- package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-Cq4p0k2K.js → quadrantDiagram-CIZ2JOQS-DPcSv5aA.js} +1 -1
- package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-DjfkyljN.js → railroadDiagram-AXF67PYL-Drxx4hkJ.js} +1 -1
- package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-DzynNRSl.js → requirementDiagram-LRYGKXZP-BCTUdU4z.js} +1 -1
- package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-Cj7TCpTJ.js → sankeyDiagram-W5VNT64P-B6wzbZmB.js} +1 -1
- package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-C73C6ykA.js → sequenceDiagram-SI44F4Z6-BGt8d3QQ.js} +1 -1
- package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-BiNLgN2x.js → sizeCapture-X5ZJPWSS-7nlhJKo7.js} +1 -1
- package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-UwvjS64-.js → stateDiagram-OKZ733FA-Cv2stqMA.js} +1 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-DC7V5vcq.js +1 -0
- package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-CC7DH98r.js → swimlanes-SLNWSIFB-qDAo4Yc1.js} +2 -2
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-Bwy4QUTO.js +8 -0
- package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-LSBXTR70.js → timeline-definition-Z64GVDOM-CKbDNKTr.js} +1 -1
- package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-BAuxWwGP.js → vennDiagram-T6HMQDX7-DI-9EHic.js} +1 -1
- package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y--E5_gjZx.js → wardleyDiagram-T6FBY63Y-BrzzRDpX.js} +1 -1
- package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-dJWNmyzF.js → xychartDiagram-ELKLHX3M-BclH5hGh.js} +1 -1
- package/dist/worker/console/static/index.html +2 -2
- package/dist/worker/console/static-src/operator-chat/chat-sse-events.js +41 -11
- package/dist/worker/console/static-src/operator-chat/compaction-message.js +3 -17
- package/dist/worker/console/static-src/operator-chat/slash-palette-nav.js +15 -5
- package/dist/worker/console/static-src/operator-chat/timeline-merge.js +29 -0
- package/dist/worker/console/static-src/operator-chat/useChatThread.js +2 -5
- package/dist/worker/console/static-src/operator-chat/useRepoBrowser.js +2 -0
- package/dist/worker/console/static-src/prd-file-import.js +3 -1
- package/dist/worker/console/workspace-context.js +17 -1
- package/dist/worker/delivery/git-transaction.js +2 -0
- package/dist/worker/feature/fullstack-validate.js +2 -0
- package/dist/worker/loop-agent/loop-agent-client.js +8 -2
- package/dist/worker/materialize/harness-task-materializer.js +4 -1
- package/dist/worker/metrics/projector.js +1 -1
- package/dist/worker/observability/event-store.js +4 -1
- package/dist/worker/observability/read-model.js +4 -1
- package/dist/worker/observe/node-transparency.js +23 -1
- package/dist/worker/observe/routes.js +4 -0
- package/dist/worker/observe/static/operator-chrome.js +3 -1
- package/dist/worker/outcomes/declared-artifacts.js +2 -0
- package/dist/worker/preflight.js +3 -0
- package/dist/worker/scheduler/scheduled-goal-dispatch.js +117 -0
- package/dist/worker/scheduler/scheduled-goal-evidence.js +167 -0
- package/dist/worker/scheduler/scheduled-goal-recovery.js +62 -0
- package/dist/worker/scheduler/scheduled-goal-store.js +699 -0
- package/dist/worker/scheduler/scheduled-goal-supervisor.js +132 -0
- package/dist/worker/scheduler/scheduled-goal-time.js +102 -0
- package/dist/worker/scheduler/scheduled-goal-types.js +95 -0
- package/dist/worker/task-spec/validate.js +4 -1
- package/dist/workflows/dag/backend-test-markdown-workflow.js +6 -24
- package/dist/workflows/dag/backend-test-plan-protocol.js +82 -5
- package/dist/workflows/dag/dag-retry-schema.js +11 -0
- package/dist/workflows/dag/decision-envelope.js +2 -0
- package/dist/workflows/dag/dynamic-runtime/shared.js +2 -2
- package/dist/workflows/dag/frontend-closeout.js +4 -2
- package/dist/workflows/dag/frontend-committed-facts.js +461 -0
- package/dist/workflows/dag/frontend-durable-tools.js +15 -3
- package/dist/workflows/dag/frontend-implementation-contract.js +365 -8
- package/dist/workflows/dag/frontend-plan-canary.js +53 -0
- package/dist/workflows/dag/frontend-plan-decision-contract.js +803 -0
- package/dist/workflows/dag/frontend-plan-render.js +0 -2
- package/dist/workflows/dag/frontend-prewrite-gate.js +3 -3
- package/dist/workflows/dag/frontend-provider-capability-matrix.js +8 -61
- package/dist/workflows/dag/frontend-recovery-run.js +57 -0
- package/dist/workflows/dag/frontend-review-context.js +43 -70
- package/dist/workflows/dag/frontend-risk.js +92 -10
- package/dist/workflows/dag/frontend-session-budget.js +117 -3
- package/dist/workflows/dag/frontend-shape.js +11 -55
- package/dist/workflows/dag/frontend-test-execution-evidence.js +35 -10
- package/dist/workflows/dag/frontend-typed-event-store.js +32 -25
- package/dist/workflows/dag/frontend-verification-trace.js +25 -12
- package/dist/workflows/dag/frontend-writer-admission.js +3 -47
- package/dist/workflows/dag/frontend-writer-status.js +0 -23
- package/dist/workflows/dag/init-hybrid.js +202 -111
- package/dist/workflows/dag/interrupt-request.js +2 -0
- package/dist/workflows/dag/lifecycle.js +11 -2
- package/dist/workflows/dag/node-execution.js +50 -13
- package/dist/workflows/dag/reconcile-run.js +2 -0
- package/dist/workflows/dag/repair-artifact.js +3 -1
- package/dist/workflows/dag/report.js +2 -0
- package/dist/workflows/dag/rerun-plan.js +10 -0
- package/dist/workflows/dag/rerun-task.js +79 -1
- package/dist/workflows/dag/retry-policy.js +18 -0
- package/dist/workflows/dag/scheduler.js +2 -4
- package/dist/workflows/dag/types.js +44 -6
- package/dist/workflows/dag/validate.js +4 -0
- package/docs/README.md +1 -0
- package/docs/governance/README.md +1 -0
- package/docs/init-surface.manifest.json +1 -0
- package/docs/operations/README.md +2 -0
- package/docs/templates/README.md +1 -1
- package/docs/templates/agent-dag.schema.json +2 -2
- package/docs/templates/backend-test-dag.json +14 -10
- package/docs/templates/frontend-implementation-contract.schema.json +0 -7
- package/docs/templates/frontend-implementation-dag.json +8 -9
- package/package.json +8 -3
- package/skills/frontend-bounded-implement/SKILL.md +3 -4
- package/skills/frontend-design-review/SKILL.md +7 -12
- package/skills/frontend-design-review/references/review-checklist.md +7 -7
- package/skills/frontend-plan/SKILL.md +8 -18
- package/skills/frontend-plan/references/decision-contract.md +19 -26
- package/skills/frontend-review/SKILL.md +21 -25
- package/skills/frontend-review/references/review-findings.md +48 -24
- package/dist/worker/console/static/assets/channel-BxdTlb_5.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-_ByA1Nf8.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-_ByA1Nf8.js +0 -1
- package/dist/worker/console/static/assets/index-B9goN3S5.css +0 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-nLgMZ0D3.js +0 -1
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-BcYqTady.js +0 -8
- package/dist/workflows/dag/frontend-shadow-dual-write.js +0 -975
|
@@ -392,6 +392,147 @@ const COMMON_MUTATION_ERRORS = [
|
|
|
392
392
|
];
|
|
393
393
|
export function buildOperatorCapabilitiesDocument() {
|
|
394
394
|
const actions = [
|
|
395
|
+
{
|
|
396
|
+
action: "prepareScheduledTask", cli: "console scheduled task preparation", kind: "mutation",
|
|
397
|
+
inputSchemaVersion: 1, resultSchemaVersion: 1, envelopeSchemaVersion: 1, requiredErrorCodes: ["INVALID_INPUT"],
|
|
398
|
+
description: "Preferred entry for natural-language one-time scheduled tasks, including read-only inspection reports. Call this directly after understanding the goal, output scope, executable acceptance and time; the server uses the CURRENT project directory and creates the immutable PRD, managed Task and strict writeSet gate, binds THIS Chat automatically and returns a REAL planned goal/confirmation card. No pre-existing task, worktree or session ID is needed: never ask the user for these internal fields and do not manually create/edit them with bash/write/newTask/importPrd. Keep preparation concise: preserve the user goal without inventing extra requirements. Omit budget for ordinary tasks. Use minimal independent acceptance commands (AC-1, AC-2), preferably existing test/build scripts or test -s scheduled-report.md for a report; no compound shell/pipelines/substitution, language-specific grep checks or redundant scope assertions (the host enforces scope). Infer routine defaults and verification commands from the repository; ask only about genuinely ambiguous goal/scope/time. For read-only requests allow just an ordinary report file in the current project directory, e.g. scheduled-report.md, not .harness/. Use schedule.delayMinutes for relative time (counted after preparation finishes), or localAt + IANA timezone for an exact date/time. The current workspace must match committed HEAD; never auto-commit/stash/reset existing changes. The card exposes the exact time, bounded defaults and committed base before one human confirmation. Same request in this Chat is idempotent. Only a returned goalId with state=planned is a prepared reservation; textual drafts, Tasks or failed operations are NOT bookings. Never replace a requested schedule with immediate execution or sleep, never call runDag or self-confirm. On failure explain the returned stage, correct business inputs and retry this tool; do not mutate imported PRD/runtime artifacts. For a new distinct appointment, make its goal/time distinct.",
|
|
399
|
+
inputParams: [{ name: "request", type: "object", required: true, description: "Business goal, workflow, allowedPaths, acceptance and schedule; optional forbiddenPaths/budget. Runtime identity is server-owned." }],
|
|
400
|
+
modelCallable: "always", humanConfirmation: "none",
|
|
401
|
+
},
|
|
402
|
+
{
|
|
403
|
+
"action": "prepareScheduledGoal",
|
|
404
|
+
"cli": "console scheduled goal service",
|
|
405
|
+
"kind": "mutation",
|
|
406
|
+
"inputSchemaVersion": 1,
|
|
407
|
+
"resultSchemaVersion": 1,
|
|
408
|
+
"envelopeSchemaVersion": 1,
|
|
409
|
+
"requiredErrorCodes": [
|
|
410
|
+
"INVALID_INPUT"
|
|
411
|
+
],
|
|
412
|
+
"description": "Advanced entry ONLY for an already prepared Task. For a new natural-language reservation use prepareScheduledTask instead. Requires the current repository or its linked worktree at frozenBase and a managed Task already strict-prepared at its writeSet gate. booking must include managedTaskId, originalGoal, chatSessionRef, workflow, worktreeRef, frozenBase, allowedPaths, forbiddenPaths, acceptance {policy, criteria [{acId,description,command}]}, budget {maxTurns,maxDagRuns,maxSupervisorCalls}, time {executeAtUtc,latestStartUtc,stopAtUtc,expiresAt,timezone,allowedHours,misfirePolicy}. Resolve natural-language dates with the user timezone; ask about ambiguous time/AC/scope. No execution or authorization occurs. Show the complete scope/time/budget for one browser confirmation. Never call runDag for this reservation.",
|
|
413
|
+
"inputParams": [
|
|
414
|
+
{
|
|
415
|
+
"name": "booking",
|
|
416
|
+
"type": "object",
|
|
417
|
+
"required": true,
|
|
418
|
+
"description": "Complete frozen booking inputs; never supply prepared, controllerRef, approval or owner tokens."
|
|
419
|
+
}
|
|
420
|
+
],
|
|
421
|
+
"modelCallable": "always",
|
|
422
|
+
"humanConfirmation": "none"
|
|
423
|
+
},
|
|
424
|
+
{
|
|
425
|
+
"action": "confirmScheduledGoal",
|
|
426
|
+
"cli": "console scheduled goal service",
|
|
427
|
+
"kind": "mutation",
|
|
428
|
+
"inputSchemaVersion": 1,
|
|
429
|
+
"resultSchemaVersion": 1,
|
|
430
|
+
"envelopeSchemaVersion": 1,
|
|
431
|
+
"requiredErrorCodes": [
|
|
432
|
+
"INVALID_INPUT"
|
|
433
|
+
],
|
|
434
|
+
"description": "Human browser confirmation of the exact displayed ScheduledGoal envelope.",
|
|
435
|
+
"inputParams": [
|
|
436
|
+
{
|
|
437
|
+
"name": "goalId",
|
|
438
|
+
"type": "string",
|
|
439
|
+
"required": true,
|
|
440
|
+
"description": "Prepared goal id"
|
|
441
|
+
},
|
|
442
|
+
{
|
|
443
|
+
"name": "stateVersion",
|
|
444
|
+
"type": "number",
|
|
445
|
+
"required": true,
|
|
446
|
+
"description": "Displayed state version"
|
|
447
|
+
},
|
|
448
|
+
{
|
|
449
|
+
"name": "envelopeHash",
|
|
450
|
+
"type": "string",
|
|
451
|
+
"required": true,
|
|
452
|
+
"description": "Displayed envelope hash"
|
|
453
|
+
}
|
|
454
|
+
],
|
|
455
|
+
"modelCallable": "never",
|
|
456
|
+
"humanConfirmation": "required"
|
|
457
|
+
},
|
|
458
|
+
{
|
|
459
|
+
"action": "cancelScheduledGoal",
|
|
460
|
+
"cli": "console scheduled goal service",
|
|
461
|
+
"kind": "mutation",
|
|
462
|
+
"inputSchemaVersion": 1,
|
|
463
|
+
"resultSchemaVersion": 1,
|
|
464
|
+
"envelopeSchemaVersion": 1,
|
|
465
|
+
"requiredErrorCodes": [
|
|
466
|
+
"INVALID_INPUT"
|
|
467
|
+
],
|
|
468
|
+
"description": "Cancel future ScheduledGoal admission; in-flight/unknown ownership remains until reconciled.",
|
|
469
|
+
"inputParams": [
|
|
470
|
+
{
|
|
471
|
+
"name": "goalId",
|
|
472
|
+
"type": "string",
|
|
473
|
+
"required": true,
|
|
474
|
+
"description": "Goal id"
|
|
475
|
+
},
|
|
476
|
+
{
|
|
477
|
+
"name": "stateVersion",
|
|
478
|
+
"type": "number",
|
|
479
|
+
"required": true,
|
|
480
|
+
"description": "Current state version"
|
|
481
|
+
},
|
|
482
|
+
{
|
|
483
|
+
"name": "reason",
|
|
484
|
+
"type": "string",
|
|
485
|
+
"required": true,
|
|
486
|
+
"description": "Human cancellation reason"
|
|
487
|
+
}
|
|
488
|
+
],
|
|
489
|
+
"modelCallable": "never",
|
|
490
|
+
"humanConfirmation": "required"
|
|
491
|
+
},
|
|
492
|
+
{
|
|
493
|
+
"action": "scheduledGoalGet",
|
|
494
|
+
"cli": "console scheduled goal service",
|
|
495
|
+
"kind": "read",
|
|
496
|
+
"inputSchemaVersion": 1,
|
|
497
|
+
"resultSchemaVersion": 1,
|
|
498
|
+
"envelopeSchemaVersion": 1,
|
|
499
|
+
"requiredErrorCodes": [
|
|
500
|
+
"INVALID_INPUT"
|
|
501
|
+
],
|
|
502
|
+
"description": "Read a durable ScheduledGoal booking and separate execution, acceptance, delivery and reconciliation results. Never implies authorization.",
|
|
503
|
+
"inputParams": [
|
|
504
|
+
{
|
|
505
|
+
"name": "goalId",
|
|
506
|
+
"type": "string",
|
|
507
|
+
"required": true,
|
|
508
|
+
"description": "Goal id"
|
|
509
|
+
}
|
|
510
|
+
],
|
|
511
|
+
"modelCallable": "always",
|
|
512
|
+
"humanConfirmation": "none"
|
|
513
|
+
},
|
|
514
|
+
{
|
|
515
|
+
"action": "scheduledGoalList",
|
|
516
|
+
"cli": "console scheduled goal service",
|
|
517
|
+
"kind": "read",
|
|
518
|
+
"inputSchemaVersion": 1,
|
|
519
|
+
"resultSchemaVersion": 1,
|
|
520
|
+
"envelopeSchemaVersion": 1,
|
|
521
|
+
"requiredErrorCodes": [
|
|
522
|
+
"INVALID_INPUT"
|
|
523
|
+
],
|
|
524
|
+
"description": "List durable ScheduledGoals, including those whose original Chat was archived or deleted.",
|
|
525
|
+
"inputParams": [
|
|
526
|
+
{
|
|
527
|
+
"name": "chatSessionRef",
|
|
528
|
+
"type": "string",
|
|
529
|
+
"required": false,
|
|
530
|
+
"description": "Optional original Chat session id"
|
|
531
|
+
}
|
|
532
|
+
],
|
|
533
|
+
"modelCallable": "always",
|
|
534
|
+
"humanConfirmation": "none"
|
|
535
|
+
},
|
|
395
536
|
{
|
|
396
537
|
action: "operatorCapabilities",
|
|
397
538
|
cli: "loop-agent operator capabilities --json",
|
|
@@ -714,6 +855,24 @@ export function buildOperatorCapabilitiesDocument() {
|
|
|
714
855
|
required: false,
|
|
715
856
|
description: "optional verify commands (label:command or shell)",
|
|
716
857
|
},
|
|
858
|
+
{
|
|
859
|
+
name: "requirementOwnership",
|
|
860
|
+
type: "array",
|
|
861
|
+
required: false,
|
|
862
|
+
description: "optional frozen requirement→file ownership for frontend-implementation DAGs: [{requirementIds, implementationFiles?, verificationFiles?}] — machine-enforced at plan finalize",
|
|
863
|
+
},
|
|
864
|
+
{
|
|
865
|
+
name: "capabilityBoundary",
|
|
866
|
+
type: "array",
|
|
867
|
+
required: false,
|
|
868
|
+
description: "optional frozen test capability boundary {allowed?, forbidden?} composed into dependencyPolicy by the runtime",
|
|
869
|
+
},
|
|
870
|
+
{
|
|
871
|
+
name: "interactionIds",
|
|
872
|
+
type: "array",
|
|
873
|
+
required: false,
|
|
874
|
+
description: "optional frozen interaction id vocabulary — contract interaction names are machine-checked against it at plan finalize",
|
|
875
|
+
},
|
|
717
876
|
],
|
|
718
877
|
modelCallable: "always",
|
|
719
878
|
humanConfirmation: "none",
|
|
@@ -1069,6 +1228,27 @@ export function buildOperatorCapabilitiesDocument() {
|
|
|
1069
1228
|
required: false,
|
|
1070
1229
|
description: "verification entries as label:command strings",
|
|
1071
1230
|
},
|
|
1231
|
+
{
|
|
1232
|
+
name: "requirementOwnership",
|
|
1233
|
+
type: "array",
|
|
1234
|
+
itemsType: "string",
|
|
1235
|
+
required: false,
|
|
1236
|
+
description: "frozen requirement→file ownership: [{requirementIds, implementationFiles?, verificationFiles?}] — machine-enforced at plan finalize",
|
|
1237
|
+
},
|
|
1238
|
+
{
|
|
1239
|
+
name: "capabilityBoundary",
|
|
1240
|
+
type: "array",
|
|
1241
|
+
itemsType: "string",
|
|
1242
|
+
required: false,
|
|
1243
|
+
description: "frozen test capability boundary {allowed?, forbidden?} composed into dependencyPolicy by the runtime",
|
|
1244
|
+
},
|
|
1245
|
+
{
|
|
1246
|
+
name: "interactionIds",
|
|
1247
|
+
type: "array",
|
|
1248
|
+
itemsType: "string",
|
|
1249
|
+
required: false,
|
|
1250
|
+
description: "frozen interaction id vocabulary — contract interaction names are machine-checked against it at plan finalize",
|
|
1251
|
+
},
|
|
1072
1252
|
{
|
|
1073
1253
|
name: "approveGate",
|
|
1074
1254
|
type: "string",
|
|
@@ -134,8 +134,10 @@ export function computePackageFingerprint(packageRoot) {
|
|
|
134
134
|
const bBuf = Buffer.from(b.relativePath, "utf-8");
|
|
135
135
|
const minLen = Math.min(aBuf.length, bBuf.length);
|
|
136
136
|
for (let i = 0; i < minLen; i++) {
|
|
137
|
-
|
|
138
|
-
|
|
137
|
+
const aByte = aBuf[i];
|
|
138
|
+
const bByte = bBuf[i];
|
|
139
|
+
if (aByte !== bByte)
|
|
140
|
+
return (aByte ?? 0) - (bByte ?? 0);
|
|
139
141
|
}
|
|
140
142
|
return aBuf.length - bBuf.length;
|
|
141
143
|
});
|
|
@@ -183,8 +185,8 @@ export function resolveBinPaths(requested, resolvedAt, inputs) {
|
|
|
183
185
|
// Search PATH
|
|
184
186
|
const pathEnv = env.PATH ?? env.Path ?? env.path ?? "";
|
|
185
187
|
const candidates = resolveFromPath(requested, pathEnv, osPlatform, env.PATHEXT ?? env.Pathext ?? env.pathext, cwd);
|
|
186
|
-
|
|
187
|
-
|
|
188
|
+
const entry = candidates[0];
|
|
189
|
+
if (entry !== undefined) {
|
|
188
190
|
assertRegularFile(entry, requested);
|
|
189
191
|
return { requested, entry, realEntry: realpathSync(entry), resolvedAt };
|
|
190
192
|
}
|
|
@@ -268,7 +268,7 @@ export function sliceUtf8Range(text, offset, maxBytes) {
|
|
|
268
268
|
}
|
|
269
269
|
const buffer = Buffer.from(text, "utf8");
|
|
270
270
|
let end = Math.min(totalBytes, start + limit);
|
|
271
|
-
while (end > start && (buffer[end] & 0b1100_0000) === 0b1000_0000) {
|
|
271
|
+
while (end > start && ((buffer[end] ?? 0) & 0b1100_0000) === 0b1000_0000) {
|
|
272
272
|
end -= 1;
|
|
273
273
|
}
|
|
274
274
|
const slice = buffer.subarray(start, end).toString("utf8");
|
|
@@ -286,6 +286,35 @@ const taskConfigObjectSchema = z.object({
|
|
|
286
286
|
verifyPreset: verifyPresetSchema.optional().default("auto"),
|
|
287
287
|
/** Task-contract commands that must be included in final DAG shell verification. */
|
|
288
288
|
verifyCommands: z.array(taskVerifyCommandSchema).optional().default([]),
|
|
289
|
+
/** Generation-frozen requirement→file ownership for frontend-implementation
|
|
290
|
+
* DAGs. Machine-checked at plan finalize: a requirement's implementation
|
|
291
|
+
* targets (and its verification targets' files) must stay inside the
|
|
292
|
+
* declared sets, so ownership never depends on model compliance with prose.
|
|
293
|
+
*/
|
|
294
|
+
requirementOwnership: z
|
|
295
|
+
.array(z
|
|
296
|
+
.object({
|
|
297
|
+
requirementIds: z.array(z.string().min(1)).min(1),
|
|
298
|
+
implementationFiles: z.array(z.string().min(1)).optional(),
|
|
299
|
+
verificationFiles: z.array(z.string().min(1)).optional(),
|
|
300
|
+
})
|
|
301
|
+
.strict()
|
|
302
|
+
.refine((entry) => (entry.implementationFiles?.length ?? 0) > 0 ||
|
|
303
|
+
(entry.verificationFiles?.length ?? 0) > 0, { message: "requirementOwnership entry needs implementationFiles or verificationFiles" }))
|
|
304
|
+
.optional(),
|
|
305
|
+
/** Generation-frozen test capability boundary composed into the canonical
|
|
306
|
+
* dependencyPolicy by the runtime (planner never maintains it). */
|
|
307
|
+
capabilityBoundary: z
|
|
308
|
+
.object({
|
|
309
|
+
allowed: z.array(z.string().min(1)).optional(),
|
|
310
|
+
forbidden: z.array(z.string().min(1)).optional(),
|
|
311
|
+
})
|
|
312
|
+
.strict()
|
|
313
|
+
.refine((entry) => (entry.allowed?.length ?? 0) > 0 || (entry.forbidden?.length ?? 0) > 0, { message: "capabilityBoundary needs allowed or forbidden entries" })
|
|
314
|
+
.optional(),
|
|
315
|
+
/** Generation-frozen interaction id vocabulary. Contract interaction names
|
|
316
|
+
* must come from this set (plan finalize deterministic check). */
|
|
317
|
+
interactionIds: z.array(z.string().min(1)).optional(),
|
|
289
318
|
/** Verification selection policy. Intermediate loops may use quota; final gates still run full required verification. */
|
|
290
319
|
verifyQuota: verifyQuotaSchema.optional().default("full"),
|
|
291
320
|
/** DAG supervised verify strategy. Final quota is fixed to full; intermediate quota may reduce cost. */
|
|
@@ -187,6 +187,15 @@ export function mergeManagedTaskConfigFields(existing, draft) {
|
|
|
187
187
|
...(draft.frontendOpenspec !== undefined
|
|
188
188
|
? { frontendOpenspec: draft.frontendOpenspec }
|
|
189
189
|
: {}),
|
|
190
|
+
...(draft.requirementOwnership !== undefined
|
|
191
|
+
? { requirementOwnership: draft.requirementOwnership }
|
|
192
|
+
: {}),
|
|
193
|
+
...(draft.capabilityBoundary !== undefined
|
|
194
|
+
? { capabilityBoundary: draft.capabilityBoundary }
|
|
195
|
+
: {}),
|
|
196
|
+
...(draft.interactionIds !== undefined
|
|
197
|
+
? { interactionIds: draft.interactionIds }
|
|
198
|
+
: {}),
|
|
190
199
|
};
|
|
191
200
|
if (draft.featureId !== undefined) {
|
|
192
201
|
next.featureId = draft.featureId;
|
|
@@ -70,6 +70,12 @@ export async function recoverTaskContract(input) {
|
|
|
70
70
|
};
|
|
71
71
|
}
|
|
72
72
|
const txId = input.txId ?? unfinished[0];
|
|
73
|
+
if (txId === undefined) {
|
|
74
|
+
return {
|
|
75
|
+
action: "manual-required",
|
|
76
|
+
message: "no unfinished transactions to recover",
|
|
77
|
+
};
|
|
78
|
+
}
|
|
73
79
|
if (!unfinished.includes(txId)) {
|
|
74
80
|
return {
|
|
75
81
|
action: "manual-required",
|
|
@@ -75,6 +75,23 @@ export const taskContractDraftSchema = z
|
|
|
75
75
|
assumptions: z.array(z.string()).optional(),
|
|
76
76
|
hardConstraints: z.array(z.string()).optional(),
|
|
77
77
|
frontendOpenspec: frontendOpenspecConfigSchema.optional(),
|
|
78
|
+
requirementOwnership: z
|
|
79
|
+
.array(z
|
|
80
|
+
.object({
|
|
81
|
+
requirementIds: z.array(z.string().min(1)).min(1),
|
|
82
|
+
implementationFiles: z.array(z.string().min(1)).optional(),
|
|
83
|
+
verificationFiles: z.array(z.string().min(1)).optional(),
|
|
84
|
+
})
|
|
85
|
+
.strict())
|
|
86
|
+
.optional(),
|
|
87
|
+
capabilityBoundary: z
|
|
88
|
+
.object({
|
|
89
|
+
allowed: z.array(z.string().min(1)).optional(),
|
|
90
|
+
forbidden: z.array(z.string().min(1)).optional(),
|
|
91
|
+
})
|
|
92
|
+
.strict()
|
|
93
|
+
.optional(),
|
|
94
|
+
interactionIds: z.array(z.string().min(1)).optional(),
|
|
78
95
|
interviewAssessmentRef: z
|
|
79
96
|
.object({
|
|
80
97
|
draftSha256: z.string().min(1),
|
|
@@ -17,7 +17,10 @@ function parseSimpleFrontmatter(block) {
|
|
|
17
17
|
const match = /^([A-Za-z0-9_-]+)\s*:\s*(.+?)\s*$/u.exec(line);
|
|
18
18
|
if (!match)
|
|
19
19
|
continue;
|
|
20
|
-
|
|
20
|
+
const [, key, value] = match;
|
|
21
|
+
if (key === undefined || value === undefined)
|
|
22
|
+
continue;
|
|
23
|
+
out[key] = parseYamlishScalar(value);
|
|
21
24
|
}
|
|
22
25
|
return out;
|
|
23
26
|
}
|
|
@@ -46,7 +49,11 @@ export function detectProductArtifactMeta(markdown) {
|
|
|
46
49
|
if (!match) {
|
|
47
50
|
return { artifactType: "unknown", recognized: false };
|
|
48
51
|
}
|
|
49
|
-
const
|
|
52
|
+
const [, frontmatter] = match;
|
|
53
|
+
if (frontmatter === undefined) {
|
|
54
|
+
return { artifactType: "unknown", recognized: false };
|
|
55
|
+
}
|
|
56
|
+
const fields = parseSimpleFrontmatter(frontmatter);
|
|
50
57
|
const artifactType = normalizeArtifactType(fields.artifact_type);
|
|
51
58
|
const recognized = artifactType !== "unknown" || Boolean(fields.artifact_version);
|
|
52
59
|
return {
|
|
@@ -90,6 +90,42 @@ function resolveAllowedRoots(input) {
|
|
|
90
90
|
return normalized.ok ? normalized.value : raw.trim();
|
|
91
91
|
});
|
|
92
92
|
}
|
|
93
|
+
function resolveInteractionIds(input) {
|
|
94
|
+
if (input.flags.interactionIds !== undefined) {
|
|
95
|
+
return input.flags.interactionIds;
|
|
96
|
+
}
|
|
97
|
+
if (input.baseDraft?.interactionIds?.length) {
|
|
98
|
+
return input.baseDraft.interactionIds;
|
|
99
|
+
}
|
|
100
|
+
if (input.existing?.interactionIds?.length) {
|
|
101
|
+
return input.existing.interactionIds;
|
|
102
|
+
}
|
|
103
|
+
return undefined;
|
|
104
|
+
}
|
|
105
|
+
function resolveCapabilityBoundary(input) {
|
|
106
|
+
if (input.flags.capabilityBoundary !== undefined) {
|
|
107
|
+
return input.flags.capabilityBoundary;
|
|
108
|
+
}
|
|
109
|
+
if (input.baseDraft?.capabilityBoundary) {
|
|
110
|
+
return input.baseDraft.capabilityBoundary;
|
|
111
|
+
}
|
|
112
|
+
if (input.existing?.capabilityBoundary) {
|
|
113
|
+
return input.existing.capabilityBoundary;
|
|
114
|
+
}
|
|
115
|
+
return undefined;
|
|
116
|
+
}
|
|
117
|
+
function resolveRequirementOwnership(input) {
|
|
118
|
+
if (input.flags.requirementOwnership !== undefined) {
|
|
119
|
+
return input.flags.requirementOwnership;
|
|
120
|
+
}
|
|
121
|
+
if (input.baseDraft?.requirementOwnership?.length) {
|
|
122
|
+
return input.baseDraft.requirementOwnership;
|
|
123
|
+
}
|
|
124
|
+
if (input.existing?.requirementOwnership?.length) {
|
|
125
|
+
return input.existing.requirementOwnership;
|
|
126
|
+
}
|
|
127
|
+
return undefined;
|
|
128
|
+
}
|
|
93
129
|
function resolveVerifyCommands(input) {
|
|
94
130
|
if (input.flags.verifyCommands !== undefined) {
|
|
95
131
|
return input.flags.verifyCommands.map((cmd) => ({
|
|
@@ -178,6 +214,21 @@ export function buildPrepareDraft(input) {
|
|
|
178
214
|
baseDraft,
|
|
179
215
|
existing: existingTaskConfig,
|
|
180
216
|
});
|
|
217
|
+
const interactionIds = resolveInteractionIds({
|
|
218
|
+
flags,
|
|
219
|
+
baseDraft,
|
|
220
|
+
existing: existingTaskConfig,
|
|
221
|
+
});
|
|
222
|
+
const capabilityBoundary = resolveCapabilityBoundary({
|
|
223
|
+
flags,
|
|
224
|
+
baseDraft,
|
|
225
|
+
existing: existingTaskConfig,
|
|
226
|
+
});
|
|
227
|
+
const requirementOwnership = resolveRequirementOwnership({
|
|
228
|
+
flags,
|
|
229
|
+
baseDraft,
|
|
230
|
+
existing: existingTaskConfig,
|
|
231
|
+
});
|
|
181
232
|
const pathAssessment = assessPreparePaths({
|
|
182
233
|
allowedPaths,
|
|
183
234
|
forbiddenPaths: finalForbidden,
|
|
@@ -215,6 +266,15 @@ export function buildPrepareDraft(input) {
|
|
|
215
266
|
})),
|
|
216
267
|
},
|
|
217
268
|
};
|
|
269
|
+
if (requirementOwnership !== undefined) {
|
|
270
|
+
draft.requirementOwnership = requirementOwnership;
|
|
271
|
+
}
|
|
272
|
+
if (capabilityBoundary !== undefined) {
|
|
273
|
+
draft.capabilityBoundary = capabilityBoundary;
|
|
274
|
+
}
|
|
275
|
+
if (interactionIds !== undefined && interactionIds.length > 0) {
|
|
276
|
+
draft.interactionIds = interactionIds;
|
|
277
|
+
}
|
|
218
278
|
if (featureId)
|
|
219
279
|
draft.featureId = featureId;
|
|
220
280
|
const backendTest = resolveBackendTest(flags, baseDraft, existingTaskConfig);
|
|
@@ -122,7 +122,10 @@ function isAtxHeading(line) {
|
|
|
122
122
|
const match = /^(#{1,6})\s+(.+?)\s*$/u.exec(line);
|
|
123
123
|
if (!match)
|
|
124
124
|
return null;
|
|
125
|
-
|
|
125
|
+
const [, hashes, text] = match;
|
|
126
|
+
if (hashes === undefined || text === undefined)
|
|
127
|
+
return null;
|
|
128
|
+
return { level: hashes.length, text: text.trim() };
|
|
126
129
|
}
|
|
127
130
|
function isListItem(line) {
|
|
128
131
|
return /^\s*(?:[-*+]|\d+[.)])\s+(?:\[(?: |x|X)\]\s+)?/.test(line);
|
|
@@ -59,11 +59,21 @@ function stripFencedAndComments(text) {
|
|
|
59
59
|
.replace(/<!--[\s\S]*?-->/g, "\n");
|
|
60
60
|
}
|
|
61
61
|
function normalizeAcceptanceId(raw) {
|
|
62
|
-
return raw
|
|
62
|
+
return (raw
|
|
63
63
|
.trim()
|
|
64
64
|
.toUpperCase()
|
|
65
65
|
.replace(/_/g, "-")
|
|
66
|
-
.replace(/^(AC)(FE|BE|UI|API)(?=-|\d)/u, "$1-$2")
|
|
66
|
+
.replace(/^(AC)(FE|BE|UI|API)(?=-|\d)/u, "$1-$2")
|
|
67
|
+
// A PRD writes `AC1` as naturally as `AC-1` or `AC_1`. Only the two earlier
|
|
68
|
+
// rules canonicalized a separator, so a bare `AC1` escaped verbatim — and the
|
|
69
|
+
// generated DAG's requirement-id schema requires a hyphen after the prefix
|
|
70
|
+
// (`/^(?:REQ|BR|AC)-[A-Z0-9]+(?:-[A-Z0-9]+)*$/`). Other consumers already
|
|
71
|
+
// assume `AC-...` (e.g. the frontend-test checklist demands `AC-FE-001`).
|
|
72
|
+
// The result was a meaningless split: the same PRD style generated fine under
|
|
73
|
+
// `taskKind: standard` and failed DAG generation under
|
|
74
|
+
// `taskKind: frontend-implementation`. Canonicalize here, once, so every
|
|
75
|
+
// workflow reads the same ids.
|
|
76
|
+
.replace(/^AC(?=\d)/u, "AC-"));
|
|
67
77
|
}
|
|
68
78
|
function parseEmbeddedAcHeading(headingText) {
|
|
69
79
|
const normalized = headingText
|
|
@@ -77,7 +87,10 @@ function parseEmbeddedAcHeading(headingText) {
|
|
|
77
87
|
const match = EMBEDDED_AC_HEADING.exec(normalized);
|
|
78
88
|
if (!match)
|
|
79
89
|
return null;
|
|
80
|
-
const
|
|
90
|
+
const [, rawId] = match;
|
|
91
|
+
if (rawId === undefined)
|
|
92
|
+
return null;
|
|
93
|
+
const id = normalizeAcceptanceId(rawId);
|
|
81
94
|
// Bold-wrapped ids leave their closing marker inside the captured text
|
|
82
95
|
// ("**AC-FE-INS-001**:xxx" captures "**:xxx"); strip emphasis remnants
|
|
83
96
|
// and leading separators so the bound text is clean prose.
|
|
@@ -154,13 +167,17 @@ function isAtxHeading(line) {
|
|
|
154
167
|
const match = /^(#{1,6})\s+(.+?)\s*$/u.exec(line);
|
|
155
168
|
if (!match)
|
|
156
169
|
return null;
|
|
157
|
-
|
|
170
|
+
const [, hashes, text] = match;
|
|
171
|
+
if (hashes === undefined || text === undefined)
|
|
172
|
+
return null;
|
|
173
|
+
return { level: hashes.length, text };
|
|
158
174
|
}
|
|
159
175
|
function parseListItem(line) {
|
|
160
176
|
const match = /^\s*(?:[-*+]|\d+[.)])\s+(?:\[(?: |x|X)\]\s+)?(.+?)\s*$/u.exec(line);
|
|
161
177
|
if (!match)
|
|
162
178
|
return null;
|
|
163
|
-
|
|
179
|
+
const [, item] = match;
|
|
180
|
+
return item === undefined ? null : item.trim();
|
|
164
181
|
}
|
|
165
182
|
function parseAcceptanceLine(line, nextId) {
|
|
166
183
|
const checklist = /^\s*[-*+]\s+\[(?: |x|X)\]\s+(.+?)\s*$/u.exec(line);
|
|
@@ -173,14 +190,20 @@ function parseAcceptanceLine(line, nextId) {
|
|
|
173
190
|
return embedded;
|
|
174
191
|
const withId = /^(AC[-_]?\d+)\s*[::]\s*(.+)$/iu.exec(body);
|
|
175
192
|
if (withId) {
|
|
176
|
-
|
|
193
|
+
const [, rawId, rawText] = withId;
|
|
194
|
+
if (rawId !== undefined && rawText !== undefined) {
|
|
195
|
+
return { id: normalizeAcceptanceId(rawId), text: rawText.trim() };
|
|
196
|
+
}
|
|
177
197
|
}
|
|
178
198
|
const bareAc = /^(AC[-_]?\d+)\s+(.+)$/iu.exec(body);
|
|
179
199
|
if (bareAc) {
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
200
|
+
const [, rawId, rawText] = bareAc;
|
|
201
|
+
if (rawId !== undefined && rawText !== undefined) {
|
|
202
|
+
return {
|
|
203
|
+
id: normalizeAcceptanceId(rawId),
|
|
204
|
+
text: rawText.trim(),
|
|
205
|
+
};
|
|
206
|
+
}
|
|
184
207
|
}
|
|
185
208
|
return { id: nextId(), text: body };
|
|
186
209
|
}
|
|
@@ -395,7 +418,9 @@ export function mergeAcceptanceCriteria(parts) {
|
|
|
395
418
|
for (const id of order) {
|
|
396
419
|
const texts = [...(byId.get(id) ?? [])];
|
|
397
420
|
if (texts.length === 1) {
|
|
398
|
-
|
|
421
|
+
const [onlyText] = texts;
|
|
422
|
+
if (onlyText !== undefined)
|
|
423
|
+
items.push({ id, text: onlyText });
|
|
399
424
|
}
|
|
400
425
|
else if (texts.length > 1) {
|
|
401
426
|
conflicts.push({ id, texts });
|
|
@@ -102,11 +102,14 @@ function stripOutOfScopeSections(markdown) {
|
|
|
102
102
|
for (const line of markdown.split(/\r?\n/)) {
|
|
103
103
|
const heading = /^(#{1,6})\s+(.+?)\s*$/.exec(line.trim());
|
|
104
104
|
if (heading) {
|
|
105
|
-
const
|
|
105
|
+
const [, hashes, title] = heading;
|
|
106
|
+
if (hashes === undefined || title === undefined)
|
|
107
|
+
continue;
|
|
108
|
+
const level = hashes.length;
|
|
106
109
|
if (skippedHeadingLevel !== null && level <= skippedHeadingLevel) {
|
|
107
110
|
skippedHeadingLevel = null;
|
|
108
111
|
}
|
|
109
|
-
if (OUT_OF_SCOPE_HEADING.test(
|
|
112
|
+
if (OUT_OF_SCOPE_HEADING.test(title.trim())) {
|
|
110
113
|
skippedHeadingLevel = level;
|
|
111
114
|
continue;
|
|
112
115
|
}
|