hecks 3.1.0 → 3.1.1

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 (39) hide show
  1. checksums.yaml +4 -4
  2. data/exe/hecks +1 -1
  3. data/lib/hecks/chapters.rb +4 -3
  4. data/lib/hecks/cli/domain_writer.rb +39 -0
  5. data/lib/hecks/cli/interview_agent.rb +59 -0
  6. data/lib/hecks/cli/interview_run.rb +87 -0
  7. data/lib/hecks/cli/interview_session.rb +299 -0
  8. data/lib/hecks/corpus.rb +1 -0
  9. data/lib/hecks/doors/cli_runner.rb +1 -1
  10. data/lib/hecks/doors/usage_cache.rb +123 -0
  11. data/lib/hecks/hecks/adapters/finding_github.adapter +7 -0
  12. data/lib/hecks/hecks/adapters/finding_github.rb +114 -0
  13. data/lib/hecks/hecks/adapters/terminal.rb +15 -0
  14. data/lib/hecks/hecks/context_map.hecksagon +1 -1
  15. data/lib/hecks/hecks/custodian.bluebook +36 -0
  16. data/lib/hecks/hecks/hecks.bluebook +18 -0
  17. data/lib/hecks/hecks/hecks.hecksagon +8 -2
  18. data/lib/hecks/hecks/hecks.world +3 -2
  19. data/lib/hecks/projections/deploy/box/settings.rb +80 -4
  20. data/lib/hecks/projections/deploy/box/templates/box.yaml.tmpl +1 -0
  21. data/lib/hecks/projections/deploy/box/templates/deploy-box.sh.tmpl +3 -5
  22. data/lib/hecks/projections/deploy/box/templates/rds.yaml.tmpl +17 -1
  23. data/lib/hecks/projections/deploy/box/templates/render-compose-taskdef.sh.tmpl +49 -0
  24. data/lib/hecks/projections/deploy/box/templates/render-compose.sh.tmpl +1 -1
  25. data/lib/hecks/projections/deploy/box/templates/restore-to-rds.sh.tmpl +91 -0
  26. data/lib/hecks/projections/deploy/box/templates/verify-copy.sh.tmpl +58 -0
  27. data/lib/hecks/projections/deploy/box.rb +185 -19
  28. data/lib/hecks/projector/cli_projector.rb +38 -14
  29. data/lib/hecks/runtime/loader.rb +31 -8
  30. data/lib/hecks/tickets/bluebook/tickets.bluebook +331 -0
  31. data/lib/hecks/tickets/bluebook/tickets.hecksagon +11 -0
  32. data/lib/hecks/tickets/bluebook/tickets.ports.hecksagon +26 -0
  33. data/lib/hecks/version.rb +1 -1
  34. data/lib/hecks.rb +1 -0
  35. data/rust/codegen/src/json_codec.rs +3 -0
  36. data/rust/codegen/src/naming.rs +4 -0
  37. data/rust/codegen/src/types.rs +45 -0
  38. data/rust/host/HECKS_RELEASE +1 -1
  39. metadata +15 -2
