ai-dev-workflow 0.3.0__tar.gz → 0.3.1__tar.gz
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.
- {ai_dev_workflow-0.3.0 → ai_dev_workflow-0.3.1}/PKG-INFO +181 -1
- {ai_dev_workflow-0.3.0 → ai_dev_workflow-0.3.1}/README.md +180 -0
- {ai_dev_workflow-0.3.0 → ai_dev_workflow-0.3.1}/pyproject.toml +5 -1
- {ai_dev_workflow-0.3.0 → ai_dev_workflow-0.3.1}/tests/test_ado_provider.py +31 -1
- {ai_dev_workflow-0.3.0 → ai_dev_workflow-0.3.1}/tests/test_ai_provider.py +17 -0
- ai_dev_workflow-0.3.1/tests/test_ai_workflow_cli.py +188 -0
- {ai_dev_workflow-0.3.0 → ai_dev_workflow-0.3.1}/tests/test_general_init.py +35 -1
- {ai_dev_workflow-0.3.0 → ai_dev_workflow-0.3.1}/tests/test_instruction_adapter.py +5 -0
- {ai_dev_workflow-0.3.0 → ai_dev_workflow-0.3.1}/tests/test_issue_publisher.py +31 -0
- ai_dev_workflow-0.3.1/tests/test_planning_approval.py +58 -0
- {ai_dev_workflow-0.3.0 → ai_dev_workflow-0.3.1}/tests/test_queue_dispatcher.py +45 -0
- {ai_dev_workflow-0.3.0 → ai_dev_workflow-0.3.1}/tests/test_setup_wizard.py +54 -3
- {ai_dev_workflow-0.3.0 → ai_dev_workflow-0.3.1}/tests/test_work_breakdown.py +17 -0
- ai_dev_workflow-0.3.1/tests/test_worker_presence.py +97 -0
- ai_dev_workflow-0.3.1/tests/test_worker_registry.py +191 -0
- ai_dev_workflow-0.3.1/tests/test_worker_runtime_manager.py +89 -0
- {ai_dev_workflow-0.3.0 → ai_dev_workflow-0.3.1}/tests/test_workflow_handoff.py +20 -0
- {ai_dev_workflow-0.3.0 → ai_dev_workflow-0.3.1}/tools/ado_provider.py +76 -0
- {ai_dev_workflow-0.3.0 → ai_dev_workflow-0.3.1}/tools/ai_dev_workflow.egg-info/PKG-INFO +181 -1
- {ai_dev_workflow-0.3.0 → ai_dev_workflow-0.3.1}/tools/ai_dev_workflow.egg-info/SOURCES.txt +7 -0
- {ai_dev_workflow-0.3.0 → ai_dev_workflow-0.3.1}/tools/ai_dev_workflow.egg-info/top_level.txt +4 -0
- {ai_dev_workflow-0.3.0 → ai_dev_workflow-0.3.1}/tools/ai_provider.py +9 -1
- {ai_dev_workflow-0.3.0 → ai_dev_workflow-0.3.1}/tools/ai_workflow_cli.py +1084 -47
- {ai_dev_workflow-0.3.0 → ai_dev_workflow-0.3.1}/tools/github_work_item_provider.py +9 -0
- {ai_dev_workflow-0.3.0 → ai_dev_workflow-0.3.1}/tools/instruction_adapter.py +5 -0
- {ai_dev_workflow-0.3.0 → ai_dev_workflow-0.3.1}/tools/issue_publisher.py +52 -4
- ai_dev_workflow-0.3.1/tools/planning_approval.py +60 -0
- {ai_dev_workflow-0.3.0 → ai_dev_workflow-0.3.1}/tools/setup_wizard.py +192 -32
- {ai_dev_workflow-0.3.0 → ai_dev_workflow-0.3.1}/tools/work_breakdown.py +18 -0
- {ai_dev_workflow-0.3.0 → ai_dev_workflow-0.3.1}/tools/work_item_provider.py +2 -0
- ai_dev_workflow-0.3.1/tools/worker_presence.py +167 -0
- {ai_dev_workflow-0.3.0 → ai_dev_workflow-0.3.1}/tools/worker_registry.py +160 -9
- ai_dev_workflow-0.3.1/tools/worker_runtime_manager.py +223 -0
- ai_dev_workflow-0.3.1/tools/worker_session.py +50 -0
- {ai_dev_workflow-0.3.0 → ai_dev_workflow-0.3.1}/tools/workflow_handoff.py +11 -0
- {ai_dev_workflow-0.3.0 → ai_dev_workflow-0.3.1}/tools/workflow_runtime.py +17 -1
- ai_dev_workflow-0.3.0/tests/test_ai_workflow_cli.py +0 -89
- ai_dev_workflow-0.3.0/tests/test_worker_registry.py +0 -93
- {ai_dev_workflow-0.3.0 → ai_dev_workflow-0.3.1}/setup.cfg +0 -0
- {ai_dev_workflow-0.3.0 → ai_dev_workflow-0.3.1}/tests/test_active_work_context.py +0 -0
- {ai_dev_workflow-0.3.0 → ai_dev_workflow-0.3.1}/tests/test_bootstrap_project.py +0 -0
- {ai_dev_workflow-0.3.0 → ai_dev_workflow-0.3.1}/tests/test_codespaces_environment.py +0 -0
- {ai_dev_workflow-0.3.0 → ai_dev_workflow-0.3.1}/tests/test_codex_cloud_executor.py +0 -0
- {ai_dev_workflow-0.3.0 → ai_dev_workflow-0.3.1}/tests/test_composite_work_item.py +0 -0
- {ai_dev_workflow-0.3.0 → ai_dev_workflow-0.3.1}/tests/test_connection_and_mcp.py +0 -0
- {ai_dev_workflow-0.3.0 → ai_dev_workflow-0.3.1}/tests/test_framework_update.py +0 -0
- {ai_dev_workflow-0.3.0 → ai_dev_workflow-0.3.1}/tests/test_package_install.py +0 -0
- {ai_dev_workflow-0.3.0 → ai_dev_workflow-0.3.1}/tests/test_planning_context.py +0 -0
- {ai_dev_workflow-0.3.0 → ai_dev_workflow-0.3.1}/tests/test_work_claim.py +0 -0
- {ai_dev_workflow-0.3.0 → ai_dev_workflow-0.3.1}/tests/test_workflow_runtime.py +0 -0
- {ai_dev_workflow-0.3.0 → ai_dev_workflow-0.3.1}/tools/active_work_context.py +0 -0
- {ai_dev_workflow-0.3.0 → ai_dev_workflow-0.3.1}/tools/ado_mcp.py +0 -0
- {ai_dev_workflow-0.3.0 → ai_dev_workflow-0.3.1}/tools/ai_dev_workflow.egg-info/dependency_links.txt +0 -0
- {ai_dev_workflow-0.3.0 → ai_dev_workflow-0.3.1}/tools/ai_dev_workflow.egg-info/entry_points.txt +0 -0
- {ai_dev_workflow-0.3.0 → ai_dev_workflow-0.3.1}/tools/ai_dev_workflow.egg-info/requires.txt +0 -0
- {ai_dev_workflow-0.3.0 → ai_dev_workflow-0.3.1}/tools/composite_work_item.py +0 -0
- {ai_dev_workflow-0.3.0 → ai_dev_workflow-0.3.1}/tools/framework_update.py +0 -0
- {ai_dev_workflow-0.3.0 → ai_dev_workflow-0.3.1}/tools/planning_context.py +0 -0
- {ai_dev_workflow-0.3.0 → ai_dev_workflow-0.3.1}/tools/setup_context.py +0 -0
- {ai_dev_workflow-0.3.0 → ai_dev_workflow-0.3.1}/tools/skill_registry.py +0 -0
- {ai_dev_workflow-0.3.0 → ai_dev_workflow-0.3.1}/tools/source_connection.py +0 -0
- {ai_dev_workflow-0.3.0 → ai_dev_workflow-0.3.1}/tools/work_claim.py +0 -0
- {ai_dev_workflow-0.3.0 → ai_dev_workflow-0.3.1}/tools/work_item_registry.py +0 -0
- {ai_dev_workflow-0.3.0 → ai_dev_workflow-0.3.1}/tools/worker_identity.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ai-dev-workflow
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.1
|
|
4
4
|
Summary: Provider-neutral AI-assisted development workflow and CLI
|
|
5
5
|
Author: vuthethienlong
|
|
6
6
|
Project-URL: Homepage, https://github.com/vuthethienlong/ai-dev-workflow
|
|
@@ -364,6 +364,26 @@ ai-workflow update
|
|
|
364
364
|
The first command upgrades the installed CLI package. The second migrates/updates the workflow installation in the current project.
|
|
365
365
|
|
|
366
366
|
|
|
367
|
+
## PM and architecture planning
|
|
368
|
+
|
|
369
|
+
Product planning and technical architecture are separate roles:
|
|
370
|
+
|
|
371
|
+
```text
|
|
372
|
+
Idea / chat
|
|
373
|
+
→ PMAgent
|
|
374
|
+
→ product Keep/Split/Merge proposal
|
|
375
|
+
→ human approval
|
|
376
|
+
→ ArchitectAgent
|
|
377
|
+
→ technical Spec / ADR / decomposition
|
|
378
|
+
→ approval for structural architecture changes
|
|
379
|
+
→ Ready Freeze
|
|
380
|
+
→ TesterAgent
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
PMAgent owns what/why: intent, value, scope, priority, product acceptance boundaries, Epic/Issue classification and product-level decomposition. ArchitectAgent owns how: technical boundaries, interfaces, data model, Spec/ADR, technical dependencies and execution decomposition.
|
|
384
|
+
|
|
385
|
+
By default `workflow.planning.approval_policy` is `always`. Create, Split, Merge, Re-parent and Ready Freeze require explicit approval before provider mutation, and frozen contracts cannot be silently changed.
|
|
386
|
+
|
|
367
387
|
## Active work and claims
|
|
368
388
|
|
|
369
389
|
A selected task is not considered started until its worker/provider acknowledges it:
|
|
@@ -380,8 +400,168 @@ ready/queued
|
|
|
380
400
|
Local agents acknowledge with the registered worker identity (for example through `ai-workflow claim`). Phase completion can be recorded with `ai-workflow complete-phase`, which releases the current claim and reserves an eligible worker for the next role. Automatic review always excludes the implementation worker_id; identity separation is enforced only when the optional strict-review policy is enabled.
|
|
381
401
|
|
|
382
402
|
|
|
403
|
+
## Azure DevOps configuration boundary
|
|
404
|
+
|
|
405
|
+
Azure DevOps project metadata and credentials are separate:
|
|
406
|
+
|
|
407
|
+
- project configuration owns organization/project, logical Epic/Issue Work Item Type mappings, and Area/Iteration defaults;
|
|
408
|
+
- worker configuration owns the Azure DevOps authentication strategy/credential reference;
|
|
409
|
+
- setup may borrow a worker credential temporarily to discover project metadata, but never persists the raw token;
|
|
410
|
+
- workers may share a credential reference when they intentionally act as the same ADO identity.
|
|
411
|
+
|
|
412
|
+
Area Path and Iteration Path options are discovered from the project's existing Azure DevOps classification nodes. Setup selects from existing values; it does not create or modify the project's classification hierarchy.
|
|
413
|
+
|
|
383
414
|
## Worker credentials and identity
|
|
384
415
|
|
|
385
416
|
Worker IDs and credentials are separate concepts. Several workers may intentionally use the same credential reference and therefore operate as the same GitHub/ADO actor. This is valid for normal planning, testing, implementation, and runtime work.
|
|
386
417
|
|
|
387
418
|
The workflow verifies effective actor identity where possible. A distinct credential is not required merely because workers are different. By default, ReviewerAgent only needs a different worker_id from the Implementer. Projects that require stronger separation may enable `reviewer.require_distinct_identity: true`.
|
|
419
|
+
|
|
420
|
+
|
|
421
|
+
## Local parallel workers
|
|
422
|
+
|
|
423
|
+
One local machine may register multiple workers that intentionally share the same GitHub/Azure DevOps credential sessions while using isolated working folders.
|
|
424
|
+
|
|
425
|
+
Example:
|
|
426
|
+
|
|
427
|
+
```yaml
|
|
428
|
+
workers:
|
|
429
|
+
- worker_id: codex-01
|
|
430
|
+
environment: local
|
|
431
|
+
provider: codex
|
|
432
|
+
workspace:
|
|
433
|
+
strategy: git-worktree
|
|
434
|
+
root: G:\ai-workers\codex-01
|
|
435
|
+
|
|
436
|
+
- worker_id: ccr-01
|
|
437
|
+
environment: local
|
|
438
|
+
provider: ccr
|
|
439
|
+
workspace:
|
|
440
|
+
strategy: git-worktree
|
|
441
|
+
root: G:\ai-workers\ccr-01
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
Add another local worker after initial setup:
|
|
445
|
+
|
|
446
|
+
```powershell
|
|
447
|
+
ai-workflow add-worker
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
or non-interactively:
|
|
451
|
+
|
|
452
|
+
```powershell
|
|
453
|
+
ai-workflow add-worker `
|
|
454
|
+
--worker-id codex-02 `
|
|
455
|
+
--provider codex `
|
|
456
|
+
--mode hybrid `
|
|
457
|
+
--workspace G:\ai-workers\codex-02 `
|
|
458
|
+
--workspace-strategy git-worktree
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
By default the new local worker inherits credential references from an existing local worker. It still receives its own `worker_id` and isolated workspace. Use `--no-inherit-credentials` when the worker must use a different identity.
|
|
462
|
+
|
|
463
|
+
At runtime, a local worker is resolved in this order:
|
|
464
|
+
|
|
465
|
+
1. explicit `--worker <id>`;
|
|
466
|
+
2. `AI_WORKFLOW_WORKER_ID`;
|
|
467
|
+
3. current working directory contained by one configured `workspace.root`.
|
|
468
|
+
|
|
469
|
+
This makes it possible to open separate terminals in separate worker folders and run tasks concurrently without repeating the worker ID.
|
|
470
|
+
|
|
471
|
+
## Claude Code Router local provider
|
|
472
|
+
|
|
473
|
+
Claude Code Router can be registered as a local provider:
|
|
474
|
+
|
|
475
|
+
```yaml
|
|
476
|
+
providers:
|
|
477
|
+
ccr:
|
|
478
|
+
type: claude-code-router
|
|
479
|
+
base_url: http://127.0.0.1:3456
|
|
480
|
+
auth:
|
|
481
|
+
type: none
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
The gateway defaults to `http://127.0.0.1:3456`. A client-key environment reference can be configured when the local router is protected. Claude Code Router uses the same `CLAUDE.md` instruction adapter as Claude Code, while `AGENTS.md` remains the shared workflow instruction source.
|
|
485
|
+
|
|
486
|
+
A local CCR worker can then be registered with its own workspace:
|
|
487
|
+
|
|
488
|
+
```powershell
|
|
489
|
+
ai-workflow add-worker `
|
|
490
|
+
--worker-id ccr-01 `
|
|
491
|
+
--provider ccr `
|
|
492
|
+
--workspace G:\ai-workers\ccr-01
|
|
493
|
+
```
|
|
494
|
+
|
|
495
|
+
|
|
496
|
+
### Step-by-step add-worker wizard
|
|
497
|
+
|
|
498
|
+
Running `ai-workflow add-worker` with no `--non-interactive` flag now opens a structured wizard:
|
|
499
|
+
|
|
500
|
+
1. review existing project/provider configuration;
|
|
501
|
+
2. choose a worker id;
|
|
502
|
+
3. choose planner/executor/hybrid mode;
|
|
503
|
+
4. choose an existing AI provider;
|
|
504
|
+
5. choose roles;
|
|
505
|
+
6. choose the local workspace folder;
|
|
506
|
+
7. choose `git-worktree` or `folder` workspace strategy;
|
|
507
|
+
8. choose whether to inherit an existing local worker's credential references or configure separate GitHub/ADO references;
|
|
508
|
+
9. choose skills and capacity;
|
|
509
|
+
10. review the final worker configuration and confirm before saving.
|
|
510
|
+
|
|
511
|
+
The wizard never stores raw tokens. It only stores credential strategies/references already supported by the worker identity model.
|
|
512
|
+
|
|
513
|
+
For scripting/automation, keep the deterministic flag-based flow:
|
|
514
|
+
|
|
515
|
+
```powershell
|
|
516
|
+
ai-workflow add-worker `
|
|
517
|
+
--non-interactive `
|
|
518
|
+
--worker-id codex-02 `
|
|
519
|
+
--provider codex `
|
|
520
|
+
--mode hybrid `
|
|
521
|
+
--roles "ArchitectAgent|TesterAgent|ImplementerAgent|ReviewerAgent" `
|
|
522
|
+
--workspace G:\ai-workers\codex-02 `
|
|
523
|
+
--workspace-strategy git-worktree
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
Use `--no-inherit-credentials` when the new worker must not reuse an existing local worker's credential references.
|
|
527
|
+
|
|
528
|
+
|
|
529
|
+
## Consumer worker registry and live presence
|
|
530
|
+
|
|
531
|
+
When a GitHub Issues or composite project has execution workers, setup writes:
|
|
532
|
+
|
|
533
|
+
```text
|
|
534
|
+
.github/ai-workflow-worker-registry.json
|
|
535
|
+
```
|
|
536
|
+
|
|
537
|
+
This committed registry contains routing metadata only:
|
|
538
|
+
|
|
539
|
+
- worker id;
|
|
540
|
+
- execution location;
|
|
541
|
+
- provider id;
|
|
542
|
+
- roles/capabilities;
|
|
543
|
+
- capacity;
|
|
544
|
+
- managed/unmanaged flag;
|
|
545
|
+
- GitHub assignee when required.
|
|
546
|
+
|
|
547
|
+
It intentionally excludes machine-local paths, machine ids, client launch commands, credential references, tokens, identities, heartbeat data, and active sessions.
|
|
548
|
+
|
|
549
|
+
For local execution workers, setup also creates or reuses one closed coordination Issue marked with:
|
|
550
|
+
|
|
551
|
+
```text
|
|
552
|
+
<!-- ai-dev-workflow:worker-presence -->
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
The Issue number is stored as project-level dispatcher metadata. Local workers publish the existing queue-dispatcher presence-v2 contract to that Issue using their own verified GitHub identity.
|
|
556
|
+
|
|
557
|
+
`ai-workflow worker open <worker-id>` keeps the local and central heartbeat alive while the configured Codex/Claude Code client process is running. When the client exits, the worker is reported offline.
|
|
558
|
+
|
|
559
|
+
For headless or daemon-style workers:
|
|
560
|
+
|
|
561
|
+
```powershell
|
|
562
|
+
ai-workflow worker serve <worker-id>
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
A worker keeps one presence comment and updates it on each heartbeat; it does not append a new comment every interval. The central dispatcher reads the consumer registry plus live presence before reserving work.
|
|
566
|
+
|
|
567
|
+
The consumer orchestration workflow remains `.github/workflows/ai-workflow.yml`. This integration does not install framework CI/check workflows, does not configure required status checks, and does not modify branch protection.
|
|
@@ -350,6 +350,26 @@ ai-workflow update
|
|
|
350
350
|
The first command upgrades the installed CLI package. The second migrates/updates the workflow installation in the current project.
|
|
351
351
|
|
|
352
352
|
|
|
353
|
+
## PM and architecture planning
|
|
354
|
+
|
|
355
|
+
Product planning and technical architecture are separate roles:
|
|
356
|
+
|
|
357
|
+
```text
|
|
358
|
+
Idea / chat
|
|
359
|
+
→ PMAgent
|
|
360
|
+
→ product Keep/Split/Merge proposal
|
|
361
|
+
→ human approval
|
|
362
|
+
→ ArchitectAgent
|
|
363
|
+
→ technical Spec / ADR / decomposition
|
|
364
|
+
→ approval for structural architecture changes
|
|
365
|
+
→ Ready Freeze
|
|
366
|
+
→ TesterAgent
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
PMAgent owns what/why: intent, value, scope, priority, product acceptance boundaries, Epic/Issue classification and product-level decomposition. ArchitectAgent owns how: technical boundaries, interfaces, data model, Spec/ADR, technical dependencies and execution decomposition.
|
|
370
|
+
|
|
371
|
+
By default `workflow.planning.approval_policy` is `always`. Create, Split, Merge, Re-parent and Ready Freeze require explicit approval before provider mutation, and frozen contracts cannot be silently changed.
|
|
372
|
+
|
|
353
373
|
## Active work and claims
|
|
354
374
|
|
|
355
375
|
A selected task is not considered started until its worker/provider acknowledges it:
|
|
@@ -366,8 +386,168 @@ ready/queued
|
|
|
366
386
|
Local agents acknowledge with the registered worker identity (for example through `ai-workflow claim`). Phase completion can be recorded with `ai-workflow complete-phase`, which releases the current claim and reserves an eligible worker for the next role. Automatic review always excludes the implementation worker_id; identity separation is enforced only when the optional strict-review policy is enabled.
|
|
367
387
|
|
|
368
388
|
|
|
389
|
+
## Azure DevOps configuration boundary
|
|
390
|
+
|
|
391
|
+
Azure DevOps project metadata and credentials are separate:
|
|
392
|
+
|
|
393
|
+
- project configuration owns organization/project, logical Epic/Issue Work Item Type mappings, and Area/Iteration defaults;
|
|
394
|
+
- worker configuration owns the Azure DevOps authentication strategy/credential reference;
|
|
395
|
+
- setup may borrow a worker credential temporarily to discover project metadata, but never persists the raw token;
|
|
396
|
+
- workers may share a credential reference when they intentionally act as the same ADO identity.
|
|
397
|
+
|
|
398
|
+
Area Path and Iteration Path options are discovered from the project's existing Azure DevOps classification nodes. Setup selects from existing values; it does not create or modify the project's classification hierarchy.
|
|
399
|
+
|
|
369
400
|
## Worker credentials and identity
|
|
370
401
|
|
|
371
402
|
Worker IDs and credentials are separate concepts. Several workers may intentionally use the same credential reference and therefore operate as the same GitHub/ADO actor. This is valid for normal planning, testing, implementation, and runtime work.
|
|
372
403
|
|
|
373
404
|
The workflow verifies effective actor identity where possible. A distinct credential is not required merely because workers are different. By default, ReviewerAgent only needs a different worker_id from the Implementer. Projects that require stronger separation may enable `reviewer.require_distinct_identity: true`.
|
|
405
|
+
|
|
406
|
+
|
|
407
|
+
## Local parallel workers
|
|
408
|
+
|
|
409
|
+
One local machine may register multiple workers that intentionally share the same GitHub/Azure DevOps credential sessions while using isolated working folders.
|
|
410
|
+
|
|
411
|
+
Example:
|
|
412
|
+
|
|
413
|
+
```yaml
|
|
414
|
+
workers:
|
|
415
|
+
- worker_id: codex-01
|
|
416
|
+
environment: local
|
|
417
|
+
provider: codex
|
|
418
|
+
workspace:
|
|
419
|
+
strategy: git-worktree
|
|
420
|
+
root: G:\ai-workers\codex-01
|
|
421
|
+
|
|
422
|
+
- worker_id: ccr-01
|
|
423
|
+
environment: local
|
|
424
|
+
provider: ccr
|
|
425
|
+
workspace:
|
|
426
|
+
strategy: git-worktree
|
|
427
|
+
root: G:\ai-workers\ccr-01
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
Add another local worker after initial setup:
|
|
431
|
+
|
|
432
|
+
```powershell
|
|
433
|
+
ai-workflow add-worker
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
or non-interactively:
|
|
437
|
+
|
|
438
|
+
```powershell
|
|
439
|
+
ai-workflow add-worker `
|
|
440
|
+
--worker-id codex-02 `
|
|
441
|
+
--provider codex `
|
|
442
|
+
--mode hybrid `
|
|
443
|
+
--workspace G:\ai-workers\codex-02 `
|
|
444
|
+
--workspace-strategy git-worktree
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
By default the new local worker inherits credential references from an existing local worker. It still receives its own `worker_id` and isolated workspace. Use `--no-inherit-credentials` when the worker must use a different identity.
|
|
448
|
+
|
|
449
|
+
At runtime, a local worker is resolved in this order:
|
|
450
|
+
|
|
451
|
+
1. explicit `--worker <id>`;
|
|
452
|
+
2. `AI_WORKFLOW_WORKER_ID`;
|
|
453
|
+
3. current working directory contained by one configured `workspace.root`.
|
|
454
|
+
|
|
455
|
+
This makes it possible to open separate terminals in separate worker folders and run tasks concurrently without repeating the worker ID.
|
|
456
|
+
|
|
457
|
+
## Claude Code Router local provider
|
|
458
|
+
|
|
459
|
+
Claude Code Router can be registered as a local provider:
|
|
460
|
+
|
|
461
|
+
```yaml
|
|
462
|
+
providers:
|
|
463
|
+
ccr:
|
|
464
|
+
type: claude-code-router
|
|
465
|
+
base_url: http://127.0.0.1:3456
|
|
466
|
+
auth:
|
|
467
|
+
type: none
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
The gateway defaults to `http://127.0.0.1:3456`. A client-key environment reference can be configured when the local router is protected. Claude Code Router uses the same `CLAUDE.md` instruction adapter as Claude Code, while `AGENTS.md` remains the shared workflow instruction source.
|
|
471
|
+
|
|
472
|
+
A local CCR worker can then be registered with its own workspace:
|
|
473
|
+
|
|
474
|
+
```powershell
|
|
475
|
+
ai-workflow add-worker `
|
|
476
|
+
--worker-id ccr-01 `
|
|
477
|
+
--provider ccr `
|
|
478
|
+
--workspace G:\ai-workers\ccr-01
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
|
|
482
|
+
### Step-by-step add-worker wizard
|
|
483
|
+
|
|
484
|
+
Running `ai-workflow add-worker` with no `--non-interactive` flag now opens a structured wizard:
|
|
485
|
+
|
|
486
|
+
1. review existing project/provider configuration;
|
|
487
|
+
2. choose a worker id;
|
|
488
|
+
3. choose planner/executor/hybrid mode;
|
|
489
|
+
4. choose an existing AI provider;
|
|
490
|
+
5. choose roles;
|
|
491
|
+
6. choose the local workspace folder;
|
|
492
|
+
7. choose `git-worktree` or `folder` workspace strategy;
|
|
493
|
+
8. choose whether to inherit an existing local worker's credential references or configure separate GitHub/ADO references;
|
|
494
|
+
9. choose skills and capacity;
|
|
495
|
+
10. review the final worker configuration and confirm before saving.
|
|
496
|
+
|
|
497
|
+
The wizard never stores raw tokens. It only stores credential strategies/references already supported by the worker identity model.
|
|
498
|
+
|
|
499
|
+
For scripting/automation, keep the deterministic flag-based flow:
|
|
500
|
+
|
|
501
|
+
```powershell
|
|
502
|
+
ai-workflow add-worker `
|
|
503
|
+
--non-interactive `
|
|
504
|
+
--worker-id codex-02 `
|
|
505
|
+
--provider codex `
|
|
506
|
+
--mode hybrid `
|
|
507
|
+
--roles "ArchitectAgent|TesterAgent|ImplementerAgent|ReviewerAgent" `
|
|
508
|
+
--workspace G:\ai-workers\codex-02 `
|
|
509
|
+
--workspace-strategy git-worktree
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
Use `--no-inherit-credentials` when the new worker must not reuse an existing local worker's credential references.
|
|
513
|
+
|
|
514
|
+
|
|
515
|
+
## Consumer worker registry and live presence
|
|
516
|
+
|
|
517
|
+
When a GitHub Issues or composite project has execution workers, setup writes:
|
|
518
|
+
|
|
519
|
+
```text
|
|
520
|
+
.github/ai-workflow-worker-registry.json
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
This committed registry contains routing metadata only:
|
|
524
|
+
|
|
525
|
+
- worker id;
|
|
526
|
+
- execution location;
|
|
527
|
+
- provider id;
|
|
528
|
+
- roles/capabilities;
|
|
529
|
+
- capacity;
|
|
530
|
+
- managed/unmanaged flag;
|
|
531
|
+
- GitHub assignee when required.
|
|
532
|
+
|
|
533
|
+
It intentionally excludes machine-local paths, machine ids, client launch commands, credential references, tokens, identities, heartbeat data, and active sessions.
|
|
534
|
+
|
|
535
|
+
For local execution workers, setup also creates or reuses one closed coordination Issue marked with:
|
|
536
|
+
|
|
537
|
+
```text
|
|
538
|
+
<!-- ai-dev-workflow:worker-presence -->
|
|
539
|
+
```
|
|
540
|
+
|
|
541
|
+
The Issue number is stored as project-level dispatcher metadata. Local workers publish the existing queue-dispatcher presence-v2 contract to that Issue using their own verified GitHub identity.
|
|
542
|
+
|
|
543
|
+
`ai-workflow worker open <worker-id>` keeps the local and central heartbeat alive while the configured Codex/Claude Code client process is running. When the client exits, the worker is reported offline.
|
|
544
|
+
|
|
545
|
+
For headless or daemon-style workers:
|
|
546
|
+
|
|
547
|
+
```powershell
|
|
548
|
+
ai-workflow worker serve <worker-id>
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
A worker keeps one presence comment and updates it on each heartbeat; it does not append a new comment every interval. The central dispatcher reads the consumer registry plus live presence before reserving work.
|
|
552
|
+
|
|
553
|
+
The consumer orchestration workflow remains `.github/workflows/ai-workflow.yml`. This integration does not install framework CI/check workflows, does not configure required status checks, and does not modify branch protection.
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "ai-dev-workflow"
|
|
7
|
-
version = "0.3.
|
|
7
|
+
version = "0.3.1"
|
|
8
8
|
description = "Provider-neutral AI-assisted development workflow and CLI"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -43,6 +43,7 @@ py-modules = [
|
|
|
43
43
|
"github_work_item_provider",
|
|
44
44
|
"instruction_adapter",
|
|
45
45
|
"issue_publisher",
|
|
46
|
+
"planning_approval",
|
|
46
47
|
"planning_context",
|
|
47
48
|
"setup_context",
|
|
48
49
|
"setup_wizard",
|
|
@@ -52,5 +53,8 @@ py-modules = [
|
|
|
52
53
|
"work_item_provider",
|
|
53
54
|
"work_item_registry",
|
|
54
55
|
"worker_identity",
|
|
56
|
+
"worker_presence",
|
|
55
57
|
"worker_registry",
|
|
58
|
+
"worker_runtime_manager",
|
|
59
|
+
"worker_session",
|
|
56
60
|
]
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import sys, unittest
|
|
2
2
|
from pathlib import Path
|
|
3
3
|
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "tools"))
|
|
4
|
-
from ado_provider import build_state_mapping, suggest_state, validate_mapping, available_fields
|
|
4
|
+
from ado_provider import build_state_mapping, suggest_state, validate_mapping, available_fields, flatten_classification_paths, validate_project_defaults
|
|
5
5
|
|
|
6
6
|
DISCOVERY={
|
|
7
7
|
"organization":"org","project":"proj","project_id":"p","process_id":"proc",
|
|
8
|
+
"area_paths":["proj","proj\\Backend"],
|
|
9
|
+
"iteration_paths":["proj","proj\\2026","proj\\2026\\Sprint 1"],
|
|
8
10
|
"work_item_types":[
|
|
9
11
|
{"name":"Bug","reference_name":"Custom.Bug","fields":[{"name":"AI Phase","reference_name":"Custom.AIPhase","type":"string","required":False,"read_only":False}],"states":[
|
|
10
12
|
{"name":"New","category":"Proposed","hidden":False},
|
|
@@ -19,6 +21,34 @@ DISCOVERY={
|
|
|
19
21
|
}
|
|
20
22
|
|
|
21
23
|
class Tests(unittest.TestCase):
|
|
24
|
+
def test_classification_tree_flattens_to_work_item_paths(self):
|
|
25
|
+
node={
|
|
26
|
+
"name":"Area",
|
|
27
|
+
"children":[
|
|
28
|
+
{"name":"Backend","children":[{"name":"API"}]},
|
|
29
|
+
{"name":"Frontend"},
|
|
30
|
+
],
|
|
31
|
+
}
|
|
32
|
+
self.assertEqual(
|
|
33
|
+
flatten_classification_paths(node,"proj"),
|
|
34
|
+
["proj","proj\\Backend","proj\\Backend\\API","proj\\Frontend"],
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
def test_project_defaults_validate_wit_area_and_iteration(self):
|
|
38
|
+
cfg={
|
|
39
|
+
"work_item_types":{"epic":"Custom.Bug","issue":"Custom.Bug"},
|
|
40
|
+
"defaults":{"area_path":"proj\\Backend","iteration_path":"proj\\2026\\Sprint 1"},
|
|
41
|
+
}
|
|
42
|
+
self.assertEqual(validate_project_defaults(DISCOVERY,cfg),[])
|
|
43
|
+
bad={
|
|
44
|
+
"work_item_types":{"epic":"Custom.Missing","issue":"Custom.Bug"},
|
|
45
|
+
"defaults":{"area_path":"proj\\Other","iteration_path":"proj\\Missing"},
|
|
46
|
+
}
|
|
47
|
+
errors=validate_project_defaults(DISCOVERY,bad)
|
|
48
|
+
self.assertTrue(any("Custom.Missing" in x for x in errors))
|
|
49
|
+
self.assertTrue(any("Area Path" in x for x in errors))
|
|
50
|
+
self.assertTrue(any("Iteration Path" in x for x in errors))
|
|
51
|
+
|
|
22
52
|
def test_name_and_category_suggestions(self):
|
|
23
53
|
self.assertEqual(suggest_state("Ready for Dev","Proposed"),"ready")
|
|
24
54
|
self.assertEqual(suggest_state("Code Review","InProgress"),"in-review")
|
|
@@ -16,6 +16,20 @@ class Tests(unittest.TestCase):
|
|
|
16
16
|
self.assertEqual(provider_template("local-openai-compatible",base_url="http://127.0.0.1:11434/v1")["auth"]["type"],"none")
|
|
17
17
|
self.assertEqual(provider_template("openai",model="gpt-5")["auth"]["type"],"api-key-env")
|
|
18
18
|
|
|
19
|
+
def test_claude_code_router_defaults_to_local_gateway(self):
|
|
20
|
+
cfg=provider_template("claude-code-router")
|
|
21
|
+
self.assertEqual(cfg["base_url"],"http://127.0.0.1:3456")
|
|
22
|
+
self.assertEqual(cfg["auth"]["type"],"none")
|
|
23
|
+
self.assertEqual(validate_provider("ccr",cfg),[])
|
|
24
|
+
|
|
25
|
+
def test_claude_code_router_can_use_client_key_env(self):
|
|
26
|
+
cfg=provider_template(
|
|
27
|
+
"claude-code-router",
|
|
28
|
+
auth_type="api-key-env",
|
|
29
|
+
env="CCR_CLIENT_KEY",
|
|
30
|
+
)
|
|
31
|
+
self.assertEqual(validate_provider("ccr",cfg),[])
|
|
32
|
+
|
|
19
33
|
def test_custom_and_litellm_require_base_url(self):
|
|
20
34
|
self.assertTrue(any("base_url" in e for e in validate_provider("x",provider_template("litellm"))))
|
|
21
35
|
cfg=provider_template("litellm",base_url="http://litellm:4000/v1",auth_type="bearer-env",env="LITELLM_API_KEY")
|
|
@@ -38,12 +52,15 @@ class Tests(unittest.TestCase):
|
|
|
38
52
|
"local=local-openai-compatible,base_url=http://host.docker.internal:11434/v1,model=qwen",
|
|
39
53
|
"litellm=litellm,base_url=http://litellm:4000/v1,auth=bearer-env,env=LITELLM_API_KEY",
|
|
40
54
|
"claude=anthropic,model=claude-sonnet,auth=api-key-env,env=ANTHROPIC_API_KEY",
|
|
55
|
+
"ccr=claude-code-router,model=sonnet",
|
|
41
56
|
])
|
|
42
57
|
self.assertIn("manual",providers)
|
|
43
58
|
self.assertIn("codex",providers)
|
|
44
59
|
self.assertEqual(providers["local"]["auth"]["type"],"none")
|
|
45
60
|
self.assertEqual(providers["litellm"]["auth"]["env"],"LITELLM_API_KEY")
|
|
46
61
|
self.assertEqual(providers["claude"]["type"],"anthropic")
|
|
62
|
+
self.assertEqual(providers["ccr"]["type"],"claude-code-router")
|
|
63
|
+
self.assertEqual(providers["ccr"]["base_url"],"http://127.0.0.1:3456")
|
|
47
64
|
|
|
48
65
|
def test_credentials_are_derived_from_auth_strategy(self):
|
|
49
66
|
providers={
|