@mgiles/perk 1.0.1 → 1.1.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.
Files changed (120) hide show
  1. package/README.md +7 -21
  2. package/extension/checkpoints/checkpoints.ts +2 -1
  3. package/extension/doors/address.ts +2 -1
  4. package/extension/doors/ciExecutor.ts +3 -2
  5. package/extension/doors/land.ts +2 -1
  6. package/extension/doors/learn.ts +239 -33
  7. package/extension/doors/learnCode.ts +100 -0
  8. package/extension/doors/learnDocs.ts +4 -3
  9. package/extension/doors/lifecycleGates.ts +2 -1
  10. package/extension/doors/prReview.ts +20 -35
  11. package/extension/doors/prReviewLocal.ts +229 -0
  12. package/extension/doors/ready.ts +2 -1
  13. package/extension/doors/selfcheck.ts +2 -1
  14. package/extension/doors/submit.ts +17 -19
  15. package/extension/factories/implementHere.ts +116 -0
  16. package/extension/factories/objective.ts +2 -1
  17. package/extension/factories/objectivePlan.ts +4 -24
  18. package/extension/factories/objectiveSave.ts +5 -15
  19. package/extension/factories/planMode.ts +5 -1
  20. package/extension/factories/planReview.ts +103 -11
  21. package/extension/factories/planSave.ts +16 -1
  22. package/extension/index.ts +42 -3
  23. package/extension/substrate/bindings.ts +1 -1
  24. package/extension/substrate/cache.ts +2 -2
  25. package/extension/substrate/command.ts +25 -0
  26. package/extension/substrate/config.ts +12 -13
  27. package/extension/substrate/consoleCapture.ts +90 -0
  28. package/extension/substrate/git.ts +34 -0
  29. package/extension/substrate/miniJinja.ts +480 -0
  30. package/extension/substrate/paths.ts +38 -0
  31. package/extension/substrate/prompts.ts +15 -24
  32. package/extension/substrate/providers.ts +1 -1
  33. package/extension/substrate/sessionData.ts +1 -1
  34. package/extension/substrate/sessionPointers.ts +155 -0
  35. package/extension/substrate/toolGating.ts +8 -0
  36. package/extension/surfaces/surfaces.ts +10 -3
  37. package/extension/worker/worker.ts +111 -25
  38. package/extension/workerMain.ts +5 -3
  39. package/package.json +1 -5
  40. package/prompts/README.md +56 -5
  41. package/prompts/_fixtures/cases.yaml +52 -131
  42. package/prompts/_fixtures/golden/cond_elif-a.txt +3 -0
  43. package/prompts/_fixtures/golden/cond_elif-b.txt +3 -0
  44. package/prompts/_fixtures/golden/cond_elif-c.txt +3 -0
  45. package/prompts/_fixtures/golden/cond_if-false.txt +3 -0
  46. package/prompts/_fixtures/golden/cond_if-true.txt +3 -0
  47. package/prompts/_fixtures/golden/cond_ops-1.txt +3 -0
  48. package/prompts/_fixtures/golden/cond_ops-2.txt +3 -0
  49. package/prompts/_fixtures/golden/no_trailing_nl.txt +2 -0
  50. package/prompts/_fixtures/golden/trailing_nl.txt +2 -0
  51. package/prompts/_fixtures/golden/trim_block.txt +3 -0
  52. package/prompts/_fixtures/golden/trim_inline.txt +1 -0
  53. package/prompts/_fixtures/live.yaml +281 -0
  54. package/prompts/_fixtures/templates/cond_elif.md +9 -0
  55. package/prompts/_fixtures/templates/cond_if.md +7 -0
  56. package/prompts/_fixtures/templates/cond_ops.md +3 -0
  57. package/prompts/_fixtures/templates/no_trailing_nl.md +2 -0
  58. package/prompts/_fixtures/templates/trailing_nl.md +2 -0
  59. package/prompts/_fixtures/templates/trim_block.md +5 -0
  60. package/prompts/_fixtures/templates/trim_inline.md +1 -0
  61. package/prompts/stages/conflict-resolution.md +4 -0
  62. package/prompts/stages/learn-code.md +8 -0
  63. package/prompts/stages/learn-docs.md +7 -6
  64. package/prompts/stages/learn-orchestrate.md +6 -0
  65. package/prompts/stages/learn.md +1 -1
  66. package/prompts/stages/objective-author/adopt.md +12 -0
  67. package/prompts/stages/objective-author/file.md +9 -0
  68. package/prompts/stages/objective-author/seed.md +9 -0
  69. package/prompts/stages/objective-plan/seed.md +2 -1
  70. package/prompts/stages/objective-reconcile.md +7 -0
  71. package/prompts/stages/objective-replan.md +14 -0
  72. package/prompts/stages/objective-save.md +9 -0
  73. package/prompts/stages/plan-from/adopt.md +10 -0
  74. package/prompts/stages/plan-from/file.md +9 -0
  75. package/prompts/stages/pr-review.md +6 -0
  76. package/prompts/stages/replan.md +13 -0
  77. package/prompts/stages/skills/create-from.md +15 -0
  78. package/prompts/stages/skills/create.md +9 -0
  79. package/prompts/stages/skills/refine.md +9 -0
  80. package/shared/README.md +7 -1
  81. package/shared/bindings.yaml +12 -0
  82. package/shared/contracts-history.md +167 -0
  83. package/shared/contracts.md +1307 -342
  84. package/shared/registry.yaml +3 -3
  85. package/shared/schemas/contracts/bindings.schema.json +38 -0
  86. package/shared/schemas/contracts/providers.schema.json +89 -0
  87. package/shared/schemas/contracts/registry.schema.json +98 -0
  88. package/shared/schemas/inputs/handoff-arg.schema.json +6 -0
  89. package/shared/schemas/inputs/resolve-threads-batch.schema.json +37 -0
  90. package/shared/schemas/inputs/review-post-batch.schema.json +84 -0
  91. package/shared/schemas/inputs/structured-roadmap-node.schema.json +102 -0
  92. package/shared/schemas/outputs/doctor-report.schema.json +236 -0
  93. package/shared/schemas/outputs/init-report.schema.json +419 -0
  94. package/shared/schemas/outputs/learn-capture.schema.json +90 -0
  95. package/shared/schemas/outputs/learn-skip.schema.json +59 -0
  96. package/shared/schemas/outputs/plan-save.schema.json +209 -0
  97. package/shared/schemas/outputs/pr-feedback.schema.json +334 -0
  98. package/shared/schemas/outputs/pr-land.schema.json +187 -0
  99. package/shared/schemas/outputs/pr-ready.schema.json +75 -0
  100. package/shared/schemas/outputs/pr-review-context.schema.json +86 -0
  101. package/shared/schemas/outputs/pr-submit.schema.json +147 -0
  102. package/prompts/_fixtures/golden/address-action-model.txt +0 -10
  103. package/prompts/_fixtures/golden/address-action.txt +0 -10
  104. package/prompts/_fixtures/golden/address-preview-model.txt +0 -6
  105. package/prompts/_fixtures/golden/address-preview.txt +0 -6
  106. package/prompts/_fixtures/golden/implement-github.txt +0 -8
  107. package/prompts/_fixtures/golden/learn-docs.txt +0 -8
  108. package/prompts/_fixtures/golden/learn-github.txt +0 -11
  109. package/prompts/_fixtures/golden/learn-linear.txt +0 -11
  110. package/prompts/_fixtures/golden/learn-no-ref.txt +0 -8
  111. package/prompts/_fixtures/golden/learn-other.txt +0 -8
  112. package/prompts/_fixtures/golden/objective-plan-guidance-linear.txt +0 -8
  113. package/prompts/_fixtures/golden/objective-plan-guidance.txt +0 -8
  114. package/prompts/_fixtures/golden/objective-plan-seed-linear.txt +0 -20
  115. package/prompts/_fixtures/golden/objective-plan-seed.txt +0 -15
  116. package/prompts/_fixtures/golden/objective-read-linear-nourl.txt +0 -1
  117. package/prompts/_fixtures/golden/objective-read-linear.txt +0 -1
  118. package/prompts/_fixtures/golden/plan-read-github.txt +0 -1
  119. package/prompts/_fixtures/golden/plan-read-linear.txt +0 -1
  120. package/prompts/_fixtures/golden/plan-read-other.txt +0 -1