@@ -0,0 +1,331 @@
1
+ # The Tickets chapter: what a maintainer observed about Hecks that needs a decision or a fix, the
2
+ # and the decisions that settle them.
3
+ #
4
+ # QualityControl has its own Ticket, the issue raised for a Bug in an outside tracker, and the
5
+ # Hecks domain has its own Release, the record of a gem version. A Finding sits before both: it is
6
+ # any observation, not yet a proven bug, and it needs no sweep or failing test to be recorded.
7
+ #
8
+ # A Finding is the record. A gap, a parity divergence, a QA finding and an idea are kinds of it, not
9
+ # separate aggregates. Hecks owns the finding's state; GitHub is driven from it through the
10
+ # GitHubIssues port, which a hecksagon binds (nothing here reads GitHub back). A finding exists whether
11
+ # or not GitHub answers: each lifecycle event asks the port, and a refused ask is recorded on the
12
+ # finding as a sync failure that a later run retries.
13
+ #
14
+ # An Adr is a decision record with its own lifecycle, linked to the finding it settles.
15
+ Hecks.bluebook "Tickets" do
16
+ vision "Track what Hecks needs, decide it, ship it, and drive GitHub from the record."
17
+
18
+ aggregate "Finding" do
19
+ description "One thing observed about Hecks that needs a decision or a fix: reported, triaged, then resolved or dismissed."
20
+
21
+ attribute :finding, FindingKey
22
+ attribute :title, Title
23
+ attribute :body, Body, optional: true
24
+ attribute :kind, Kind, optional: true
25
+ attribute :severity, Severity, optional: true
26
+ attribute :source, Source
27
+ attribute :fingerprint, Fingerprint, optional: true
28
+ attribute :issue_number, Number, optional: true
29
+ attribute :fix_pr_number, Number, optional: true
30
+ attribute :dismissal, Body, optional: true
31
+ attribute :sync_failure, Body, optional: true
32
+ identified_by :finding
33
+
34
+ value_object "FindingKey" do
35
+ attribute :value, String, pattern: '[^ \t\n\r]'
36
+
37
+ invariant("a finding is named") { !value.to_s.empty? }
38
+ end
39
+
40
+ value_object "Title" do
41
+ attribute :value, String
42
+
43
+ invariant("a finding has a title") { !value.to_s.empty? }
44
+ end
45
+
46
+ value_object "Body" do
47
+ attribute :value, String
48
+ end
49
+
50
+ # What the finding is: a `gap` Hecks cannot yet express, a `parity` divergence between the Ruby
51
+ # and Rust runtimes, a `qa` finding from the QA loop, or an `idea`.
52
+ value_object "Kind" do
53
+ attribute :value, String, one_of: ["gap", "parity", "qa", "idea"]
54
+ end
55
+
56
+ value_object "Severity" do
57
+ attribute :value, String, one_of: ["low", "medium", "high"]
58
+ end
59
+
60
+ # Where it came from: the QA loop, work for a client, a parity check, or a maintainer by hand.
61
+ value_object "Source" do
62
+ attribute :value, String, one_of: ["qa_loop", "client_work", "parity_check", "maintainer"]
63
+ end
64
+
65
+ # The same finding refiled by the QA loop carries the same fingerprint, so a report of it while an
66
+ # open finding holds it changes nothing.
67
+ value_object "Fingerprint" do
68
+ attribute :value, String, pattern: '[^ \t\n\r]'
69
+ end
70
+
71
+ value_object "Number" do
72
+ attribute :value, Integer
73
+
74
+ invariant("a number is positive") { value.positive? }
75
+ end
76
+
77
+ lifecycle :status, default: "reported" do
78
+ transition "Triage" => "triaged", from: %w[reported triaged]
79
+ transition "Resolve" => "resolved", from: "triaged"
80
+ transition "Dismiss" => "dismissed", from: %w[reported triaged]
81
+ transition "Reopen" => "triaged", from: %w[resolved dismissed]
82
+ end
83
+
84
+ command "Report" do
85
+ goal "Record something observed about Hecks as a finding"
86
+
87
+ attribute :finding, FindingKey
88
+ attribute :title, Title
89
+ attribute :body, Body, optional: true
90
+ attribute :source, Source
91
+ attribute :fingerprint, Fingerprint, optional: true
92
+
93
+ sets :finding
94
+ sets :title
95
+ sets :body
96
+ sets :source
97
+ sets :fingerprint
98
+
99
+ emits "FindingReported"
100
+ end
101
+
102
+ # A failed Codebase run reports itself: the run's key names the finding and doubles as its
103
+ # fingerprint, so the same run failing again while its finding is open changes nothing.
104
+ command "ReportFailedRun" do
105
+ goal "Record a failed conformance or gate run as a finding"
106
+
107
+ attribute :finding, FindingKey
108
+ attribute :body, Body
109
+
110
+ sets :finding
111
+ sets :body
112
+ sets :fingerprint, to: "run"
113
+ sets :title, to: "A Codebase run failed"
114
+ sets :source, to: "qa_loop"
115
+
116
+ emits "RunFindingReported"
117
+ end
118
+
119
+ command "Triage" do
120
+ role "Maintainer"
121
+ goal "Give a finding its kind and severity"
122
+
123
+ reference_to Finding
124
+ attribute :kind, Kind
125
+ attribute :severity, Severity
126
+
127
+ sets :kind
128
+ sets :severity
129
+
130
+ emits "FindingTriaged"
131
+ end
132
+
133
+ command "LinkFix" do
134
+ role "Maintainer"
135
+ goal "Record the pull request that fixes a triaged finding"
136
+
137
+ reference_to Finding
138
+ attribute :fix_pr_number, Number
139
+
140
+ sets :fix_pr_number
141
+
142
+ emits "FixLinked"
143
+ end
144
+
145
+ command "Resolve" do
146
+ role "Maintainer"
147
+ goal "Close a triaged finding as resolved"
148
+
149
+ reference_to Finding
150
+
151
+ emits "FindingResolved"
152
+ end
153
+
154
+ command "Dismiss" do
155
+ role "Maintainer"
156
+ goal "Close a finding without a fix, with the reason"
157
+
158
+ reference_to Finding
159
+ attribute :dismissal, Body
160
+
161
+ sets :dismissal
162
+
163
+ emits "FindingDismissed"
164
+ end
165
+
166
+ command "Reopen" do
167
+ role "Maintainer"
168
+ goal "Take a resolved or dismissed finding back to triaged, as when a fix regresses"
169
+
170
+ reference_to Finding
171
+
172
+ emits "FindingReopened"
173
+ end
174
+
175
+ command "RecordIssue" do
176
+ goal "Record the GitHub issue number once the issue is opened"
177
+
178
+ reference_to Finding
179
+ attribute :issue_number, Number
180
+
181
+ sets :issue_number
182
+
183
+ emits "IssueRecorded"
184
+ end
185
+
186
+ command "RecordSyncFailure" do
187
+ goal "Record that GitHub could not be driven, so a later run retries"
188
+
189
+ reference_to Finding
190
+ attribute :sync_failure, Body
191
+
192
+ sets :sync_failure
193
+
194
+ emits "SyncFailed"
195
+ end
196
+
197
+ query "Open" do
198
+ description "Every finding not yet resolved or dismissed."
199
+ where(status: { in: "reported,triaged" })
200
+ order_by :finding
201
+ end
202
+ end
203
+
204
+ aggregate "Adr" do
205
+ description "A decision record: drafted, accepted, and possibly superseded, linked to the tickets it settles."
206
+
207
+ attribute :adr, AdrNumber
208
+ attribute :title, AdrTitle
209
+ attribute :supersedes, AdrNumber, optional: true
210
+ attribute :settles, FindingKey, optional: true
211
+ identified_by :adr
212
+
213
+ value_object "AdrNumber" do
214
+ attribute :value, String, pattern: '\A[0-9]{4}\z'
215
+ end
216
+
217
+ value_object "AdrTitle" do
218
+ attribute :value, String
219
+
220
+ invariant("a decision has a title") { !value.to_s.empty? }
221
+ end
222
+
223
+ value_object "FindingKey" do
224
+ attribute :value, String, pattern: '[^ \t\n\r]'
225
+ end
226
+
227
+ lifecycle :status, default: "draft" do
228
+ transition "Accept" => "accepted", from: "draft"
229
+ transition "Supersede" => "superseded", from: "accepted"
230
+ end
231
+
232
+ command "Draft" do
233
+ role "Maintainer"
234
+ goal "Open a decision record, optionally for the finding it settles"
235
+
236
+ attribute :adr, AdrNumber
237
+ attribute :title, AdrTitle
238
+ attribute :settles, FindingKey, optional: true
239
+
240
+ sets :adr
241
+ sets :title
242
+ sets :settles
243
+
244
+ emits "AdrDrafted"
245
+ end
246
+
247
+ command "Accept" do
248
+ role "Maintainer"
249
+ goal "Record that the decision was accepted"
250
+
251
+ reference_to Adr
252
+
253
+ emits "AdrAccepted"
254
+ end
255
+
256
+ command "Supersede" do
257
+ role "Maintainer"
258
+ goal "Record that a later decision replaces this one"
259
+
260
+ reference_to Adr
261
+ attribute :supersedes, AdrNumber
262
+
263
+ sets :supersedes
264
+
265
+ emits "AdrSuperseded"
266
+ end
267
+
268
+ query "Standing" do
269
+ description "Every decision that is accepted and not superseded."
270
+ where(status: "accepted")
271
+ order_by :adr
272
+ end
273
+ end
274
+
275
+ # Each lifecycle event drives GitHub. A finding's own state never waits on the answer.
276
+ policy "OpenIssueWhenReported" do
277
+ on "Finding.FindingReported"
278
+ trigger Finding::GitHubIssues::OpenIssue, with: { finding: :finding }
279
+ end
280
+
281
+ policy "OpenIssueWhenRunReported" do
282
+ on "Finding.RunFindingReported"
283
+ trigger Finding::GitHubIssues::OpenIssue, with: { finding: :finding }
284
+ end
285
+
286
+ policy "LabelIssueWhenTriaged" do
287
+ on "Finding.FindingTriaged"
288
+ trigger Finding::GitHubIssues::LabelIssue, with: { finding: :finding }
289
+ end
290
+
291
+ policy "CommentWhenFixLinked" do
292
+ on "Finding.FixLinked"
293
+ trigger Finding::GitHubIssues::CommentOnIssue, with: { finding: :finding }
294
+ end
295
+
296
+ policy "CloseIssueWhenResolved" do
297
+ on "Finding.FindingResolved"
298
+ trigger Finding::GitHubIssues::CloseIssue, with: { finding: :finding }
299
+ end
300
+
301
+ policy "CloseIssueWhenDismissed" do
302
+ on "Finding.FindingDismissed"
303
+ trigger Finding::GitHubIssues::CloseIssue, with: { finding: :finding }
304
+ end
305
+
306
+ policy "ReopenIssueWhenReopened" do
307
+ on "Finding.FindingReopened"
308
+ trigger Finding::GitHubIssues::ReopenIssue, with: { finding: :finding }
309
+ end
310
+
311
+ # A conformance or gate run that faults files its own finding.
312
+ policy "ReportWhenConformanceFaulted" do
313
+ on "ConformanceRun.ConformanceFaulted"
314
+ trigger Finding::ReportFailedRun, with: { finding: :run, body: :refusal }
315
+ end
316
+
317
+ policy "ReportWhenGateFaulted" do
318
+ on "GateRun.GateFaulted"
319
+ trigger Finding::ReportFailedRun, with: { finding: :run, body: :refusal }
320
+ end
321
+
322
+ policy "RecordTheIssue" do
323
+ on "Finding.IssueOpened"
324
+ trigger Finding::RecordIssue, with: { issue_number: :issue_number }
325
+ end
326
+
327
+ policy "RecordTheSyncFailure" do
328
+ on "Finding.GitHubRefused"
329
+ trigger Finding::RecordSyncFailure, with: { sync_failure: :refusal }
330
+ end
331
+ end
@@ -0,0 +1,11 @@
1
+ # The Tickets domain, bound so it boots standing alone (a fuzz or model_check boot of this
2
+ # directory). The GitHubIssues port every attaching hecksagon shares is in tickets.ports.hecksagon.
3
+ Hecks.hecksagon "Tickets" do
4
+ attaches "Governance"
5
+ persisted_by "Memory"
6
+ end
7
+
8
+ # The anti-corruption layer for Governance, which the chapter's roles are checked against.
9
+ Hecks.hecksagon "Governance" do
10
+ persisted_by "Memory"
11
+ end
@@ -0,0 +1,26 @@
1
+ # The port Tickets declares, for every hecksagon that attaches the chapter (`Chapters` loads this
2
+ # file with it). Each lifecycle event of a finding asks the GitHubIssues port, which the Hecks domain
3
+ # binds (lib/hecks/hecks/adapters/finding_github.rb): the outside a finding reaches. The ask is
4
+ # answered with the record's own arguments or refused with a reason, and a refusal is recorded on the
5
+ # finding and never blocks it. The port has to be declared even where no adapter binds it, so the
6
+ # policies have a target and model_check's deaf-policy check can see it.
7
+ #
8
+ # Only OpenIssue answers with the issue number, so only its answer is recorded on the finding; the
9
+ # other asks answer with a line saying what was done.
10
+ Hecks.hecksagon "Tickets" do
11
+ Tickets::Finding.port "GitHubIssues" do
12
+ asks "OpenIssue", to: Finding do
13
+ attribute :finding, FindingKey
14
+ answers "IssueOpened"
15
+ refuses "GitHubRefused"
16
+ end
17
+
18
+ %w[LabelIssue CommentOnIssue CloseIssue ReopenIssue].each do |ask|
19
+ asks ask, to: Finding do
20
+ attribute :finding, FindingKey
21
+ answers "GitHubAnswered"
22
+ refuses "GitHubRefused"
23
+ end
24
+ end
25
+ end
26
+ end
data/lib/hecks/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  module Hecks
2
2
  # Read directly by the gemspec, so this file must never require the
