@polymorphism-tech/morph-spec 7.5.0 → 7.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/bin/morph-spec.js +18 -0
- package/claude-plugin.json +1 -1
- package/docs/CHEATSHEET.md +1 -1
- package/docs/QUICKSTART.md +1 -1
- package/framework/CLAUDE.md +12 -4
- package/framework/MORPH.md +18 -10
- package/framework/agents.json +13 -5
- package/framework/commands/morph-preflight.md +10 -5
- package/framework/hooks/README.md +8 -10
- package/framework/hooks/claude-code/core/gate-guard.js +36 -16
- package/framework/hooks/claude-code/core/protect-spec-files.js +20 -5
- package/framework/hooks/claude-code/core/tasks-json-guard.js +81 -0
- package/framework/hooks/shared/tasks-validator.js +68 -0
- package/framework/mcp/registry.json +5 -48
- package/framework/rubrics/backend.json +3 -3
- package/framework/rubrics/default.json +3 -3
- package/framework/rubrics/frontend.json +3 -3
- package/framework/rules/infrastructure-standards.md +4 -4
- package/framework/skills/core/create-umbraco-lp/SKILL.md +22 -2
- package/framework/skills/core/migrate-lp-to-umbraco/SKILL.md +84 -5
- package/framework/skills/core/morph-apply/SKILL.md +53 -40
- package/framework/skills/core/morph-brainstorming/SKILL.md +7 -12
- package/framework/skills/core/morph-eval/SKILL.md +10 -8
- package/framework/skills/core/morph-implement/SKILL.md +27 -21
- package/framework/skills/core/morph-plan/SKILL.md +12 -21
- package/framework/skills/core/morph-proposal/SKILL.md +3 -8
- package/framework/skills/core/morph-review/SKILL.md +30 -14
- package/framework/skills/core/morph-stack-scan/SKILL.md +1 -1
- package/framework/skills/core/morph-standards/SKILL.md +1 -1
- package/framework/standards/STANDARDS.json +80 -8
- package/framework/standards/ai-agents/durable-workflows-hitl.md +191 -0
- package/framework/standards/ai-agents/rag-custom-pgvector.md +246 -243
- package/framework/standards/ai-agents/setup.md +3 -0
- package/framework/standards/ai-agents/vector-data-extensions.md +170 -0
- package/framework/standards/ai-agents/workflows.md +190 -187
- package/framework/standards/infrastructure/docker/{easypanel-deploy.md → coolify-deploy.md} +49 -20
- package/framework/standards/integration/mcp/mcp-tools.md +38 -43
- package/framework/templates/README.md +7 -7
- package/framework/templates/REGISTRY.json +14 -14
- package/framework/templates/context/CONTEXT.md +3 -3
- package/framework/templates/docs/proposal.md +2 -2
- package/framework/templates/frontend/nextjs/Dockerfile.nextjs.hbs +1 -1
- package/framework/templates/infrastructure/docker/coolify.template.json +49 -0
- package/framework/templates/infrastructure/github/README.md +6 -6
- package/framework/templates/infrastructure/github/workflows/deploy-coolify.yml.hbs +33 -0
- package/package.json +1 -1
- package/src/commands/project/doctor.js +36 -1
- package/src/commands/state/approve.js +29 -4
- package/src/commands/state/score.js +88 -0
- package/src/commands/tasks/dag.js +68 -0
- package/src/dashboard/scanner/rubrics-scanner.js +1 -1
- package/src/lib/generators/recap-generator.js +1 -1
- package/src/lib/tasks/dispatch-planner.js +201 -0
- package/src/lib/validators/score-aggregator.js +3 -3
- package/src/scripts/setup-infra.js +42 -0
- package/src/utils/agents-installer.js +142 -10
- package/src/utils/hooks-installer.js +13 -5
- package/framework/rubrics/eval-rubric.json +0 -66
- package/framework/templates/infrastructure/docker/easypanel.template.json +0 -46
- package/framework/templates/infrastructure/github/workflows/deploy-easypanel.yml.hbs +0 -31
|
@@ -1495,9 +1495,9 @@
|
|
|
1495
1495
|
"digest": "Vitest for unit tests, React Testing Library for component tests. Mock next/navigation with vi.mock. Test Server Actions with direct function calls. Use MSW for API mocking in component tests. Playwright for E2E tests against running app. Never test implementation details — test user behavior and output."
|
|
1496
1496
|
},
|
|
1497
1497
|
{
|
|
1498
|
-
"id": "infrastructure-docker-
|
|
1499
|
-
"name": "
|
|
1500
|
-
"path": "infrastructure/docker/
|
|
1498
|
+
"id": "infrastructure-docker-coolify-deploy",
|
|
1499
|
+
"name": "coolify deploy",
|
|
1500
|
+
"path": "infrastructure/docker/coolify-deploy.md",
|
|
1501
1501
|
"category": "infrastructure",
|
|
1502
1502
|
"subcategory": "docker",
|
|
1503
1503
|
"tags": [
|
|
@@ -1508,17 +1508,20 @@
|
|
|
1508
1508
|
"docker"
|
|
1509
1509
|
],
|
|
1510
1510
|
"aliases": [
|
|
1511
|
-
"
|
|
1511
|
+
"coolify",
|
|
1512
1512
|
"docker deploy",
|
|
1513
1513
|
"self-hosted",
|
|
1514
1514
|
"VPS deployment",
|
|
1515
|
-
"docker compose"
|
|
1515
|
+
"docker compose",
|
|
1516
|
+
"coolify api",
|
|
1517
|
+
"ssh deploy"
|
|
1516
1518
|
],
|
|
1517
1519
|
"anchors": {
|
|
1518
|
-
"setup": "#
|
|
1519
|
-
"deployment": "#zero-downtime-deploys"
|
|
1520
|
+
"setup": "#coolify-service-config",
|
|
1521
|
+
"deployment": "#zero-downtime-deploys",
|
|
1522
|
+
"ssh": "#triggering-a-deploy-via-ssh--api"
|
|
1520
1523
|
},
|
|
1521
|
-
"digest": "
|
|
1524
|
+
"digest": "Coolify is the self-hosted Docker PaaS. No MCP/CLI exists — all access is via SSH into the VPS, hitting the Coolify API at localhost:8000/api/v1 with a server-side token (never printed, never leaves the SSH session). Configure environment variables in Coolify UI/API — not in Dockerfile. Configure /health endpoint for health checks. HTTPS via Let's Encrypt automatic (Traefik). Redeploys trigger via GET /deploy?uuid={uuid} over SSH."
|
|
1522
1525
|
},
|
|
1523
1526
|
{
|
|
1524
1527
|
"id": "infrastructure-neon-setup",
|
|
@@ -1657,6 +1660,75 @@
|
|
|
1657
1660
|
"edit-workflows": "#iterative-editing-workflows"
|
|
1658
1661
|
},
|
|
1659
1662
|
"digest": "Guidelines for generating project images with Gemini Image MCP — prompt patterns, aspect ratios, design-system-aware prompts, iterative editing, and assets.md format."
|
|
1663
|
+
},
|
|
1664
|
+
{
|
|
1665
|
+
"id": "ai-agents-durable-workflows-hitl",
|
|
1666
|
+
"name": "durable workflows hitl",
|
|
1667
|
+
"path": "ai-agents/durable-workflows-hitl.md",
|
|
1668
|
+
"category": "ai-agents",
|
|
1669
|
+
"subcategory": null,
|
|
1670
|
+
"tags": [
|
|
1671
|
+
"ai-agents",
|
|
1672
|
+
"maf",
|
|
1673
|
+
"workflow",
|
|
1674
|
+
"durability"
|
|
1675
|
+
],
|
|
1676
|
+
"stacks": [
|
|
1677
|
+
"dotnet"
|
|
1678
|
+
],
|
|
1679
|
+
"aliases": [
|
|
1680
|
+
"durable workflow",
|
|
1681
|
+
"checkpoint",
|
|
1682
|
+
"checkpointing",
|
|
1683
|
+
"human in the loop",
|
|
1684
|
+
"hitl",
|
|
1685
|
+
"requestport",
|
|
1686
|
+
"requestinfoevent",
|
|
1687
|
+
"resume workflow",
|
|
1688
|
+
"long running workflow",
|
|
1689
|
+
"approval workflow",
|
|
1690
|
+
"icheckpointstore"
|
|
1691
|
+
],
|
|
1692
|
+
"anchors": {
|
|
1693
|
+
"when": "#quando-usar-este-standard",
|
|
1694
|
+
"hitl": "#human-in-the-loop-via-requestport",
|
|
1695
|
+
"checkpointing": "#checkpointing--durável-sem-depender-de-azure",
|
|
1696
|
+
"durable-task": "#azure-durable-task-extension--escape-hatch-not-default"
|
|
1697
|
+
},
|
|
1698
|
+
"digest": "HITL via RequestPort — a workflow node that pauses and waits for an external (human) response via RequestInfoEvent. Checkpointing is GA and Azure-free: CheckpointManager.CreateInMemory() for tests, CreateJson(FileSystemJsonCheckpointStore) for local-disk durability, or a custom ICheckpointStore (recommended against the project's own Postgres). Microsoft.Agents.AI.DurableTask (Azure Durable Task Scheduler) is documented as an escape hatch only, not adopted as default."
|
|
1699
|
+
},
|
|
1700
|
+
{
|
|
1701
|
+
"id": "ai-agents-vector-data-extensions",
|
|
1702
|
+
"name": "vector data extensions",
|
|
1703
|
+
"path": "ai-agents/vector-data-extensions.md",
|
|
1704
|
+
"category": "ai-agents",
|
|
1705
|
+
"subcategory": null,
|
|
1706
|
+
"tags": [
|
|
1707
|
+
"ai-agents",
|
|
1708
|
+
"maf",
|
|
1709
|
+
"rag",
|
|
1710
|
+
"vector-data"
|
|
1711
|
+
],
|
|
1712
|
+
"stacks": [
|
|
1713
|
+
"dotnet"
|
|
1714
|
+
],
|
|
1715
|
+
"aliases": [
|
|
1716
|
+
"microsoft extensions vectordata",
|
|
1717
|
+
"vectorstorecollection",
|
|
1718
|
+
"vector store abstraction",
|
|
1719
|
+
"data ingestion",
|
|
1720
|
+
"ingestion pipeline",
|
|
1721
|
+
"semantic kernel connectors exception",
|
|
1722
|
+
"pgvector connector",
|
|
1723
|
+
"vectorstorewriter"
|
|
1724
|
+
],
|
|
1725
|
+
"anchors": {
|
|
1726
|
+
"naming-trap": "#a-pegadinha-de-nomenclatura-crítico--leia-antes-de-tudo",
|
|
1727
|
+
"maturity": "#maturidade-atual-verificado-2026-07-06",
|
|
1728
|
+
"decision-matrix": "#decision-matrix--custom-pgvector-vs-vectordata",
|
|
1729
|
+
"data-ingestion": "#microsoftextensionsdataingestion-preview--pipeline-pattern-para-adoção-futura"
|
|
1730
|
+
},
|
|
1731
|
+
"digest": "Microsoft.Extensions.VectorData.Abstractions (GA) is the provider-agnostic vector-store abstraction; Microsoft.Extensions.DataIngestion (preview) is the companion ETL pipeline. Concrete connectors (Postgres, Qdrant, SQL Server...) ship under Microsoft.SemanticKernel.Connectors.* package names despite having nothing to do with Semantic Kernel — an explicit exception to ai-agents-setup's SK ban. Default RAG storage stays ai-agents-rag-custom-pgvector; adopt VectorData only for genuine multi-backend portability, since the Postgres connector is still prerelease."
|
|
1660
1732
|
}
|
|
1661
1733
|
],
|
|
1662
1734
|
"sharedAliases": {
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
# MAF Workflows — Checkpointing & Human-in-the-Loop
|
|
2
|
+
|
|
3
|
+
> **Scope:** stacks=["dotnet"]
|
|
4
|
+
> **Layer:** 1 (on-keyword)
|
|
5
|
+
> **Keywords:** durable workflow, checkpoint, checkpointing, human in the loop, hitl, requestport, requestinfoevent, resume workflow, long running workflow, approval workflow, icheckpointstore, filesystemjsoncheckpointstore
|
|
6
|
+
> **Read by Claude in:** plan (when `ai-agents-workflows` identifies a genuine HITL or long-running need) + implement (wiring `RequestPort` / `CheckpointManager`)
|
|
7
|
+
|
|
8
|
+
**Verified against:** Microsoft.Agents.AI 1.0 GA (`Microsoft.Agents.AI.Workflows` namespace) + Microsoft.Agents.AI.DurableTask (prerelease, Azure-coupled — documented as an escape hatch, not adopted as default). Last-verified: 2026-07-06.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Quando usar este standard
|
|
13
|
+
|
|
14
|
+
Read `ai-agents-sweet-spot` and `ai-agents-workflows` first. This standard applies only once `ai-agents-workflows` has justified a Workflow **and** the reason is one of:
|
|
15
|
+
|
|
16
|
+
- Long-running execution with a human-in-the-loop (HITL) approval step.
|
|
17
|
+
- A workflow whose state must survive a process restart (deploy, crash, restart) between steps.
|
|
18
|
+
|
|
19
|
+
If neither applies, a plain workflow (or no workflow at all — see `ai-agents-sweet-spot`) is enough; do not add checkpointing or `RequestPort` "just in case."
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Human-in-the-Loop via `RequestPort`
|
|
24
|
+
|
|
25
|
+
HITL is modeled with `RequestPort` — a special node in the workflow graph that pauses execution and waits for an external (human) response instead of processing automatically.
|
|
26
|
+
|
|
27
|
+
```csharp
|
|
28
|
+
using Microsoft.Agents.AI.Workflows;
|
|
29
|
+
|
|
30
|
+
// Request type the port sends out, response type it expects back.
|
|
31
|
+
RequestPort<ApprovalRequest, bool> approvalPort =
|
|
32
|
+
RequestPort.Create<ApprovalRequest, bool>("RefundApproval");
|
|
33
|
+
|
|
34
|
+
var workflow = new WorkflowBuilder(refundAnalyzerAgent)
|
|
35
|
+
.AddEdge(refundAnalyzerAgent, approvalPort)
|
|
36
|
+
.AddEdge(approvalPort, refundProcessorExecutor)
|
|
37
|
+
.WithOutputFrom(refundProcessorExecutor)
|
|
38
|
+
.Build();
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Running the workflow, the caller watches for `RequestInfoEvent` and sends the human's answer back — the framework routes the response to the executor that made the request:
|
|
42
|
+
|
|
43
|
+
```csharp
|
|
44
|
+
await using StreamingRun run = await InProcessExecution.RunStreamingAsync(workflow, input);
|
|
45
|
+
await foreach (WorkflowEvent evt in run.WatchStreamAsync())
|
|
46
|
+
{
|
|
47
|
+
switch (evt)
|
|
48
|
+
{
|
|
49
|
+
case RequestInfoEvent requestEvt:
|
|
50
|
+
// Surface requestEvt.Request to a human (dashboard, email, Slack, ...).
|
|
51
|
+
// This is where execution pauses until an external answer arrives.
|
|
52
|
+
bool approved = await GetHumanDecisionAsync(requestEvt.Request);
|
|
53
|
+
await run.SendResponseAsync(requestEvt.Request.CreateResponse(approved));
|
|
54
|
+
break;
|
|
55
|
+
|
|
56
|
+
case WorkflowOutputEvent outputEvt:
|
|
57
|
+
Console.WriteLine($"Workflow completed: {outputEvt.Data}");
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
**Agent tool-approval uses the same mechanism.** When an agent orchestration (sequential, concurrent, group chat) calls a tool marked as requiring approval, the workflow pauses and emits a `RequestInfoEvent` whose payload is a `ToolApprovalRequestContent` instead of a custom request type — no separate API to learn. See `ai-agents-multi-agent-patterns` for agent orchestration patterns this composes with.
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Checkpointing — durável sem depender de Azure
|
|
68
|
+
|
|
69
|
+
Checkpointing is part of the **base, GA** `Microsoft.Agents.AI.Workflows` namespace — no extra/preview package required. A checkpoint captures the full workflow state at each superstep boundary: executor state, pending messages, and pending `RequestPort` requests (so a pending approval survives a restore).
|
|
70
|
+
|
|
71
|
+
### Three storage options
|
|
72
|
+
|
|
73
|
+
| Store | Durability | When to use |
|
|
74
|
+
|-------|-----------|-------------|
|
|
75
|
+
| `CheckpointManager.CreateInMemory()` | In-process only, lost on restart | Tests, demos, short-lived workflows |
|
|
76
|
+
| `CheckpointManager.CreateJson(new FileSystemJsonCheckpointStore(dir))` | Local disk, survives process restart | Single-instance VPS deployments — no Azure, no preview package |
|
|
77
|
+
| Custom `ICheckpointStore` implementation | Whatever backend you implement it against | **Recommended for production** — implement against the project's own Neon Postgres table, matching the ownership model already used by `ai-agents-rag-custom-pgvector` |
|
|
78
|
+
|
|
79
|
+
```csharp
|
|
80
|
+
using Microsoft.Agents.AI.Workflows;
|
|
81
|
+
|
|
82
|
+
// Local-disk durability — no Azure dependency:
|
|
83
|
+
var checkpointFolder = Directory.CreateDirectory("./checkpoints");
|
|
84
|
+
CheckpointManager checkpointManager = CheckpointManager.CreateJson(
|
|
85
|
+
new FileSystemJsonCheckpointStore(checkpointFolder));
|
|
86
|
+
|
|
87
|
+
StreamingRun run = await InProcessExecution.RunStreamingAsync(workflow, input, checkpointManager);
|
|
88
|
+
await foreach (WorkflowEvent evt in run.WatchStreamAsync())
|
|
89
|
+
{
|
|
90
|
+
if (evt is SuperStepCompletedEvent stepEvt)
|
|
91
|
+
{
|
|
92
|
+
CheckpointInfo? checkpoint = stepEvt.CompletionInfo?.Checkpoint;
|
|
93
|
+
// Persist checkpoint.CheckpointId alongside the business record
|
|
94
|
+
// (e.g. the refund request row) so it can be resumed after a restart.
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Resuming after a restart — rehydrate into a **new** run instance from the last known checkpoint:
|
|
100
|
+
|
|
101
|
+
```csharp
|
|
102
|
+
StreamingRun resumedRun = await InProcessExecution.ResumeStreamingAsync(
|
|
103
|
+
newWorkflowInstance, savedCheckpoint, checkpointManager);
|
|
104
|
+
|
|
105
|
+
await foreach (WorkflowEvent evt in resumedRun.WatchStreamAsync())
|
|
106
|
+
{
|
|
107
|
+
// A pending RequestPort request is re-emitted here as a RequestInfoEvent —
|
|
108
|
+
// the paused approval survives the restart.
|
|
109
|
+
if (evt is RequestInfoEvent requestEvt) { /* re-surface to the human */ }
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Custom executor state
|
|
114
|
+
|
|
115
|
+
An executor with instance state beyond the message flow must opt in explicitly:
|
|
116
|
+
|
|
117
|
+
```csharp
|
|
118
|
+
internal sealed class RefundAnalyzerExecutor() : Executor("RefundAnalyzer")
|
|
119
|
+
{
|
|
120
|
+
private const string StateKey = "AnalysisHistory";
|
|
121
|
+
private List<string> _history = [];
|
|
122
|
+
|
|
123
|
+
protected override ValueTask OnCheckpointingAsync(IWorkflowContext context, CancellationToken ct = default)
|
|
124
|
+
=> context.QueueStateUpdateAsync(StateKey, _history);
|
|
125
|
+
|
|
126
|
+
protected override async ValueTask OnCheckpointRestoredAsync(IWorkflowContext context, CancellationToken ct = default)
|
|
127
|
+
=> _history = await context.ReadStateAsync<List<string>>(StateKey);
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### `ICheckpointStore` — Neon/Postgres-backed (recommended production pattern)
|
|
132
|
+
|
|
133
|
+
Implementing `ICheckpointStore` against the project's own Postgres database keeps checkpoint durability inside the same infrastructure the rest of the project already trusts (see `infrastructure-neon-setup`), instead of introducing a new storage dependency:
|
|
134
|
+
|
|
135
|
+
```csharp
|
|
136
|
+
public sealed class PostgresCheckpointStore(NpgsqlDataSource dataSource) : ICheckpointStore
|
|
137
|
+
{
|
|
138
|
+
// Persist/retrieve checkpoint blobs in a workflow_checkpoints table
|
|
139
|
+
// (workflow_id, checkpoint_id, payload jsonb/bytea, created_at).
|
|
140
|
+
// Implement per the ICheckpointStore contract — see Microsoft.Agents.AI.Workflows docs.
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
> **Security:** checkpoint storage is a trust boundary. Never restore a checkpoint from an untrusted or unauthenticated source — a tampered checkpoint can inject arbitrary workflow state.
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## Azure Durable Task extension — escape hatch, not default
|
|
149
|
+
|
|
150
|
+
`Microsoft.Agents.AI.DurableTask` (prerelease) adds durability backed by the **Azure Durable Task Scheduler**, including cost-efficient multi-day HITL waits with zero compute cost while paused. Even its "bring-your-own-compute / self-hosted" mode still requires a Durable Task Scheduler backend (`Microsoft.DurableTask.*.AzureManaged` packages) — self-hosted means your own worker process, not an Azure-free backend.
|
|
151
|
+
|
|
152
|
+
This framework deploys to VPS/Coolify by default and does not adopt Azure as a default dependency (see `ai-agents-setup` §3.4 on Azure OpenAI). For that reason, `Microsoft.Agents.AI.DurableTask` is **not adopted as default** here. The `CheckpointManager` + custom `ICheckpointStore` pattern above covers the same durability need without an Azure dependency. Only reach for the Durable Task extension when a specific client already runs on Azure and needs multi-day/serverless HITL waits — record that decision in `decisions.md`.
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## Anti-patterns
|
|
157
|
+
|
|
158
|
+
| Anti-pattern | Why it's wrong | Right way |
|
|
159
|
+
|--------------|----------------|-----------|
|
|
160
|
+
| Adding a `Workflow` with `RequestPort` but no `CheckpointManager` | A pending human approval is lost if the process restarts while waiting | Wire a persistent `CheckpointManager` (file-based or custom `ICheckpointStore`) whenever a HITL wait can outlive a single process lifetime |
|
|
161
|
+
| Reaching for `Microsoft.Agents.AI.DurableTask` by default | Adds an Azure Durable Task Scheduler dependency this framework's VPS-first stack doesn't otherwise need | Use base `CheckpointManager` + custom `ICheckpointStore`; reserve the Durable Task extension for projects already committed to Azure |
|
|
162
|
+
| Storing checkpoints in a public or unauthenticated location | Checkpoint storage is a trust boundary — a tampered checkpoint can inject arbitrary state on restore | Restrict read/write access to the checkpoint store the same way you would a secrets store |
|
|
163
|
+
| Skipping `OnCheckpointingAsync`/`OnCheckpointRestoredAsync` on an executor with instance state | State silently resets to defaults after a resume, corrupting workflow logic | Any executor with fields beyond the message flow must implement both methods |
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## Checklist (verifiable by morph-eval)
|
|
168
|
+
|
|
169
|
+
- [ ] `ai-agents-workflows`' HITL or long-running criterion is documented in `decisions.md` before this standard is applied.
|
|
170
|
+
- [ ] Every HITL wait point uses `RequestPort` + handles `RequestInfoEvent`.
|
|
171
|
+
- [ ] A `CheckpointManager` is wired whenever the workflow can pause across a process restart — `CreateInMemory()` is acceptable only for tests/demos.
|
|
172
|
+
- [ ] If a custom `ICheckpointStore` was implemented, it persists to infrastructure already owned by the project (e.g., Neon Postgres), not a new ad hoc store.
|
|
173
|
+
- [ ] Executors with instance state implement `OnCheckpointingAsync` and `OnCheckpointRestoredAsync`.
|
|
174
|
+
- [ ] `Microsoft.Agents.AI.DurableTask` is present only if the project already runs on Azure and the choice is recorded in `decisions.md`.
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## References
|
|
179
|
+
|
|
180
|
+
- `ai-agents-workflows` — when a Workflow (and therefore this standard) is justified
|
|
181
|
+
- `ai-agents-sweet-spot` — single agent vs workflow decision
|
|
182
|
+
- `ai-agents-multi-agent-patterns` — agent orchestrations that share the tool-approval HITL mechanism
|
|
183
|
+
- `ai-agents-setup` — the VPS-first, non-Azure-default stance this standard follows for durability
|
|
184
|
+
- `infrastructure-neon-setup` — Postgres connection patterns for a custom `ICheckpointStore`
|
|
185
|
+
- Human-in-the-loop (HITL) | Microsoft Learn: https://learn.microsoft.com/en-us/agent-framework/workflows/human-in-the-loop
|
|
186
|
+
- Checkpoints | Microsoft Learn: https://learn.microsoft.com/en-us/agent-framework/workflows/checkpoints
|
|
187
|
+
- Durable Extension | Microsoft Learn: https://learn.microsoft.com/en-us/agent-framework/integrations/durable-extension
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
*MORPH-SPEC by Polymorphism Tech — ai-agents/durable-workflows-hitl.md v1.0 (2026-07-06)*
|