@@ -27,7 +27,7 @@ state_keys:
27
27
  - comments # discussion comments
28
28
  - review-threads # review threads (distinct API from comments)
29
29
  - learn # the perk:learn knowledge-capture issue (P2.T8b)
30
- # Tier 2 · .pi/workflow/ — the local cache (see contracts.md §8.1).
30
+ # Tier 2 · .perk/workflow/ — the local cache (see contracts.md §8.1).
31
31
  cache:
32
32
  - plan # materialized plan body cache
33
33
  - plan-ref # provider-agnostic plan->branch ref (see contracts.md §8.4)
@@ -175,7 +175,7 @@ stages:
175
175
  command: pr land
176
176
  requires: [github.pr] # T5b: the PR to merge must exist
177
177
  reads: [cache.plan-ref, github.pr, github.objective] # T5b ref->branch->PR; T11a node lookup
178
- writes: [github.pr, cache.markers, github.objective] # T5b merge+marker; T11a mechanical node-done
178
+ writes: [github.pr, cache.markers, github.objective, github.plan] # T5b merge+marker; T11a mechanical node-done; §8.36 learn_state header stamp
179
179
  predecessors: [address]
180
180
  successors: [learn]
181
181
 
@@ -194,6 +194,6 @@ stages:
194
194
  # keys (no new gateway op) — the existing learn tool / learn capture worker still persist.