3
3
  # rest of the gem (its dependencies aren't resolved yet at that point).
4
- VERSION = "3.1.0".freeze
4
+ VERSION = "3.1.1".freeze
5
5
  end
data/lib/hecks.rb CHANGED
@@ -29,6 +29,7 @@ require_relative "hecks/projector"
29
29
  require_relative "hecks/projections"
30
30
  # After `Projector`, which dispatches against the `:cli` projection.
31
31
  require_relative "hecks/doors/cli_door"
32
+ require_relative "hecks/doors/usage_cache"
32
33
  require_relative "hecks/doors/cli_runner"
33
34
  require_relative "hecks/storehouse"
34
35
  require_relative "hecks/mcp_stdio_guard"
@@ -44,6 +44,7 @@ pub fn scalar_json_accessor(scalar_type: &str) -> &'static str {
44
44
  "String" => "as_str",
45
45
  "Integer" => "as_i64",
46
46
  "Float" => "as_f64",
47
+ "TrueClass" | "FalseClass" => "as_bool",
47
48
  other => panic!("no JSON accessor for scalar type {other:?}"),
48
49
  }
49
50
  }
@@ -77,6 +78,7 @@ pub fn scalar_to_json_expr(scalar_type: &str, rust_expr: &str) -> String {
77
78
  "String" => format!("crate::kernel::Json::Str({rust_expr}.clone())"),
78
79
  "Integer" => format!("crate::kernel::Json::int({rust_expr})"),
79
80
  "Float" => format!("crate::kernel::Json::Float({rust_expr})"),
81
+ "TrueClass" | "FalseClass" => format!("crate::kernel::Json::Bool({rust_expr})"),
80
82
  other => panic!("no to_json expr for scalar type {other:?}"),
81
83
  }
