principles 0.0.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.
- checksums.yaml +7 -0
- data/exe/principles +10 -0
- data/lib/principles/after_commit_hook_options.rb +44 -0
- data/lib/principles/cli.rb +149 -0
- data/lib/principles/command_line.rb +188 -0
- data/lib/principles/command_routes.rb +60 -0
- data/lib/principles/controllers/acknowledgement.rb +106 -0
- data/lib/principles/controllers/answer.rb +172 -0
- data/lib/principles/controllers/audit.rb +203 -0
- data/lib/principles/controllers/audit_completion.rb +113 -0
- data/lib/principles/controllers/command.rb +201 -0
- data/lib/principles/controllers/correction.rb +99 -0
- data/lib/principles/controllers/help.rb +107 -0
- data/lib/principles/controllers/inventory.rb +181 -0
- data/lib/principles/controllers/mapping.rb +56 -0
- data/lib/principles/controllers/member_entries.rb +149 -0
- data/lib/principles/controllers/members_a_commit_changed.rb +43 -0
- data/lib/principles/controllers/members_to_assess.rb +160 -0
- data/lib/principles/controllers/meta_principle_setup.rb +92 -0
- data/lib/principles/controllers/repoint.rb +68 -0
- data/lib/principles/controllers/running_tool.rb +41 -0
- data/lib/principles/data/audit_files.rb +96 -0
- data/lib/principles/data/bounded_file.rb +45 -0
- data/lib/principles/data/candidate_files_found.rb +105 -0
- data/lib/principles/data/command-steps.json +305 -0
- data/lib/principles/data/command_steps_file.rb +50 -0
- data/lib/principles/data/expected_type.rb +71 -0
- data/lib/principles/data/ignored_by_git.rb +54 -0
- data/lib/principles/data/json_text.rb +57 -0
- data/lib/principles/data/known_fields.rb +42 -0
- data/lib/principles/data/linked_path.rb +102 -0
- data/lib/principles/data/map_files.rb +104 -0
- data/lib/principles/data/principle_id.rb +32 -0
- data/lib/principles/data/principles_subfolder.rb +93 -0
- data/lib/principles/data/project_files.rb +109 -0
- data/lib/principles/data/repository.rb +165 -0
- data/lib/principles/data/running_version.rb +44 -0
- data/lib/principles/data/schema_check.rb +139 -0
- data/lib/principles/data/schemas/acknowledgement-answer.schema.json +25 -0
- data/lib/principles/data/schemas/answer-guide.schema.json +99 -0
- data/lib/principles/data/schemas/assessment-answer.schema.json +332 -0
- data/lib/principles/data/schemas/audit-record.schema.json +277 -0
- data/lib/principles/data/schemas/command-steps.schema.json +83 -0
- data/lib/principles/data/schemas/correction-answer-guide.schema.json +68 -0
- data/lib/principles/data/schemas/correction-answer.schema.json +306 -0
- data/lib/principles/data/schemas/member-map.schema.json +39 -0
- data/lib/principles/data/schemas/repointing-answer.schema.json +44 -0
- data/lib/principles/error.rb +102 -0
- data/lib/principles/invocation_options.rb +77 -0
- data/lib/principles/models/accepted_loading.rb +36 -0
- data/lib/principles/models/acknowledgement.rb +203 -0
- data/lib/principles/models/activation.rb +64 -0
- data/lib/principles/models/agent_loads.rb +64 -0
- data/lib/principles/models/answer_fields.rb +67 -0
- data/lib/principles/models/answer_place.rb +53 -0
- data/lib/principles/models/answer_text.rb +37 -0
- data/lib/principles/models/answered_time.rb +65 -0
- data/lib/principles/models/assessment_answer.rb +131 -0
- data/lib/principles/models/assessment_basis.rb +47 -0
- data/lib/principles/models/assessment_report.rb +62 -0
- data/lib/principles/models/audit.rb +200 -0
- data/lib/principles/models/audit_record.rb +249 -0
- data/lib/principles/models/audit_records.rb +103 -0
- data/lib/principles/models/audit_start.rb +96 -0
- data/lib/principles/models/audited_member_lines.rb +45 -0
- data/lib/principles/models/candidate_files.rb +66 -0
- data/lib/principles/models/candidate_inventory.rb +67 -0
- data/lib/principles/models/candidate_listing.rb +32 -0
- data/lib/principles/models/carried_assessments.rb +76 -0
- data/lib/principles/models/check_since_last_audit.rb +61 -0
- data/lib/principles/models/cited_files.rb +39 -0
- data/lib/principles/models/command_steps.rb +270 -0
- data/lib/principles/models/commits_brought_in.rb +27 -0
- data/lib/principles/models/commits_since_base.rb +32 -0
- data/lib/principles/models/correction_answer.rb +66 -0
- data/lib/principles/models/correction_basis.rb +70 -0
- data/lib/principles/models/dated_line.rb +29 -0
- data/lib/principles/models/decided_prior_findings.rb +106 -0
- data/lib/principles/models/declared_map_changes.rb +156 -0
- data/lib/principles/models/disposition.rb +233 -0
- data/lib/principles/models/entry_file.rb +65 -0
- data/lib/principles/models/entry_files.rb +46 -0
- data/lib/principles/models/evidence_item.rb +48 -0
- data/lib/principles/models/evidence_lines_since.rb +57 -0
- data/lib/principles/models/evidence_replacements.rb +99 -0
- data/lib/principles/models/finding_write_ups.rb +108 -0
- data/lib/principles/models/findings_left_open.rb +34 -0
- data/lib/principles/models/first_raised_claim.rb +128 -0
- data/lib/principles/models/frontmatter_fields.rb +128 -0
- data/lib/principles/models/hook_commands.rb +100 -0
- data/lib/principles/models/ignored_candidates.rb +46 -0
- data/lib/principles/models/json_digest.rb +35 -0
- data/lib/principles/models/json_path_query.rb +131 -0
- data/lib/principles/models/json_path_selectors.rb +64 -0
- data/lib/principles/models/json_path_string.rb +76 -0
- data/lib/principles/models/kept_prior_finding.rb +70 -0
- data/lib/principles/models/last_completed_revision.rb +70 -0
- data/lib/principles/models/line_span.rb +49 -0
- data/lib/principles/models/loaded_files.rb +60 -0
- data/lib/principles/models/loading_decision.rb +45 -0
- data/lib/principles/models/loading_facts.rb +45 -0
- data/lib/principles/models/loads_to_check.rb +93 -0
- data/lib/principles/models/locate_refusal.rb +23 -0
- data/lib/principles/models/located_text.rb +43 -0
- data/lib/principles/models/locator.rb +52 -0
- data/lib/principles/models/map_members.rb +171 -0
- data/lib/principles/models/markdown_file.rb +92 -0
- data/lib/principles/models/member.rb +171 -0
- data/lib/principles/models/member_assessments.rb +144 -0
- data/lib/principles/models/member_elsewhere.rb +74 -0
- data/lib/principles/models/member_file.rb +156 -0
- data/lib/principles/models/member_grounds.rb +32 -0
- data/lib/principles/models/member_history.rb +68 -0
- data/lib/principles/models/member_lines.rb +95 -0
- data/lib/principles/models/member_loads.rb +197 -0
- data/lib/principles/models/member_map.rb +219 -0
- data/lib/principles/models/member_map_history.rb +143 -0
- data/lib/principles/models/member_maps.rb +185 -0
- data/lib/principles/models/member_moves.rb +95 -0
- data/lib/principles/models/member_problems.rb +253 -0
- data/lib/principles/models/member_sighting.rb +176 -0
- data/lib/principles/models/member_snapshots.rb +36 -0
- data/lib/principles/models/member_state.rb +35 -0
- data/lib/principles/models/members_elsewhere.rb +46 -0
- data/lib/principles/models/members_sharing_lines.rb +116 -0
- data/lib/principles/models/meta_principle.rb +51 -0
- data/lib/principles/models/missing_files.rb +85 -0
- data/lib/principles/models/misspelt_member_id.rb +45 -0
- data/lib/principles/models/open_finding.rb +221 -0
- data/lib/principles/models/open_findings_elsewhere.rb +45 -0
- data/lib/principles/models/other_principles.rb +47 -0
- data/lib/principles/models/placement.rb +42 -0
- data/lib/principles/models/plain_text_file.rb +32 -0
- data/lib/principles/models/principles_folder_move.rb +59 -0
- data/lib/principles/models/principles_package.rb +53 -0
- data/lib/principles/models/prior_finding_decision.rb +162 -0
- data/lib/principles/models/prior_finding_outcomes.rb +60 -0
- data/lib/principles/models/prior_findings.rb +109 -0
- data/lib/principles/models/problem_report.rb +110 -0
- data/lib/principles/models/project.rb +214 -0
- data/lib/principles/models/project_history.rb +203 -0
- data/lib/principles/models/record_judged_against.rb +42 -0
- data/lib/principles/models/recorded_entry.rb +93 -0
- data/lib/principles/models/recorded_finding.rb +97 -0
- data/lib/principles/models/recorded_findings.rb +58 -0
- data/lib/principles/models/recorded_members.rb +149 -0
- data/lib/principles/models/repoint.rb +112 -0
- data/lib/principles/models/reported_check.rb +130 -0
- data/lib/principles/models/request_id.rb +70 -0
- data/lib/principles/models/runs_from.rb +36 -0
- data/lib/principles/models/skill_loads.rb +123 -0
- data/lib/principles/models/still_holds_restatement.rb +87 -0
- data/lib/principles/models/text_size.rb +26 -0
- data/lib/principles/models/uncommitted_outside_the_map.rb +30 -0
- data/lib/principles/models/waits_on.rb +58 -0
- data/lib/principles/models/write_up_opening.rb +93 -0
- data/lib/principles/models/write_up_pointer.rb +50 -0
- data/lib/principles/models/write_up_repoint.rb +39 -0
- data/lib/principles/prose_list.rb +23 -0
- data/lib/principles/supported_ruby.rb +93 -0
- data/lib/principles/version.rb +11 -0
- data/lib/principles/views/acknowledged_since_last_audit.rb +34 -0
- data/lib/principles/views/acknowledgement_result.rb +44 -0
- data/lib/principles/views/activation_in_hand.rb +47 -0
- data/lib/principles/views/assessment_request.rb +131 -0
- data/lib/principles/views/audit_changes.rb +79 -0
- data/lib/principles/views/audit_commit.rb +55 -0
- data/lib/principles/views/audit_result.rb +147 -0
- data/lib/principles/views/candidate_files_result.rb +95 -0
- data/lib/principles/views/check_result_template.rb +75 -0
- data/lib/principles/views/diff_since_last_audit.rb +29 -0
- data/lib/principles/views/findings_result.rb +45 -0
- data/lib/principles/views/help.rb +119 -0
- data/lib/principles/views/invocation.rb +66 -0
- data/lib/principles/views/landed_since_base.rb +27 -0
- data/lib/principles/views/lines_shared_with_member.rb +111 -0
- data/lib/principles/views/loads_to_check_result.rb +45 -0
- data/lib/principles/views/map_result.rb +169 -0
- data/lib/principles/views/member_change_since_baseline.rb +58 -0
- data/lib/principles/views/member_repairs.rb +82 -0
- data/lib/principles/views/members_a_commit_changed.rb +66 -0
- data/lib/principles/views/members_with_no_baseline.rb +56 -0
- data/lib/principles/views/meta_principle_passage.rb +23 -0
- data/lib/principles/views/meta_principle_result.rb +170 -0
- data/lib/principles/views/open_findings_elsewhere_result.rb +32 -0
- data/lib/principles/views/open_findings_line.rb +125 -0
- data/lib/principles/views/other_principles_unjudged_result.rb +32 -0
- data/lib/principles/views/outside_the_map_result.rb +31 -0
- data/lib/principles/views/package_since_last_audit_result.rb +34 -0
- data/lib/principles/views/principle_read_result.rb +86 -0
- data/lib/principles/views/principle_with_changed_members.rb +26 -0
- data/lib/principles/views/principles_with_no_completed_audit.rb +30 -0
- data/lib/principles/views/printed_principle.rb +45 -0
- data/lib/principles/views/prior_finding_decisions_result.rb +35 -0
- data/lib/principles/views/prior_findings_result.rb +80 -0
- data/lib/principles/views/problem_lines.rb +84 -0
- data/lib/principles/views/problem_result.rb +107 -0
- data/lib/principles/views/prompts/acknowledge-a-change/say-whether-the-change-keeps-the-meaning.md +12 -0
- data/lib/principles/views/prompts/answer-any-judgement-request/what-a-self-audit-cannot-show.md +6 -0
- data/lib/principles/views/prompts/assess-every-member/answer-guide.json +63 -0
- data/lib/principles/views/prompts/assess-every-member/assess-each-member-and-the-set.md +12 -0
- data/lib/principles/views/prompts/assess-every-member/check-roles-other-principles-give-these-lines.md +7 -0
- data/lib/principles/views/prompts/assess-every-member/decide-each-member-loading.md +17 -0
- data/lib/principles/views/prompts/assess-every-member/decide-each-prior-finding.md +38 -0
- data/lib/principles/views/prompts/assess-every-member/give-problem-evidence-at-still-holds.md +2 -0
- data/lib/principles/views/prompts/assess-every-member/give-the-evidence-a-prior-finding-lacks.md +7 -0
- data/lib/principles/views/prompts/assess-every-member/have-a-changed-check-reviewed-before-running-it.md +4 -0
- data/lib/principles/views/prompts/assess-every-member/have-a-new-check-reviewed-before-running-it.md +3 -0
- data/lib/principles/views/prompts/assess-every-member/have-hidden-characters-in-a-check-explained.md +4 -0
- data/lib/principles/views/prompts/assess-every-member/judge-acknowledged-edits-together.md +6 -0
- data/lib/principles/views/prompts/assess-every-member/judge-the-keeping-against-the-other-principles.md +7 -0
- data/lib/principles/views/prompts/assess-every-member/judge-the-keeping-under-the-release-since-the-last-audit.md +10 -0
- data/lib/principles/views/prompts/assess-every-member/judge-the-set-with-carried-assessments.md +10 -0
- data/lib/principles/views/prompts/assess-every-member/keep-the-last-review-basis-unless-you-give-a-new-one.md +1 -0
- data/lib/principles/views/prompts/assess-every-member/name-another-principles-open-finding-rather-than-raise-it.md +9 -0
- data/lib/principles/views/prompts/assess-every-member/read-whether-each-prior-finding-s-evidence-changed.md +12 -0
- data/lib/principles/views/prompts/assess-every-member/run-a-named-check-at-every-full-audit.md +2 -0
- data/lib/principles/views/prompts/assess-every-member/run-the-check-then-report-it.md +2 -0
- data/lib/principles/views/prompts/assess-every-member/run-the-reviewed-check-and-say-what-its-review-rested-on.md +6 -0
- data/lib/principles/views/prompts/assess-every-member/uncommitted-files-outside-the-map.md +4 -0
- data/lib/principles/views/prompts/assess-every-member/why-each-member-is-judged-again.md +24 -0
- data/lib/principles/views/prompts/dispose-of-each-finding/answer-guide.json +34 -0
- data/lib/principles/views/prompts/dispose-of-each-finding/fix-or-record-each-finding.md +24 -0
- data/lib/principles/views/prompts/find-a-principle-to-map/ask-the-owner-before-mapping.md +1 -0
- data/lib/principles/views/prompts/find-a-principle-to-map/choose-one-principle.md +5 -0
- data/lib/principles/views/prompts/find-a-principle-to-map/owner-ask-ignored-folders.md +2 -0
- data/lib/principles/views/prompts/find-a-principle-to-map/owner-ask-ignored.md +3 -0
- data/lib/principles/views/prompts/find-a-principle-to-map/owner-ask-possibly-test-data.md +2 -0
- data/lib/principles/views/prompts/find-a-principle-to-map/owner-ask-untracked.md +2 -0
- data/lib/principles/views/prompts/find-a-principle-to-map/what-each-command-writes.md +4 -0
- data/lib/principles/views/prompts/find-a-principle-to-map/where-the-inventory-looks.md +10 -0
- data/lib/principles/views/prompts/learn-what-a-command-does/add-member.md +45 -0
- data/lib/principles/views/prompts/learn-what-a-command-does/change-activation.md +21 -0
- data/lib/principles/views/prompts/learn-what-a-command-does/change-description.md +2 -0
- data/lib/principles/views/prompts/learn-what-a-command-does/change-member-check.md +17 -0
- data/lib/principles/views/prompts/learn-what-a-command-does/change-member-role.md +9 -0
- data/lib/principles/views/prompts/learn-what-a-command-does/create-principle.md +6 -0
- data/lib/principles/views/prompts/learn-what-a-command-does/every-command-and-how-they-chain.md +28 -0
- data/lib/principles/views/prompts/learn-what-a-command-does/list-candidate-files.md +17 -0
- data/lib/principles/views/prompts/learn-what-a-command-does/list-member-problems.md +73 -0
- data/lib/principles/views/prompts/learn-what-a-command-does/list-open-findings.md +71 -0
- data/lib/principles/views/prompts/learn-what-a-command-does/list-principles.md +7 -0
- data/lib/principles/views/prompts/learn-what-a-command-does/move-member.md +11 -0
- data/lib/principles/views/prompts/learn-what-a-command-does/remove-member-check.md +10 -0
- data/lib/principles/views/prompts/learn-what-a-command-does/remove-member.md +6 -0
- data/lib/principles/views/prompts/learn-what-a-command-does/show-answer-check.md +16 -0
- data/lib/principles/views/prompts/learn-what-a-command-does/show-audit.md +20 -0
- data/lib/principles/views/prompts/learn-what-a-command-does/show-meta-principle-passage.md +52 -0
- data/lib/principles/views/prompts/learn-what-a-command-does/show-principle.md +86 -0
- data/lib/principles/views/prompts/learn-what-a-command-does/start-audit.md +68 -0
- data/lib/principles/views/prompts/learn-what-a-command-does/submit-answer.md +56 -0
- data/lib/principles/views/prompts/repoint-write-ups/point-each-moved-write-up-at-its-new-place.md +10 -0
- data/lib/principles/views/prompts/report-after-a-commit/it-refused-after-the-commits-touched-the-maps.md +2 -0
- data/lib/principles/views/prompts/report-after-a-commit/others-are-still-listed.md +1 -0
- data/lib/principles/views/prompts/report-after-a-commit/the-commits-changed-these-members.md +2 -0
- data/lib/principles/views/prompts/report-after-a-commit/this-command-shows-each-one.md +1 -0
- data/lib/principles/views/prompts/report-the-completed-audit/commit-only-what-the-audit-changed.md +2 -0
- data/lib/principles/views/prompts/report-the-completed-audit/replace-the-default-commit-message.md +4 -0
- data/lib/principles/views/prompts/report-the-completed-audit/what-completion-means.md +2 -0
- data/lib/principles/views/prompts/set-principles-up/entry-file-passage.md +3 -0
- data/lib/principles/views/prompts/set-principles-up/name-the-step-each-member-lacks.md +15 -0
- data/lib/principles/views/prompts/set-principles-up/place-the-passage-with-the-user.md +31 -0
- data/lib/principles/views/prompts/set-principles-up/set-up-first.md +2 -0
- data/lib/principles/views/prompts/set-principles-up/what-the-passage-presumes.md +4 -0
- data/lib/principles/views/prompts/start-a-session/act-on-the-open-findings.md +5 -0
- data/lib/principles/views/prompts/start-a-session/it-returns-after-each-clear-or-compaction-too.md +1 -0
- data/lib/principles/views/prompts/start-a-session/it-returns-at-each-session-start.md +1 -0
- data/lib/principles/views/prompts/start-a-session/raise-them-at-the-next-pause.md +1 -0
- data/lib/principles/views/prompts/start-a-session/raise-them-before-the-first-task.md +1 -0
- data/lib/principles/views/prompts.rb +71 -0
- data/lib/principles/views/repoint_result.rb +80 -0
- data/lib/principles/views/request_part.rb +26 -0
- data/lib/principles/views/request_parts.rb +26 -0
- data/lib/principles/views/shell_word.rb +29 -0
- data/lib/principles/views/visible_text.rb +26 -0
- data/lib/principles/views/workflow_diagram.rb +77 -0
- data/lib/principles.rb +5 -0
- metadata +326 -0
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
# typed: strict
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "time"
|
|
5
|
+
require_relative "command"
|
|
6
|
+
require_relative "../models/finding_write_ups"
|
|
7
|
+
require_relative "../models/audit"
|
|
8
|
+
require_relative "../models/request_id"
|
|
9
|
+
require_relative "acknowledgement"
|
|
10
|
+
require_relative "correction"
|
|
11
|
+
require_relative "repoint"
|
|
12
|
+
require_relative "audit_completion"
|
|
13
|
+
|
|
14
|
+
module Principles
|
|
15
|
+
# Each runs one command: reads models, applies their rules and prints through a view.
|
|
16
|
+
# controllers/CLAUDE.md owns the boundary.
|
|
17
|
+
module Controllers
|
|
18
|
+
# Answering an audit's requests: this tool checks the answer against the project's files and, when the
|
|
19
|
+
# audit completes, writes the committed audit record. Nothing else is stored: each request id is a
|
|
20
|
+
# digest of what the request depends on, so an answer is checked against the project as it is now (D25).
|
|
21
|
+
class Answer < Command
|
|
22
|
+
#: (String, String?, Hash[String, untyped]) -> untyped
|
|
23
|
+
def call(command, id, options)
|
|
24
|
+
naming_the_executable do
|
|
25
|
+
case command
|
|
26
|
+
when "submit-answer" then submit_answer(required_id(id), submitted(required_id(id), options))
|
|
27
|
+
when "show-answer-check"
|
|
28
|
+
check_answer(required_id(id), submitted(required_id(id), options), options.fetch("file"))
|
|
29
|
+
else unknown(command)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
# The answer from --file, where - means it was read from stdin, checked against the schema for the phase
|
|
37
|
+
# the request id names.
|
|
38
|
+
#: (String, Hash[String, untyped]) -> untyped
|
|
39
|
+
def submitted(request_text, options)
|
|
40
|
+
@project.answer(options.fetch("file"), stdin: options["stdin"], phase: Models::RequestId.parse(request_text).phase)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Accepts the answer and writes the record changes it makes.
|
|
44
|
+
#: (String, untyped) -> untyped
|
|
45
|
+
def submit_answer(request_text, response)
|
|
46
|
+
output, changes = judged(request_text, response)
|
|
47
|
+
wrote = changes.map { |record| @audit_records.save(record) }
|
|
48
|
+
audit_result.present(output).merge("wrote" => wrote)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Runs every check submit-answer would, and says what it would write, writing nothing; its submit command
|
|
52
|
+
# gives answer_file, the --file value it was checked from, again.
|
|
53
|
+
#: (String, untyped, String) -> untyped
|
|
54
|
+
def check_answer(request_text, response, answer_file)
|
|
55
|
+
_, changes = judged(request_text, response)
|
|
56
|
+
written_up = Models::FindingWriteUps.of(@project, changes).written_up
|
|
57
|
+
# Only a correction's fixed dispositions claim map entries; for any other answer this is empty, read from
|
|
58
|
+
# no map, and left out.
|
|
59
|
+
audit_result.acceptable(request_text, changes.map { |record| @audit_records.file(record.principle_id) },
|
|
60
|
+
answer_file:, open_findings_will_print: (written_up unless written_up.empty?),
|
|
61
|
+
map_entry_changes: claimed_map_entry_changes(request_text, response))
|
|
62
|
+
.merge("wrote" => [])
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# What each map entry a correction's fix claims changed, from the map its audit started from; its audit is
|
|
66
|
+
# built only when a fix claims one.
|
|
67
|
+
#: (String, untyped) -> Array[Hash[String, untyped]]
|
|
68
|
+
def claimed_map_entry_changes(request_text, response)
|
|
69
|
+
handed(Correction).map_entry_changes(response) { audit(Models::RequestId.parse(request_text).principle_id) }
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# The result of answering, and each record change the answer makes, not yet written.
|
|
73
|
+
#: (String, untyped) -> [untyped, Array[Models::AuditRecord]]
|
|
74
|
+
def judged(request_text, response)
|
|
75
|
+
request_id = Models::RequestId.parse(request_text)
|
|
76
|
+
request_id.check_answer(response)
|
|
77
|
+
case request_id.phase
|
|
78
|
+
when "acknowledgement" then handed(Acknowledgement).answered(request_id, response)
|
|
79
|
+
when "repointing" then handed(Repoint).answered(request_id, response)
|
|
80
|
+
when "assessment" then answer_assessment(request_id, response, audit(request_id.principle_id))
|
|
81
|
+
else handed(Correction).answered(request_id, response, audit(request_id.principle_id))
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# The audit of principle id, against its members' hashes now.
|
|
86
|
+
#: (String) -> Models::Audit
|
|
87
|
+
def audit(id)
|
|
88
|
+
map = @member_maps.find(id)
|
|
89
|
+
Models::Audit.new(map: map, now: @project.snapshots(map).hashes)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
#: (Models::RequestId, untyped, Models::Audit) -> [untyped, Array[Models::AuditRecord]]
|
|
93
|
+
def answer_assessment(request_id, response, audit)
|
|
94
|
+
basis = Models::AssessmentBasis.new(response.fetch("basis"))
|
|
95
|
+
judged_against = record_judged_against(audit)
|
|
96
|
+
prior = checked_request(request_id, basis, audit, judged_against.loads)
|
|
97
|
+
basis.printed_after.refusing_stale_first(audit.id, @audit_records.find(audit.id)) do
|
|
98
|
+
judged_assessment(response, audit, prior, judged_against, basis)
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# The assessment's fields and its decisions on the prior findings checked, then the audit completed or its
|
|
103
|
+
# correction asked for.
|
|
104
|
+
#: (untyped, Models::Audit, Models::PriorFindings, Models::RecordJudgedAgainst, Models::AssessmentBasis)
|
|
105
|
+
#| -> [untyped, Array[Models::AuditRecord]]
|
|
106
|
+
def judged_assessment(response, audit, prior, judged_against, basis)
|
|
107
|
+
assessed = audit.assessment(response, judged_against, Time.now.utc.iso8601) do |locator|
|
|
108
|
+
snapshot(locator)
|
|
109
|
+
end
|
|
110
|
+
findings = assessed.findings
|
|
111
|
+
decided = prior.decided(response["prior_finding_decisions"], findings, records: @audit_records) do |locator|
|
|
112
|
+
snapshot(locator)
|
|
113
|
+
end
|
|
114
|
+
correction(audit.assessed_start(basis.base, assessed, grounds(audit)), audit, findings, decided, basis)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# The request an assessment answers, checked against the project now, with the prior findings it listed.
|
|
118
|
+
#: (Models::RequestId, Models::AssessmentBasis, Models::Audit, Models::LoadsToCheck) -> Models::PriorFindings
|
|
119
|
+
def checked_request(request_id, basis, audit, loads)
|
|
120
|
+
audit.check_assessment_request(request_id, basis: basis, committed: committed(basis.base, audit.map),
|
|
121
|
+
record: @audit_records.find(audit.id), loads: loads)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# Completes an audit with no findings. Otherwise asks the agent to correct them. Each is refused once the last
|
|
125
|
+
# completed record changed after the assessment's request was printed, the completion unless it writes
|
|
126
|
+
# nothing (D50).
|
|
127
|
+
#: (Models::AuditStart, Models::Audit, Array[untyped], Models::DecidedPriorFindings, Models::AssessmentBasis)
|
|
128
|
+
#| -> [untyped, Array[Models::AuditRecord]]
|
|
129
|
+
def correction(start, audit, findings, decided, assessed)
|
|
130
|
+
if findings.empty?
|
|
131
|
+
return handed(AuditCompletion, replacing: assessed.printed_after).completed(start, audit, [], [], decided)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
correction_request(start, audit, findings, decided, assessed)
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
# The correction request for findings, and outside git the open record that keeps what the audit began from.
|
|
138
|
+
# It is refused before it is printed once the last completed record changed, so no fix is made for an audit
|
|
139
|
+
# that cannot complete (D50). The check results travel in the basis, so the completed record keeps them (D30).
|
|
140
|
+
#: (Models::AuditStart, Models::Audit, Array[untyped], Models::DecidedPriorFindings, Models::AssessmentBasis)
|
|
141
|
+
#| -> [untyped, Array[Models::AuditRecord]]
|
|
142
|
+
def correction_request(start, audit, findings, decided, assessed)
|
|
143
|
+
assessed.printed_after.confirm_unchanged(audit.id, @audit_records.find(audit.id))
|
|
144
|
+
basis = printed_basis(start, findings, decided, assessed)
|
|
145
|
+
[audit_result.correction_request(request_id: basis.request_id(audit.id, audit.now).to_s,
|
|
146
|
+
principle_id: audit.id, findings: findings, basis: basis.to_h,
|
|
147
|
+
placeholders: Models::Disposition::PLACEHOLDERS),
|
|
148
|
+
open_record_changes(start, audit, basis.to_h)]
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
# The basis a correction request prints, for the agent to hand back with its answer.
|
|
152
|
+
# Its revision is the one the assessment was printed after, carried forward, so the correction is refused once
|
|
153
|
+
# that record changes (#646, D50).
|
|
154
|
+
#: (Models::AuditStart, Array[untyped], Models::DecidedPriorFindings, Models::AssessmentBasis)
|
|
155
|
+
#| -> Models::CorrectionBasis
|
|
156
|
+
def printed_basis(start, findings, decided, assessed)
|
|
157
|
+
Models::CorrectionBasis.printed(start, findings: findings, prior: decided, revision: assessed.revision)
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
# Outside git, the open record that keeps what the audit began from, and the last completed record, so a
|
|
161
|
+
# restarted audit still lists its prior findings (D35); in git, nothing.
|
|
162
|
+
#: (Models::AuditStart, Models::Audit, Hash[String, untyped]) -> Array[Models::AuditRecord]
|
|
163
|
+
def open_record_changes(start, audit, basis)
|
|
164
|
+
return [] if start.base
|
|
165
|
+
|
|
166
|
+
last = @audit_records.find(audit.id)&.last_completed
|
|
167
|
+
record = handed(AuditCompletion).record(start, basis.fetch("findings"), "open", audit.now, last)
|
|
168
|
+
@audit_records.changes(record)
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
end
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
# typed: strict
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require_relative "command"
|
|
5
|
+
require_relative "../models/audit"
|
|
6
|
+
require_relative "../models/evidence_lines_since"
|
|
7
|
+
require_relative "../models/findings_left_open"
|
|
8
|
+
require_relative "../models/meta_principle"
|
|
9
|
+
require_relative "../models/other_principles"
|
|
10
|
+
require_relative "../models/finding_write_ups"
|
|
11
|
+
require_relative "../models/uncommitted_outside_the_map"
|
|
12
|
+
require_relative "../views/assessment_request"
|
|
13
|
+
require_relative "../views/findings_result"
|
|
14
|
+
require_relative "../views/loads_to_check_result"
|
|
15
|
+
require_relative "../views/open_findings_elsewhere_result"
|
|
16
|
+
require_relative "../views/open_findings_line"
|
|
17
|
+
require_relative "../views/other_principles_unjudged_result"
|
|
18
|
+
require_relative "../views/outside_the_map_result"
|
|
19
|
+
require_relative "../views/package_since_last_audit_result"
|
|
20
|
+
require_relative "../views/prior_findings_result"
|
|
21
|
+
require_relative "acknowledgement"
|
|
22
|
+
require_relative "members_to_assess"
|
|
23
|
+
require_relative "repoint"
|
|
24
|
+
|
|
25
|
+
module Principles
|
|
26
|
+
# Each runs one command: reads models, applies their rules and prints through a view.
|
|
27
|
+
# controllers/CLAUDE.md owns the boundary.
|
|
28
|
+
module Controllers
|
|
29
|
+
# Starting and showing an audit: start-audit hands the agent the assessment request, and show-audit
|
|
30
|
+
# prints the committed record. Starting writes nothing: the request id is a digest of what the request
|
|
31
|
+
# depends on, so Answer checks the answer against the project as it is then (D25).
|
|
32
|
+
class Audit < Command
|
|
33
|
+
#: (String, String?, Hash[String, untyped]) -> untyped
|
|
34
|
+
def call(command, id, options)
|
|
35
|
+
return started_audit(required_id(id), options) if command == "start-audit"
|
|
36
|
+
|
|
37
|
+
naming_the_executable do
|
|
38
|
+
case command
|
|
39
|
+
when "show-audit" then shown_audit(required_id(id))
|
|
40
|
+
when "list-open-findings" then options["short"] ? open_findings_line(id, options) : open_findings(id)
|
|
41
|
+
else unknown(command)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
private
|
|
47
|
+
|
|
48
|
+
# The audit start-audit's options ask for: a one-member audit with --member, a repoint of the open
|
|
49
|
+
# findings' write-ups with --write-ups (D59), else a full audit.
|
|
50
|
+
#: (String, Hash[String, untyped]) -> Hash[String, untyped]
|
|
51
|
+
def started_audit(id, options)
|
|
52
|
+
return acknowledge(id, options["member"]) if options["member"]
|
|
53
|
+
return handed(Repoint).start(id) if options["write_ups"]
|
|
54
|
+
|
|
55
|
+
naming_the_executable { start_audit(id) }
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# id's committed record. With none, an id no map has is refused as show-principle refuses it, since
|
|
59
|
+
# starting its audit would be refused too; a record kept after its map was removed still shows (#577).
|
|
60
|
+
#: (String) -> Hash[String, untyped]
|
|
61
|
+
def shown_audit(id)
|
|
62
|
+
@member_maps.find(id) unless @audit_records.exist?(id)
|
|
63
|
+
@audit_records.fetch(id).shown.merge("wrote" => [])
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# A one-member audit of member_id (D33).
|
|
67
|
+
#: (String, String) -> Hash[String, untyped]
|
|
68
|
+
def acknowledge(id, member_id)
|
|
69
|
+
handed(Acknowledgement).start(id, member_id)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# The findings the last completed audit of map id, or of every map, deferred or accepted (#292, D35).
|
|
73
|
+
#: (String?) -> Hash[String, untyped]
|
|
74
|
+
def open_findings(id)
|
|
75
|
+
listed = Models::FindingWriteUps.of(@project, @audit_records.of(@member_maps.ids_of(id))).listed
|
|
76
|
+
Views::FindingsResult.new(invocation).open(listed).merge("wrote" => [])
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# The one line saying how many findings are open and how long the oldest has waited until now, and which
|
|
80
|
+
# write-ups can no longer be found (#694), or nothing when none is open, for a session-start hook (D47),
|
|
81
|
+
# worded for the session's start, startup unless --session-start names another (#717).
|
|
82
|
+
#: (String?, Hash[String, untyped]) -> Views::Lines
|
|
83
|
+
def open_findings_line(id, options)
|
|
84
|
+
records = @audit_records.of(@member_maps.ids_of(id))
|
|
85
|
+
waiting = Models::FindingsLeftOpen.of(records).waiting_at(Time.now.utc)
|
|
86
|
+
Views::OpenFindingsLine.new(invocation).short(waiting, Models::FindingWriteUps.of(@project, records).not_found,
|
|
87
|
+
source: options["session_start"] || "startup")
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
#: (String) -> untyped
|
|
91
|
+
def start_audit(id)
|
|
92
|
+
auditable = @member_maps.auditable(id)
|
|
93
|
+
base = base_commit(id, auditable)
|
|
94
|
+
current = @project.snapshots(auditable)
|
|
95
|
+
audit = Models::Audit.new(map: auditable, now: current.hashes)
|
|
96
|
+
listing = handed(MembersToAssess, principle_id: id).listed(audit, current)
|
|
97
|
+
output = assessment_request(audit, base, listing)
|
|
98
|
+
audit_result.present(with_record_notice(output, id, base)).merge("wrote" => [])
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# The request, listing the findings the last completed audit left to decide, and with an id that digests them
|
|
102
|
+
# (D35) and the revision of that audit's record (#653), but not the findings other principles leave open on
|
|
103
|
+
# members sharing these lines (D62).
|
|
104
|
+
#: (Models::Audit, String?, MembersToAssess::Listing) -> Hash[String, untyped]
|
|
105
|
+
def assessment_request(audit, base, listing)
|
|
106
|
+
record = @audit_records.find(audit.id)
|
|
107
|
+
prior = audit.prior_findings(record)
|
|
108
|
+
loads = loads_to_check(audit).listed
|
|
109
|
+
basis = Models::AssessmentBasis.printed(base, record)
|
|
110
|
+
audit_result.assessment_request(request_id: audit.assessment_id(basis, prior.digested, loads).to_s,
|
|
111
|
+
request: request_to_assess(audit, basis, listing.members,
|
|
112
|
+
parts_to_read(audit, prior, listing, loads)))
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# What the agent assesses: the members, with what else it reads beside them (D60).
|
|
116
|
+
#: (Models::Audit, Models::AssessmentBasis, Array[Hash[String, untyped]], Array[Views::RequestPart])
|
|
117
|
+
#| -> Views::AssessmentRequest
|
|
118
|
+
def request_to_assess(audit, basis, members, parts)
|
|
119
|
+
Views::AssessmentRequest.new(principle_id: audit.id, description: audit.map.description, members: members,
|
|
120
|
+
basis: basis.to_h, parts: parts)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# What the agent reads beside the members, in order (D60): the files outside the map that differ from the
|
|
124
|
+
# base commit, which a check and the answer's evidence read as they are now (#409); the prior findings
|
|
125
|
+
# (D35); the findings other principles leave open on members sharing these lines (D62); and the members to
|
|
126
|
+
# check against the activation (#355); each when it lists any; and, on the meta-principle's audit, the release
|
|
127
|
+
# since its last audit (D68) and the other principles with members no audit has judged (D71).
|
|
128
|
+
#: (Models::Audit, Models::PriorFindings, MembersToAssess::Listing, Hash[String, untyped]?)
|
|
129
|
+
#| -> Array[Views::RequestPart]
|
|
130
|
+
def parts_to_read(audit, prior, listing, loads)
|
|
131
|
+
[outside_the_map(audit), prior_findings_part(prior),
|
|
132
|
+
Views::OpenFindingsElsewhereResult.new(listing.open_findings_elsewhere).part,
|
|
133
|
+
Views::LoadsToCheckResult.new(invocation, loads, audit.id).part, package_since_last_audit(audit.map),
|
|
134
|
+
other_principles_unjudged(audit.map)].compact
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
# The part listing each other principle with members no audit has judged as they are now, as
|
|
138
|
+
# list-member-problems reports them, for the principle whose audit states them; nil for any other (D71).
|
|
139
|
+
#: (Models::MemberMap) -> Views::RequestPart?
|
|
140
|
+
def other_principles_unjudged(map)
|
|
141
|
+
return unless map.keeps_others_held?
|
|
142
|
+
|
|
143
|
+
listed = Models::OtherPrinciples.of(@project, but: map.id).unjudged.map do |other, members|
|
|
144
|
+
Views::PrincipleWithChangedMembers.new(principle_id: other, members: members)
|
|
145
|
+
end
|
|
146
|
+
Views::OtherPrinciplesUnjudgedResult.new(listed).part
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
# The part stating the release of principles the last completed audit ran under beside the one now, and
|
|
150
|
+
# whether the passage changed since, for a principle whose audit keeps one; nil for any other (D68).
|
|
151
|
+
#: (Models::MemberMap) -> Views::RequestPart?
|
|
152
|
+
def package_since_last_audit(map)
|
|
153
|
+
now = @tool.release_kept_by(map) or return
|
|
154
|
+
last = @audit_records.find(map.id)&.last_completed&.package
|
|
155
|
+
Views::PackageSinceLastAuditResult.new(invocation, at_last_audit: last&.version, now: now.version,
|
|
156
|
+
passage_changed: last && now.passage_changed_since?(last))
|
|
157
|
+
.part
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
# The part listing the prior findings, in git with each evidence item saying whether its text changed since the
|
|
161
|
+
# commit the audit that left them open was based on, and whether it is found now (#858, #877); nil when there are
|
|
162
|
+
# none.
|
|
163
|
+
#: (Models::PriorFindings) -> Views::RequestPart?
|
|
164
|
+
def prior_findings_part(prior)
|
|
165
|
+
shown = prior.shown { |item, base| Models::EvidenceLinesSince.of(item, since: base, project: @project).facts }
|
|
166
|
+
Views::PriorFindingsResult.new(shown, last_audited_commit: prior.last_audited_commit).part
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
# The part naming the files outside the map that differ from the base commit, or nil when none do.
|
|
170
|
+
#: (Models::Audit) -> Views::RequestPart?
|
|
171
|
+
def outside_the_map(audit)
|
|
172
|
+
outside = @history.uncommitted_outside(audited_files(audit.id, audit.map))
|
|
173
|
+
Views::OutsideTheMapResult.new(outside && Models::UncommittedOutsideTheMap.new(outside).shown).part
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
# The commit the audit is judged against, over the map and every member's file; nil outside git.
|
|
177
|
+
#: (String, Models::MemberMap) -> String?
|
|
178
|
+
def base_commit(id, map)
|
|
179
|
+
@history.base_commit(id, audited_files(id, map))
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
# The map's file and every member's file.
|
|
183
|
+
#: (String, Models::MemberMap) -> Array[String]
|
|
184
|
+
def audited_files(id, map)
|
|
185
|
+
[@member_maps.file(id), *map.members.map(&:path)]
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
# The request, with a notice when the last audit's record was left uncommitted.
|
|
189
|
+
#: (Hash[String, untyped], String, String?) -> Hash[String, untyped]
|
|
190
|
+
def with_record_notice(output, id, base)
|
|
191
|
+
return output unless base && uncommitted_record?(id)
|
|
192
|
+
|
|
193
|
+
output.merge("notice" => audit_result.uncommitted_record_notice(@audit_records.file(id)))
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
# Whether the last audit's record exists but differs from the last commit, so it may be left behind.
|
|
197
|
+
#: (String) -> bool
|
|
198
|
+
def uncommitted_record?(id)
|
|
199
|
+
@audit_records.exist?(id) && @history.uncommitted([@audit_records.file(id)]).any?
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
end
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# typed: strict
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "time"
|
|
5
|
+
require_relative "command"
|
|
6
|
+
require_relative "../models/audit"
|
|
7
|
+
require_relative "../models/commits_since_base"
|
|
8
|
+
require_relative "../models/other_principles"
|
|
9
|
+
require_relative "../views/prior_finding_decisions_result"
|
|
10
|
+
|
|
11
|
+
module Principles
|
|
12
|
+
# Each runs one command: reads models, applies their rules and prints through a view.
|
|
13
|
+
# controllers/CLAUDE.md owns the boundary.
|
|
14
|
+
module Controllers
|
|
15
|
+
# A full audit's record: the open record a correction request leaves outside git, and the last step, which
|
|
16
|
+
# submit-answer reaches from an assessment with no findings or from a correction, with the record it writes,
|
|
17
|
+
# the files to commit and what landed since the base commit.
|
|
18
|
+
class AuditCompletion < Command
|
|
19
|
+
# map_changes are the changes a correction declared to the map, which name the map file to commit (D40).
|
|
20
|
+
# replacing is the revision of the last completed record when the request that completes the audit was
|
|
21
|
+
# printed, which refuses to replace a record changed since (#646).
|
|
22
|
+
#: (Models::Project, tool: RunningTool, ?map_changes: Models::DeclaredMapChanges?,
|
|
23
|
+
#| ?replacing: Models::LastCompletedRevision?) -> void
|
|
24
|
+
def initialize(project, tool:, map_changes: nil, replacing: nil)
|
|
25
|
+
super(project, tool: tool)
|
|
26
|
+
@map_changes = map_changes #: Models::DeclaredMapChanges?
|
|
27
|
+
@replacing = replacing #: Models::LastCompletedRevision?
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# The completed result, and the record change it makes, not yet written.
|
|
31
|
+
# Each prior finding's decision is applied: a kept one stays in the record, and a closed one is reported (D35).
|
|
32
|
+
#: (Models::AuditStart, Models::Audit, Array[Models::Disposition], Array[untyped], Models::DecidedPriorFindings)
|
|
33
|
+
#| -> [untyped, Array[Models::AuditRecord]]
|
|
34
|
+
def completed(start, audit, dispositions, findings, decided)
|
|
35
|
+
written = record(start, audit.outcomes(findings, dispositions, decided), "completed", audit.now)
|
|
36
|
+
changes = @audit_records.changes(written)
|
|
37
|
+
@replacing&.confirm_writable(audit.id, @audit_records.find(audit.id), changes)
|
|
38
|
+
[completion_result(start, audit, dispositions, decided, written), changes]
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# The record an audit writes, made now, saying what its assessments answered, with each assessment carried
|
|
42
|
+
# forward taken from the record it replaces (D49), and the release of principles it ran under when its
|
|
43
|
+
# principle keeps one (D68).
|
|
44
|
+
#: (Models::AuditStart, Array[untyped], String, Hash[String, String], ?Models::AuditRecord?)
|
|
45
|
+
#| -> Models::AuditRecord
|
|
46
|
+
def record(start, findings, status, members, last_completed = nil)
|
|
47
|
+
Models::AuditRecord.written(start, status: status, audited_at: Time.now.utc.iso8601, members: members,
|
|
48
|
+
findings: findings)
|
|
49
|
+
.judged(start.judged_against(Views::AssessmentRequest.question))
|
|
50
|
+
.carrying(@audit_records.find(start.id)).packaged(@tool.release_kept_by(start.map))
|
|
51
|
+
.keeping(last_completed)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
private
|
|
55
|
+
|
|
56
|
+
# What the completed audit prints: its resolved and open findings, as the record it writes holds them, so they
|
|
57
|
+
# agree with list-open-findings (#714); what it changed; and each prior finding's decision (D35).
|
|
58
|
+
#: (Models::AuditStart, Models::Audit, Array[Models::Disposition], Models::DecidedPriorFindings,
|
|
59
|
+
#| Models::AuditRecord) -> untyped
|
|
60
|
+
def completion_result(start, audit, dispositions, decided, written)
|
|
61
|
+
decisions = Views::PriorFindingDecisionsResult.new(kept_ids: decided.kept_ids, closed: decided.closed,
|
|
62
|
+
dropped: decided.dropped,
|
|
63
|
+
waits_on_dropped: decided.waits_on_dropped,
|
|
64
|
+
evidence_replaced: decided.evidence_replaced)
|
|
65
|
+
audit_result.completion(principle_id: audit.id, resolved: written.resolved_ids(decided),
|
|
66
|
+
open: written.open_ids, changes: changes(start, audit, dispositions, written),
|
|
67
|
+
decisions: decisions)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# What the audit changed in the project: the files to commit, in git the commits since the base, the
|
|
71
|
+
# other principles whose members its fixes changed, and the members its correction added (T69).
|
|
72
|
+
#: (Models::AuditStart, Models::Audit, Array[Models::Disposition], Models::AuditRecord) -> Views::AuditChanges
|
|
73
|
+
def changes(start, audit, dispositions, written)
|
|
74
|
+
changed = audit.changed_files(dispositions)
|
|
75
|
+
added = start.added(now: audit.now)
|
|
76
|
+
map = @map_changes&.files_to_commit(@member_maps.file(audit.id), added: added) || []
|
|
77
|
+
files = @audit_records.files_to_commit(written, changed + map, start.reported)
|
|
78
|
+
Views::AuditChanges.new(files_to_commit: files, landed: landed_since_base(start, audit), added: added,
|
|
79
|
+
other_changed: other_changed(audit, changed),
|
|
80
|
+
cited_files_missing: @audit_records.cited_files_missing(written))
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Each other principle with a member in paths, the files this audit's fixes changed, whose own text now
|
|
84
|
+
# differs from what this tool last knew of it or whose reference broke, as list-member-problems reports it
|
|
85
|
+
# (#410). A map this tool
|
|
86
|
+
# cannot read names none here; list-member-problems reports it.
|
|
87
|
+
#: (Models::Audit, Array[String]) -> Array[Views::PrincipleWithChangedMembers]
|
|
88
|
+
def other_changed(audit, paths)
|
|
89
|
+
Models::OtherPrinciples.of(@project, but: audit.id).changed_or_broken_in(paths).map do |id, changed|
|
|
90
|
+
Views::PrincipleWithChangedMembers.new(principle_id: id, members: changed.map(&:to_h))
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# In git, what landed since the base commit, as the completed result prints it; nil outside git.
|
|
95
|
+
#: (Models::AuditStart, Models::Audit) -> Views::LandedSinceBase?
|
|
96
|
+
def landed_since_base(start, audit)
|
|
97
|
+
landed = commits_since_base(start, audit) or return nil
|
|
98
|
+
Views::LandedSinceBase.new(commits_by_member: landed.by_member, head_past_base: landed.head_past_base)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# In git, for each member that changed during the audit, the commits since the base commit that touched
|
|
102
|
+
# its file, so the owner can see how each fix landed (alpha feedback A4), and HEAD now. nil outside git.
|
|
103
|
+
#: (Models::AuditStart, Models::Audit) -> Models::CommitsSinceBase?
|
|
104
|
+
def commits_since_base(start, audit)
|
|
105
|
+
base = start.base or return nil
|
|
106
|
+
by_member = start.changed(now: audit.now).to_h do |member|
|
|
107
|
+
[member, @history.commits_since(base, audit.path_of(member))]
|
|
108
|
+
end
|
|
109
|
+
Models::CommitsSinceBase.new(base: base, head: @history.head, by_member: by_member)
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|