dorfl 0.0.0 → 0.1.1
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/advance-ci-template.d.ts +73 -0
- package/dist/advance-ci-template.d.ts.map +1 -0
- package/dist/advance-ci-template.js +104 -0
- package/dist/advance-ci-template.js.map +1 -0
- package/dist/advance-classify.d.ts +132 -0
- package/dist/advance-classify.d.ts.map +1 -0
- package/dist/advance-classify.js +120 -0
- package/dist/advance-classify.js.map +1 -0
- package/dist/advance-drivers.d.ts +182 -0
- package/dist/advance-drivers.d.ts.map +1 -0
- package/dist/advance-drivers.js +231 -0
- package/dist/advance-drivers.js.map +1 -0
- package/dist/advance-isolated.d.ts +156 -0
- package/dist/advance-isolated.d.ts.map +1 -0
- package/dist/advance-isolated.js +256 -0
- package/dist/advance-isolated.js.map +1 -0
- package/dist/advance-lifecycle-template.d.ts +107 -0
- package/dist/advance-lifecycle-template.d.ts.map +1 -0
- package/dist/advance-lifecycle-template.js +668 -0
- package/dist/advance-lifecycle-template.js.map +1 -0
- package/dist/advance-loop-driver.d.ts +325 -0
- package/dist/advance-loop-driver.d.ts.map +1 -0
- package/dist/advance-loop-driver.js +437 -0
- package/dist/advance-loop-driver.js.map +1 -0
- package/dist/advance-treeless-publish.d.ts +108 -0
- package/dist/advance-treeless-publish.d.ts.map +1 -0
- package/dist/advance-treeless-publish.js +71 -0
- package/dist/advance-treeless-publish.js.map +1 -0
- package/dist/advance.d.ts +340 -0
- package/dist/advance.d.ts.map +1 -0
- package/dist/advance.js +1122 -0
- package/dist/advance.js.map +1 -0
- package/dist/advancing-lock.d.ts +294 -0
- package/dist/advancing-lock.d.ts.map +1 -0
- package/dist/advancing-lock.js +594 -0
- package/dist/advancing-lock.js.map +1 -0
- package/dist/agent-launch.d.ts +79 -0
- package/dist/agent-launch.d.ts.map +1 -0
- package/dist/agent-launch.js +61 -0
- package/dist/agent-launch.js.map +1 -0
- package/dist/agent-stop.d.ts +149 -0
- package/dist/agent-stop.d.ts.map +1 -0
- package/dist/agent-stop.js +307 -0
- package/dist/agent-stop.js.map +1 -0
- package/dist/apply-decide.d.ts +127 -0
- package/dist/apply-decide.d.ts.map +1 -0
- package/dist/apply-decide.js +176 -0
- package/dist/apply-decide.js.map +1 -0
- package/dist/apply-merge-action.d.ts +206 -0
- package/dist/apply-merge-action.d.ts.map +1 -0
- package/dist/apply-merge-action.js +307 -0
- package/dist/apply-merge-action.js.map +1 -0
- package/dist/apply-persist.d.ts +174 -0
- package/dist/apply-persist.d.ts.map +1 -0
- package/dist/apply-persist.js +359 -0
- package/dist/apply-persist.js.map +1 -0
- package/dist/arbiter.d.ts +120 -0
- package/dist/arbiter.d.ts.map +1 -0
- package/dist/arbiter.js +255 -0
- package/dist/arbiter.js.map +1 -0
- package/dist/brand.d.ts +70 -0
- package/dist/brand.d.ts.map +1 -0
- package/dist/brand.js +84 -0
- package/dist/brand.js.map +1 -0
- package/dist/buildable-body.d.ts +132 -0
- package/dist/buildable-body.d.ts.map +1 -0
- package/dist/buildable-body.js +131 -0
- package/dist/buildable-body.js.map +1 -0
- package/dist/categorise.d.ts +66 -0
- package/dist/categorise.d.ts.map +1 -0
- package/dist/categorise.js +106 -0
- package/dist/categorise.js.map +1 -0
- package/dist/claim-cas.d.ts +117 -0
- package/dist/claim-cas.d.ts.map +1 -0
- package/dist/claim-cas.js +312 -0
- package/dist/claim-cas.js.map +1 -0
- package/dist/cli-spinner.d.ts +112 -0
- package/dist/cli-spinner.d.ts.map +1 -0
- package/dist/cli-spinner.js +157 -0
- package/dist/cli-spinner.js.map +1 -0
- package/dist/cli.d.ts +11 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +3100 -0
- package/dist/cli.js.map +1 -0
- package/dist/close-job-template.d.ts +70 -0
- package/dist/close-job-template.d.ts.map +1 -0
- package/dist/close-job-template.js +180 -0
- package/dist/close-job-template.js.map +1 -0
- package/dist/close-job.d.ts +95 -0
- package/dist/close-job.d.ts.map +1 -0
- package/dist/close-job.js +226 -0
- package/dist/close-job.js.map +1 -0
- package/dist/complete.d.ts +361 -0
- package/dist/complete.d.ts.map +1 -0
- package/dist/complete.js +885 -0
- package/dist/complete.js.map +1 -0
- package/dist/concurrency.d.ts +68 -0
- package/dist/concurrency.d.ts.map +1 -0
- package/dist/concurrency.js +112 -0
- package/dist/concurrency.js.map +1 -0
- package/dist/config-override.d.ts +76 -0
- package/dist/config-override.d.ts.map +1 -0
- package/dist/config-override.js +50 -0
- package/dist/config-override.js.map +1 -0
- package/dist/config.d.ts +668 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +241 -0
- package/dist/config.js.map +1 -0
- package/dist/continue-branch.d.ts +249 -0
- package/dist/continue-branch.d.ts.map +1 -0
- package/dist/continue-branch.js +389 -0
- package/dist/continue-branch.js.map +1 -0
- package/dist/cwd-section.d.ts +186 -0
- package/dist/cwd-section.d.ts.map +1 -0
- package/dist/cwd-section.js +209 -0
- package/dist/cwd-section.js.map +1 -0
- package/dist/decision-engine.d.ts +170 -0
- package/dist/decision-engine.d.ts.map +1 -0
- package/dist/decision-engine.js +136 -0
- package/dist/decision-engine.js.map +1 -0
- package/dist/detect.d.ts +17 -0
- package/dist/detect.d.ts.map +1 -0
- package/dist/detect.js +118 -0
- package/dist/detect.js.map +1 -0
- package/dist/do-autopick.d.ts +85 -0
- package/dist/do-autopick.d.ts.map +1 -0
- package/dist/do-autopick.js +112 -0
- package/dist/do-autopick.js.map +1 -0
- package/dist/do-config.d.ts +312 -0
- package/dist/do-config.d.ts.map +1 -0
- package/dist/do-config.js +358 -0
- package/dist/do-config.js.map +1 -0
- package/dist/do-remote-auto.d.ts +75 -0
- package/dist/do-remote-auto.d.ts.map +1 -0
- package/dist/do-remote-auto.js +111 -0
- package/dist/do-remote-auto.js.map +1 -0
- package/dist/do.d.ts +621 -0
- package/dist/do.d.ts.map +1 -0
- package/dist/do.js +1882 -0
- package/dist/do.js.map +1 -0
- package/dist/drop-source.d.ts +96 -0
- package/dist/drop-source.d.ts.map +1 -0
- package/dist/drop-source.js +91 -0
- package/dist/drop-source.js.map +1 -0
- package/dist/eligibility.d.ts +46 -0
- package/dist/eligibility.d.ts.map +1 -0
- package/dist/eligibility.js +34 -0
- package/dist/eligibility.js.map +1 -0
- package/dist/env-config.d.ts +51 -0
- package/dist/env-config.d.ts.map +1 -0
- package/dist/env-config.js +272 -0
- package/dist/env-config.js.map +1 -0
- package/dist/failure-cause.d.ts +70 -0
- package/dist/failure-cause.d.ts.map +1 -0
- package/dist/failure-cause.js +126 -0
- package/dist/failure-cause.js.map +1 -0
- package/dist/format.d.ts +43 -0
- package/dist/format.d.ts.map +1 -0
- package/dist/format.js +256 -0
- package/dist/format.js.map +1 -0
- package/dist/frontmatter.d.ts +208 -0
- package/dist/frontmatter.d.ts.map +1 -0
- package/dist/frontmatter.js +344 -0
- package/dist/frontmatter.js.map +1 -0
- package/dist/gate-readiness.d.ts +84 -0
- package/dist/gate-readiness.d.ts.map +1 -0
- package/dist/gate-readiness.js +103 -0
- package/dist/gate-readiness.js.map +1 -0
- package/dist/gc.d.ts +165 -0
- package/dist/gc.d.ts.map +1 -0
- package/dist/gc.js +313 -0
- package/dist/gc.js.map +1 -0
- package/dist/gh-failure.d.ts +42 -0
- package/dist/gh-failure.d.ts.map +1 -0
- package/dist/gh-failure.js +49 -0
- package/dist/gh-failure.js.map +1 -0
- package/dist/git.d.ts +75 -0
- package/dist/git.d.ts.map +1 -0
- package/dist/git.js +130 -0
- package/dist/git.js.map +1 -0
- package/dist/github.d.ts +187 -0
- package/dist/github.d.ts.map +1 -0
- package/dist/github.js +343 -0
- package/dist/github.js.map +1 -0
- package/dist/harness.d.ts +242 -0
- package/dist/harness.d.ts.map +1 -0
- package/dist/harness.js +157 -0
- package/dist/harness.js.map +1 -0
- package/dist/identity.d.ts +167 -0
- package/dist/identity.d.ts.map +1 -0
- package/dist/identity.js +231 -0
- package/dist/identity.js.map +1 -0
- package/dist/index.d.ts +147 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +76 -0
- package/dist/index.js.map +1 -0
- package/dist/install-ci-branch-protection.d.ts +147 -0
- package/dist/install-ci-branch-protection.d.ts.map +1 -0
- package/dist/install-ci-branch-protection.js +166 -0
- package/dist/install-ci-branch-protection.js.map +1 -0
- package/dist/install-ci-capabilities/advance-lifecycle.d.ts +15 -0
- package/dist/install-ci-capabilities/advance-lifecycle.d.ts.map +1 -0
- package/dist/install-ci-capabilities/advance-lifecycle.js +28 -0
- package/dist/install-ci-capabilities/advance-lifecycle.js.map +1 -0
- package/dist/install-ci-capabilities/close-job.d.ts +13 -0
- package/dist/install-ci-capabilities/close-job.d.ts.map +1 -0
- package/dist/install-ci-capabilities/close-job.js +26 -0
- package/dist/install-ci-capabilities/close-job.js.map +1 -0
- package/dist/install-ci-capabilities/example-noop.d.ts +16 -0
- package/dist/install-ci-capabilities/example-noop.d.ts.map +1 -0
- package/dist/install-ci-capabilities/example-noop.js +23 -0
- package/dist/install-ci-capabilities/example-noop.js.map +1 -0
- package/dist/install-ci-capabilities/intake.d.ts +15 -0
- package/dist/install-ci-capabilities/intake.d.ts.map +1 -0
- package/dist/install-ci-capabilities/intake.js +28 -0
- package/dist/install-ci-capabilities/intake.js.map +1 -0
- package/dist/install-ci-capabilities/verify.d.ts +14 -0
- package/dist/install-ci-capabilities/verify.d.ts.map +1 -0
- package/dist/install-ci-capabilities/verify.js +27 -0
- package/dist/install-ci-capabilities/verify.js.map +1 -0
- package/dist/install-ci-core.d.ts +446 -0
- package/dist/install-ci-core.d.ts.map +1 -0
- package/dist/install-ci-core.js +760 -0
- package/dist/install-ci-core.js.map +1 -0
- package/dist/install-ci-github.d.ts +167 -0
- package/dist/install-ci-github.d.ts.map +1 -0
- package/dist/install-ci-github.js +315 -0
- package/dist/install-ci-github.js.map +1 -0
- package/dist/install-ci.d.ts +105 -0
- package/dist/install-ci.d.ts.map +1 -0
- package/dist/install-ci.js +363 -0
- package/dist/install-ci.js.map +1 -0
- package/dist/intake-event.d.ts +88 -0
- package/dist/intake-event.d.ts.map +1 -0
- package/dist/intake-event.js +66 -0
- package/dist/intake-event.js.map +1 -0
- package/dist/intake-marker.d.ts +95 -0
- package/dist/intake-marker.d.ts.map +1 -0
- package/dist/intake-marker.js +127 -0
- package/dist/intake-marker.js.map +1 -0
- package/dist/intake-triage.d.ts +48 -0
- package/dist/intake-triage.d.ts.map +1 -0
- package/dist/intake-triage.js +95 -0
- package/dist/intake-triage.js.map +1 -0
- package/dist/intake-trigger-template.d.ts +185 -0
- package/dist/intake-trigger-template.d.ts.map +1 -0
- package/dist/intake-trigger-template.js +449 -0
- package/dist/intake-trigger-template.js.map +1 -0
- package/dist/intake.d.ts +569 -0
- package/dist/intake.d.ts.map +1 -0
- package/dist/intake.js +1628 -0
- package/dist/intake.js.map +1 -0
- package/dist/integration-core.d.ts +539 -0
- package/dist/integration-core.d.ts.map +1 -0
- package/dist/integration-core.js +2195 -0
- package/dist/integration-core.js.map +1 -0
- package/dist/integrator.d.ts +343 -0
- package/dist/integrator.d.ts.map +1 -0
- package/dist/integrator.js +400 -0
- package/dist/integrator.js.map +1 -0
- package/dist/isolation.d.ts +219 -0
- package/dist/isolation.d.ts.map +1 -0
- package/dist/isolation.js +261 -0
- package/dist/isolation.js.map +1 -0
- package/dist/issue-provider.d.ts +349 -0
- package/dist/issue-provider.d.ts.map +1 -0
- package/dist/issue-provider.js +360 -0
- package/dist/issue-provider.js.map +1 -0
- package/dist/item-lock.d.ts +626 -0
- package/dist/item-lock.d.ts.map +1 -0
- package/dist/item-lock.js +1381 -0
- package/dist/item-lock.js.map +1 -0
- package/dist/item-path.d.ts +49 -0
- package/dist/item-path.d.ts.map +1 -0
- package/dist/item-path.js +66 -0
- package/dist/item-path.js.map +1 -0
- package/dist/ledger-lint.d.ts +129 -0
- package/dist/ledger-lint.d.ts.map +1 -0
- package/dist/ledger-lint.js +249 -0
- package/dist/ledger-lint.js.map +1 -0
- package/dist/ledger-read.d.ts +357 -0
- package/dist/ledger-read.d.ts.map +1 -0
- package/dist/ledger-read.js +442 -0
- package/dist/ledger-read.js.map +1 -0
- package/dist/ledger-write.d.ts +330 -0
- package/dist/ledger-write.d.ts.map +1 -0
- package/dist/ledger-write.js +411 -0
- package/dist/ledger-write.js.map +1 -0
- package/dist/lifecycle-gather.d.ts +30 -0
- package/dist/lifecycle-gather.d.ts.map +1 -0
- package/dist/lifecycle-gather.js +205 -0
- package/dist/lifecycle-gather.js.map +1 -0
- package/dist/lifecycle-pools.d.ts +180 -0
- package/dist/lifecycle-pools.d.ts.map +1 -0
- package/dist/lifecycle-pools.js +78 -0
- package/dist/lifecycle-pools.js.map +1 -0
- package/dist/merge-question-surfacer.d.ts +166 -0
- package/dist/merge-question-surfacer.d.ts.map +1 -0
- package/dist/merge-question-surfacer.js +297 -0
- package/dist/merge-question-surfacer.js.map +1 -0
- package/dist/mint-adr.d.ts +126 -0
- package/dist/mint-adr.d.ts.map +1 -0
- package/dist/mint-adr.js +257 -0
- package/dist/mint-adr.js.map +1 -0
- package/dist/mirror-pool-scan.d.ts +125 -0
- package/dist/mirror-pool-scan.d.ts.map +1 -0
- package/dist/mirror-pool-scan.js +104 -0
- package/dist/mirror-pool-scan.js.map +1 -0
- package/dist/needs-attention.d.ts +341 -0
- package/dist/needs-attention.d.ts.map +1 -0
- package/dist/needs-attention.js +900 -0
- package/dist/needs-attention.js.map +1 -0
- package/dist/orphan-sidecar.d.ts +79 -0
- package/dist/orphan-sidecar.d.ts.map +1 -0
- package/dist/orphan-sidecar.js +71 -0
- package/dist/orphan-sidecar.js.map +1 -0
- package/dist/output.d.ts +48 -0
- package/dist/output.d.ts.map +1 -0
- package/dist/output.js +66 -0
- package/dist/output.js.map +1 -0
- package/dist/pi-harness.d.ts +179 -0
- package/dist/pi-harness.d.ts.map +1 -0
- package/dist/pi-harness.js +342 -0
- package/dist/pi-harness.js.map +1 -0
- package/dist/placement.d.ts +99 -0
- package/dist/placement.d.ts.map +1 -0
- package/dist/placement.js +67 -0
- package/dist/placement.js.map +1 -0
- package/dist/prd-to-spec.d.ts +329 -0
- package/dist/prd-to-spec.d.ts.map +1 -0
- package/dist/prd-to-spec.js +706 -0
- package/dist/prd-to-spec.js.map +1 -0
- package/dist/prepare.d.ts +121 -0
- package/dist/prepare.d.ts.map +1 -0
- package/dist/prepare.js +140 -0
- package/dist/prepare.js.map +1 -0
- package/dist/prompt.d.ts +363 -0
- package/dist/prompt.d.ts.map +1 -0
- package/dist/prompt.js +499 -0
- package/dist/prompt.js.map +1 -0
- package/dist/protocol/ADR-FORMAT.md +47 -0
- package/dist/protocol/CLAIM-PROTOCOL.md +217 -0
- package/dist/protocol/REVIEW-PROTOCOL.md +119 -0
- package/dist/protocol/SURFACE-PROTOCOL.md +121 -0
- package/dist/protocol/TASKING-PROTOCOL.md +122 -0
- package/dist/protocol/WORK-CONTRACT.md +276 -0
- package/dist/protocol/spec-template.md +71 -0
- package/dist/protocol/task-template.md +65 -0
- package/dist/readiness.d.ts +66 -0
- package/dist/readiness.d.ts.map +1 -0
- package/dist/readiness.js +36 -0
- package/dist/readiness.js.map +1 -0
- package/dist/reap-branches.d.ts +102 -0
- package/dist/reap-branches.d.ts.map +1 -0
- package/dist/reap-branches.js +149 -0
- package/dist/reap-branches.js.map +1 -0
- package/dist/recover-isolated.d.ts +72 -0
- package/dist/recover-isolated.d.ts.map +1 -0
- package/dist/recover-isolated.js +188 -0
- package/dist/recover-isolated.js.map +1 -0
- package/dist/registry.d.ts +172 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +296 -0
- package/dist/registry.js.map +1 -0
- package/dist/repo-config.d.ts +201 -0
- package/dist/repo-config.d.ts.map +1 -0
- package/dist/repo-config.js +414 -0
- package/dist/repo-config.js.map +1 -0
- package/dist/repo-key.d.ts +20 -0
- package/dist/repo-key.d.ts.map +1 -0
- package/dist/repo-key.js +68 -0
- package/dist/repo-key.js.map +1 -0
- package/dist/repo-mirror.d.ts +177 -0
- package/dist/repo-mirror.d.ts.map +1 -0
- package/dist/repo-mirror.js +271 -0
- package/dist/repo-mirror.js.map +1 -0
- package/dist/retry-backoff.d.ts +90 -0
- package/dist/retry-backoff.d.ts.map +1 -0
- package/dist/retry-backoff.js +98 -0
- package/dist/retry-backoff.js.map +1 -0
- package/dist/review-gate.d.ts +173 -0
- package/dist/review-gate.d.ts.map +1 -0
- package/dist/review-gate.js +261 -0
- package/dist/review-gate.js.map +1 -0
- package/dist/review-verdict.d.ts +149 -0
- package/dist/review-verdict.d.ts.map +1 -0
- package/dist/review-verdict.js +332 -0
- package/dist/review-verdict.js.map +1 -0
- package/dist/run.d.ts +221 -0
- package/dist/run.d.ts.map +1 -0
- package/dist/run.js +963 -0
- package/dist/run.js.map +1 -0
- package/dist/scan.d.ts +308 -0
- package/dist/scan.d.ts.map +1 -0
- package/dist/scan.js +374 -0
- package/dist/scan.js.map +1 -0
- package/dist/select-order.d.ts +75 -0
- package/dist/select-order.d.ts.map +1 -0
- package/dist/select-order.js +108 -0
- package/dist/select-order.js.map +1 -0
- package/dist/select-priority.d.ts +188 -0
- package/dist/select-priority.d.ts.map +1 -0
- package/dist/select-priority.js +80 -0
- package/dist/select-priority.js.map +1 -0
- package/dist/select.d.ts +25 -0
- package/dist/select.d.ts.map +1 -0
- package/dist/select.js +43 -0
- package/dist/select.js.map +1 -0
- package/dist/session-path.d.ts +36 -0
- package/dist/session-path.d.ts.map +1 -0
- package/dist/session-path.js +129 -0
- package/dist/session-path.js.map +1 -0
- package/dist/sidecar-apply.d.ts +83 -0
- package/dist/sidecar-apply.d.ts.map +1 -0
- package/dist/sidecar-apply.js +111 -0
- package/dist/sidecar-apply.js.map +1 -0
- package/dist/sidecar.d.ts +245 -0
- package/dist/sidecar.d.ts.map +1 -0
- package/dist/sidecar.js +481 -0
- package/dist/sidecar.js.map +1 -0
- package/dist/slug-namespace.d.ts +204 -0
- package/dist/slug-namespace.d.ts.map +1 -0
- package/dist/slug-namespace.js +229 -0
- package/dist/slug-namespace.js.map +1 -0
- package/dist/spec-complete.d.ts +44 -0
- package/dist/spec-complete.d.ts.map +1 -0
- package/dist/spec-complete.js +69 -0
- package/dist/spec-complete.js.map +1 -0
- package/dist/start.d.ts +97 -0
- package/dist/start.d.ts.map +1 -0
- package/dist/start.js +633 -0
- package/dist/start.js.map +1 -0
- package/dist/status.d.ts +199 -0
- package/dist/status.d.ts.map +1 -0
- package/dist/status.js +228 -0
- package/dist/status.js.map +1 -0
- package/dist/surface-gate.d.ts +162 -0
- package/dist/surface-gate.d.ts.map +1 -0
- package/dist/surface-gate.js +206 -0
- package/dist/surface-gate.js.map +1 -0
- package/dist/surface-persist.d.ts +86 -0
- package/dist/surface-persist.d.ts.map +1 -0
- package/dist/surface-persist.js +129 -0
- package/dist/surface-persist.js.map +1 -0
- package/dist/tasker-review-loop.d.ts +249 -0
- package/dist/tasker-review-loop.d.ts.map +1 -0
- package/dist/tasker-review-loop.js +369 -0
- package/dist/tasker-review-loop.js.map +1 -0
- package/dist/tasking-eligibility.d.ts +74 -0
- package/dist/tasking-eligibility.d.ts.map +1 -0
- package/dist/tasking-eligibility.js +52 -0
- package/dist/tasking-eligibility.js.map +1 -0
- package/dist/tasking-lock.d.ts +111 -0
- package/dist/tasking-lock.d.ts.map +1 -0
- package/dist/tasking-lock.js +256 -0
- package/dist/tasking-lock.js.map +1 -0
- package/dist/tasking.d.ts +275 -0
- package/dist/tasking.d.ts.map +1 -0
- package/dist/tasking.js +951 -0
- package/dist/tasking.js.map +1 -0
- package/dist/triage-gate.d.ts +127 -0
- package/dist/triage-gate.d.ts.map +1 -0
- package/dist/triage-gate.js +139 -0
- package/dist/triage-gate.js.map +1 -0
- package/dist/triage-persist.d.ts +163 -0
- package/dist/triage-persist.d.ts.map +1 -0
- package/dist/triage-persist.js +387 -0
- package/dist/triage-persist.js.map +1 -0
- package/dist/verdict-json.d.ts +32 -0
- package/dist/verdict-json.d.ts.map +1 -0
- package/dist/verdict-json.js +74 -0
- package/dist/verdict-json.js.map +1 -0
- package/dist/verify-workflow-template.d.ts +60 -0
- package/dist/verify-workflow-template.d.ts.map +1 -0
- package/dist/verify-workflow-template.js +126 -0
- package/dist/verify-workflow-template.js.map +1 -0
- package/dist/verify.d.ts +60 -0
- package/dist/verify.d.ts.map +1 -0
- package/dist/verify.js +62 -0
- package/dist/verify.js.map +1 -0
- package/dist/watch-session.d.ts +112 -0
- package/dist/watch-session.d.ts.map +1 -0
- package/dist/watch-session.js +347 -0
- package/dist/watch-session.js.map +1 -0
- package/dist/work-layout.d.ts +198 -0
- package/dist/work-layout.d.ts.map +1 -0
- package/dist/work-layout.js +217 -0
- package/dist/work-layout.js.map +1 -0
- package/dist/work-on.d.ts +154 -0
- package/dist/work-on.d.ts.map +1 -0
- package/dist/work-on.js +387 -0
- package/dist/work-on.js.map +1 -0
- package/dist/workspace.d.ts +224 -0
- package/dist/workspace.d.ts.map +1 -0
- package/dist/workspace.js +325 -0
- package/dist/workspace.js.map +1 -0
- package/package.json +46 -2
- package/src/advance-ci-template.ts +203 -0
- package/src/advance-classify.ts +197 -0
- package/src/advance-drivers.ts +414 -0
- package/src/advance-isolated.ts +432 -0
- package/src/advance-lifecycle-template.ts +791 -0
- package/src/advance-loop-driver.ts +745 -0
- package/src/advance-treeless-publish.ts +177 -0
- package/src/advance.ts +1564 -0
- package/src/advancing-lock.ts +988 -0
- package/src/agent-launch.ts +137 -0
- package/src/agent-stop.ts +361 -0
- package/src/apply-decide.ts +242 -0
- package/src/apply-merge-action.ts +502 -0
- package/src/apply-persist.ts +518 -0
- package/src/arbiter.ts +372 -0
- package/src/brand.ts +111 -0
- package/src/buildable-body.ts +196 -0
- package/src/categorise.ts +158 -0
- package/src/claim-cas.ts +513 -0
- package/src/cli-spinner.ts +225 -0
- package/src/cli.ts +4379 -0
- package/src/close-job-template.ts +236 -0
- package/src/close-job.ts +319 -0
- package/src/complete.ts +1379 -0
- package/src/concurrency.ts +151 -0
- package/src/config-override.ts +116 -0
- package/src/config.ts +883 -0
- package/src/continue-branch.ts +542 -0
- package/src/cwd-section.ts +392 -0
- package/src/decision-engine.ts +272 -0
- package/src/detect.ts +124 -0
- package/src/do-autopick.ts +223 -0
- package/src/do-config.ts +589 -0
- package/src/do-remote-auto.ts +197 -0
- package/src/do.ts +2623 -0
- package/src/drop-source.ts +194 -0
- package/src/eligibility.ts +79 -0
- package/src/env-config.ts +305 -0
- package/src/failure-cause.ts +142 -0
- package/src/format.ts +313 -0
- package/src/frontmatter.ts +477 -0
- package/src/gate-readiness.ts +147 -0
- package/src/gc.ts +510 -0
- package/src/gh-failure.ts +53 -0
- package/src/git.ts +186 -0
- package/src/github.ts +468 -0
- package/src/harness.ts +355 -0
- package/src/identity.ts +322 -0
- package/src/index.ts +785 -0
- package/src/install-ci-branch-protection.ts +255 -0
- package/src/install-ci-capabilities/advance-lifecycle.ts +34 -0
- package/src/install-ci-capabilities/close-job.ts +32 -0
- package/src/install-ci-capabilities/example-noop.ts +24 -0
- package/src/install-ci-capabilities/intake.ts +34 -0
- package/src/install-ci-capabilities/verify.ts +33 -0
- package/src/install-ci-core.ts +1088 -0
- package/src/install-ci-github.ts +376 -0
- package/src/install-ci.ts +552 -0
- package/src/intake-event.ts +102 -0
- package/src/intake-marker.ts +195 -0
- package/src/intake-triage.ts +138 -0
- package/src/intake-trigger-template.ts +591 -0
- package/src/intake.ts +2445 -0
- package/src/integration-core.ts +3065 -0
- package/src/integrator.ts +771 -0
- package/src/isolation.ts +484 -0
- package/src/issue-provider.ts +733 -0
- package/src/item-lock.ts +1858 -0
- package/src/item-path.ts +75 -0
- package/src/ledger-lint.ts +332 -0
- package/src/ledger-read.ts +924 -0
- package/src/ledger-write.ts +865 -0
- package/src/lifecycle-gather.ts +298 -0
- package/src/lifecycle-pools.ts +250 -0
- package/src/merge-question-surfacer.ts +496 -0
- package/src/mint-adr.ts +362 -0
- package/src/mirror-pool-scan.ts +240 -0
- package/src/needs-attention.ts +1506 -0
- package/src/orphan-sidecar.ts +150 -0
- package/src/output.ts +89 -0
- package/src/pi-harness.ts +403 -0
- package/src/placement.ts +131 -0
- package/src/prd-to-spec.ts +1059 -0
- package/src/prepare.ts +230 -0
- package/src/prompt.ts +763 -0
- package/src/readiness.ts +98 -0
- package/src/reap-branches.ts +278 -0
- package/src/recover-isolated.ts +276 -0
- package/src/registry.ts +475 -0
- package/src/repo-config.ts +550 -0
- package/src/repo-key.ts +74 -0
- package/src/repo-mirror.ts +367 -0
- package/src/retry-backoff.ts +130 -0
- package/src/review-gate.ts +389 -0
- package/src/review-verdict.ts +422 -0
- package/src/run.ts +1430 -0
- package/src/scan.ts +611 -0
- package/src/select-order.ts +143 -0
- package/src/select-priority.ts +266 -0
- package/src/select.ts +62 -0
- package/src/session-path.ts +153 -0
- package/src/sidecar-apply.ts +216 -0
- package/src/sidecar.ts +700 -0
- package/src/slug-namespace.ts +367 -0
- package/src/spec-complete.ts +118 -0
- package/src/start.ts +974 -0
- package/src/status.ts +441 -0
- package/src/surface-gate.ts +337 -0
- package/src/surface-persist.ts +241 -0
- package/src/tasker-review-loop.ts +671 -0
- package/src/tasking-eligibility.ts +114 -0
- package/src/tasking-lock.ts +416 -0
- package/src/tasking.ts +1437 -0
- package/src/triage-gate.ts +248 -0
- package/src/triage-persist.ts +570 -0
- package/src/verdict-json.ts +73 -0
- package/src/verify-workflow-template.ts +159 -0
- package/src/verify.ts +123 -0
- package/src/watch-session.ts +397 -0
- package/src/work-layout.ts +262 -0
- package/src/work-on.ts +660 -0
- package/src/workspace.ts +502 -0
|
@@ -0,0 +1,570 @@
|
|
|
1
|
+
import {readFileSync} from 'node:fs';
|
|
2
|
+
import {join} from 'node:path';
|
|
3
|
+
import {run, type RunResult} from './git.js';
|
|
4
|
+
import {workItemRel} from './work-layout.js';
|
|
5
|
+
import {
|
|
6
|
+
createItemThroughCas,
|
|
7
|
+
type CasContentionBudget,
|
|
8
|
+
type CreateItemThroughCasResult,
|
|
9
|
+
} from './advancing-lock.js';
|
|
10
|
+
import {resolveSidecarIdentity, sidecarPathFor} from './sidecar.js';
|
|
11
|
+
import type {TriageAutoKind} from './triage-gate.js';
|
|
12
|
+
import {renderTaskBody, renderSpecBody} from './buildable-body.js';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* The engine-owned TRIAGE PERSIST (prd `advance-loop`, task `advance-rung-triage`,
|
|
16
|
+
* US #16/17/24/30) — the half of the observation-triage rung the ENGINE owns (the
|
|
17
|
+
* triage gate JUDGES, the engine ACTS). It is the SIBLING of `surface-persist.ts`
|
|
18
|
+
* (the surface rung's persist) and `apply-persist.ts` (the apply rung's persist),
|
|
19
|
+
* kept file-orthogonal so the rung bodies land in different tasks.
|
|
20
|
+
*
|
|
21
|
+
* It delivers the two WRITES the triage rung needs beyond the always-allowed
|
|
22
|
+
* question-gated surface path (which reuses `surface-persist.ts` verbatim):
|
|
23
|
+
*
|
|
24
|
+
* 1. **the conservative auto-disposition** ({@link autoDispositionObservation},
|
|
25
|
+
* US #17, `observationTriage: 'auto'`-gated): act on the no-question case on
|
|
26
|
+
* the UNTRIAGED observation in ONE local commit. BOTH no-question cases now
|
|
27
|
+
* DISCHARGE the redundant note BY DELETION (there is no resting `triaged:keep`
|
|
28
|
+
* state any more — task `agentic-apply-retire-disposition-vocabulary`):
|
|
29
|
+
* - `duplicate` → `git rm` the duplicate in a standalone commit, the
|
|
30
|
+
* duplicated-of identity + reason in the commit message (git history =
|
|
31
|
+
* archive). A duplicate is a redundant copy of an already-captured signal,
|
|
32
|
+
* so deleting it loses nothing; or
|
|
33
|
+
* - `map` → the note is already covered by the existing item it maps onto, so
|
|
34
|
+
* it is settled — `git rm` it in a standalone commit, the mapped-onto
|
|
35
|
+
* identity + reason recorded in the commit message (mirroring `duplicate`).
|
|
36
|
+
* There is no resting `triaged:keep` note any more.
|
|
37
|
+
* 2. **promote → SELF-CONTAINED new-item creation + DELETE through the CAS**
|
|
38
|
+
* ({@link promoteObservation}, US #1/#3/#8): an ANSWERED "promote" drafts a
|
|
39
|
+
* new `work/tasks/ready/<new-slug>.md` whose body is built FROM the
|
|
40
|
+
* observation (mechanism + fix prose into `## What to build`, the
|
|
41
|
+
* `## Open questions` scoping transcribed, `needsAnswers` set when questions
|
|
42
|
+
* remain), routed THROUGH the CAS keyed on the NEW item's identity (its
|
|
43
|
+
* target path) — so the (unlikely) same-slug new-item race needs NO special
|
|
44
|
+
* case (the loser fails the CAS and backs off). On a WIN the observation +
|
|
45
|
+
* its answered sidecar are `git rm`-ed IN THE SAME atomic create commit
|
|
46
|
+
* (discharge by DELETION; the human's ratified "promote" answer authors it),
|
|
47
|
+
* so a crash never strands the note without its successor.
|
|
48
|
+
*
|
|
49
|
+
* Like its sibling persists, the auto-disposition is a LOCAL one-commit primitive
|
|
50
|
+
* over a working tree (the throwaway-git-repo test pattern); the CAS-create (now
|
|
51
|
+
* carrying the note+sidecar deletion in the SAME commit) is the ONLY arbiter race
|
|
52
|
+
* (it IS the new-item-creation CAS helper from `advancing-lock-borrow`). The
|
|
53
|
+
* `advancing` CAS lock that makes the triage rung WINNER-ONLY on the OBSERVATION
|
|
54
|
+
* is held by `performAdvance` BEFORE this is called.
|
|
55
|
+
*
|
|
56
|
+
* **NEVER auto-deletes a NON-duplicate signal; NEVER auto-promotes a judgement
|
|
57
|
+
* call (US #17).** The auto-disposition is bounded to `duplicate`/`map` (the gate's
|
|
58
|
+
* high bar). A `duplicate` IS discharged by deletion (it is a redundant copy of an
|
|
59
|
+
* already-captured signal — deleting it loses nothing, the original carries the
|
|
60
|
+
* signal), which is NOT "auto-deleting a live signal". Promotion is ALWAYS a human
|
|
61
|
+
* answer (the apply path), never an auto-disposition.
|
|
62
|
+
*/
|
|
63
|
+
|
|
64
|
+
function gitSoft(
|
|
65
|
+
args: string[],
|
|
66
|
+
cwd: string,
|
|
67
|
+
env: NodeJS.ProcessEnv | undefined,
|
|
68
|
+
): RunResult {
|
|
69
|
+
return run('git', args, cwd, {env});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function gitHard(
|
|
73
|
+
args: string[],
|
|
74
|
+
cwd: string,
|
|
75
|
+
env: NodeJS.ProcessEnv | undefined,
|
|
76
|
+
): RunResult {
|
|
77
|
+
const result = run('git', args, cwd, {env});
|
|
78
|
+
if (result.status !== 0) {
|
|
79
|
+
throw new TriagePersistError(
|
|
80
|
+
`git ${args.join(' ')} failed (exit ${result.status}): ${result.stderr.trim()}`,
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
return result;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function resolveBy(cwd: string, env: NodeJS.ProcessEnv | undefined): string {
|
|
87
|
+
const name = gitSoft(['config', 'user.name'], cwd, env);
|
|
88
|
+
if (name.status === 0 && name.stdout.trim() !== '') {
|
|
89
|
+
return name.stdout.trim();
|
|
90
|
+
}
|
|
91
|
+
const e = env ?? process.env;
|
|
92
|
+
return e.USER ?? e.USERNAME ?? '';
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** Read the observation body from the tree (committed) then the working file. */
|
|
96
|
+
function readItem(
|
|
97
|
+
cwd: string,
|
|
98
|
+
itemPath: string,
|
|
99
|
+
env: NodeJS.ProcessEnv | undefined,
|
|
100
|
+
): string {
|
|
101
|
+
const show = gitSoft(['show', `:${itemPath}`], cwd, env);
|
|
102
|
+
if (show.status === 0) {
|
|
103
|
+
return show.stdout;
|
|
104
|
+
}
|
|
105
|
+
try {
|
|
106
|
+
return readFileSync(join(cwd, itemPath), 'utf8');
|
|
107
|
+
} catch {
|
|
108
|
+
throw new TriagePersistError(
|
|
109
|
+
`cannot read observation body for '${itemPath}' (the triage rung needs the item file)`,
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/** Raised for usage errors (a missing repo, an unreadable observation). */
|
|
115
|
+
export class TriagePersistError extends Error {
|
|
116
|
+
constructor(message: string) {
|
|
117
|
+
super(message);
|
|
118
|
+
this.name = 'TriagePersistError';
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// --- The conservative auto-disposition (US #17) ---------------------------
|
|
123
|
+
|
|
124
|
+
export interface AutoDispositionOptions {
|
|
125
|
+
/** Working clone/worktree the disposition commits in. */
|
|
126
|
+
cwd: string;
|
|
127
|
+
/** The namespaced observation identity (`observation:<slug>`). */
|
|
128
|
+
item: string;
|
|
129
|
+
/** The observation file path RELATIVE to `cwd` (e.g. `work/notes/observations/foo.md`). */
|
|
130
|
+
itemPath: string;
|
|
131
|
+
/** The no-question case (`duplicate` / `map`). */
|
|
132
|
+
kind: TriageAutoKind;
|
|
133
|
+
/** The existing item this duplicates / maps onto (`<namespace>:<slug>`). */
|
|
134
|
+
existing: string;
|
|
135
|
+
/** A short reason recorded with the disposition. */
|
|
136
|
+
reason?: string;
|
|
137
|
+
/** Advisory committer id for the commit subject. Defaults to git user.name. */
|
|
138
|
+
by?: string;
|
|
139
|
+
/** Environment for child git processes. */
|
|
140
|
+
env?: NodeJS.ProcessEnv;
|
|
141
|
+
/** Sink for human-readable progress notes. */
|
|
142
|
+
note?: (message: string) => void;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export interface AutoDispositionResult {
|
|
146
|
+
/**
|
|
147
|
+
* Always `deleted`: BOTH no-question cases DISCHARGE the redundant note BY
|
|
148
|
+
* DELETION (`git rm` in a standalone commit, the reason in the message). A
|
|
149
|
+
* `duplicate` is a redundant copy of `existing`; a `map` is already covered by
|
|
150
|
+
* `existing` — either way the note carries no unique signal, so it leaves the
|
|
151
|
+
* inbox by being gone. There is no resting `triaged:keep` state any more (task
|
|
152
|
+
* `agentic-apply-retire-disposition-vocabulary`). NEVER an auto-delete of a
|
|
153
|
+
* NON-redundant signal.
|
|
154
|
+
*/
|
|
155
|
+
outcome: 'deleted';
|
|
156
|
+
/** The commit sha the disposition produced. */
|
|
157
|
+
commit: string;
|
|
158
|
+
/** The path the note WAS at before it was deleted (the note is gone after this returns). */
|
|
159
|
+
itemPath: string;
|
|
160
|
+
/** A human-readable summary. */
|
|
161
|
+
message: string;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Execute a CONSERVATIVE auto-disposition on an UNTRIAGED observation (US #17),
|
|
166
|
+
* ONE local commit, no question surfaced. BOTH no-question cases DISCHARGE the
|
|
167
|
+
* redundant note BY DELETION (`git rm` in a STANDALONE commit, the mapped/
|
|
168
|
+
* duplicated-of identity + reason in the commit message; git history = archive).
|
|
169
|
+
* There is no resting `triaged:keep` state any more (task
|
|
170
|
+
* `agentic-apply-retire-disposition-vocabulary` — a signal is still-open,
|
|
171
|
+
* acted-on, or deleted):
|
|
172
|
+
*
|
|
173
|
+
* - `duplicate` → the note is an EXACT duplicate of `existing` (already
|
|
174
|
+
* captured); the original carries the signal, so the copy is deleted; or
|
|
175
|
+
* - `map` → the note maps UNAMBIGUOUSLY onto `existing` (already covered there),
|
|
176
|
+
* so it is settled — deleted, the mapping recorded in the commit message
|
|
177
|
+
* (mirroring `duplicate`).
|
|
178
|
+
*
|
|
179
|
+
* It NEVER promotes (promotion is a human "worth building?" answer, the apply path)
|
|
180
|
+
* and NEVER auto-deletes a NON-redundant signal (the gate's high bar bounds it to
|
|
181
|
+
* `duplicate`/`map`, both of which carry no unique signal).
|
|
182
|
+
*/
|
|
183
|
+
export function autoDispositionObservation(
|
|
184
|
+
options: AutoDispositionOptions,
|
|
185
|
+
): AutoDispositionResult {
|
|
186
|
+
const {cwd, item, itemPath, kind, existing, env} = options;
|
|
187
|
+
const note = options.note ?? (() => {});
|
|
188
|
+
|
|
189
|
+
if (gitSoft(['rev-parse', '--git-dir'], cwd, env).status !== 0) {
|
|
190
|
+
throw new TriagePersistError('not inside a git repository');
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const reason = options.reason?.trim() ?? '';
|
|
194
|
+
const by = options.by || resolveBy(cwd, env);
|
|
195
|
+
|
|
196
|
+
// DISCHARGE BY DELETION (both cases): `git rm` the redundant note in a STANDALONE
|
|
197
|
+
// commit (no spawned artifact), the relationship + reason in the commit message.
|
|
198
|
+
// No body marker, no `triaged:` stamp — the note is out of the pool by being gone.
|
|
199
|
+
gitHard(['rm', '--quiet', '--', itemPath], cwd, env);
|
|
200
|
+
const relationship =
|
|
201
|
+
kind === 'duplicate'
|
|
202
|
+
? `an EXACT duplicate of ${existing} (already captured; the original carries the signal`
|
|
203
|
+
: `mapped UNAMBIGUOUSLY onto ${existing} (already covered there; the existing item carries the signal`;
|
|
204
|
+
const subject = `advance: triage ${item} → ${kind} (by ${by})`;
|
|
205
|
+
const messageBody =
|
|
206
|
+
`Discharged by deletion: ${relationship}, git history is the archive).` +
|
|
207
|
+
(reason !== '' ? `\n\nreason: ${reason}` : '');
|
|
208
|
+
gitHard(['commit', '--quiet', '-m', subject, '-m', messageBody], cwd, env);
|
|
209
|
+
const commit = gitHard(['rev-parse', 'HEAD'], cwd, env).stdout.trim();
|
|
210
|
+
const message =
|
|
211
|
+
`auto-triaged ${item} → ${kind} of ${existing}: DELETED the note in a ` +
|
|
212
|
+
'standalone commit (relationship + reason in the commit message, git history is the archive).';
|
|
213
|
+
note(message);
|
|
214
|
+
return {outcome: 'deleted', commit, itemPath, message};
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// --- Promote → new-item creation through the CAS (US #24) -----------------
|
|
218
|
+
|
|
219
|
+
export interface PromoteObservationOptions {
|
|
220
|
+
/** Working clone/worktree the promote runs in. */
|
|
221
|
+
cwd: string;
|
|
222
|
+
/** The namespaced observation identity (`observation:<slug>`). */
|
|
223
|
+
item: string;
|
|
224
|
+
/** The observation file path RELATIVE to `cwd` (e.g. `work/notes/observations/foo.md`). */
|
|
225
|
+
itemPath: string;
|
|
226
|
+
/**
|
|
227
|
+
* The artifact TYPE to mint, chosen by the AGENTIC apply VERDICT (task
|
|
228
|
+
* `agentic-apply-retire-disposition-vocabulary` — NOT a human `promote-*` field
|
|
229
|
+
* any more): `'task'` → `work/tasks/ready/<slug>.md` (the default); `'spec'` →
|
|
230
|
+
* `work/specs/proposed/<slug>.md` (a SPEC-sized signal lands in `proposed/`
|
|
231
|
+
* staging, which a human later promotes to `ready/`). BOTH go through the SAME
|
|
232
|
+
* triage-local {@link createItemThroughCas} writer (one local commit through the
|
|
233
|
+
* CAS) — NOT intake's branch+integrate band — so the CAS-loser-backs-off
|
|
234
|
+
* guarantee and the same-commit note deletion are uniform across the two routes.
|
|
235
|
+
* MIGRATE step (prd `prd-to-spec-vocabulary-cutover-and-migration-command`): the
|
|
236
|
+
* produced VALUE is `'spec'` (the verdict outcome renamed from `'prd'`).
|
|
237
|
+
*/
|
|
238
|
+
artifact?: 'task' | 'spec';
|
|
239
|
+
/**
|
|
240
|
+
* The NEW backlog slug to draft. Defaults to the observation's own slug (the
|
|
241
|
+
* promoted item is `work/backlog/<obs-slug>.md`). The CAS is keyed on the new
|
|
242
|
+
* item's PATH, so a same-slug new-item race ⇒ the loser fails the CAS.
|
|
243
|
+
*/
|
|
244
|
+
newSlug?: string;
|
|
245
|
+
/**
|
|
246
|
+
* The new task's content. Defaults to a SELF-CONTAINED body built from the
|
|
247
|
+
* observation (its mechanism + fix prose carried into `## What to build`, its
|
|
248
|
+
* `## Open questions` transcribed, `needsAnswers` set when questions remain) —
|
|
249
|
+
* so the spawned task is buildable on its own and the note is safely deletable.
|
|
250
|
+
*/
|
|
251
|
+
stubContent?: string;
|
|
252
|
+
/** Name of the arbiter remote (`--arbiter`). Defaults to `origin`. */
|
|
253
|
+
arbiter?: string;
|
|
254
|
+
/** Advisory committer id for the commit subject. Defaults to git user.name. */
|
|
255
|
+
by?: string;
|
|
256
|
+
/** Environment for child git processes. */
|
|
257
|
+
env?: NodeJS.ProcessEnv;
|
|
258
|
+
/** Show the intended CAS push without mutating the arbiter (`--dry-run`). */
|
|
259
|
+
dryRun?: boolean;
|
|
260
|
+
/**
|
|
261
|
+
* The CAS CONTENTION-RETRY BUDGET (jittered inter-retry delay + widened
|
|
262
|
+
* attempt / wall-clock envelope). Threaded through to
|
|
263
|
+
* {@link createItemThroughCas}. The lifecycle driver passes
|
|
264
|
+
* `LIFECYCLE_CAS_CONTENTION` here so a propose-tick FAN-OUT of parallel
|
|
265
|
+
* promote legs desynchronises and DRAINS instead of thrashing to `contended`.
|
|
266
|
+
* Absent ⇒ the interactive default (3 retries, no delay).
|
|
267
|
+
*/
|
|
268
|
+
contention?: CasContentionBudget;
|
|
269
|
+
/** Sink for human-readable progress notes. */
|
|
270
|
+
note?: (message: string) => void;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
export interface PromoteObservationResult {
|
|
274
|
+
/**
|
|
275
|
+
* `promoted` (the new item landed via the CAS + the observation+sidecar were
|
|
276
|
+
* deleted in the SAME commit), `lost` (the same-slug new-item race was lost —
|
|
277
|
+
* the loser backs off, observation left INTACT), or `contended` (the CAS push
|
|
278
|
+
* kept failing). Maps onto the claim-CAS exit codes.
|
|
279
|
+
*/
|
|
280
|
+
outcome: 'promoted' | 'lost' | 'contended' | 'usage-error';
|
|
281
|
+
exitCode: 0 | 1 | 2 | 3;
|
|
282
|
+
/** The new task's path (relative to repo root) on a WIN. */
|
|
283
|
+
newItemPath?: string;
|
|
284
|
+
/** A human-readable summary. */
|
|
285
|
+
message: string;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Promote an ANSWERED observation to a NEW, SELF-CONTAINED artifact (US #1/#3/#8
|
|
290
|
+
* for the task route; US #4/#9 for the PRD route): CAS-create the new item keyed
|
|
291
|
+
* on the NEW item's identity (its target path), with the observation note + its
|
|
292
|
+
* answered sidecar `git rm`-ed IN THE SAME atomic commit. Promote is ONE commit
|
|
293
|
+
* (create + delete).
|
|
294
|
+
*
|
|
295
|
+
* The artifact TYPE (`options.artifact`) selects the target + body shape: `'task'`
|
|
296
|
+
* (default) mints `work/tasks/ready/<slug>.md`; `'prd'` mints
|
|
297
|
+
* `work/prds/proposed/<slug>.md` (PRD staging — a human later promotes it to
|
|
298
|
+
* `ready/`). BOTH routes use the SAME triage-local {@link createItemThroughCas}
|
|
299
|
+
* writer (NOT intake's `switchToWorkBranch`/`performIntegration` branch+integrate
|
|
300
|
+
* band, which is intake's standalone front door): one create/integrate surface for
|
|
301
|
+
* triage, the CAS-loser-backs-off guarantee uniform across task and PRD promotion.
|
|
302
|
+
*
|
|
303
|
+
* The minted body is built FROM the observation (see {@link buildPromotedBody}):
|
|
304
|
+
* its mechanism + fix prose is carried into the artifact's lead section (`## What
|
|
305
|
+
* to build` for a task, `## Problem Statement` for a PRD), and its
|
|
306
|
+
* `## Open questions` scoping is transcribed into the new item's own
|
|
307
|
+
* `## Open questions` block with `needsAnswers` set when questions remain (cleared
|
|
308
|
+
* when none do) — so an agent can build from the artifact ALONE and no decision
|
|
309
|
+
* residue is lost on deletion. This self-containment is the PRECONDITION for the
|
|
310
|
+
* same-commit deletion.
|
|
311
|
+
*
|
|
312
|
+
* The CAS-create is the new-item-creation helper from `advancing-lock-borrow`
|
|
313
|
+
* ({@link createItemThroughCas}): a same-slug new-item race needs NO special case
|
|
314
|
+
* — exactly one creator lands the file, the LOSER fails the CAS (exit 2) and backs
|
|
315
|
+
* off WITHOUT deleting the observation (so a retry can re-promote). The observation
|
|
316
|
+
* (+ its sidecar) is deleted ONLY on a WIN, riding the winning creator's commit.
|
|
317
|
+
*/
|
|
318
|
+
export async function promoteObservation(
|
|
319
|
+
options: PromoteObservationOptions,
|
|
320
|
+
): Promise<PromoteObservationResult> {
|
|
321
|
+
const {cwd, item, itemPath, env} = options;
|
|
322
|
+
const note = options.note ?? (() => {});
|
|
323
|
+
|
|
324
|
+
const {slug: obsSlug} = resolveSidecarIdentity(item);
|
|
325
|
+
const newSlug = (options.newSlug ?? obsSlug).trim();
|
|
326
|
+
const artifact = options.artifact ?? 'task';
|
|
327
|
+
if (newSlug === '') {
|
|
328
|
+
return {
|
|
329
|
+
outcome: 'usage-error',
|
|
330
|
+
exitCode: 1,
|
|
331
|
+
message: `promote ${item}: empty new slug — cannot draft a ${artifact}`,
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
// Branch the target on artifact TYPE: `task` → the agent pool (`tasks-ready`);
|
|
335
|
+
// `spec` → SPEC STAGING (`specs-proposed`), the conservative default a human later
|
|
336
|
+
// promotes to `ready/`. Both still go through the SAME createItemThroughCas
|
|
337
|
+
// writer below — only the destination folder + body shape differ.
|
|
338
|
+
const newItemPath = workItemRel(
|
|
339
|
+
artifact === 'spec' ? 'specs-proposed' : 'tasks-ready',
|
|
340
|
+
`${newSlug}.md`,
|
|
341
|
+
);
|
|
342
|
+
const by = options.by || resolveBy(cwd, env);
|
|
343
|
+
const content = ensureTaskDispatchable(
|
|
344
|
+
artifact,
|
|
345
|
+
newSlug,
|
|
346
|
+
options.stubContent ??
|
|
347
|
+
buildPromotedBody(artifact, newSlug, readItem(cwd, itemPath, env)),
|
|
348
|
+
);
|
|
349
|
+
|
|
350
|
+
// The note + its answered sidecar `git rm` IN THE SAME create commit (promote =
|
|
351
|
+
// ONE atomic commit). A CAS LOSER never reaches the commit, so it leaves both
|
|
352
|
+
// INTACT for a retry (today's loser-backs-off guarantee, now over deletion).
|
|
353
|
+
const sidecarPath = sidecarPathFor(item);
|
|
354
|
+
|
|
355
|
+
// CAS-CREATE the new task keyed on its identity, carrying the note+sidecar
|
|
356
|
+
// deletion in the SAME commit. A same-slug race ⇒ the loser fails here and
|
|
357
|
+
// backs off WITHOUT deleting the observation.
|
|
358
|
+
const created: CreateItemThroughCasResult = await createItemThroughCas({
|
|
359
|
+
path: newItemPath,
|
|
360
|
+
content,
|
|
361
|
+
deletePaths: [itemPath, sidecarPath],
|
|
362
|
+
cwd,
|
|
363
|
+
arbiter: options.arbiter,
|
|
364
|
+
by,
|
|
365
|
+
dryRun: options.dryRun,
|
|
366
|
+
env,
|
|
367
|
+
note,
|
|
368
|
+
...(options.contention !== undefined
|
|
369
|
+
? {contention: options.contention}
|
|
370
|
+
: {}),
|
|
371
|
+
});
|
|
372
|
+
if (created.exitCode !== 0) {
|
|
373
|
+
const message =
|
|
374
|
+
`promote ${item}: the new item ${newItemPath} ${created.outcome} the ` +
|
|
375
|
+
`create CAS (${created.message}) — backing off, the observation is left ` +
|
|
376
|
+
'intact for a retry.';
|
|
377
|
+
note(message);
|
|
378
|
+
return {
|
|
379
|
+
outcome: created.outcome === 'lost' ? 'lost' : 'contended',
|
|
380
|
+
exitCode: created.exitCode,
|
|
381
|
+
message,
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
const message =
|
|
386
|
+
`promoted ${item} → CREATED ${newItemPath} (via the CAS) + DELETED the ` +
|
|
387
|
+
'observation + its sidecar in the same commit.';
|
|
388
|
+
note(message);
|
|
389
|
+
return {outcome: 'promoted', exitCode: 0, newItemPath, message};
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* Build a SELF-CONTAINED body from a promoted observation. The observation's body
|
|
394
|
+
* (its mechanism + fix prose) is lifted into the artifact's LEAD section; its
|
|
395
|
+
* `## Open questions` section — if any — is SPLIT OUT and transcribed into the new
|
|
396
|
+
* item's own `## Open questions` block, and `needsAnswers: true` is stamped iff
|
|
397
|
+
* that block carries content (so deleting the note loses no scoping residue).
|
|
398
|
+
*
|
|
399
|
+
* The artifact TYPE selects the frontmatter + lead heading: a `task` gets
|
|
400
|
+
* `## What to build` + `blockedBy: []` + a `## Prompt` (the buildable-task shape);
|
|
401
|
+
* a `prd` gets `## Problem Statement` (the PRD document shape, with no `blockedBy` —
|
|
402
|
+
* a PRD is not a blockable task — and no `## Prompt`, since a PRD is not
|
|
403
|
+
* dispatched by `do`/`run`). BOTH carry the SAME transcribed mechanism prose +
|
|
404
|
+
* open-question block, so a PRD minted into `proposed/` is just as self-contained
|
|
405
|
+
* as a task.
|
|
406
|
+
*
|
|
407
|
+
* The `## Prompt` (task only) is the STRUCTURAL dispatchability the validator
|
|
408
|
+
* `resolveTask`/`extractPromptSection` (`prompt.ts`) requires: without it a
|
|
409
|
+
* dispatched build throws "has no '## Prompt' section". The body BELOW the
|
|
410
|
+
* frontmatter (lead section + mechanism prose + optional `## Open questions` +
|
|
411
|
+
* the task-only `## Prompt`) is rendered by the SHARED owner of the
|
|
412
|
+
* buildable-task/PRD schema, {@link renderTaskBody} / {@link renderSpecBody}
|
|
413
|
+
* (`buildable-body.ts`), so the producer and the consumer cannot drift apart
|
|
414
|
+
* (prd `centralize-buildable-task-renderer-shared-by-intake-and-promotion`,
|
|
415
|
+
* US #3/#5/#6). This function owns only the FRONTMATTER writer; the section
|
|
416
|
+
* skeleton lives in the one renderer. The empty-mechanism `## Prompt` seed is
|
|
417
|
+
* passed EXPLICITLY (`Build the task '<slug>', described above.`) so promotion's
|
|
418
|
+
* output is byte-for-byte unchanged — it differs from the renderer's generic
|
|
419
|
+
* `Build the task described above.` default.
|
|
420
|
+
*
|
|
421
|
+
* Composition rule (recorded in the done record `## Decisions`): the split point
|
|
422
|
+
* is the observation's FIRST `## Open questions` heading (any later sibling text
|
|
423
|
+
* up to the next same-level heading, or EOF, is the scoping). Everything BEFORE it
|
|
424
|
+
* is the mechanism/fix prose. We copy PROSE (not a back-pointer) so the artifact is
|
|
425
|
+
* buildable on its own.
|
|
426
|
+
*/
|
|
427
|
+
/**
|
|
428
|
+
* Guarantee a minted TASK body is DISPATCHABLE (carries a `## Prompt`). The
|
|
429
|
+
* agentic apply path (`apply-decide` → `promoteObservation` with `stubContent`)
|
|
430
|
+
* lets a fresh-context agent AUTHOR the task body, and that agent frequently omits
|
|
431
|
+
* the `## Prompt` section (drafting its own `## Context`/`## Definition of done`
|
|
432
|
+
* skeleton instead) — so the raw drafted body bypasses {@link buildPromotedBody}'s
|
|
433
|
+
* renderer and lands NON-dispatchable: the `advance --propose` build leg then
|
|
434
|
+
* fails with `has no '## Prompt' section` (the `extractPromptSection`/`resolveTask`
|
|
435
|
+
* guard in `prompt.ts`). This is the robust backstop that closes that hole
|
|
436
|
+
* regardless of agent compliance: for a TASK, if the body has no `## Prompt`
|
|
437
|
+
* heading, append a seeded one (blockquoted, matching the renderer's shape). A PRD
|
|
438
|
+
* is left UNTOUCHED — a PRD is a north-star doc, not dispatched by `do`/`run`, and carries no
|
|
439
|
+
* `## Prompt` by design.
|
|
440
|
+
*/
|
|
441
|
+
function ensureTaskDispatchable(
|
|
442
|
+
artifact: 'task' | 'spec',
|
|
443
|
+
slug: string,
|
|
444
|
+
body: string,
|
|
445
|
+
): string {
|
|
446
|
+
if (artifact === 'spec') {
|
|
447
|
+
return body;
|
|
448
|
+
}
|
|
449
|
+
// A task WITH a `## Prompt` heading (any level-2 spelling the validator matches)
|
|
450
|
+
// is already dispatchable — leave it byte-for-byte.
|
|
451
|
+
if (/^##\s+Prompt\b/im.test(body)) {
|
|
452
|
+
return body;
|
|
453
|
+
}
|
|
454
|
+
// No `## Prompt`: append a seeded, blockquoted one so the minted task never
|
|
455
|
+
// lands non-dispatchable. The seed points the builder at the body above (the
|
|
456
|
+
// same shape `renderTaskBody`'s empty-mechanism default uses).
|
|
457
|
+
const trimmed = body.replace(/\s+$/, '');
|
|
458
|
+
const seed = `Build the task '${slug}', described above.`;
|
|
459
|
+
const promptBlock = `## Prompt\n\n> ${seed}\n`;
|
|
460
|
+
return `${trimmed}\n\n${promptBlock}`;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
function buildPromotedBody(
|
|
464
|
+
artifact: 'task' | 'spec',
|
|
465
|
+
slug: string,
|
|
466
|
+
observation: string,
|
|
467
|
+
): string {
|
|
468
|
+
const {mechanism, openQuestions} = splitObservationBody(observation);
|
|
469
|
+
const hasQuestions = openQuestions.trim() !== '';
|
|
470
|
+
const frontmatter: string[] = [
|
|
471
|
+
'---',
|
|
472
|
+
`title: ${slug}`,
|
|
473
|
+
`slug: ${slug}`,
|
|
474
|
+
`needsAnswers: ${hasQuestions ? 'true' : 'false'}`,
|
|
475
|
+
// A PRD is a north-star doc, not a blockable task — only the task shape carries
|
|
476
|
+
// `blockedBy`.
|
|
477
|
+
...(artifact === 'spec' ? [] : ['blockedBy: []']),
|
|
478
|
+
'---',
|
|
479
|
+
];
|
|
480
|
+
// One BLANK line separates the closing frontmatter fence from the rendered
|
|
481
|
+
// body (`---\n\n## ...`): the shared renderer starts AT its first heading with no
|
|
482
|
+
// leading blank, so the separator is owned here. This keeps promotion's output
|
|
483
|
+
// byte-for-byte identical to the pre-rewire hand-rolled body (which placed an
|
|
484
|
+
// empty array element between the `---` fence and the lead heading) and matches
|
|
485
|
+
// what intake will emit once it adopts the same renderer. RATIFIED as a
|
|
486
|
+
// cross-module convention in `docs/adr/frontmatter-owns-fence-to-heading-blank-line.md`
|
|
487
|
+
// — frontmatter owns the `\n\n`, the renderer starts at the first heading with
|
|
488
|
+
// no leading blank. Do NOT move the separator into the renderer.
|
|
489
|
+
const fenceToBody = frontmatter.join('\n') + '\n\n';
|
|
490
|
+
// The body BELOW the frontmatter is rendered by the SHARED schema owner so the
|
|
491
|
+
// section skeleton has one home, not two (prd
|
|
492
|
+
// `centralize-buildable-task-renderer-shared-by-intake-and-promotion`). A PRD
|
|
493
|
+
// goes through `renderSpecBody` (no `## Prompt`); a task through
|
|
494
|
+
// `renderTaskBody` (always a `## Prompt`).
|
|
495
|
+
if (artifact === 'spec') {
|
|
496
|
+
return (
|
|
497
|
+
fenceToBody +
|
|
498
|
+
renderSpecBody({
|
|
499
|
+
problemStatement: mechanism,
|
|
500
|
+
openQuestions,
|
|
501
|
+
})
|
|
502
|
+
);
|
|
503
|
+
}
|
|
504
|
+
// Pass the slug-bearing empty-mechanism seed EXPLICITLY: the renderer's generic
|
|
505
|
+
// default is `Build the task described above.`, but promotion has always seeded
|
|
506
|
+
// the empty-mechanism case with the slug (`Build the task '<slug>', described
|
|
507
|
+
// above.`), so we keep that byte-for-byte by handing the seed in rather than
|
|
508
|
+
// relying on the renderer default. A non-empty mechanism seeds the `## Prompt`
|
|
509
|
+
// from the mechanism prose (the renderer blockquotes it).
|
|
510
|
+
const promptSeed =
|
|
511
|
+
mechanism.trim() === ''
|
|
512
|
+
? `Build the task '${slug}', described above.`
|
|
513
|
+
: mechanism;
|
|
514
|
+
return (
|
|
515
|
+
fenceToBody +
|
|
516
|
+
renderTaskBody({
|
|
517
|
+
whatToBuild: mechanism,
|
|
518
|
+
openQuestions,
|
|
519
|
+
prompt: promptSeed,
|
|
520
|
+
})
|
|
521
|
+
);
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
/**
|
|
525
|
+
* Split an observation's text into its mechanism/fix PROSE (before the first
|
|
526
|
+
* `## Open questions` heading) and its open-questions SCOPING (that section's
|
|
527
|
+
* body, up to the next `## ` heading or EOF). The frontmatter fence is dropped
|
|
528
|
+
* (the new task gets its own). When there is no `## Open questions` heading the
|
|
529
|
+
* whole body is mechanism and the scoping is empty.
|
|
530
|
+
*/
|
|
531
|
+
function splitObservationBody(observation: string): {
|
|
532
|
+
mechanism: string;
|
|
533
|
+
openQuestions: string;
|
|
534
|
+
} {
|
|
535
|
+
const body = stripFrontmatter(observation);
|
|
536
|
+
const lines = body.split('\n');
|
|
537
|
+
// Match `## Open questions` (and tolerant variants like
|
|
538
|
+
// `## Open questions to NOT guess` the capture-signal skill writes).
|
|
539
|
+
const startIdx = lines.findIndex((l) => /^##\s+Open questions\b/i.test(l));
|
|
540
|
+
if (startIdx === -1) {
|
|
541
|
+
return {mechanism: body, openQuestions: ''};
|
|
542
|
+
}
|
|
543
|
+
let endIdx = lines.length;
|
|
544
|
+
for (let i = startIdx + 1; i < lines.length; i++) {
|
|
545
|
+
if (/^##\s+/.test(lines[i])) {
|
|
546
|
+
endIdx = i;
|
|
547
|
+
break;
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
const mechanism = lines.slice(0, startIdx).join('\n');
|
|
551
|
+
const openQuestions = lines.slice(startIdx + 1, endIdx).join('\n');
|
|
552
|
+
return {mechanism, openQuestions};
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
/** Strip a leading `---\n…\n---` frontmatter fence, returning the body. */
|
|
556
|
+
function stripFrontmatter(content: string): string {
|
|
557
|
+
const normalized = content.replace(/\r\n/g, '\n').replace(/^\uFEFF/, '');
|
|
558
|
+
if (!normalized.startsWith('---\n')) {
|
|
559
|
+
return normalized;
|
|
560
|
+
}
|
|
561
|
+
const lines = normalized.split('\n');
|
|
562
|
+
const closing = lines.indexOf('---', 1);
|
|
563
|
+
if (closing === -1) {
|
|
564
|
+
return normalized;
|
|
565
|
+
}
|
|
566
|
+
return lines
|
|
567
|
+
.slice(closing + 1)
|
|
568
|
+
.join('\n')
|
|
569
|
+
.replace(/^\n+/, '');
|
|
570
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The SHARED "first JSON object in agent prose" extractor — the single
|
|
3
|
+
* implementation behind every prompt→verdict→dispatch seam in this package
|
|
4
|
+
* (the Gate-2 PR/code review gate and the task-SET acceptance gate in
|
|
5
|
+
* `review-gate.ts`, the tasker IMPROVER loop in `tasker-review-loop.ts`, and the
|
|
6
|
+
* issue-intake decision in `intake.ts`). Each of those launches an agent that
|
|
7
|
+
* EMITS a single JSON object (possibly fenced / wrapped in prose) and the runner
|
|
8
|
+
* pulls it back out to dispatch on it — the SAME need, so it is ONE extractor, not
|
|
9
|
+
* a forked copy per caller (coherence; task `intake-production-verdict-parse`).
|
|
10
|
+
*
|
|
11
|
+
* The only thing that varies between callers is the DISCRIMINATOR KEY they brace-
|
|
12
|
+
* match outward from: the review gates emit `{"verdict": …}`, intake emits
|
|
13
|
+
* `{"outcome": …}`. {@link extractJsonObjectSpan} takes that key as a parameter
|
|
14
|
+
* (defaulting to `"verdict"` so the review-gate callers read identically).
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Locate the first JSON object that carries a `"<key>"` field in arbitrary agent
|
|
19
|
+
* output (it may be fenced, prefixed with prose, or bare), returning its `[start,
|
|
20
|
+
* end)` span (`output.slice(start, end)` is the JSON). Brace-matched from the
|
|
21
|
+
* `"<key>"` occurrence OUTWARD (walk back to the enclosing `{`, then brace-match
|
|
22
|
+
* forward, respecting strings) so a surrounding fence / prose does not defeat
|
|
23
|
+
* parsing. Returns `undefined` when none is found.
|
|
24
|
+
*
|
|
25
|
+
* @param output the agent's raw textual output.
|
|
26
|
+
* @param key the discriminator field name to anchor on, WITHOUT quotes
|
|
27
|
+
* (defaults to `verdict`, the review gates' key; intake passes `outcome`).
|
|
28
|
+
*/
|
|
29
|
+
export function extractJsonObjectSpan(
|
|
30
|
+
output: string,
|
|
31
|
+
key = 'verdict',
|
|
32
|
+
): {start: number; end: number} | undefined {
|
|
33
|
+
const anchor = output.indexOf(`"${key}"`);
|
|
34
|
+
if (anchor === -1) {
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
// Walk back to the opening brace of the object containing the key.
|
|
38
|
+
let start = anchor;
|
|
39
|
+
while (start >= 0 && output[start] !== '{') {
|
|
40
|
+
start--;
|
|
41
|
+
}
|
|
42
|
+
if (start < 0) {
|
|
43
|
+
return undefined;
|
|
44
|
+
}
|
|
45
|
+
// Brace-match forward from that opening brace, respecting strings.
|
|
46
|
+
let depth = 0;
|
|
47
|
+
let inString = false;
|
|
48
|
+
let escaped = false;
|
|
49
|
+
for (let i = start; i < output.length; i++) {
|
|
50
|
+
const ch = output[i];
|
|
51
|
+
if (inString) {
|
|
52
|
+
if (escaped) {
|
|
53
|
+
escaped = false;
|
|
54
|
+
} else if (ch === '\\') {
|
|
55
|
+
escaped = true;
|
|
56
|
+
} else if (ch === '"') {
|
|
57
|
+
inString = false;
|
|
58
|
+
}
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
if (ch === '"') {
|
|
62
|
+
inString = true;
|
|
63
|
+
} else if (ch === '{') {
|
|
64
|
+
depth++;
|
|
65
|
+
} else if (ch === '}') {
|
|
66
|
+
depth--;
|
|
67
|
+
if (depth === 0) {
|
|
68
|
+
return {start, end: i + 1};
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return undefined;
|
|
73
|
+
}
|