82
84
  }
@@ -565,6 +567,7 @@ pub fn emit_closed_set_table_codec(exemplar: &Exemplar, vo: &Json) -> String {
565
567
  Some("String") => format!("crate::kernel::Json::Str(self.{ident}.to_string())"),
566
568
  Some("Integer") => format!("crate::kernel::Json::int(self.{ident})"),
567
569
  Some("Float") => format!("crate::kernel::Json::Float(self.{ident})"),
570
+ Some("TrueClass" | "FalseClass") => format!("crate::kernel::Json::Bool(self.{ident})"),
568
571
  _ => String::new(),
569
572
  };
570
573
  exemplar.render("to_json_field", &[("\"tmpl_field_name\"", naming::ruby_inspect_string(&key)), ("tmpl_json_value_placeholder()", value_expr)])
@@ -7,6 +7,7 @@ pub fn scalar_rust_type(type_name: &str) -> Option<&'static str> {
7
7
  "String" => Some("String"),
8
8
  "Integer" => Some("i64"),
9
9
  "Float" => Some("f64"),
10
+ "TrueClass" | "FalseClass" => Some("bool"),
10
11
  _ => None,
11
12
  }
12
13
  }
@@ -29,6 +30,8 @@ pub fn effective_scalar_type(type_name: &str) -> Option<&'static str> {
29
30
  "String" => Some("String"),
