specweave 1.0.464 → 1.0.466
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/plugins/specweave/lib/vendor/core/ac-test-validator-cli.d.ts +16 -0
- package/dist/plugins/specweave/lib/vendor/core/ac-test-validator-cli.js +139 -0
- package/dist/plugins/specweave/lib/vendor/core/ac-test-validator-cli.js.map +1 -0
- package/dist/plugins/specweave/lib/vendor/core/ac-test-validator.d.ts +111 -0
- package/dist/plugins/specweave/lib/vendor/core/ac-test-validator.js +304 -0
- package/dist/plugins/specweave/lib/vendor/core/ac-test-validator.js.map +1 -0
- package/dist/plugins/specweave/lib/vendor/core/increment/ac-status-manager.d.ts +115 -0
- package/dist/plugins/specweave/lib/vendor/core/increment/ac-status-manager.js +359 -0
- package/dist/plugins/specweave/lib/vendor/core/increment/ac-status-manager.js.map +1 -0
- package/dist/plugins/specweave/lib/vendor/core/increment/active-increment-manager.d.ts +121 -0
- package/dist/plugins/specweave/lib/vendor/core/increment/active-increment-manager.js +273 -0
- package/dist/plugins/specweave/lib/vendor/core/increment/active-increment-manager.js.map +1 -0
- package/dist/plugins/specweave/lib/vendor/core/increment/auto-transition-manager.d.ts +72 -0
- package/dist/plugins/specweave/lib/vendor/core/increment/auto-transition-manager.js +237 -0
- package/dist/plugins/specweave/lib/vendor/core/increment/auto-transition-manager.js.map +1 -0
- package/dist/plugins/specweave/lib/vendor/core/increment/duplicate-detector.d.ts +52 -0
- package/dist/plugins/specweave/lib/vendor/core/increment/duplicate-detector.js +281 -0
- package/dist/plugins/specweave/lib/vendor/core/increment/duplicate-detector.js.map +1 -0
- package/dist/plugins/specweave/lib/vendor/core/increment/metadata-manager.d.ts +278 -0
- package/dist/plugins/specweave/lib/vendor/core/increment/metadata-manager.js +925 -0
- package/dist/plugins/specweave/lib/vendor/core/increment/metadata-manager.js.map +1 -0
- package/dist/plugins/specweave/lib/vendor/core/increment/status-auto-transition.d.ts +113 -0
- package/dist/plugins/specweave/lib/vendor/core/increment/status-auto-transition.js +317 -0
- package/dist/plugins/specweave/lib/vendor/core/increment/status-auto-transition.js.map +1 -0
- package/dist/plugins/specweave/lib/vendor/core/types/increment-metadata.d.ts +442 -0
- package/dist/plugins/specweave/lib/vendor/core/types/increment-metadata.js +246 -0
- package/dist/plugins/specweave/lib/vendor/core/types/increment-metadata.js.map +1 -0
- package/dist/plugins/specweave/lib/vendor/core/universal-auto-create.d.ts +64 -0
- package/dist/plugins/specweave/lib/vendor/core/universal-auto-create.js +228 -0
- package/dist/plugins/specweave/lib/vendor/core/universal-auto-create.js.map +1 -0
- package/dist/plugins/specweave/lib/vendor/generators/spec/task-parser.d.ts +95 -0
- package/dist/plugins/specweave/lib/vendor/generators/spec/task-parser.js +300 -0
- package/dist/plugins/specweave/lib/vendor/generators/spec/task-parser.js.map +1 -0
- package/dist/plugins/specweave/lib/vendor/sync/config.d.ts +73 -0
- package/dist/plugins/specweave/lib/vendor/sync/config.js +132 -0
- package/dist/plugins/specweave/lib/vendor/sync/config.js.map +1 -0
- package/dist/plugins/specweave/lib/vendor/sync/github-reconciler.d.ts +163 -0
- package/dist/plugins/specweave/lib/vendor/sync/github-reconciler.js +898 -0
- package/dist/plugins/specweave/lib/vendor/sync/github-reconciler.js.map +1 -0
- package/dist/plugins/specweave/lib/vendor/sync/provider-router.d.ts +86 -0
- package/dist/plugins/specweave/lib/vendor/sync/provider-router.js +147 -0
- package/dist/plugins/specweave/lib/vendor/sync/provider-router.js.map +1 -0
- package/dist/plugins/specweave/lib/vendor/sync/status-mapper.d.ts +120 -0
- package/dist/plugins/specweave/lib/vendor/sync/status-mapper.js +164 -0
- package/dist/plugins/specweave/lib/vendor/sync/status-mapper.js.map +1 -0
- package/dist/plugins/specweave/lib/vendor/utils/auth-helpers.d.ts +151 -0
- package/dist/plugins/specweave/lib/vendor/utils/auth-helpers.js +359 -0
- package/dist/plugins/specweave/lib/vendor/utils/auth-helpers.js.map +1 -0
- package/dist/plugins/specweave/lib/vendor/utils/chalk-fallback.d.ts +38 -0
- package/dist/plugins/specweave/lib/vendor/utils/chalk-fallback.js +118 -0
- package/dist/plugins/specweave/lib/vendor/utils/chalk-fallback.js.map +1 -0
- package/dist/plugins/specweave/lib/vendor/utils/clean-env.d.ts +47 -0
- package/dist/plugins/specweave/lib/vendor/utils/clean-env.js +63 -0
- package/dist/plugins/specweave/lib/vendor/utils/clean-env.js.map +1 -0
- package/dist/plugins/specweave/lib/vendor/utils/credential-masker.d.ts +118 -0
- package/dist/plugins/specweave/lib/vendor/utils/credential-masker.js +275 -0
- package/dist/plugins/specweave/lib/vendor/utils/credential-masker.js.map +1 -0
- package/dist/plugins/specweave/lib/vendor/utils/execFileNoThrow.d.ts +99 -0
- package/dist/plugins/specweave/lib/vendor/utils/execFileNoThrow.js +149 -0
- package/dist/plugins/specweave/lib/vendor/utils/execFileNoThrow.js.map +1 -0
- package/dist/plugins/specweave/lib/vendor/utils/feature-id-derivation.d.ts +63 -0
- package/dist/plugins/specweave/lib/vendor/utils/feature-id-derivation.js +85 -0
- package/dist/plugins/specweave/lib/vendor/utils/feature-id-derivation.js.map +1 -0
- package/dist/plugins/specweave/lib/vendor/utils/fs-native.d.ts +219 -0
- package/dist/plugins/specweave/lib/vendor/utils/fs-native.js +397 -0
- package/dist/plugins/specweave/lib/vendor/utils/fs-native.js.map +1 -0
- package/dist/plugins/specweave/lib/vendor/utils/logger.d.ts +56 -0
- package/dist/plugins/specweave/lib/vendor/utils/logger.js +123 -0
- package/dist/plugins/specweave/lib/vendor/utils/logger.js.map +1 -0
- package/dist/plugins/specweave/lib/vendor/utils/translation.d.ts +187 -0
- package/dist/plugins/specweave/lib/vendor/utils/translation.js +414 -0
- package/dist/plugins/specweave/lib/vendor/utils/translation.js.map +1 -0
- package/dist/plugins/specweave-ado/lib/ado-ac-checkbox-sync.js +1 -1
- package/dist/plugins/specweave-ado/lib/ado-ac-checkbox-sync.js.map +1 -1
- package/dist/plugins/specweave-ado/lib/ado-spec-sync.js +1 -1
- package/dist/plugins/specweave-ado/lib/ado-spec-sync.js.map +1 -1
- package/dist/plugins/specweave-github/lib/github-ac-checkbox-sync.js +2 -2
- package/dist/plugins/specweave-github/lib/github-ac-checkbox-sync.js.map +1 -1
- package/dist/plugins/specweave-github/lib/github-feature-sync.d.ts.map +1 -1
- package/dist/plugins/specweave-github/lib/github-feature-sync.js +13 -4
- package/dist/plugins/specweave-github/lib/github-feature-sync.js.map +1 -1
- package/dist/plugins/specweave-jira/lib/jira-ac-checkbox-sync.js +1 -1
- package/dist/plugins/specweave-jira/lib/jira-ac-checkbox-sync.js.map +1 -1
- package/dist/plugins/specweave-jira/lib/jira-spec-sync.js +1 -1
- package/dist/plugins/specweave-jira/lib/jira-spec-sync.js.map +1 -1
- package/dist/src/sync/spec-to-living-docs-sync.js +1 -1
- package/dist/src/sync/spec-to-living-docs-sync.js.map +1 -1
- package/package.json +1 -1
- package/plugins/specweave/lib/vendor/utils/auth-helpers.d.ts +151 -0
- package/plugins/specweave/lib/vendor/utils/auth-helpers.js +359 -0
- package/plugins/specweave/lib/vendor/utils/auth-helpers.js.map +1 -0
- package/plugins/specweave/skills/team-lead/SKILL.md +150 -56
- package/plugins/specweave/skills/team-lead/agents/backend.md +13 -9
- package/plugins/specweave/skills/team-lead/agents/database.md +13 -9
- package/plugins/specweave/skills/team-lead/agents/frontend.md +12 -8
- package/plugins/specweave/skills/team-lead/agents/security.md +13 -9
- package/plugins/specweave/skills/team-lead/agents/testing.md +12 -8
- package/plugins/specweave-ado/lib/ado-ac-checkbox-sync.js +1 -1
- package/plugins/specweave-ado/lib/ado-ac-checkbox-sync.ts +1 -1
- package/plugins/specweave-ado/lib/ado-spec-sync.js +1 -1
- package/plugins/specweave-ado/lib/ado-spec-sync.ts +1 -1
- package/plugins/specweave-github/lib/github-ac-checkbox-sync.js +1 -1
- package/plugins/specweave-github/lib/github-ac-checkbox-sync.ts +2 -2
- package/plugins/specweave-github/lib/github-feature-sync.js +11 -3
- package/plugins/specweave-github/lib/github-feature-sync.ts +13 -4
- package/plugins/specweave-jira/lib/jira-ac-checkbox-sync.js +1 -1
- package/plugins/specweave-jira/lib/jira-ac-checkbox-sync.ts +1 -1
- package/plugins/specweave-jira/lib/jira-spec-sync.js +1 -1
- package/plugins/specweave-jira/lib/jira-spec-sync.ts +1 -1
|
@@ -314,11 +314,17 @@ Analyze domains
|
|
|
314
314
|
|
|
315
315
|
## 3b. Plan Review Workflow
|
|
316
316
|
|
|
317
|
-
The team lead
|
|
317
|
+
The team lead reviews agent plans **asynchronously**. Agents do NOT wait for approval — they proceed to implementation immediately after creating plans and sending a notification.
|
|
318
318
|
|
|
319
|
-
### Why Review
|
|
319
|
+
### Why Async Review
|
|
320
320
|
|
|
321
|
-
|
|
321
|
+
The previous blocking PLAN_READY/PLAN_APPROVED handshake caused sessions to freeze:
|
|
322
|
+
- When 3-5 Phase 2 agents spawned simultaneously, they ALL blocked waiting for approval
|
|
323
|
+
- Team-lead had to review each plan sequentially while all agents sat idle
|
|
324
|
+
- If team-lead was processing another message (or in extended thinking), agents waited indefinitely
|
|
325
|
+
- In tmux/iTerm2, this appeared as a completely frozen session
|
|
326
|
+
|
|
327
|
+
Async review eliminates the bottleneck: agents proceed immediately, and the team-lead only intervenes when something is wrong.
|
|
322
328
|
|
|
323
329
|
### Permission Mode: bypassPermissions (CRITICAL)
|
|
324
330
|
|
|
@@ -330,56 +336,56 @@ Without review, agents may duplicate work across domains, misinterpret scope, ma
|
|
|
330
336
|
|
|
331
337
|
**NEVER use `mode: "plan"` for agent spawns** — it causes agents to block on the trust-folder prompt.
|
|
332
338
|
|
|
333
|
-
### Protocol (
|
|
334
|
-
|
|
335
|
-
Since agents use `bypassPermissions` (not `plan` mode), plan review uses an explicit SendMessage protocol:
|
|
339
|
+
### Protocol (Async Notify + Correct)
|
|
336
340
|
|
|
337
341
|
**Agent side** (built into every agent prompt template):
|
|
338
342
|
1. Read the increment spec and explore the codebase
|
|
339
343
|
2. Create plan files (spec.md, plan.md, tasks.md) in the increment directory
|
|
340
|
-
3. Send plan
|
|
344
|
+
3. Send a structured plan notification to team-lead:
|
|
341
345
|
```
|
|
342
346
|
SendMessage({
|
|
343
347
|
type: "message",
|
|
344
348
|
recipient: "team-lead",
|
|
345
|
-
content: "PLAN_READY: Created
|
|
346
|
-
summary: "Plan ready
|
|
349
|
+
content: "PLAN_READY: Created .specweave/increments/[ID]/\nTasks: [count]\nACs covered: [list AC-IDs]\nKey decisions: [1-2 sentence summary]\nFiles to create/modify: [file list]\nArchitecture: [pattern/approach chosen]",
|
|
350
|
+
summary: "Plan ready — proceeding to implementation"
|
|
347
351
|
});
|
|
348
352
|
```
|
|
349
|
-
4. **
|
|
353
|
+
4. **Proceed to implementation IMMEDIATELY.** Do NOT wait for any response.
|
|
354
|
+
5. If team-lead sends `PLAN_CORRECTION`, pause current work, revise the plan, and continue.
|
|
350
355
|
|
|
351
356
|
**Team-lead side**:
|
|
352
|
-
1. Receive `PLAN_READY`
|
|
353
|
-
2.
|
|
354
|
-
3.
|
|
355
|
-
-
|
|
356
|
-
-
|
|
357
|
-
-
|
|
358
|
-
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
```
|
|
363
|
-
//
|
|
357
|
+
1. Receive `PLAN_READY` notification from agent
|
|
358
|
+
2. Review using the **structured summary in the message** (do NOT read full plan files unless a concern is detected)
|
|
359
|
+
3. Quick-evaluate:
|
|
360
|
+
- Do the covered ACs match what this agent should handle?
|
|
361
|
+
- Are the files within this agent's ownership boundaries?
|
|
362
|
+
- Do any key decisions conflict with other agents' plans?
|
|
363
|
+
- Is the task count reasonable (<15)?
|
|
364
|
+
4. If plan looks good: **do nothing** — agent is already implementing
|
|
365
|
+
5. If plan has issues: send correction:
|
|
366
|
+
|
|
367
|
+
```
|
|
368
|
+
// Correct a plan issue (agent is already implementing)
|
|
364
369
|
SendMessage({
|
|
365
370
|
type: "message",
|
|
366
371
|
recipient: "database-agent",
|
|
367
|
-
content: "
|
|
368
|
-
summary: "Plan
|
|
369
|
-
});
|
|
370
|
-
|
|
371
|
-
// Reject with feedback
|
|
372
|
-
SendMessage({
|
|
373
|
-
type: "message",
|
|
374
|
-
recipient: "database-agent",
|
|
375
|
-
content: "PLAN_REJECTED: Revise: 1) Add index on user_id for sessions. 2) Missing migration for AC-US1-03.",
|
|
376
|
-
summary: "Plan needs revision"
|
|
372
|
+
content: "PLAN_CORRECTION: 1) Add index on user_id for sessions. 2) You're missing AC-US1-03 — add a task for it. Pause current work and revise before continuing.",
|
|
373
|
+
summary: "Plan needs correction"
|
|
377
374
|
});
|
|
378
375
|
```
|
|
376
|
+
6. If agent ignores `PLAN_CORRECTION` (continues without revising after 2 turns):
|
|
377
|
+
```
|
|
378
|
+
SendMessage({ type: "shutdown_request", recipient: "database-agent" });
|
|
379
|
+
// Report to user: "Agent ignored correction, shutting down. Manual intervention needed."
|
|
380
|
+
```
|
|
379
381
|
|
|
380
|
-
###
|
|
382
|
+
### Review Priorities
|
|
381
383
|
|
|
382
|
-
|
|
384
|
+
Not all plans need deep review. Prioritize:
|
|
385
|
+
- **Phase 1 (upstream) plans** — errors here cascade to all downstream agents
|
|
386
|
+
- **Plans with >10 tasks** — higher risk of scope creep
|
|
387
|
+
- **Plans touching shared files** — ownership conflicts
|
|
388
|
+
- **Single-agent teams** — skip review entirely (no coordination needed)
|
|
383
389
|
|
|
384
390
|
### Multi-Increment Consideration
|
|
385
391
|
|
|
@@ -482,8 +488,11 @@ Agents communicate contract readiness, blocking issues, and completion status us
|
|
|
482
488
|
| Prefix | Purpose | Sender | Receiver |
|
|
483
489
|
|--------|---------|--------|----------|
|
|
484
490
|
| `CONTRACT_READY:` | Upstream contract is published | Upstream agent | team-lead (broadcasts to downstream) |
|
|
491
|
+
| `PLAN_READY:` | Plan created, agent proceeding to implementation | Any agent | team-lead (async review) |
|
|
492
|
+
| `STATUS:` | Heartbeat — task progress update | Any agent | team-lead (stuck detection) |
|
|
485
493
|
| `BLOCKING_ISSUE:` | Agent is stuck, needs help | Any agent | team-lead |
|
|
486
494
|
| `COMPLETION:` | Agent finished all tasks | Any agent | team-lead |
|
|
495
|
+
| `PLAN_CORRECTION:` | Plan needs revision (async) | team-lead | Specific agent |
|
|
487
496
|
|
|
488
497
|
### Message Examples
|
|
489
498
|
|
|
@@ -496,6 +505,22 @@ SendMessage({
|
|
|
496
505
|
summary: "Shared types contract ready"
|
|
497
506
|
});
|
|
498
507
|
|
|
508
|
+
// Agent notifies plan is ready (does NOT wait for response)
|
|
509
|
+
SendMessage({
|
|
510
|
+
type: "message",
|
|
511
|
+
recipient: "team-lead",
|
|
512
|
+
content: "PLAN_READY: Created .specweave/increments/0202-checkout-backend/\nTasks: 8\nACs covered: AC-US1-01, AC-US1-02, AC-US2-01\nKey decisions: REST API with Express, JWT auth middleware\nFiles: src/api/checkout.ts, src/services/payment.ts, src/middleware/auth.ts\nArchitecture: Controller-Service-Repository pattern",
|
|
513
|
+
summary: "Backend plan ready — proceeding to implementation"
|
|
514
|
+
});
|
|
515
|
+
|
|
516
|
+
// Agent heartbeat after each task completion
|
|
517
|
+
SendMessage({
|
|
518
|
+
type: "message",
|
|
519
|
+
recipient: "team-lead",
|
|
520
|
+
content: "STATUS: T-003/8 complete. Next: T-004 (implement payment service). Tests: 12/12 passing.",
|
|
521
|
+
summary: "Backend agent: task 3 of 8 done"
|
|
522
|
+
});
|
|
523
|
+
|
|
499
524
|
// Agent reports a blocking issue
|
|
500
525
|
SendMessage({
|
|
501
526
|
type: "message",
|
|
@@ -511,6 +536,14 @@ SendMessage({
|
|
|
511
536
|
content: "COMPLETION: All 8 tasks done. Tests passing (24/24). Ready for team-lead closure.",
|
|
512
537
|
summary: "Frontend agent completed all tasks"
|
|
513
538
|
});
|
|
539
|
+
|
|
540
|
+
// Team-lead sends async plan correction (agent is already implementing)
|
|
541
|
+
SendMessage({
|
|
542
|
+
type: "message",
|
|
543
|
+
recipient: "database-agent",
|
|
544
|
+
content: "PLAN_CORRECTION: 1) Add index on user_id for sessions table. 2) Missing AC-US1-03 — add a migration task. Pause and revise.",
|
|
545
|
+
summary: "Plan correction for database agent"
|
|
546
|
+
});
|
|
514
547
|
```
|
|
515
548
|
|
|
516
549
|
---
|
|
@@ -528,7 +561,7 @@ TeamCreate({
|
|
|
528
561
|
|
|
529
562
|
### Step 2: Spawn Upstream Agents (Phase 1)
|
|
530
563
|
|
|
531
|
-
All agents are spawned with `mode: "bypassPermissions"` to prevent blocking on trust-folder prompts.
|
|
564
|
+
All agents are spawned with `mode: "bypassPermissions"` to prevent blocking on trust-folder prompts. Agents notify team-lead of their plans via PLAN_READY but proceed to implementation immediately (see Section 3b for async review protocol).
|
|
532
565
|
|
|
533
566
|
For each agent: **Read the agent definition file** (see Section 4 reference table), replace placeholders (`[INCREMENT_ID]`, `[MASTER_INCREMENT_PATH]`, `{ORG}`, `{repo-name}`), and use the full content as the Task() prompt.
|
|
534
567
|
|
|
@@ -598,15 +631,39 @@ Agent Workflow:
|
|
|
598
631
|
|
|
599
632
|
**Why agents don't run /sw:done**: The /sw:done skill invokes 4 sub-skills (grill, judge-llm, sync-docs, qa), each loading a full SKILL.md. After 15+ tasks of auto-mode context, this pushes agents into extended thinking (30+ min hangs). Centralizing closure on the team-lead (which has a cleaner context) avoids this.
|
|
600
633
|
|
|
601
|
-
###
|
|
634
|
+
### Active Phase Rules (CRITICAL — While Agents Are Implementing)
|
|
635
|
+
|
|
636
|
+
**During the active phase (between spawning agents and receiving ALL COMPLETION signals), the team-lead MUST NOT run any closure operations.**
|
|
602
637
|
|
|
603
|
-
|
|
638
|
+
```
|
|
639
|
+
ALLOWED during active phase:
|
|
640
|
+
✓ Process SendMessage from agents (PLAN_READY, STATUS, CONTRACT_READY, BLOCKING_ISSUE, COMPLETION)
|
|
641
|
+
✓ Async plan review (read PLAN_READY summaries, send PLAN_CORRECTION if needed)
|
|
642
|
+
✓ Track heartbeat STATUS per agent for stuck detection
|
|
643
|
+
✓ Respond to BLOCKING_ISSUE messages
|
|
644
|
+
✓ Send STATUS_CHECK to silent agents
|
|
645
|
+
✓ Shutdown stuck agents
|
|
646
|
+
|
|
647
|
+
FORBIDDEN during active phase:
|
|
648
|
+
✗ Run /sw:grill on any increment
|
|
649
|
+
✗ Run /sw:done on any increment
|
|
650
|
+
✗ Invoke any closure-related skills (judge-llm, sync-docs, qa)
|
|
651
|
+
✗ Read full plan/spec files (use PLAN_READY summaries instead)
|
|
652
|
+
```
|
|
653
|
+
|
|
654
|
+
**Why**: Closure loads 4+ skill definitions into context. Running it while agents are active causes the orchestrator to enter extended thinking (30+ min) and stop responding to agent messages — freezing the entire session.
|
|
655
|
+
|
|
656
|
+
### Orchestrator Quality Gate — Closure Phase (After ALL Agents Complete)
|
|
657
|
+
|
|
658
|
+
**Closure begins ONLY after ALL agents have signaled COMPLETION (or been declared stuck).**
|
|
659
|
+
|
|
660
|
+
The team-lead runs closure **centrally** for each increment, sequentially in dependency order.
|
|
604
661
|
|
|
605
662
|
**CRITICAL: Increments MUST be closed sequentially, not skipped on failure.**
|
|
606
663
|
|
|
607
664
|
```
|
|
608
|
-
|
|
609
|
-
1.
|
|
665
|
+
Closure Phase (triggered when all COMPLETION signals received):
|
|
666
|
+
1. Verify: all agents signaled COMPLETION (or declared stuck)
|
|
610
667
|
2. No unresolved BLOCKING_ISSUE messages
|
|
611
668
|
3. Run full test suite (all domains combined)
|
|
612
669
|
4. For EACH increment in dependency order (shared → database → backend → frontend → testing → security):
|
|
@@ -655,34 +712,56 @@ Orchestrator Final Check:
|
|
|
655
712
|
|
|
656
713
|
---
|
|
657
714
|
|
|
658
|
-
## 8b. Agent Timeout and Stuck Detection
|
|
715
|
+
## 8b. Agent Timeout and Stuck Detection (Heartbeat-Based)
|
|
716
|
+
|
|
717
|
+
Agents send `STATUS: T-{N}/{total}` heartbeat messages after each task completion. The team-lead uses these to detect stuck agents proactively.
|
|
659
718
|
|
|
660
|
-
|
|
719
|
+
### Heartbeat Tracking
|
|
720
|
+
|
|
721
|
+
The team-lead maintains a mental log of the last STATUS received from each agent:
|
|
722
|
+
|
|
723
|
+
```
|
|
724
|
+
Agent Heartbeat Log (example):
|
|
725
|
+
backend-agent: STATUS T-003/8 (last seen: 2 turns ago)
|
|
726
|
+
frontend-agent: STATUS T-005/12 (last seen: this turn)
|
|
727
|
+
database-agent: COMPLETION (done)
|
|
728
|
+
testing-agent: STATUS T-001/6 (last seen: 4 turns ago) ← STUCK?
|
|
729
|
+
```
|
|
661
730
|
|
|
662
731
|
### Stuck Detection Rules
|
|
663
732
|
|
|
664
|
-
**Note**: Claude Code has no built-in timers.
|
|
733
|
+
**Note**: Claude Code has no built-in timers. Heartbeats are tracked relative to team-lead turns (each time the orchestrator processes messages).
|
|
665
734
|
|
|
666
735
|
| Condition | Action |
|
|
667
736
|
|-----------|--------|
|
|
668
|
-
| Agent
|
|
669
|
-
|
|
|
670
|
-
|
|
|
737
|
+
| Agent sent STATUS within last 2 team-lead turns | Healthy — no action needed |
|
|
738
|
+
| No STATUS from agent for 2 consecutive turns | Send `STATUS_CHECK` message to agent |
|
|
739
|
+
| No STATUS for 3 consecutive turns (or no response to STATUS_CHECK) | Declare agent stuck |
|
|
740
|
+
| Agent sends STATUS but task number hasn't changed for 3+ heartbeats | Stuck in loop — declare stuck |
|
|
671
741
|
| All agents stuck | STOP team, report to user |
|
|
672
742
|
|
|
743
|
+
### Stuck-in-Loop Detection
|
|
744
|
+
|
|
745
|
+
An agent may appear to send heartbeats but actually be looping on the same task (e.g., test fails → fix → test fails → fix → ...). To detect this:
|
|
746
|
+
|
|
747
|
+
- Track the task number in each STATUS message
|
|
748
|
+
- If the same task number appears in 3+ consecutive STATUS messages from the same agent, the agent is stuck in a loop
|
|
749
|
+
- Action: send a message to the agent with guidance, or declare stuck if the loop continues
|
|
750
|
+
|
|
673
751
|
### Stuck Agent Recovery
|
|
674
752
|
|
|
675
753
|
When an agent is declared stuck:
|
|
676
|
-
1. Do NOT wait for it — proceed with
|
|
677
|
-
2. Note the stuck agent's increment ID and last known task progress
|
|
678
|
-
3.
|
|
679
|
-
4.
|
|
754
|
+
1. Do NOT wait for it — proceed with other agents
|
|
755
|
+
2. Note the stuck agent's increment ID and last known task progress (from last STATUS)
|
|
756
|
+
3. Send shutdown_request to the stuck agent to free resources
|
|
757
|
+
4. During closure phase, the stuck agent's increment is left open for manual completion
|
|
680
758
|
|
|
681
759
|
### Preventing Stuck Agents
|
|
682
760
|
|
|
683
761
|
- Enforce the 15-task cap (Section 3b)
|
|
684
762
|
- Agents use `--simple` flag in auto-mode (reduces context per iteration)
|
|
685
763
|
- Agents do NOT run /sw:done (team-lead handles closure centrally)
|
|
764
|
+
- Heartbeat STATUS messages let team-lead detect problems early instead of after long silences
|
|
686
765
|
- If an agent's task count exceeds 15 despite the cap, the team-lead should split it before spawning
|
|
687
766
|
|
|
688
767
|
---
|
|
@@ -697,18 +776,29 @@ When an agent is declared stuck:
|
|
|
697
776
|
│ └── Missing? → Auto-invoke /sw:increment, wait for completion
|
|
698
777
|
├── Step 0b: ACTIVATE MASTER INCREMENT (MANDATORY)
|
|
699
778
|
│ └── Edit metadata.json: set status to "active" BEFORE spawning agents
|
|
700
|
-
├── Step 1: Analyze feature (from master spec)
|
|
779
|
+
├── Step 1: Analyze feature (from master spec) → identify domains → decide increment split
|
|
701
780
|
├── Step 2: Create team via TeamCreate
|
|
702
781
|
├── Step 3: Create per-domain increments (derived from master spec)
|
|
782
|
+
│
|
|
783
|
+
│ ── ACTIVE PHASE (agents implementing, team-lead monitoring) ──
|
|
784
|
+
│
|
|
703
785
|
├── Step 4: Contract-first spawning (all agents with mode: "bypassPermissions")
|
|
704
786
|
│ ├── Phase 1: Spawn shared + database
|
|
705
|
-
│ │ └──
|
|
706
|
-
│ │ └──
|
|
787
|
+
│ │ └── Agents send PLAN_READY notification → proceed immediately
|
|
788
|
+
│ │ └── Team-lead reviews async, sends PLAN_CORRECTION only if needed
|
|
789
|
+
│ │ └── Wait for CONTRACT_READY
|
|
707
790
|
│ └── Phase 2: Spawn backend + frontend + testing
|
|
708
|
-
│ └──
|
|
709
|
-
├── Step 5: Monitor progress via
|
|
710
|
-
├──
|
|
711
|
-
├──
|
|
791
|
+
│ └── Agents send PLAN_READY notification → proceed immediately
|
|
792
|
+
├── Step 5: Monitor progress via STATUS heartbeats
|
|
793
|
+
│ ├── Track per-agent: last STATUS task number and turn count
|
|
794
|
+
│ ├── No STATUS for 2 turns → send STATUS_CHECK
|
|
795
|
+
│ ├── No STATUS for 3 turns or same task 3+ times → declare stuck
|
|
796
|
+
│ └── DO NOT run grill/done/closure during this phase
|
|
797
|
+
├── Step 6: Collect all COMPLETION signals (or declare remaining agents stuck)
|
|
798
|
+
│
|
|
799
|
+
│ ── CLOSURE PHASE (all agents done, team-lead runs quality gates) ──
|
|
800
|
+
│
|
|
801
|
+
├── Step 7: Team-lead runs centralized closure per increment (dependency order):
|
|
712
802
|
│ ├── Pre-closure: verify/fix metadata.json status → must be "active"
|
|
713
803
|
│ ├── /sw:grill → fix findings → retry if needed (max 2)
|
|
714
804
|
│ └── /sw:done --auto → fix gate failures → retry if needed (max 2)
|
|
@@ -761,6 +851,10 @@ To execute, run without --dry-run.
|
|
|
761
851
|
|-------|-------|-----|
|
|
762
852
|
| **TeamCreate blocked by guard** | No increment with spec.md exists | Run `/sw:increment "feature"` first, then retry `/sw:team-lead`. The guard requires a substantive spec.md (>200 bytes, not a template) |
|
|
763
853
|
| **Agent stuck on trust folder** | Agent spawned without `bypassPermissions` | ALWAYS use `mode: "bypassPermissions"` — NEVER `mode: "plan"`. Trust prompts require interactive input agents cannot provide |
|
|
854
|
+
| **Session freezes after first agent completes** | Closure ran during active phase (pre-v0528 bug) | Ensure §8 active-phase rules are followed: NO grill/done until ALL agents signal COMPLETION |
|
|
855
|
+
| **Agent proceeds with wrong plan** | Async model means agents don't wait for approval | Send `PLAN_CORRECTION` immediately; agent should pause and revise. If ignored, send `shutdown_request` |
|
|
856
|
+
| **No heartbeat STATUS from agent** | Agent didn't implement heartbeat or is stuck | Check if agent template includes heartbeat step. If yes, agent is stuck — send STATUS_CHECK, then declare stuck after 3 turns |
|
|
857
|
+
| **Agent stuck in loop (same task repeated)** | Test fail → fix → test fail cycle | Heartbeat shows same task number 3+ times. Send guidance message or declare stuck |
|
|
764
858
|
| **Agents editing same files** | Overlapping file ownership patterns | Review ownership map; reassign conflicting files to a single owner; use `--dry-run` to validate before launch |
|
|
765
859
|
| **Token cost too high** | Too many agents or overly large prompts | Reduce `--max-agents`; use `--domains` to limit scope; split feature into smaller increments |
|
|
766
860
|
| **Agent stuck in extended thinking** | Too many tasks (>15) causing context overflow | Enforce 15-task cap per agent; split large domains into 2 agents; agents use `--simple` mode |
|
|
@@ -38,17 +38,21 @@ WORKFLOW:
|
|
|
38
38
|
- Read prisma/schema.prisma for database schema
|
|
39
39
|
- Read src/types/ for shared interfaces
|
|
40
40
|
8. Create plan files (plan.md, tasks.md) for your increment
|
|
41
|
-
9. Send plan to team-lead
|
|
41
|
+
9. Send structured plan notification to team-lead (do NOT wait for approval):
|
|
42
42
|
SendMessage({ type: "message", recipient: "team-lead",
|
|
43
|
-
content: "PLAN_READY: [increment path]
|
|
44
|
-
summary: "Backend plan ready
|
|
45
|
-
10.
|
|
43
|
+
content: "PLAN_READY: Created [increment path]\nTasks: [count]\nACs covered: [AC-IDs]\nKey decisions: [summary]\nFiles: [file list]\nArchitecture: [approach]",
|
|
44
|
+
summary: "Backend plan ready — proceeding to implementation" })
|
|
45
|
+
10. Proceed to implementation IMMEDIATELY. If team-lead sends "PLAN_CORRECTION", pause current work, revise, then continue.
|
|
46
46
|
11. Execute tasks autonomously: /sw:auto --simple (minimal context mode to prevent context overflow)
|
|
47
|
-
12.
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
47
|
+
12. After EACH task completion, send heartbeat:
|
|
48
|
+
SendMessage({ type: "message", recipient: "team-lead",
|
|
49
|
+
content: "STATUS: T-{N}/{total} complete. Next: T-{N+1}. Tests: [pass/fail count].",
|
|
50
|
+
summary: "Backend agent: task {N} of {total} done" })
|
|
51
|
+
13. Generate or update OpenAPI spec if API routes change
|
|
52
|
+
14. Run all tests for owned code (unit + integration): npm test
|
|
53
|
+
15. Do NOT signal completion until all tests pass
|
|
54
|
+
16. Signal COMPLETION via SendMessage to team-lead with summary of tasks done and test results
|
|
55
|
+
17. Do NOT run /sw:done or /sw:grill yourself — team-lead handles closure centrally
|
|
52
56
|
|
|
53
57
|
RULES:
|
|
54
58
|
- WRITE only to files you own (listed above)
|
|
@@ -27,19 +27,23 @@ WORKFLOW:
|
|
|
27
27
|
5. Read the MASTER SPEC at [MASTER_INCREMENT_PATH]/spec.md for scope and ACs
|
|
28
28
|
6. Design database schema changes
|
|
29
29
|
7. Create plan files (plan.md, tasks.md) for your increment
|
|
30
|
-
8. Send plan to team-lead
|
|
30
|
+
8. Send structured plan notification to team-lead (do NOT wait for approval):
|
|
31
31
|
SendMessage({ type: "message", recipient: "team-lead",
|
|
32
|
-
content: "PLAN_READY: [increment path]
|
|
33
|
-
summary: "Database plan ready
|
|
34
|
-
9.
|
|
32
|
+
content: "PLAN_READY: Created [increment path]\nTasks: [count]\nACs covered: [AC-IDs]\nKey decisions: [schema changes summary]\nFiles: [migration files, schema changes]\nArchitecture: [approach]",
|
|
33
|
+
summary: "Database plan ready — proceeding to implementation" })
|
|
34
|
+
9. Proceed to implementation IMMEDIATELY. If team-lead sends "PLAN_CORRECTION", pause current work, revise, then continue.
|
|
35
35
|
10. Generate Prisma migration: npx prisma migrate dev --name <migration-name>
|
|
36
36
|
11. Write seed data if needed
|
|
37
37
|
12. Execute tasks autonomously: /sw:auto --simple (minimal context mode to prevent context overflow)
|
|
38
|
-
13.
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
38
|
+
13. After EACH task completion, send heartbeat:
|
|
39
|
+
SendMessage({ type: "message", recipient: "team-lead",
|
|
40
|
+
content: "STATUS: T-{N}/{total} complete. Next: T-{N+1}. Tests: [pass/fail count].",
|
|
41
|
+
summary: "Database agent: task {N} of {total} done" })
|
|
42
|
+
14. Run all tests for owned code (migration, seed): npm test
|
|
43
|
+
15. Do NOT signal completion until all tests pass
|
|
44
|
+
16. Signal CONTRACT_READY with schema details via SendMessage to team-lead
|
|
45
|
+
17. Signal COMPLETION via SendMessage to team-lead with summary of tasks done and test results
|
|
46
|
+
18. Do NOT run /sw:done or /sw:grill yourself — team-lead handles closure centrally
|
|
43
47
|
|
|
44
48
|
RULES:
|
|
45
49
|
- WRITE only to files you own (listed above)
|
|
@@ -40,16 +40,20 @@ WORKFLOW:
|
|
|
40
40
|
- Read src/types/ for shared interfaces
|
|
41
41
|
- Read openapi.yaml for API endpoints (if backend produces one)
|
|
42
42
|
8. Create plan files (plan.md, tasks.md) for your increment
|
|
43
|
-
9. Send plan to team-lead
|
|
43
|
+
9. Send structured plan notification to team-lead (do NOT wait for approval):
|
|
44
44
|
SendMessage({ type: "message", recipient: "team-lead",
|
|
45
|
-
content: "PLAN_READY: [increment path]
|
|
46
|
-
summary: "Frontend plan ready
|
|
47
|
-
10.
|
|
45
|
+
content: "PLAN_READY: Created [increment path]\nTasks: [count]\nACs covered: [AC-IDs]\nKey decisions: [summary]\nFiles: [file list]\nArchitecture: [approach]",
|
|
46
|
+
summary: "Frontend plan ready — proceeding to implementation" })
|
|
47
|
+
10. Proceed to implementation IMMEDIATELY. If team-lead sends "PLAN_CORRECTION", pause current work, revise, then continue.
|
|
48
48
|
11. Execute tasks autonomously: /sw:auto --simple (minimal context mode to prevent context overflow)
|
|
49
|
-
12.
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
49
|
+
12. After EACH task completion, send heartbeat:
|
|
50
|
+
SendMessage({ type: "message", recipient: "team-lead",
|
|
51
|
+
content: "STATUS: T-{N}/{total} complete. Next: T-{N+1}. Tests: [pass/fail count].",
|
|
52
|
+
summary: "Frontend agent: task {N} of {total} done" })
|
|
53
|
+
13. Run all tests for owned code (unit + integration): npm test
|
|
54
|
+
14. Do NOT signal completion until all tests pass
|
|
55
|
+
15. Signal COMPLETION via SendMessage to team-lead with summary of tasks done and test results
|
|
56
|
+
16. Do NOT run /sw:done or /sw:grill yourself — team-lead handles closure centrally
|
|
53
57
|
|
|
54
58
|
RULES:
|
|
55
59
|
- WRITE only to files you own (listed above)
|
|
@@ -28,19 +28,23 @@ WORKFLOW:
|
|
|
28
28
|
5. Read the MASTER SPEC at [MASTER_INCREMENT_PATH]/spec.md for scope and ACs
|
|
29
29
|
6. Audit code produced by other agents for security issues
|
|
30
30
|
7. Create plan files (plan.md, tasks.md) for your increment
|
|
31
|
-
8. Send plan to team-lead
|
|
31
|
+
8. Send structured plan notification to team-lead (do NOT wait for approval):
|
|
32
32
|
SendMessage({ type: "message", recipient: "team-lead",
|
|
33
|
-
content: "PLAN_READY: [increment path]
|
|
34
|
-
summary: "Security plan ready
|
|
35
|
-
9.
|
|
33
|
+
content: "PLAN_READY: Created [increment path]\nTasks: [count]\nACs covered: [AC-IDs]\nKey decisions: [security findings, hardening approach]\nFiles: [file list]\nRisk areas: [identified vulnerabilities]",
|
|
34
|
+
summary: "Security plan ready — proceeding to implementation" })
|
|
35
|
+
9. Proceed to implementation IMMEDIATELY. If team-lead sends "PLAN_CORRECTION", pause current work, revise, then continue.
|
|
36
36
|
10. Implement auth/authz middleware if needed
|
|
37
37
|
11. Add input validation and sanitization
|
|
38
38
|
12. Execute tasks autonomously: /sw:auto --simple (minimal context mode to prevent context overflow)
|
|
39
|
-
13.
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
39
|
+
13. After EACH task completion, send heartbeat:
|
|
40
|
+
SendMessage({ type: "message", recipient: "team-lead",
|
|
41
|
+
content: "STATUS: T-{N}/{total} complete. Next: T-{N+1}. Tests: [pass/fail count].",
|
|
42
|
+
summary: "Security agent: task {N} of {total} done" })
|
|
43
|
+
14. Run all tests for owned code (security tests): npm test
|
|
44
|
+
15. Run security audit tools (npm audit, dependency check)
|
|
45
|
+
16. Do NOT signal completion until all tests pass
|
|
46
|
+
17. Signal COMPLETION via SendMessage to team-lead with summary of tasks done, test results, and security findings
|
|
47
|
+
18. Do NOT run /sw:done or /sw:grill yourself — team-lead handles closure centrally
|
|
44
48
|
|
|
45
49
|
RULES:
|
|
46
50
|
- WRITE only to files you own (listed above)
|
|
@@ -33,19 +33,23 @@ WORKFLOW:
|
|
|
33
33
|
5. Read the MASTER SPEC at [MASTER_INCREMENT_PATH]/spec.md for scope and ACs
|
|
34
34
|
6. Wait for ALL other agents to produce initial code
|
|
35
35
|
7. Create plan files (plan.md, tasks.md) for your increment
|
|
36
|
-
8. Send plan to team-lead
|
|
36
|
+
8. Send structured plan notification to team-lead (do NOT wait for approval):
|
|
37
37
|
SendMessage({ type: "message", recipient: "team-lead",
|
|
38
|
-
content: "PLAN_READY: [increment path]
|
|
39
|
-
summary: "Testing plan ready
|
|
40
|
-
9.
|
|
38
|
+
content: "PLAN_READY: Created [increment path]\nTasks: [count]\nACs covered: [AC-IDs]\nKey decisions: [test strategy, frameworks]\nFiles: [test file list]\nCoverage plan: [unit/integration/E2E breakdown]",
|
|
39
|
+
summary: "Testing plan ready — proceeding to implementation" })
|
|
40
|
+
9. Proceed to implementation IMMEDIATELY. If team-lead sends "PLAN_CORRECTION", pause current work, revise, then continue.
|
|
41
41
|
10. Write unit tests for new services/components
|
|
42
42
|
11. Write integration tests for API endpoints
|
|
43
43
|
12. Write E2E tests for user journeys
|
|
44
44
|
13. Execute tasks autonomously: /sw:auto --simple (minimal context mode to prevent context overflow)
|
|
45
|
-
14.
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
45
|
+
14. After EACH task completion, send heartbeat:
|
|
46
|
+
SendMessage({ type: "message", recipient: "team-lead",
|
|
47
|
+
content: "STATUS: T-{N}/{total} complete. Next: T-{N+1}. Tests: [pass/fail count].",
|
|
48
|
+
summary: "Testing agent: task {N} of {total} done" })
|
|
49
|
+
15. Run all tests (unit + integration + E2E): npm test && npx playwright test
|
|
50
|
+
16. Do NOT signal completion until all tests pass -- if tests fail, fix and repeat
|
|
51
|
+
17. Signal COMPLETION via SendMessage to team-lead with summary of tasks done and test results
|
|
52
|
+
18. Do NOT run /sw:done or /sw:grill yourself — team-lead handles closure centrally
|
|
49
53
|
|
|
50
54
|
RULES:
|
|
51
55
|
- WRITE only to test files (listed above)
|
|
@@ -292,7 +292,7 @@ ${acLines}
|
|
|
292
292
|
external_source: fm.external_source,
|
|
293
293
|
external_id: fm.external_id, external_url: fm.external_url,
|
|
294
294
|
imported_at: fm.imported_at, origin: fm.origin,
|
|
295
|
-
external_tools: fm.
|
|
295
|
+
external_tools: { ...(fm.external || {}), ...(fm.external_tools || {}) },
|
|
296
296
|
});
|
|
297
297
|
}
|
|
298
298
|
}
|
|
@@ -411,7 +411,7 @@ ${SpecParser.extractOverview(spec.markdown).replace(/\n/g, "<br>")}
|
|
|
411
411
|
* Generate story description from user story
|
|
412
412
|
*/
|
|
413
413
|
generateStoryDescription(us) {
|
|
414
|
-
const acList = us.acceptanceCriteria.map((ac) => `<li>${ac.status === "done" ? "\u2611" : "\u2610"} ${ac.description}</li>`).join("\n");
|
|
414
|
+
const acList = us.acceptanceCriteria.map((ac) => `<li>${ac.status === "done" ? "\u2611" : "\u2610"} ${ac.id}: ${ac.description}</li>`).join("\n");
|
|
415
415
|
return `
|
|
416
416
|
<h2>User Story</h2>
|
|
417
417
|
|
|
@@ -563,7 +563,7 @@ ${SpecParser.extractOverview(spec.markdown).replace(/\n/g, '<br>')}
|
|
|
563
563
|
*/
|
|
564
564
|
private generateStoryDescription(us: UserStory): string {
|
|
565
565
|
const acList = us.acceptanceCriteria
|
|
566
|
-
.map(ac => `<li>${ac.status === 'done' ? '☑' : '☐'} ${ac.description}</li>`)
|
|
566
|
+
.map(ac => `<li>${ac.status === 'done' ? '☑' : '☐'} ${ac.id}: ${ac.description}</li>`)
|
|
567
567
|
.join('\n');
|
|
568
568
|
|
|
569
569
|
return `
|
|
@@ -262,7 +262,7 @@ ${[...usAcStatus.entries()].map(
|
|
|
262
262
|
const match = fileContent.match(/^---\n([\s\S]*?)\n---/);
|
|
263
263
|
if (match) {
|
|
264
264
|
const fm = yaml.parse(match[1]);
|
|
265
|
-
const externalTools = fm.
|
|
265
|
+
const externalTools = { ...fm.external || {}, ...fm.external_tools || {} };
|
|
266
266
|
usFiles.push({
|
|
267
267
|
id: fm.id,
|
|
268
268
|
title: fm.title,
|
|
@@ -367,8 +367,8 @@ ${[...usAcStatus.entries()].map(([id, done]) =>
|
|
|
367
367
|
const match = fileContent.match(/^---\n([\s\S]*?)\n---/);
|
|
368
368
|
if (match) {
|
|
369
369
|
const fm = yaml.parse(match[1]);
|
|
370
|
-
//
|
|
371
|
-
const externalTools = fm.
|
|
370
|
+
// Merge both external_tools and external (GitHub writes external, JIRA/ADO write external_tools)
|
|
371
|
+
const externalTools = { ...(fm.external || {}), ...(fm.external_tools || {}) };
|
|
372
372
|
usFiles.push({
|
|
373
373
|
id: fm.id,
|
|
374
374
|
title: fm.title,
|
|
@@ -5,8 +5,8 @@ import * as yaml from "yaml";
|
|
|
5
5
|
import { UserStoryIssueBuilder } from "./user-story-issue-builder.js";
|
|
6
6
|
import { CompletionCalculator } from "./completion-calculator.js";
|
|
7
7
|
import { DuplicateDetector } from "./duplicate-detector.js";
|
|
8
|
-
import { execFileNoThrow } from "
|
|
9
|
-
import { getGitHubAuthFromProject } from "
|
|
8
|
+
import { execFileNoThrow } from "../../specweave/lib/vendor/utils/execFileNoThrow.js";
|
|
9
|
+
import { getGitHubAuthFromProject } from "../../specweave/lib/vendor/utils/auth-helpers.js";
|
|
10
10
|
const _GitHubFeatureSync = class _GitHubFeatureSync {
|
|
11
11
|
// 30 seconds
|
|
12
12
|
constructor(client, specsDir, projectRoot) {
|
|
@@ -974,6 +974,14 @@ ${newFrontmatter}---${bodyContent}`;
|
|
|
974
974
|
throw new Error(`${userStoryPath}: Missing YAML frontmatter`);
|
|
975
975
|
}
|
|
976
976
|
const frontmatter = yaml.parse(match[1]);
|
|
977
|
+
if (!frontmatter.external_tools) {
|
|
978
|
+
frontmatter.external_tools = {};
|
|
979
|
+
}
|
|
980
|
+
if (!frontmatter.external_tools.github) {
|
|
981
|
+
frontmatter.external_tools.github = {};
|
|
982
|
+
}
|
|
983
|
+
frontmatter.external_tools.github.issue = issueNumber;
|
|
984
|
+
frontmatter.external_tools.github.url = `https://github.com/${this.client.getOwner()}/${this.client.getRepo()}/issues/${issueNumber}`;
|
|
977
985
|
if (!frontmatter.external) {
|
|
978
986
|
frontmatter.external = {};
|
|
979
987
|
}
|
|
@@ -981,7 +989,7 @@ ${newFrontmatter}---${bodyContent}`;
|
|
|
981
989
|
frontmatter.external.github = {};
|
|
982
990
|
}
|
|
983
991
|
frontmatter.external.github.issue = issueNumber;
|
|
984
|
-
frontmatter.external.github.url =
|
|
992
|
+
frontmatter.external.github.url = frontmatter.external_tools.github.url;
|
|
985
993
|
const newFrontmatter = yaml.stringify(frontmatter);
|
|
986
994
|
const bodyContent = content.slice(match[0].length);
|
|
987
995
|
const newContent = `---
|