195
195
  requires: [cache.markers] # pending-learn gates the worktree
196
196
  reads: [cache.markers, cache.plan-ref] # was it set? + the plan ref -> issue number/run_id
197
- writes: [cache.markers, github.learn, github.comments] # clear marker; create learn issue + back-link
197
+ writes: [cache.markers, github.learn, github.comments, github.plan] # clear marker; create learn issue + back-link; §8.36 learn_state header stamp
198
198
  predecessors: [land]
199
199
  successors: []
@@ -0,0 +1,38 @@
1
+ {
2
+ "$defs": {
3
+ "BindingEntry": {
4
+ "description": "Tolerant parse shape for one stored ``bindings.yaml`` entry.\n\nLenient base: unknown keys dropped (``extra=\"ignore\"``); absent keys default to ``\"\"`` so\n``validate()`` reports them as content findings. A present non-string scalar is a genuine\ntype error and raises (translated to ``BindingsError`` at the load boundary).",
5
+ "properties": {
6
+ "trigger": {
7
+ "default": "",
8
+ "title": "Trigger",
9
+ "type": "string"
10
+ },
11
+ "skill": {
12
+ "default": "",
13
+ "title": "Skill",
14
+ "type": "string"
15
+ },
16
+ "mode": {
17
+ "default": "",
18
+ "title": "Mode",
19
+ "type": "string"
20
+ }
21
+ },
22
+ "title": "BindingEntry",
23
+ "type": "object"
24
+ }
25
+ },
26
+ "description": "Whole-file parse shape.\n\n``schema_version`` stays OUT of the model (a structural pre-check in ``load_bindings`` owns\nits byte-identical message; ``extra=\"ignore\"`` drops the key here). A non-list ``bindings:``\nraises.",
27
+ "properties": {
28
+ "bindings": {
29
+ "items": {
30
+ "$ref": "#/$defs/BindingEntry"
31
+ },
32
+ "title": "Bindings",
33
+ "type": "array"
34
+ }
35
+ },
36
+ "title": "BindingsFile",
37
+ "type": "object"
38
+ }
@@ -0,0 +1,89 @@
1
+ {
2
+ "$defs": {
3
+ "ProviderEntry": {
4
+ "description": "The lenient per-entry parse model at the file boundary.\n\n``id``/``seam`` are typed ``str | None`` (not ``str = \"\"``) so an explicit YAML ``null`` parses\ncleanly; the converter normalizes ``None -> \"\"`` and ``validate()`` then surfaces the\nmissing-``id`` / bad-``seam`` content findings. Other fields coerce leniently (drop unknown\nkeys, coerce ordinary scalars) per the lenient base \u2014 content findings are the *validator*'s\njob, never construction's.",
5
+ "properties": {
6
+ "id": {
7
+ "anyOf": [
8
+ {
9
+ "type": "string"
10
+ },
11
+ {
12
+ "type": "null"
13
+ }
14
+ ],
15
+ "default": null,
16
+ "title": "Id"
17
+ },
18
+ "seam": {
19
+ "anyOf": [
20
+ {
21
+ "type": "string"
22
+ },
23
+ {
24
+ "type": "null"
25
+ }
26
+ ],
27
+ "default": null,
28
+ "title": "Seam"
29
+ },
30
+ "package": {
31
+ "anyOf": [
32
+ {
33
+ "type": "string"
34
+ },
35
+ {
36
+ "type": "null"
37
+ }
38
+ ],
39
+ "default": null,
40
+ "title": "Package"
41
+ },
42
+ "adapter": {
43
+ "anyOf": [
44
+ {
45
+ "type": "string"
46
+ },
47
+ {
48
+ "type": "null"
49
+ }
50
+ ],
51
+ "default": null,
52
+ "title": "Adapter"
53
+ },
54
+ "default": {
55
+ "type": "boolean",
56
+ "default": false,
57
+ "title": "Default"
58
+ },
59
+ "package_filter": {
60
+ "anyOf": [
61
+ {
62
+ "additionalProperties": true,
63
+ "type": "object"
64
+ },
65
+ {
66
+ "type": "null"
67
+ }
68
+ ],
69
+ "default": null,
70
+ "title": "Package Filter"
71
+ }
72
+ },
73
+ "title": "ProviderEntry",
74
+ "type": "object"
75
+ }
76
+ },
77
+ "description": "The lenient whole-file parse model.\n\n``schema_version`` is deliberately NOT a field: it stays a structural pre-check in\n``load_providers`` (it must run before generic validation and raise its own message).\n``extra=\"ignore\"`` drops it (and any other top-level key) from this model.",
78
+ "properties": {
79
+ "providers": {
80
+ "items": {
81
+ "$ref": "#/$defs/ProviderEntry"
82
+ },
83
+ "title": "Providers",
84
+ "type": "array"
85
+ }
86
+ },
87
+ "title": "ProvidersFile",
88
+ "type": "object"
89
+ }
@@ -0,0 +1,98 @@
1
+ {
2
+ "$defs": {
3
+ "StageEntry": {
4
+ "description": "The lenient per-stage parse model at the file boundary.\n\nSame fields/defaults as the ``Stage`` domain dataclass; tolerant parsing\n(drop unknown keys, coerce ordinary scalars) per the lenient base.",
5
+ "properties": {
6
+ "id": {
7
+ "default": "",
8
+ "title": "Id",
9
+ "type": "string"
10
+ },
11
+ "summary": {
12
+ "default": "",
13
+ "title": "Summary",
14
+ "type": "string"
15
+ },
16
+ "mode": {
17
+ "default": "",
18
+ "title": "Mode",
19
+ "type": "string"
20
+ },
21
+ "worktree": {
22
+ "default": "",
23
+ "title": "Worktree",
24
+ "type": "string"
25
+ },
26
+ "doors": {
27
+ "additionalProperties": true,
28
+ "title": "Doors",
29
+ "type": "object"
30
+ },
31
+ "run_id": {
32
+ "additionalProperties": true,
33
+ "title": "Run Id",
34
+ "type": "object"
35
+ },
36
+ "command": {
37
+ "default": "",
38
+ "title": "Command",
39
+ "type": "string"
40
+ },
41
+ "requires": {
42
+ "items": {
43
+ "type": "string"
44
+ },
45
+ "title": "Requires",
46
+ "type": "array"
47
+ },
48
+ "reads": {
49
+ "items": {
50
+ "type": "string"
51
+ },
52
+ "title": "Reads",
53
+ "type": "array"
54
+ },
55
+ "writes": {
56
+ "items": {
57
+ "type": "string"
58
+ },
59
+ "title": "Writes",
60
+ "type": "array"
61
+ },
62
+ "predecessors": {
63
+ "items": {
64
+ "type": "string"
65
+ },
66
+ "title": "Predecessors",
67
+ "type": "array"
68
+ },
69
+ "successors": {
70
+ "items": {
71
+ "type": "string"
72
+ },
73
+ "title": "Successors",
74
+ "type": "array"
75
+ }
76
+ },
77
+ "title": "StageEntry",
78
+ "type": "object"
79
+ }
80
+ },
81
+ "description": "The lenient whole-file parse model.\n\n``schema_version`` is deliberately NOT a field: it stays a structural\npre-check in ``load_registry`` (it must run before generic validation and\nraise its own message). ``extra=\"ignore\"`` drops it (and any other top-level\nkey) from this model.",
82
+ "properties": {
83
+ "state_keys": {
84
+ "additionalProperties": true,
85
+ "title": "State Keys",
86
+ "type": "object"
87
+ },
88
+ "stages": {
89
+ "items": {
90
+ "$ref": "#/$defs/StageEntry"
91
+ },
92
+ "title": "Stages",
93
+ "type": "array"
94
+ }
95
+ },
96
+ "title": "RegistryFile",
97
+ "type": "object"
98
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "additionalProperties": true,
3
+ "description": "Minimal strict parse: the ``--handoff`` payload must be a JSON object.\n\nThe handoff is open-ended (cache ``HandoffModel`` is ``extra=\"allow\"``), so this only\nenforces the object shape (a list/scalar fails loudly with a field path).",
4
+ "title": "HandoffArgInput",
5
+ "type": "object"
6
+ }
@@ -0,0 +1,37 @@
1
+ {
2
+ "$defs": {
3
+ "ResolveThreadInput": {
4
+ "additionalProperties": false,
5
+ "description": "One strict batch item (`{thread_id, comment?}`); a typo/wrong type fails loudly.",
6
+ "properties": {
7
+ "thread_id": {
8
+ "title": "Thread Id",
9
+ "type": "string"
10
+ },
11
+ "comment": {
12
+ "anyOf": [
13
+ {
14
+ "type": "string"
15
+ },
16
+ {
17
+ "type": "null"
18
+ }
19
+ ],
20
+ "default": null,
21
+ "title": "Comment"
22
+ }
23
+ },
24
+ "required": [
25
+ "thread_id"
26
+ ],
27
+ "title": "ResolveThreadInput",
28
+ "type": "object"
29
+ }
30
+ },
31
+ "description": "The strict batch root: a JSON array of thread items (a non-array fails loudly).",
32
+ "items": {
33
+ "$ref": "#/$defs/ResolveThreadInput"
34
+ },
35
+ "title": "ResolveThreadsBatch",
36
+ "type": "array"
37
+ }
@@ -0,0 +1,84 @@
1
+ {
2
+ "$defs": {
3
+ "ReviewCommentInput": {
4
+ "additionalProperties": false,
5
+ "description": "One inline review finding in the machine-authored batch (strict: a typo fails loudly).",
6
+ "properties": {
7
+ "path": {
8
+ "minLength": 1,
9
+ "title": "Path",
10
+ "type": "string"
11
+ },
12
+ "line": {
13
+ "title": "Line",
14
+ "type": "integer"
15
+ },
16
+ "body": {
17
+ "minLength": 1,
18
+ "title": "Body",
19
+ "type": "string"
20
+ }
21
+ },
22
+ "required": [
23
+ "path",
24
+ "line",
25
+ "body"
26
+ ],
27
+ "title": "ReviewCommentInput",
28
+ "type": "object"
29
+ }
30
+ },
31
+ "additionalProperties": false,
32
+ "description": "The strict `/pr-review` batch shape (`{verdict, summary, comments?, fyi?}`).\n\n`comments`/`fyi` stay nullable so an explicit `null` is tolerated (today's behavior),\nnormalized to `[]` in conversion. `line: int` under strict rejects `bool`/`float`/`str`\n(preserving the old `isinstance(line, bool)` guard).",
33
+ "properties": {
34
+ "verdict": {
35
+ "enum": [
36
+ "clean",
37
+ "actionable"
38
+ ],
39
+ "title": "Verdict",
40
+ "type": "string"
41
+ },
42
+ "summary": {
43
+ "minLength": 1,
44
+ "title": "Summary",
45
+ "type": "string"
46
+ },
47
+ "comments": {
48
+ "anyOf": [
49
+ {
50
+ "items": {
51
+ "$ref": "#/$defs/ReviewCommentInput"
52
+ },
53
+ "type": "array"
54
+ },
55
+ {
56
+ "type": "null"
57
+ }
58
+ ],
59
+ "default": null,
60
+ "title": "Comments"
61
+ },
62
+ "fyi": {
63
+ "anyOf": [
64
+ {
65
+ "items": {
66
+ "type": "string"
67
+ },
68
+ "type": "array"
69
+ },
70
+ {
71
+ "type": "null"
72
+ }
73
+ ],
74
+ "default": null,
75
+ "title": "Fyi"
76
+ }
77
+ },
78
+ "required": [
79
+ "verdict",
80
+ "summary"
81
+ ],
82
+ "title": "ReviewBatchInput",
83
+ "type": "object"
84
+ }
@@ -0,0 +1,102 @@
1
+ {
2
+ "$defs": {
3
+ "NodeStatus": {
4
+ "description": "A roadmap node's explicit status (open #3: never inferred from a PR column).",
5
+ "enum": [
6
+ "pending",
7
+ "planning",
8
+ "in_progress",
9
+ "done",
10
+ "blocked",
11
+ "skipped"
12
+ ],
13
+ "title": "NodeStatus",
14
+ "type": "string"
15
+ }
16
+ },
17
+ "additionalProperties": false,
18
+ "description": "Strict machine-input shape for one ``objective create --roadmap`` / ``objective_save`` node.\n\nMirrors the TS ``ROADMAP_PARAM_SCHEMA`` (``additionalProperties: false``): unknown keys fail\nloudly. ``status`` and ``depends_on`` are the only intentionally-coercing fields under the\notherwise-strict model (a raw enum value / a list of strings).",
19
+ "properties": {
20
+ "id": {
21
+ "title": "Id",
22
+ "type": "string"
23
+ },
24
+ "description": {
25
+ "title": "Description",
26
+ "type": "string"
27
+ },
28
+ "status": {
29
+ "$ref": "#/$defs/NodeStatus",
30
+ "default": "pending"
31
+ },
32
+ "slug": {
33
+ "anyOf": [
34
+ {
35
+ "type": "string"
36
+ },
37
+ {
38
+ "type": "null"
39
+ }
40
+ ],
41
+ "default": null,
42
+ "title": "Slug"
43
+ },
44
+ "pr": {
45
+ "anyOf": [
46
+ {
47
+ "type": "string"
48
+ },
49
+ {
50
+ "type": "null"
51
+ }
52
+ ],
53
+ "default": null,
54
+ "title": "Pr"
55
+ },
56
+ "depends_on": {
57
+ "anyOf": [
58
+ {
59
+ "items": {
60
+ "type": "string"
61
+ },
62
+ "type": "array"
63
+ },
64
+ {
65
+ "type": "null"
66
+ }
67
+ ],
68
+ "default": null,
69
+ "title": "Depends On"
70
+ },
71
+ "comment": {
72
+ "anyOf": [
73
+ {
74
+ "type": "string"
75
+ },
76
+ {
77
+ "type": "null"
78
+ }
79
+ ],
80
+ "default": null,
81
+ "title": "Comment"
82
+ },
83
+ "adopt_issue": {
84
+ "anyOf": [
85
+ {
86
+ "type": "string"
87
+ },
88
+ {
89
+ "type": "null"
90
+ }
91
+ ],
92
+ "default": null,
93
+ "title": "Adopt Issue"
94
+ }
95
+ },
96
+ "required": [
97
+ "id",
98
+ "description"
99
+ ],
100
+ "title": "StructuredRoadmapNode",
101
+ "type": "object"
102
+ }