30
31
  "Integer" => Some("Integer"),
31
32
  "Float" => Some("Float"),
33
+ "TrueClass" => Some("TrueClass"),
34
+ "FalseClass" => Some("FalseClass"),
32
35
  _ => None,
33
36
  }
34
37
  }
@@ -250,6 +253,7 @@ pub fn scalar_to_value(type_name: &str, rust_expr: &str) -> Option<String> {
250
253
  "String" => Some(format!("Value::Str({rust_expr}.clone())")),
251
254
  "Integer" => Some(format!("Value::Int({rust_expr})")),
252
255
  "Float" => Some(format!("Value::Float({rust_expr})")),
256
+ "TrueClass" | "FalseClass" => Some(format!("Value::Bool({rust_expr})")),
253
257
  _ => None,
254
258
  }
255
259
  }
@@ -360,3 +360,48 @@ pub fn emit_projected_field_table(aggregate: &Json) -> String {
360
360
  .collect();
361
361
  format!("pub static {name}_PROJECTED_FIELDS: &[crate::kernel::ProjectedFieldSpec] = &[\n{}\n];\n", rows.join("\n"))
362
362
  }
363
+
364
+ #[cfg(test)]
365
+ mod tests {
366
+ use super::*;
367
+
368
+ /// A value object with one attribute per Ruby spelling of a boolean.
369
+ fn flag_value_object() -> Json {
370
+ Json::parse(
371
+ r#"{
372
+ "name":"Entry",
373
+ "attributes":[
374
+ {"name":"on","type":"TrueClass","list":false,"optional":false,"default":false},
375
+ {"name":"off","type":"FalseClass","list":false,"optional":false}
376
+ ]
377
+ }"#,
378
+ )
379
+ .unwrap()
380
+ }
381
+
382
+ #[test]
383
+ fn boolean_attributes_are_rust_bool_not_a_type_named_for_the_ruby_class() {
384
+ let vo = flag_value_object();
385
+ let generated = emit_value_object(&Exemplar::load(), &vo, &HashMap::new(), &HashMap::new());
386
+
387
+ assert!(generated.contains("pub on: bool,"));
388
+ assert!(generated.contains("pub off: bool,"));
389
+ assert!(generated.contains("Value::Bool(self.on)"));
390
+ assert!(!generated.contains("TrueClass,"));
391
+ assert!(!generated.contains("FalseClass,"));
392
+ }
393
+
394
+ #[test]
395
+ fn boolean_attributes_round_trip_through_json_as_bool() {
396
+ let vo = flag_value_object();
397
+ let attributes = vo.get("attributes").map(Json::each).unwrap_or(&[]);
398
+ let by_name = HashMap::new();
399
+ let exemplar = Exemplar::load();
400
+ let from_json = crate::json_codec::emit_from_json_flat(&exemplar, "Entry", attributes, &by_name, None, None, false, false, None);
401
+ let to_json = crate::json_codec::emit_to_json_flat(&exemplar, "Entry", attributes, &by_name, false, &[], None);
402
+
403
+ assert!(from_json.contains("x.as_bool()"));
404
+ assert!(!from_json.contains("TrueClass::from_json"));
405
+ assert!(to_json.contains("crate::kernel::Json::Bool(self.on)"));
406
+ }
407
+ }
@@ -1 +1 @@
1
- 3.1.0
1
+ 3.1.1
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hecks
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.0
4
+ version: 3.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Young
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-10-03 00:00:00.000000000 Z
11
+ date: 2026-10-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: prism
@@ -216,10 +216,14 @@ files:
216
216
  - lib/hecks/cli/doc_coverage.rb
