devrites 7.3.4 → 7.3.5
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/CHANGELOG.md +18 -0
- package/README.md +1 -1
- package/docs/adr/0039-autocomplete-structural-admission.md +87 -0
- package/docs/adr/README.md +1 -0
- package/docs/cli.md +103 -5
- package/docs/engine/commands.md +46 -1
- package/engine/internal/lib/claims.go +65 -8
- package/engine/internal/lib/continuation.go +6 -1
- package/engine/internal/lib/dispatch.go +78 -32
- package/engine/internal/lib/frontier.go +103 -47
- package/engine/internal/lib/frontier_controller.go +652 -0
- package/engine/internal/lib/frontier_roadmap.go +168 -0
- package/engine/internal/lib/next.go +9 -0
- package/engine/internal/parallel/repository.go +10 -0
- package/pack/.claude/skills/devrites-lib/reference/parallel-workspaces.md +106 -115
- package/pack/.claude/skills/devrites-lib/reference/standards/afk-hitl.md +18 -17
- package/pack/.claude/skills/devrites-lib/reference/workspace-artifact-schema.md +41 -38
- package/pack/.claude/skills/rite-autocomplete/SKILL.md +33 -38
- package/pack/.claude/skills/rite-autocomplete/reference/loop.md +46 -52
- package/pack/.claude/skills/rite-autocomplete/reference/stop-conditions.md +28 -28
- package/pack/.claude/skills/rite-build/reference/parallel-batch.md +17 -15
- package/pack/generated/claude/skills/devrites-lib/reference/parallel-workspaces.md +106 -115
- package/pack/generated/claude/skills/devrites-lib/reference/standards/afk-hitl.md +18 -17
- package/pack/generated/claude/skills/devrites-lib/reference/workspace-artifact-schema.md +41 -38
- package/pack/generated/claude/skills/rite-autocomplete/SKILL.md +33 -38
- package/pack/generated/claude/skills/rite-autocomplete/reference/loop.md +46 -52
- package/pack/generated/claude/skills/rite-autocomplete/reference/stop-conditions.md +28 -28
- package/pack/generated/claude/skills/rite-build/reference/parallel-batch.md +17 -15
- package/pack/generated/codex/skills/devrites-lib/reference/parallel-workspaces.md +106 -115
- package/pack/generated/codex/skills/devrites-lib/reference/standards/afk-hitl.md +18 -17
- package/pack/generated/codex/skills/devrites-lib/reference/workspace-artifact-schema.md +41 -38
- package/pack/generated/codex/skills/rite-autocomplete/SKILL.md +33 -38
- package/pack/generated/codex/skills/rite-autocomplete/reference/loop.md +46 -52
- package/pack/generated/codex/skills/rite-autocomplete/reference/stop-conditions.md +28 -28
- package/pack/generated/codex/skills/rite-build/reference/parallel-batch.md +17 -15
- package/pack/generated/devin/skills/devrites-lib/reference/parallel-workspaces.md +106 -115
- package/pack/generated/devin/skills/devrites-lib/reference/standards/afk-hitl.md +18 -17
- package/pack/generated/devin/skills/devrites-lib/reference/workspace-artifact-schema.md +41 -38
- package/pack/generated/devin/skills/rite-autocomplete/SKILL.md +33 -38
- package/pack/generated/devin/skills/rite-autocomplete/reference/loop.md +46 -52
- package/pack/generated/devin/skills/rite-autocomplete/reference/stop-conditions.md +28 -28
- package/pack/generated/devin/skills/rite-build/reference/parallel-batch.md +17 -15
- package/pack/generated/dsh/skills/devrites-lib/reference/parallel-workspaces.md +106 -115
- package/pack/generated/dsh/skills/devrites-lib/reference/standards/afk-hitl.md +18 -17
- package/pack/generated/dsh/skills/devrites-lib/reference/workspace-artifact-schema.md +41 -38
- package/pack/generated/dsh/skills/rite-autocomplete/SKILL.md +33 -38
- package/pack/generated/dsh/skills/rite-autocomplete/reference/loop.md +46 -52
- package/pack/generated/dsh/skills/rite-autocomplete/reference/stop-conditions.md +28 -28
- package/pack/generated/dsh/skills/rite-build/reference/parallel-batch.md +17 -15
- package/pack/generated/omp/skills/devrites-lib/reference/parallel-workspaces.md +106 -115
- package/pack/generated/omp/skills/devrites-lib/reference/standards/afk-hitl.md +18 -17
- package/pack/generated/omp/skills/devrites-lib/reference/workspace-artifact-schema.md +41 -38
- package/pack/generated/omp/skills/rite-autocomplete/SKILL.md +33 -38
- package/pack/generated/omp/skills/rite-autocomplete/reference/loop.md +46 -52
- package/pack/generated/omp/skills/rite-autocomplete/reference/stop-conditions.md +28 -28
- package/pack/generated/omp/skills/rite-build/reference/parallel-batch.md +17 -15
- package/pack/generated/pi/skills/devrites-lib/reference/parallel-workspaces.md +106 -115
- package/pack/generated/pi/skills/devrites-lib/reference/standards/afk-hitl.md +18 -17
- package/pack/generated/pi/skills/devrites-lib/reference/workspace-artifact-schema.md +41 -38
- package/pack/generated/pi/skills/rite-autocomplete/SKILL.md +33 -38
- package/pack/generated/pi/skills/rite-autocomplete/reference/loop.md +46 -52
- package/pack/generated/pi/skills/rite-autocomplete/reference/stop-conditions.md +28 -28
- package/pack/generated/pi/skills/rite-build/reference/parallel-batch.md +17 -15
- package/package.json +1 -1
|
@@ -5,7 +5,6 @@ import (
|
|
|
5
5
|
"io"
|
|
6
6
|
"os"
|
|
7
7
|
"path/filepath"
|
|
8
|
-
"sort"
|
|
9
8
|
"strconv"
|
|
10
9
|
"strings"
|
|
11
10
|
|
|
@@ -241,6 +240,10 @@ func frontierQuote(s string) string { return "'" + strings.ReplaceAll(s, "'", "'
|
|
|
241
240
|
|
|
242
241
|
// FrontierLines reports structural obligations, never semantic authorization or Ship approval.
|
|
243
242
|
func FrontierLines(root, slug string) ([]string, error) {
|
|
243
|
+
mode, err := autocompleteMode(root)
|
|
244
|
+
if err != nil {
|
|
245
|
+
return nil, err
|
|
246
|
+
}
|
|
244
247
|
if slug == "" {
|
|
245
248
|
var err error
|
|
246
249
|
slug, err = devritespaths.ActiveSlug(root)
|
|
@@ -248,11 +251,13 @@ func FrontierLines(root, slug string) ([]string, error) {
|
|
|
248
251
|
return nil, err
|
|
249
252
|
}
|
|
250
253
|
}
|
|
254
|
+
workspaceOverride := ""
|
|
251
255
|
if slug != "" {
|
|
252
256
|
if !devritespaths.ValidSlug(slug) {
|
|
253
257
|
return nil, fmt.Errorf("invalid source slug")
|
|
254
258
|
}
|
|
255
|
-
|
|
259
|
+
workspaceOverride, err = devritespaths.WorkspaceOverrideChecked(root, slug)
|
|
260
|
+
if err != nil {
|
|
256
261
|
return nil, err
|
|
257
262
|
}
|
|
258
263
|
}
|
|
@@ -288,44 +293,21 @@ func FrontierLines(root, slug string) ([]string, error) {
|
|
|
288
293
|
}
|
|
289
294
|
chain, chainErr := frontierChain(nodes, slug)
|
|
290
295
|
if chainErr != nil {
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
if !changed {
|
|
304
|
-
break
|
|
305
|
-
}
|
|
306
|
-
}
|
|
296
|
+
location := "work"
|
|
297
|
+
if source.location == "archive" {
|
|
298
|
+
location = "archive"
|
|
299
|
+
}
|
|
300
|
+
artifact := filepath.Join(root, location, slug, "state.md")
|
|
301
|
+
return []string{
|
|
302
|
+
"frontier: blocked", "frontier-source: " + slug,
|
|
303
|
+
fmt.Sprintf("frontier-workspace: %s location=%s action=repair reason=%s", slug, source.location, chainErr),
|
|
304
|
+
"frontier-review-sequence: " + artifact + " reason=native authority-normalization required: " + chainErr.Error(),
|
|
305
|
+
}, nil
|
|
306
|
+
}
|
|
307
|
+
ordered, related := frontierRelated(nodes, chain)
|
|
307
308
|
if len(related) == 1 && source.parent == "" && !source.hasPosition && !source.hasRemaining && frontierSpecTarget(source) == "" {
|
|
308
309
|
return []string{"frontier: none"}, nil
|
|
309
310
|
}
|
|
310
|
-
ordered := make([]string, 0, len(related))
|
|
311
|
-
for name := range related {
|
|
312
|
-
ordered = append(ordered, name)
|
|
313
|
-
}
|
|
314
|
-
depth := make(map[string]int, len(ordered))
|
|
315
|
-
for _, name := range ordered {
|
|
316
|
-
chain, _ := frontierChain(nodes, name)
|
|
317
|
-
depth[name] = len(chain)
|
|
318
|
-
}
|
|
319
|
-
sort.Slice(ordered, func(i, j int) bool {
|
|
320
|
-
a, b := nodes[ordered[i]], nodes[ordered[j]]
|
|
321
|
-
if depth[a.slug] != depth[b.slug] {
|
|
322
|
-
return depth[a.slug] < depth[b.slug]
|
|
323
|
-
}
|
|
324
|
-
if a.position != b.position {
|
|
325
|
-
return a.position < b.position
|
|
326
|
-
}
|
|
327
|
-
return a.slug < b.slug
|
|
328
|
-
})
|
|
329
311
|
controller := ""
|
|
330
312
|
for _, name := range ordered {
|
|
331
313
|
if nodes[name].location == "live" {
|
|
@@ -350,6 +332,9 @@ func FrontierLines(root, slug string) ([]string, error) {
|
|
|
350
332
|
if err != nil {
|
|
351
333
|
return nil, err
|
|
352
334
|
}
|
|
335
|
+
if workspaceOverride != "" {
|
|
336
|
+
allowFuture = false
|
|
337
|
+
}
|
|
353
338
|
if lease != nil && lease.Capacity > 0 && capN > lease.Capacity {
|
|
354
339
|
capN = lease.Capacity
|
|
355
340
|
}
|
|
@@ -364,11 +349,30 @@ func FrontierLines(root, slug string) ([]string, error) {
|
|
|
364
349
|
if source.hasRemaining && source.remaining == 0 {
|
|
365
350
|
allowFuture = false
|
|
366
351
|
}
|
|
367
|
-
maps, artifacts, mapProblem := frontierRoadmap(nodes, ordered)
|
|
352
|
+
maps, artifacts, mapProblem, invalidCanonical := frontierRoadmap(nodes, ordered)
|
|
353
|
+
if invalidCanonical {
|
|
354
|
+
return []string{"frontier: blocked", "frontier-source: " + slug, "frontier-review-sequence: " + strings.Join(artifacts, ",") + " reason=native authority-normalization required: invalid canonical authority: " + mapProblem}, nil
|
|
355
|
+
}
|
|
356
|
+
if len(maps) > 0 && mapProblem == "" {
|
|
357
|
+
lines = append(lines, "frontier-authority: "+strings.Join(artifacts, ","))
|
|
358
|
+
}
|
|
359
|
+
records := frontierRecords{}
|
|
360
|
+
if mode {
|
|
361
|
+
records, err = frontierEvidence(root, slug)
|
|
362
|
+
if err != nil {
|
|
363
|
+
return nil, err
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
sequenceDeferred := mode && records.blocked["sequence"] != ""
|
|
368
367
|
if mapProblem != "" {
|
|
369
|
-
|
|
370
|
-
|
|
368
|
+
if sequenceDeferred {
|
|
369
|
+
lines = append(lines, "frontier-blocked: sequence — "+records.blocked["sequence"]+"; scheduling deferred, not normalized")
|
|
370
|
+
} else {
|
|
371
|
+
lines = append(lines, "frontier-review-sequence: "+strings.Join(artifacts, ",")+" reason=native authority-normalization required: "+mapProblem)
|
|
372
|
+
blocked = true
|
|
373
|
+
}
|
|
371
374
|
}
|
|
375
|
+
deferred := map[string]string{}
|
|
372
376
|
prepared := map[string]bool{}
|
|
373
377
|
for _, name := range ordered {
|
|
374
378
|
n := nodes[name]
|
|
@@ -386,15 +390,21 @@ func FrontierLines(root, slug string) ([]string, error) {
|
|
|
386
390
|
if err != nil {
|
|
387
391
|
action, reason, n.selectionHeld = "repair", err.Error(), true
|
|
388
392
|
}
|
|
393
|
+
if mode && action == "prepare" && deferred[name] != "" {
|
|
394
|
+
action, reason, n.selectionHeld = "wait", "frontier-blocked: "+name+" — "+deferred[name], true
|
|
395
|
+
}
|
|
389
396
|
if !n.selectionHeld {
|
|
390
397
|
live = append(live, name)
|
|
391
398
|
}
|
|
392
|
-
held = action == "blocked" || err != nil
|
|
399
|
+
held = action == "blocked" || err != nil || mode && action == "wait" && deferred[name] != ""
|
|
393
400
|
switch action {
|
|
394
401
|
case "inspect", "prepare", "repair":
|
|
395
402
|
actionable = true
|
|
396
403
|
case "wait":
|
|
397
404
|
waiting = true
|
|
405
|
+
case "no-cursor":
|
|
406
|
+
blocked = true
|
|
407
|
+
action = "wait"
|
|
398
408
|
case "blocked":
|
|
399
409
|
blocked = true
|
|
400
410
|
action = "wait"
|
|
@@ -409,7 +419,7 @@ func FrontierLines(root, slug string) ([]string, error) {
|
|
|
409
419
|
target = maps[n.position+1]
|
|
410
420
|
}
|
|
411
421
|
if mapProblem != "" {
|
|
412
|
-
if target != "" || n.hasRemaining && n.remaining > 0 {
|
|
422
|
+
if !sequenceDeferred && (target != "" || n.hasRemaining && n.remaining > 0) {
|
|
413
423
|
actionable = true
|
|
414
424
|
}
|
|
415
425
|
continue
|
|
@@ -429,6 +439,20 @@ func FrontierLines(root, slug string) ([]string, error) {
|
|
|
429
439
|
actionable, blocked = true, true
|
|
430
440
|
continue
|
|
431
441
|
}
|
|
442
|
+
if mode && target != "" {
|
|
443
|
+
sourceRecords := records
|
|
444
|
+
if name != slug {
|
|
445
|
+
sourceRecords, err = frontierEvidence(root, name)
|
|
446
|
+
if err != nil {
|
|
447
|
+
return nil, err
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
if reason := sourceRecords.blocked[target]; reason != "" {
|
|
451
|
+
deferred[target] = reason
|
|
452
|
+
lines = append(lines, "frontier-blocked: "+target+" source="+name+" — "+reason+"; preparation deferred, not approved")
|
|
453
|
+
continue
|
|
454
|
+
}
|
|
455
|
+
}
|
|
432
456
|
if target != "" && nodes[target] == nil && !prepared[target] {
|
|
433
457
|
prepared[target] = true
|
|
434
458
|
// A table identifies a preparation obligation, not approval to implement it.
|
|
@@ -439,6 +463,23 @@ func FrontierLines(root, slug string) ([]string, error) {
|
|
|
439
463
|
actionable, blocked = true, true
|
|
440
464
|
}
|
|
441
465
|
}
|
|
466
|
+
if mode {
|
|
467
|
+
filtered := candidates[:0]
|
|
468
|
+
for _, candidate := range candidates {
|
|
469
|
+
workspace := candidate.Workspace
|
|
470
|
+
if workspace == "" {
|
|
471
|
+
workspace = controller
|
|
472
|
+
}
|
|
473
|
+
if workspace != slug {
|
|
474
|
+
if reason := frontierSerialReason(records, slug, workspace, candidate.ID); reason != "" {
|
|
475
|
+
lines = append(lines, "frontier-serial: "+workspace+"/"+candidate.ID+" — "+reason+"; ordered handoff retained")
|
|
476
|
+
continue
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
filtered = append(filtered, candidate)
|
|
480
|
+
}
|
|
481
|
+
candidates = filtered
|
|
482
|
+
}
|
|
442
483
|
if controller != "" && controllerProblem == "" && len(live) > 0 {
|
|
443
484
|
lines = append(lines, fmt.Sprintf("frontier-select-command: devrites-engine parallel select --root %s --slug %s --from-plan --workspaces %s --cap %d", frontierQuote(filepath.Dir(root)), frontierQuote(controller), frontierQuote(strings.Join(live, ",")), capN))
|
|
444
485
|
if len(candidates) > 0 {
|
|
@@ -638,12 +679,22 @@ func frontierLocal(root, controller string, n *frontierWorkspace, candidates *[]
|
|
|
638
679
|
n.selectionHeld = true
|
|
639
680
|
return "wait", "Ship requires existing native authority; controller invocation is not approval", nil
|
|
640
681
|
}
|
|
682
|
+
if n.next == "" {
|
|
683
|
+
// Missing local work is not a hold on independently recorded preparation.
|
|
684
|
+
n.selectionHeld = true
|
|
685
|
+
return "no-cursor", "no actionable native internal cursor; review state without inventing authority", nil
|
|
686
|
+
}
|
|
641
687
|
return "blocked", "no actionable native internal cursor; review state without inventing authority", nil
|
|
642
688
|
}
|
|
643
689
|
|
|
644
|
-
//
|
|
645
|
-
//
|
|
646
|
-
func frontierRoadmap(nodes map[string]*frontierWorkspace, ordered []string) (map[int]string, []string, string) {
|
|
690
|
+
// Current canonical authority supersedes historical tables without rewriting them.
|
|
691
|
+
// Without it, differing exact legacy maps require native normalization.
|
|
692
|
+
func frontierRoadmap(nodes map[string]*frontierWorkspace, ordered []string) (map[int]string, []string, string, bool) {
|
|
693
|
+
if mapping, artifacts, err := frontierCanonicalRoadmap(nodes, ordered); err != nil {
|
|
694
|
+
return nil, artifacts, err.Error(), true
|
|
695
|
+
} else if mapping != nil {
|
|
696
|
+
return mapping, artifacts, "", false
|
|
697
|
+
}
|
|
647
698
|
result := map[int]string{}
|
|
648
699
|
var artifacts []string
|
|
649
700
|
problem := ""
|
|
@@ -743,7 +794,7 @@ func frontierRoadmap(nodes map[string]*frontierWorkspace, ordered []string) (map
|
|
|
743
794
|
artifacts = append(artifacts, filepath.Join(nodes[slug].dir, "state.md"))
|
|
744
795
|
}
|
|
745
796
|
}
|
|
746
|
-
return result, artifacts, problem
|
|
797
|
+
return result, artifacts, problem, false
|
|
747
798
|
}
|
|
748
799
|
|
|
749
800
|
func frontierCells(line string) []string {
|
|
@@ -782,6 +833,12 @@ func frontierBoundSpec(root, slug, action string) bool {
|
|
|
782
833
|
if err != nil {
|
|
783
834
|
return false
|
|
784
835
|
}
|
|
836
|
+
ordered, _ := frontierRelated(nodes, chain)
|
|
837
|
+
mapping, _, problem, invalidCanonical := frontierRoadmap(nodes, ordered)
|
|
838
|
+
if invalidCanonical {
|
|
839
|
+
return false
|
|
840
|
+
}
|
|
841
|
+
// Existing checked children remain resumable under ambiguous historical maps.
|
|
785
842
|
if child := nodes[target]; child != nil {
|
|
786
843
|
if child.parent != slug {
|
|
787
844
|
return false
|
|
@@ -791,7 +848,6 @@ func frontierBoundSpec(root, slug, action string) bool {
|
|
|
791
848
|
}
|
|
792
849
|
return true
|
|
793
850
|
}
|
|
794
|
-
mapping, _, problem := frontierRoadmap(nodes, chain)
|
|
795
851
|
if problem != "" || n.hasPosition && mapping[n.position+1] != "" && mapping[n.position+1] != target {
|
|
796
852
|
return false
|
|
797
853
|
}
|