@use-the-fork/spindle 0.1.0 → 0.2.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/build/Assets/Blueprints/Catalog.js +7 -2
- package/build/Assets/Blueprints/agents/sdd-implementer.agent.md +6 -6
- package/build/Assets/Blueprints/agents/sdd-orchestrator.agent.md +4 -7
- package/build/Assets/Blueprints/skills/author-agent/SKILL.md +2 -2
- package/build/Assets/Blueprints/skills/author-instruction/SKILL.md +2 -2
- package/build/Assets/Blueprints/skills/author-skill/SKILL.md +2 -2
- package/build/Assets/Blueprints/skills/int-subagent-driven-dev/SKILL.md +13 -9
- package/build/Assets/Blueprints/skills/int-subagent-driven-dev/assets/implementer-prompt.md +2 -2
- package/build/Assets/Blueprints/skills/int-subagent-driven-dev/references/example-workflow.md +11 -9
- package/build/Assets/Blueprints/skills/int-subagent-driven-dev/references/full-spec.md +33 -13
- package/build/Assets/Blueprints/skills/int-subagent-driven-dev/references/review-inputs.md +7 -7
- package/build/Assets/Blueprints/skills/{asd-ste100 → ref-asd-ste100}/SKILL.md +1 -1
- package/build/Assets/Blueprints/skills/sdd-author-design/SKILL.md +2 -2
- package/build/Assets/Blueprints/skills/sdd-implement-spec/SKILL.md +4 -6
- package/build/Assets/Templates/project/ticket-tracker.md +10 -2
- package/build/SubagentDrivenDevelopment/Commands/ChecksRecordCommand.js +27 -5
- package/build/SubagentDrivenDevelopment/Commands/ChecksRequireCommand.js +31 -7
- package/build/SubagentDrivenDevelopment/Commands/CorrectCommand.js +0 -1
- package/build/SubagentDrivenDevelopment/Commands/FinishCommand.js +2 -1
- package/build/SubagentDrivenDevelopment/Commands/ImplementCommand.js +2 -0
- package/build/SubagentDrivenDevelopment/Commands/{ClaimCommand.js → IntegrateCommand.js} +8 -7
- package/build/SubagentDrivenDevelopment/Commands/ReviewCommand.js +9 -9
- package/build/SubagentDrivenDevelopment/Commands/StartCommand.js +23 -0
- package/build/SubagentDrivenDevelopment/Commands/StatusCommand.js +5 -0
- package/build/SubagentDrivenDevelopment/Commands/groups.js +3 -2
- package/build/SubagentDrivenDevelopment/Evidence/GitEvidence.js +188 -37
- package/build/SubagentDrivenDevelopment/Models/Workflow.js +0 -2
- package/build/SubagentDrivenDevelopment/Persistence/AssignmentSchema.js +4 -0
- package/build/SubagentDrivenDevelopment/Persistence/CheckSchema.js +4 -13
- package/build/SubagentDrivenDevelopment/Persistence/LedgerRepository.js +66 -5
- package/build/SubagentDrivenDevelopment/Persistence/ProgressSchema.js +54 -4
- package/build/SubagentDrivenDevelopment/Persistence/ReviewSchema.js +4 -0
- package/build/SubagentDrivenDevelopment/Policies/AssignmentPolicy.js +0 -3
- package/build/SubagentDrivenDevelopment/Policies/CheckPolicy.js +6 -3
- package/build/SubagentDrivenDevelopment/Policies/ReadinessPolicy.js +16 -6
- package/build/SubagentDrivenDevelopment/Policies/ReviewPolicy.js +16 -2
- package/build/SubagentDrivenDevelopment/Policies/WorkflowPolicy.js +8 -8
- package/build/SubagentDrivenDevelopment/Services/AssignmentService.js +73 -51
- package/build/SubagentDrivenDevelopment/Services/ChecksService.js +376 -21
- package/build/SubagentDrivenDevelopment/Services/CorrectionService.js +83 -14
- package/build/SubagentDrivenDevelopment/Services/DeliveryCorrectionService.js +3 -7
- package/build/SubagentDrivenDevelopment/Services/DeliveryService.js +43 -38
- package/build/SubagentDrivenDevelopment/Services/FeatureCreationService.js +1 -1
- package/build/SubagentDrivenDevelopment/Services/FeatureFinalizationService.js +1202 -0
- package/build/SubagentDrivenDevelopment/Services/FeatureInspectionService.js +41 -49
- package/build/SubagentDrivenDevelopment/Services/FeatureWorktreeService.js +544 -0
- package/build/SubagentDrivenDevelopment/Services/ReadinessService.js +2 -2
- package/build/SubagentDrivenDevelopment/Services/ReviewService.js +39 -3
- package/build/SubagentDrivenDevelopment/Services/SubmissionService.js +4 -1
- package/build/SubagentDrivenDevelopment/Services/TicketIntegrationService.js +621 -0
- package/build/SubagentDrivenDevelopment/Services/TicketService.js +3 -0
- package/build/SubagentDrivenDevelopment/Services/TicketWorktreeService.js +317 -0
- package/build/SubagentDrivenDevelopment/Services/WorkflowRecordsCommitter.js +336 -0
- package/build/SubagentDrivenDevelopment/SubagentDrivenDevelopmentServiceProvider.js +18 -8
- package/build/TemplateRendering/Computed/Providers/AuthoringFlowchartProvider.js +1 -1
- package/package.json +2 -2
- package/build/SubagentDrivenDevelopment/Services/IntegrationService.js +0 -258
- /package/build/Assets/Blueprints/skills/{asd-ste100 → ref-asd-ste100}/CREDITS.MD +0 -0
- /package/build/Assets/Blueprints/skills/{asd-ste100 → ref-asd-ste100}/examples/before-after.md +0 -0
- /package/build/Assets/Blueprints/skills/{asd-ste100 → ref-asd-ste100}/references/writing-rules.md +0 -0
|
@@ -2,19 +2,20 @@ import { ServiceProvider } from "../Foundation/ServiceProvider.js";
|
|
|
2
2
|
import { GitService } from "../Git/Services/GitService.js";
|
|
3
3
|
import { ChecksRecordCommand } from "./Commands/ChecksRecordCommand.js";
|
|
4
4
|
import { ChecksRequireCommand } from "./Commands/ChecksRequireCommand.js";
|
|
5
|
-
import { ClaimCommand } from "./Commands/ClaimCommand.js";
|
|
6
5
|
import { CorrectCommand } from "./Commands/CorrectCommand.js";
|
|
7
6
|
import { CreateCommand } from "./Commands/CreateCommand.js";
|
|
8
7
|
import { FindingCreateCommand } from "./Commands/FindingCreateCommand.js";
|
|
9
8
|
import { FindingUpdateCommand } from "./Commands/FindingUpdateCommand.js";
|
|
10
9
|
import { FinishCommand } from "./Commands/FinishCommand.js";
|
|
11
10
|
import { ImplementCommand } from "./Commands/ImplementCommand.js";
|
|
11
|
+
import { IntegrateCommand } from "./Commands/IntegrateCommand.js";
|
|
12
12
|
import { NextCommand } from "./Commands/NextCommand.js";
|
|
13
13
|
import { ReadyCommand } from "./Commands/ReadyCommand.js";
|
|
14
14
|
import { RequirementsDecideCommand } from "./Commands/RequirementsDecideCommand.js";
|
|
15
15
|
import { ResumeCommand } from "./Commands/ResumeCommand.js";
|
|
16
16
|
import { ReviewCommand } from "./Commands/ReviewCommand.js";
|
|
17
17
|
import { ReviewRequireCommand } from "./Commands/ReviewRequireCommand.js";
|
|
18
|
+
import { StartCommand } from "./Commands/StartCommand.js";
|
|
18
19
|
import { StatusCommand } from "./Commands/StatusCommand.js";
|
|
19
20
|
import { SubmitCommand } from "./Commands/SubmitCommand.js";
|
|
20
21
|
import { TicketCommentCommand } from "./Commands/TicketCommentCommand.js";
|
|
@@ -43,23 +44,27 @@ import { DeliveryFindingService } from "./Services/DeliveryFindingService.js";
|
|
|
43
44
|
import { DeliveryService } from "./Services/DeliveryService.js";
|
|
44
45
|
import { DeliverySubmissionService } from "./Services/DeliverySubmissionService.js";
|
|
45
46
|
import { FeatureCreationService } from "./Services/FeatureCreationService.js";
|
|
47
|
+
import { FeatureFinalizationService } from "./Services/FeatureFinalizationService.js";
|
|
46
48
|
import { FeatureInspectionService } from "./Services/FeatureInspectionService.js";
|
|
49
|
+
import { FeatureWorktreeService } from "./Services/FeatureWorktreeService.js";
|
|
47
50
|
import { FindingService } from "./Services/FindingService.js";
|
|
48
|
-
import { IntegrationService } from "./Services/IntegrationService.js";
|
|
49
51
|
import { ReadinessService } from "./Services/ReadinessService.js";
|
|
50
52
|
import { RequirementsService } from "./Services/RequirementsService.js";
|
|
51
53
|
import { ReviewService } from "./Services/ReviewService.js";
|
|
52
54
|
import { SubmissionService } from "./Services/SubmissionService.js";
|
|
55
|
+
import { TicketIntegrationService } from "./Services/TicketIntegrationService.js";
|
|
53
56
|
import { TicketService } from "./Services/TicketService.js";
|
|
57
|
+
import { TicketWorktreeService } from "./Services/TicketWorktreeService.js";
|
|
58
|
+
import { WorkflowRecordsCommitter } from "./Services/WorkflowRecordsCommitter.js";
|
|
54
59
|
export class SubagentDrivenDevelopmentServiceProvider extends ServiceProvider {
|
|
55
60
|
static commands() {
|
|
56
61
|
return [
|
|
57
62
|
CreateCommand,
|
|
63
|
+
StartCommand,
|
|
58
64
|
TicketCreateCommand,
|
|
59
65
|
TicketUpdateCommand,
|
|
60
66
|
TicketCommentCommand,
|
|
61
67
|
ReadyCommand,
|
|
62
|
-
ClaimCommand,
|
|
63
68
|
ChecksRequireCommand,
|
|
64
69
|
ChecksRecordCommand,
|
|
65
70
|
ImplementCommand,
|
|
@@ -70,6 +75,7 @@ export class SubagentDrivenDevelopmentServiceProvider extends ServiceProvider {
|
|
|
70
75
|
FindingUpdateCommand,
|
|
71
76
|
RequirementsDecideCommand,
|
|
72
77
|
SubmitCommand,
|
|
78
|
+
IntegrateCommand,
|
|
73
79
|
FinishCommand,
|
|
74
80
|
ResumeCommand,
|
|
75
81
|
NextCommand,
|
|
@@ -77,14 +83,17 @@ export class SubagentDrivenDevelopmentServiceProvider extends ServiceProvider {
|
|
|
77
83
|
];
|
|
78
84
|
}
|
|
79
85
|
register() {
|
|
86
|
+
this.app.singleton(FeatureFinalizationService, async (app) => new FeatureFinalizationService(app, await app.make(GitService), await app.make(LedgerRepository)));
|
|
87
|
+
this.app.singleton(TicketWorktreeService, async (app) => new TicketWorktreeService(app, await app.make(GitService), await app.make(GitEvidence)));
|
|
88
|
+
this.app.singleton(FeatureWorktreeService, async (app) => new FeatureWorktreeService(app, await app.make(GitService), await app.make(FeatureInspectionService), await app.make(WorkspaceTransaction)));
|
|
80
89
|
this.app.singleton(ReadinessReader, async (app) => new ReadinessReader(app, await app.make(TicketRepository), await app.make(LedgerRepository), await app.make(PathSafety)));
|
|
81
90
|
this.app.singleton(ReadinessPolicy, async (app) => new ReadinessPolicy(app, await app.make(TicketRepository)));
|
|
82
91
|
this.app.singleton(FeatureCreationService, async (app) => new FeatureCreationService(app, await app.make(FeatureWorkspace), await app.make(PathSafety), await app.make(WorkspaceTransaction), await app.make(GitEvidence)));
|
|
83
|
-
this.app.singleton(FeatureInspectionService, async (app) => new FeatureInspectionService(app, await app.make(GitEvidence), await app.make(ReportEvidence), await app.make(FeatureWorkspace), await app.make(TicketRepository), await app.make(
|
|
92
|
+
this.app.singleton(FeatureInspectionService, async (app) => new FeatureInspectionService(app, await app.make(GitEvidence), await app.make(ReportEvidence), await app.make(FeatureWorkspace), await app.make(TicketRepository), await app.make(AssignmentPolicy), await app.make(CheckPolicy), await app.make(FindingPolicy), await app.make(ReviewPolicy)));
|
|
84
93
|
this.app.singleton(TicketService, async (app) => new TicketService(app, await app.make(TicketRepository), await app.make(LedgerRepository), await app.make(PathSafety), await app.make(WorkspaceTransaction), await app.make(FeatureInspectionService)));
|
|
85
94
|
this.app.singleton(ReadinessService, async (app) => new ReadinessService(app, await app.make(FeatureInspectionService), await app.make(ReadinessReader), await app.make(ReadinessPolicy), await app.make(PathSafety)));
|
|
86
|
-
this.app.singleton(AssignmentService, async (app) => new AssignmentService(app, await app.make(GitEvidence), await app.make(ReportEvidence), await app.make(TicketRepository), await app.make(LedgerRepository), await app.make(WorkspaceTransaction), await app.make(AssignmentPolicy), await app.make(CheckPolicy), await app.make(ReviewPolicy), await app.make(WorkflowPolicy), await app.make(FeatureInspectionService)));
|
|
87
|
-
this.app.singleton(CorrectionService, async (app) => new CorrectionService(app, await app.make(GitEvidence), await app.make(ReportEvidence), await app.make(TicketRepository), await app.make(LedgerRepository), await app.make(WorkspaceTransaction), await app.make(WorkflowPolicy), await app.make(DeliveryCorrectionService), await app.make(FeatureInspectionService)));
|
|
95
|
+
this.app.singleton(AssignmentService, async (app) => new AssignmentService(app, await app.make(GitEvidence), await app.make(ReportEvidence), await app.make(TicketRepository), await app.make(LedgerRepository), await app.make(WorkspaceTransaction), await app.make(AssignmentPolicy), await app.make(CheckPolicy), await app.make(ReviewPolicy), await app.make(ReadinessPolicy), await app.make(WorkflowPolicy), await app.make(FeatureInspectionService), await app.make(TicketWorktreeService), await app.make(WorkflowRecordsCommitter)));
|
|
96
|
+
this.app.singleton(CorrectionService, async (app) => new CorrectionService(app, await app.make(GitEvidence), await app.make(ReportEvidence), await app.make(TicketRepository), await app.make(LedgerRepository), await app.make(WorkspaceTransaction), await app.make(WorkflowPolicy), await app.make(DeliveryCorrectionService), await app.make(FeatureInspectionService), await app.make(ChecksService)));
|
|
88
97
|
this.app.singleton(DeliveryCorrectionService, async (app) => new DeliveryCorrectionService(app, await app.make(GitEvidence), await app.make(ReportEvidence), await app.make(TicketRepository), await app.make(LedgerRepository), await app.make(WorkspaceTransaction), await app.make(FeatureInspectionService)));
|
|
89
98
|
this.app.singleton(ChecksService, async (app) => new ChecksService(app, await app.make(GitEvidence), await app.make(TicketRepository), await app.make(LedgerRepository), await app.make(WorkspaceTransaction), await app.make(WorkflowPolicy), await app.make(FeatureInspectionService)));
|
|
90
99
|
this.app.singleton(ReviewService, async (app) => new ReviewService(app, await app.make(GitEvidence), await app.make(ReportEvidence), await app.make(TicketRepository), await app.make(LedgerRepository), await app.make(WorkspaceTransaction), await app.make(AssignmentPolicy), await app.make(CheckPolicy), await app.make(ReviewPolicy), await app.make(WorkflowPolicy), await app.make(FeatureInspectionService)));
|
|
@@ -93,8 +102,9 @@ export class SubagentDrivenDevelopmentServiceProvider extends ServiceProvider {
|
|
|
93
102
|
this.app.singleton(RequirementsService, async (app) => new RequirementsService(app, await app.make(GitEvidence), await app.make(TicketRepository), await app.make(LedgerRepository), await app.make(WorkspaceTransaction), await app.make(WorkflowPolicy), await app.make(FeatureInspectionService)));
|
|
94
103
|
this.app.singleton(SubmissionService, async (app) => new SubmissionService(app, await app.make(GitEvidence), await app.make(ReportEvidence), await app.make(TicketRepository), await app.make(LedgerRepository), await app.make(WorkspaceTransaction), await app.make(CheckPolicy), await app.make(ReviewPolicy), await app.make(WorkflowPolicy), await app.make(DeliverySubmissionService), await app.make(FeatureInspectionService)));
|
|
95
104
|
this.app.singleton(DeliverySubmissionService, async (app) => new DeliverySubmissionService(app, await app.make(GitEvidence), await app.make(ReportEvidence), await app.make(TicketRepository), await app.make(LedgerRepository), await app.make(WorkspaceTransaction), await app.make(CheckPolicy), await app.make(ReviewPolicy), await app.make(FeatureInspectionService)));
|
|
96
|
-
this.app.singleton(
|
|
97
|
-
this.app.singleton(
|
|
105
|
+
this.app.singleton(TicketIntegrationService, async (app) => new TicketIntegrationService(app, await app.make(GitService), await app.make(GitEvidence), await app.make(ReportEvidence), await app.make(TicketRepository), await app.make(LedgerRepository), await app.make(WorkspaceTransaction), await app.make(AcceptancePolicy), await app.make(WorkflowPolicy), await app.make(FeatureInspectionService), await app.make(WorkflowRecordsCommitter)));
|
|
106
|
+
this.app.singleton(WorkflowRecordsCommitter, async (app) => new WorkflowRecordsCommitter(app, await app.make(GitService)));
|
|
107
|
+
this.app.singleton(DeliveryService, async (app) => new DeliveryService(app, await app.make(GitEvidence), await app.make(ReportEvidence), await app.make(TicketRepository), await app.make(LedgerRepository), await app.make(WorkspaceTransaction), await app.make(CheckPolicy), await app.make(FindingPolicy), await app.make(ReviewPolicy), await app.make(FeatureInspectionService), await app.make(FeatureFinalizationService)));
|
|
98
108
|
this.app.singleton(FeatureWorkspace, async (app) => new FeatureWorkspace(app, await app.make(LedgerRepository), await app.make(PathSafety)));
|
|
99
109
|
this.app.singleton(LedgerRepository, async (app) => new LedgerRepository(app));
|
|
100
110
|
this.app.singleton(TicketRepository, async (app) => new TicketRepository(app, await app.make(PathSafety), await app.make(LedgerRepository)));
|
|
@@ -4,7 +4,7 @@ export class AuthoringFlowchartProvider extends ComputedVariableProvider {
|
|
|
4
4
|
return [
|
|
5
5
|
"```mermaid",
|
|
6
6
|
"flowchart TD",
|
|
7
|
-
' A["Read and consider only the `int-writing-for-agents` and `asd-ste100` skills"]',
|
|
7
|
+
' A["Read and consider only the `int-writing-for-agents` and `ref-asd-ste100` skills"]',
|
|
8
8
|
' A --> B["Use the `grill` skill on the user request"]',
|
|
9
9
|
' B --> C{"Shared understanding confirmed?"}',
|
|
10
10
|
' C -- "No" --> B',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@use-the-fork/spindle",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"keywords": [],
|
|
6
6
|
"license": "ISC",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"devEngines": {
|
|
41
41
|
"packageManager": {
|
|
42
42
|
"name": "pnpm",
|
|
43
|
-
"version": "12.
|
|
43
|
+
"version": ">=12.9.0",
|
|
44
44
|
"onFail": "warn"
|
|
45
45
|
}
|
|
46
46
|
},
|
|
@@ -1,258 +0,0 @@
|
|
|
1
|
-
import matter from "gray-matter";
|
|
2
|
-
import { Service } from "../../Foundation/Service.js";
|
|
3
|
-
import { validateAuthor, validateTicketId, } from "../Policies/InputValidation.js";
|
|
4
|
-
import { requiredTicketReviewers } from "../Policies/RequiredReviewers.js";
|
|
5
|
-
export class IntegrationService extends Service {
|
|
6
|
-
gitEvidence;
|
|
7
|
-
reportEvidence;
|
|
8
|
-
ticketRepository;
|
|
9
|
-
ledgerRepository;
|
|
10
|
-
workspaceTransaction;
|
|
11
|
-
acceptancePolicy;
|
|
12
|
-
workflowPolicy;
|
|
13
|
-
featureInspectionService;
|
|
14
|
-
constructor(app, gitEvidence, reportEvidence, ticketRepository, ledgerRepository, workspaceTransaction, acceptancePolicy, workflowPolicy, featureInspectionService) {
|
|
15
|
-
super(app);
|
|
16
|
-
this.gitEvidence = gitEvidence;
|
|
17
|
-
this.reportEvidence = reportEvidence;
|
|
18
|
-
this.ticketRepository = ticketRepository;
|
|
19
|
-
this.ledgerRepository = ledgerRepository;
|
|
20
|
-
this.workspaceTransaction = workspaceTransaction;
|
|
21
|
-
this.acceptancePolicy = acceptancePolicy;
|
|
22
|
-
this.workflowPolicy = workflowPolicy;
|
|
23
|
-
this.featureInspectionService = featureInspectionService;
|
|
24
|
-
}
|
|
25
|
-
accept(options) {
|
|
26
|
-
validateTicketId(options.ticket);
|
|
27
|
-
validateAuthor(options.author);
|
|
28
|
-
const feature = this.featureInspectionService.resolveFeature(options.spec);
|
|
29
|
-
return this.workspaceTransaction.run(feature.workspace, () => {
|
|
30
|
-
const ledger = this.ledgerRepository.readLedger(feature);
|
|
31
|
-
const ticket = this.ticketRepository.requireTicket(this.ticketRepository.readTickets(feature.workspace), options.ticket);
|
|
32
|
-
const progress = this.workflowPolicy.requireProgress(ledger, options.ticket);
|
|
33
|
-
if (progress.execution !== "reviewing" &&
|
|
34
|
-
progress.execution !== "changes-requested" &&
|
|
35
|
-
progress.execution !== "accepted") {
|
|
36
|
-
throw new Error(`Ticket ${options.ticket} must be reviewing before it can be accepted.`);
|
|
37
|
-
}
|
|
38
|
-
if (!progress.owner || progress.owner !== options.author.trim()) {
|
|
39
|
-
throw new Error("Only the current controller may accept this ticket.");
|
|
40
|
-
}
|
|
41
|
-
const identity = this.gitEvidence.contentIdentity(feature, ticket, progress.baseSha, progress.checks);
|
|
42
|
-
const blockers = this.acceptancePolicy.acceptBlockers(feature, ledger, ticket, progress, identity);
|
|
43
|
-
if (blockers.length > 0) {
|
|
44
|
-
throw new Error(`Ticket ${options.ticket} cannot be accepted:\n${blockers.join("\n")}`);
|
|
45
|
-
}
|
|
46
|
-
const reviews = requiredTicketReviewers(ledger, progress).map(({ agent, details }) => {
|
|
47
|
-
const assignment = progress.reviewAssignments.find((candidate) => candidate.agent === agent &&
|
|
48
|
-
candidate.objective === details &&
|
|
49
|
-
candidate.scope === "initial");
|
|
50
|
-
return {
|
|
51
|
-
agent,
|
|
52
|
-
assignment: assignment.id,
|
|
53
|
-
result: "passed",
|
|
54
|
-
...(assignment.noFindings === true
|
|
55
|
-
? { noFindings: true }
|
|
56
|
-
: { findingIds: assignment.findingIds }),
|
|
57
|
-
};
|
|
58
|
-
});
|
|
59
|
-
if (progress.execution === "accepted") {
|
|
60
|
-
if (!progress.acceptedEvidence) {
|
|
61
|
-
throw new Error(`Accepted ticket ${options.ticket} has no frozen integration evidence.`);
|
|
62
|
-
}
|
|
63
|
-
return {
|
|
64
|
-
ticket: options.ticket,
|
|
65
|
-
execution: "accepted",
|
|
66
|
-
reviews,
|
|
67
|
-
idempotent: true,
|
|
68
|
-
...identity,
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
const confirmedTicket = this.ticketRepository.requireTicket(this.ticketRepository.readTickets(feature.workspace), options.ticket);
|
|
72
|
-
const confirmedIdentity = this.gitEvidence.contentIdentity(feature, confirmedTicket, progress.baseSha, progress.checks);
|
|
73
|
-
const confirmedBlockers = this.acceptancePolicy.acceptBlockers(feature, ledger, confirmedTicket, progress, confirmedIdentity);
|
|
74
|
-
if (confirmedIdentity.snapshot !== identity.snapshot || confirmedBlockers.length > 0) {
|
|
75
|
-
throw new Error(`Ticket content changed while accepting; revalidate current review and check coverage:\n${confirmedBlockers.join("\n")}`);
|
|
76
|
-
}
|
|
77
|
-
const acceptedFiles = this.workflowPolicy.acceptedInventory(progress, options.ticket);
|
|
78
|
-
if (JSON.stringify(this.gitEvidence.changedPaths(progress.baseSha)) !==
|
|
79
|
-
JSON.stringify(acceptedFiles)) {
|
|
80
|
-
throw new Error("Accepted Git inventory changed while accepting the ticket.");
|
|
81
|
-
}
|
|
82
|
-
const contentDigest = this.gitEvidence.worktreeContentDigest(acceptedFiles);
|
|
83
|
-
progress.execution = "accepted";
|
|
84
|
-
progress.acceptedEvidence = {
|
|
85
|
-
snapshot: identity.snapshot,
|
|
86
|
-
codeSnapshot: identity.codeSnapshot,
|
|
87
|
-
requirementsSnapshot: identity.requirementsSnapshot,
|
|
88
|
-
files: acceptedFiles,
|
|
89
|
-
contentDigest,
|
|
90
|
-
};
|
|
91
|
-
const afterTicket = matter.stringify(this.ticketRepository.appendAudit(ticket.body, options.author, `Ticket accepted with current passing checks and complete initial review coverage: ${reviews.map((review) => `${review.agent} (${review.assignment})`).join(", ")}.`), this.ticketRepository.metadata(ticket));
|
|
92
|
-
this.workspaceTransaction.writeWorkflowState(feature, ticket, afterTicket, ledger);
|
|
93
|
-
return {
|
|
94
|
-
ticket: options.ticket,
|
|
95
|
-
execution: "accepted",
|
|
96
|
-
reviews,
|
|
97
|
-
...identity,
|
|
98
|
-
};
|
|
99
|
-
});
|
|
100
|
-
}
|
|
101
|
-
integrate(options) {
|
|
102
|
-
validateTicketId(options.ticket);
|
|
103
|
-
validateAuthor(options.author);
|
|
104
|
-
if (options.commit && !/^[0-9a-f]{40,64}$/i.test(options.commit)) {
|
|
105
|
-
throw new Error("--commit must be an existing full Git commit SHA.");
|
|
106
|
-
}
|
|
107
|
-
const feature = this.featureInspectionService.resolveFeature(options.spec);
|
|
108
|
-
return this.workspaceTransaction.run(feature.workspace, () => {
|
|
109
|
-
const ledger = this.ledgerRepository.readLedger(feature);
|
|
110
|
-
const ticket = this.ticketRepository.requireTicket(this.ticketRepository.readTickets(feature.workspace), options.ticket);
|
|
111
|
-
const progress = this.workflowPolicy.requireProgress(ledger, options.ticket);
|
|
112
|
-
if (progress.execution !== "accepted" && progress.execution !== "integrated") {
|
|
113
|
-
throw new Error(`Ticket ${options.ticket} must be accepted before integration.`);
|
|
114
|
-
}
|
|
115
|
-
if (!progress.owner || progress.owner !== options.author.trim()) {
|
|
116
|
-
throw new Error("Only the current controller may integrate this ticket.");
|
|
117
|
-
}
|
|
118
|
-
const accepted = progress.acceptedEvidence;
|
|
119
|
-
if (!accepted) {
|
|
120
|
-
throw new Error(`Ticket ${options.ticket} has no frozen accepted inventory and evidence.`);
|
|
121
|
-
}
|
|
122
|
-
if (!progress.baseSha) {
|
|
123
|
-
throw new Error(`Ticket ${options.ticket} has no recorded Git baseline for integration.`);
|
|
124
|
-
}
|
|
125
|
-
const identity = this.gitEvidence.contentIdentity(feature, ticket, progress.baseSha, progress.checks);
|
|
126
|
-
if (identity.requirementsSnapshot !== accepted.requirementsSnapshot) {
|
|
127
|
-
throw new Error("Accepted requirements evidence is stale; re-review is required.");
|
|
128
|
-
}
|
|
129
|
-
const inventory = this.gitEvidence.changedPaths(progress.baseSha);
|
|
130
|
-
if (JSON.stringify(inventory) !== JSON.stringify(accepted.files)) {
|
|
131
|
-
throw new Error(`Git-derived inventory changed after acceptance; expected ${JSON.stringify(accepted.files)}, found ${JSON.stringify(inventory)}.`);
|
|
132
|
-
}
|
|
133
|
-
const currentDigest = this.gitEvidence.worktreeContentDigest(accepted.files);
|
|
134
|
-
if (currentDigest !== accepted.contentDigest) {
|
|
135
|
-
throw new Error("Accepted file content changed after acceptance.");
|
|
136
|
-
}
|
|
137
|
-
this.gitEvidence.assertSafeIntegrationChanges(feature, accepted.files, ledger);
|
|
138
|
-
this.reportEvidence.assertAcceptedReportsCurrent(feature, progress);
|
|
139
|
-
if (!options.commit) {
|
|
140
|
-
if (progress.execution === "integrated") {
|
|
141
|
-
return {
|
|
142
|
-
ticket: options.ticket,
|
|
143
|
-
execution: "integrated",
|
|
144
|
-
acceptedFiles: accepted.files,
|
|
145
|
-
deliveryRecords: this.gitEvidence.deliveryRecordPaths(feature),
|
|
146
|
-
commitSha: progress.integration?.commitSha,
|
|
147
|
-
idempotent: true,
|
|
148
|
-
...identity,
|
|
149
|
-
};
|
|
150
|
-
}
|
|
151
|
-
const blockers = this.acceptancePolicy.acceptBlockers(feature, ledger, ticket, progress, identity);
|
|
152
|
-
if (blockers.length > 0) {
|
|
153
|
-
throw new Error(`Ticket ${options.ticket} cannot be integrated:\n${blockers.join("\n")}`);
|
|
154
|
-
}
|
|
155
|
-
return {
|
|
156
|
-
ticket: options.ticket,
|
|
157
|
-
execution: "accepted",
|
|
158
|
-
acceptedFiles: accepted.files,
|
|
159
|
-
deliveryRecords: this.gitEvidence.deliveryRecordPaths(feature),
|
|
160
|
-
...identity,
|
|
161
|
-
};
|
|
162
|
-
}
|
|
163
|
-
const requestedCommit = this.gitEvidence
|
|
164
|
-
.gitBuffer(["rev-parse", "--verify", `${options.commit}^{commit}`])
|
|
165
|
-
.toString("utf8")
|
|
166
|
-
.trim()
|
|
167
|
-
.toLowerCase();
|
|
168
|
-
if (requestedCommit !== options.commit.toLowerCase()) {
|
|
169
|
-
throw new Error(`Commit ${options.commit} did not resolve to the requested commit.`);
|
|
170
|
-
}
|
|
171
|
-
if (progress.execution === "integrated") {
|
|
172
|
-
if (progress.integration?.commitSha !== requestedCommit) {
|
|
173
|
-
throw new Error(`Ticket ${options.ticket} is already integrated through ${progress.integration?.commitSha ?? "an unknown commit"}.`);
|
|
174
|
-
}
|
|
175
|
-
if (this.gitEvidence.gitIndexContentDigest(accepted.files) !== accepted.contentDigest) {
|
|
176
|
-
throw new Error("Staged index content does not match the accepted file content.");
|
|
177
|
-
}
|
|
178
|
-
return {
|
|
179
|
-
ticket: options.ticket,
|
|
180
|
-
execution: "integrated",
|
|
181
|
-
acceptedFiles: accepted.files,
|
|
182
|
-
deliveryRecords: this.gitEvidence.deliveryRecordPaths(feature),
|
|
183
|
-
commitSha: requestedCommit,
|
|
184
|
-
idempotent: true,
|
|
185
|
-
...identity,
|
|
186
|
-
};
|
|
187
|
-
}
|
|
188
|
-
const acceptedIdentity = {
|
|
189
|
-
snapshot: accepted.snapshot,
|
|
190
|
-
codeSnapshot: accepted.codeSnapshot,
|
|
191
|
-
requirementsSnapshot: accepted.requirementsSnapshot,
|
|
192
|
-
headSha: identity.headSha,
|
|
193
|
-
};
|
|
194
|
-
const acceptanceBlockers = this.acceptancePolicy.acceptBlockers(feature, ledger, ticket, progress, acceptedIdentity);
|
|
195
|
-
if (acceptanceBlockers.length > 0) {
|
|
196
|
-
throw new Error(`Accepted evidence is no longer valid for integration:\n${acceptanceBlockers.join("\n")}`);
|
|
197
|
-
}
|
|
198
|
-
const headSha = this.gitEvidence.headSha();
|
|
199
|
-
if (headSha !== requestedCommit) {
|
|
200
|
-
throw new Error(`Commit ${requestedCommit} must be the current HEAD (${headSha}) before integration can be confirmed.`);
|
|
201
|
-
}
|
|
202
|
-
const ancestry = this.gitEvidence
|
|
203
|
-
.gitBuffer(["rev-list", "--parents", "-n", "1", requestedCommit])
|
|
204
|
-
.toString("utf8")
|
|
205
|
-
.trim()
|
|
206
|
-
.split(/\s+/);
|
|
207
|
-
if (ancestry.length !== 2 || ancestry[1] !== progress.baseSha) {
|
|
208
|
-
throw new Error(`Commit ${requestedCommit} must be a caller-created child of the recorded baseline ${progress.baseSha}.`);
|
|
209
|
-
}
|
|
210
|
-
const committedFiles = this.gitEvidence
|
|
211
|
-
.gitBuffer([
|
|
212
|
-
"diff",
|
|
213
|
-
"--name-only",
|
|
214
|
-
"-z",
|
|
215
|
-
"--no-renames",
|
|
216
|
-
progress.baseSha,
|
|
217
|
-
requestedCommit,
|
|
218
|
-
"--",
|
|
219
|
-
".",
|
|
220
|
-
])
|
|
221
|
-
.toString("utf8")
|
|
222
|
-
.split("\0")
|
|
223
|
-
.filter(Boolean)
|
|
224
|
-
.sort();
|
|
225
|
-
if (JSON.stringify(committedFiles) !== JSON.stringify(accepted.files)) {
|
|
226
|
-
throw new Error(`Commit contents do not match the accepted inventory; expected ${JSON.stringify(accepted.files)}, found ${JSON.stringify(committedFiles)}.`);
|
|
227
|
-
}
|
|
228
|
-
if (this.gitEvidence.gitTreeContentDigest(requestedCommit, accepted.files) !==
|
|
229
|
-
accepted.contentDigest) {
|
|
230
|
-
throw new Error("Caller commit content does not match the accepted file content.");
|
|
231
|
-
}
|
|
232
|
-
if (this.gitEvidence.worktreeContentDigest(accepted.files) !== accepted.contentDigest) {
|
|
233
|
-
throw new Error("Accepted file content changed before integration confirmation.");
|
|
234
|
-
}
|
|
235
|
-
if (this.gitEvidence.gitIndexContentDigest(accepted.files) !== accepted.contentDigest) {
|
|
236
|
-
throw new Error("Staged index content does not match the accepted file content.");
|
|
237
|
-
}
|
|
238
|
-
progress.execution = "integrated";
|
|
239
|
-
progress.integration = {
|
|
240
|
-
commitSha: requestedCommit,
|
|
241
|
-
integratedAt: new Date().toISOString(),
|
|
242
|
-
integratedBy: options.author.trim(),
|
|
243
|
-
files: accepted.files,
|
|
244
|
-
contentDigest: accepted.contentDigest,
|
|
245
|
-
};
|
|
246
|
-
const afterTicket = matter.stringify(this.ticketRepository.appendAudit(ticket.body, options.author, `Ticket integration confirmed against caller-owned commit ${requestedCommit}; delivery records remain caller-owned.`), this.ticketRepository.metadata(ticket));
|
|
247
|
-
this.workspaceTransaction.writeWorkflowState(feature, ticket, afterTicket, ledger);
|
|
248
|
-
return {
|
|
249
|
-
ticket: options.ticket,
|
|
250
|
-
execution: "integrated",
|
|
251
|
-
acceptedFiles: accepted.files,
|
|
252
|
-
deliveryRecords: this.gitEvidence.deliveryRecordPaths(feature),
|
|
253
|
-
commitSha: requestedCommit,
|
|
254
|
-
...this.gitEvidence.contentIdentity(feature, this.ticketRepository.requireTicket(this.ticketRepository.readTickets(feature.workspace), options.ticket), progress.baseSha, progress.checks),
|
|
255
|
-
};
|
|
256
|
-
});
|
|
257
|
-
}
|
|
258
|
-
}
|
|
File without changes
|
/package/build/Assets/Blueprints/skills/{asd-ste100 → ref-asd-ste100}/examples/before-after.md
RENAMED
|
File without changes
|
/package/build/Assets/Blueprints/skills/{asd-ste100 → ref-asd-ste100}/references/writing-rules.md
RENAMED
|
File without changes
|