217
217
  - lib/hecks/cli/document.rb
218
218
  - lib/hecks/cli/domain_stub.rb
219
+ - lib/hecks/cli/domain_writer.rb
219
220
  - lib/hecks/cli/expression_projection.rb
220
221
  - lib/hecks/cli/follow.rb
221
222
  - lib/hecks/cli/history.rb
223
+ - lib/hecks/cli/interview_agent.rb
222
224
  - lib/hecks/cli/interview_draft.rb
225
+ - lib/hecks/cli/interview_run.rb
226
+ - lib/hecks/cli/interview_session.rb
223
227
  - lib/hecks/cli/ir.rb
224
228
  - lib/hecks/cli/mcp.rb
225
229
  - lib/hecks/cli/model_check.rb
@@ -264,6 +268,7 @@ files:
264
268
  - lib/hecks/doors/ruby_door.rb
265
269
  - lib/hecks/doors/ruby_door/aggregate_door.rb
266
270
  - lib/hecks/doors/ruby_door/chapter.rb
271
+ - lib/hecks/doors/usage_cache.rb
267
272
  - lib/hecks/embryonaut_bluebook.rb
268
273
  - lib/hecks/embryonaut_bluebook/lock.rb
269
274
  - lib/hecks/embryonaut_bluebook/shape.rb
@@ -369,6 +374,8 @@ files:
369
374
  - lib/hecks/hecks/adapters/console_capture.rb
370
375
  - lib/hecks/hecks/adapters/deploy_toolchain.adapter
371
376
  - lib/hecks/hecks/adapters/deploy_toolchain.rb
377
+ - lib/hecks/hecks/adapters/finding_github.adapter
378
+ - lib/hecks/hecks/adapters/finding_github.rb
372
379
  - lib/hecks/hecks/adapters/git.adapter
373
380
  - lib/hecks/hecks/adapters/git.rb
374
381
  - lib/hecks/hecks/adapters/host_http.adapter
@@ -533,7 +540,10 @@ files:
533
540
  - lib/hecks/projections/deploy/box/templates/deploy-box.sh.tmpl
534
541
  - lib/hecks/projections/deploy/box/templates/fetch-secrets.sh
535
542
  - lib/hecks/projections/deploy/box/templates/rds.yaml.tmpl
543
+ - lib/hecks/projections/deploy/box/templates/render-compose-taskdef.sh.tmpl
536
544
  - lib/hecks/projections/deploy/box/templates/render-compose.sh.tmpl
545
+ - lib/hecks/projections/deploy/box/templates/restore-to-rds.sh.tmpl
546
+ - lib/hecks/projections/deploy/box/templates/verify-copy.sh.tmpl
537
547
  - lib/hecks/projections/deploy/fargate.rb
538
548
  - lib/hecks/projections/deploy/fargate/assembly.rb
539
549
  - lib/hecks/projections/deploy/fargate/cdn.rb
@@ -763,6 +773,9 @@ files:
763
773
  - lib/hecks/tenancy/bluebook/tenancy.hecksagon
764
774
  - lib/hecks/three_zero.rb
765
775
  - lib/hecks/three_zero/forms.yml
776
+ - lib/hecks/tickets/bluebook/tickets.bluebook
777
+ - lib/hecks/tickets/bluebook/tickets.hecksagon
778
+ - lib/hecks/tickets/bluebook/tickets.ports.hecksagon
766
779
  - lib/hecks/tools.rb
767
780
  - lib/hecks/tools/argument_gate_matrix.rb
768
781
  - lib/hecks/tools/ci_gate_decision.rb