Class: WorkItem
- Inherits:
-
Object
- Object
- WorkItem
- Defined in:
- lib/almirah/doc_items/work_item.rb
Overview
A single Scope-table row of a Decision Record, modelled as a node in the
per-row dependency network (ADR-194). Each work item carries its canonical
identity (<record>.<step>.<activity>), the bounded per-row Status it reads
its readiness from (ADR-193), and predecessor / successor edges spanning both
intra-record (step order) and cross-record (Depends On) links.
predecessors / successors follow the house list-of-single-key-hashes shape
(ADR-197): each entry maps a readable record.step.activity label to the
resolved WorkItem. Every cross-record edge additionally records whether it
stays within a decision_groups folder (in-group) or crosses to another
(cross-group); that tag is inert here and consumed by the critical-chain step
(ADR-195). Readiness ignores it — a cross-group predecessor blocks exactly
like an in-group one.
Constant Summary collapse
- ACTIVITY_ORDER =
Canonical phase order used only as the fallback for activity-type-aligned resolution when the prerequisite has no row of the dependent's exact Item.
%w[Analysis Requirements Code Tests].freeze
Instance Attribute Summary collapse
-
#activity ⇒ Object
readonly
Returns the value of attribute activity.
-
#cross_group_predecessor_labels ⇒ Object
Returns the value of attribute cross_group_predecessor_labels.
-
#depends_on_refs ⇒ Object
readonly
Returns the value of attribute depends_on_refs.
-
#focused_estimate ⇒ Object
readonly
Returns the value of attribute focused_estimate.
-
#owner ⇒ Object
readonly
Returns the value of attribute owner.
-
#predecessors ⇒ Object
Returns the value of attribute predecessors.
-
#record_id ⇒ Object
readonly
Returns the value of attribute record_id.
-
#record_sequence ⇒ Object
readonly
Returns the value of attribute record_sequence.
-
#resolved_dependencies ⇒ Object
Returns the value of attribute resolved_dependencies.
-
#safe_estimate ⇒ Object
readonly
Returns the value of attribute safe_estimate.
-
#start_date ⇒ Object
readonly
Returns the value of attribute start_date.
-
#status ⇒ Object
readonly
Returns the value of attribute status.
-
#step ⇒ Object
readonly
Returns the value of attribute step.
-
#successors ⇒ Object
Returns the value of attribute successors.
-
#target_date ⇒ Object
readonly
Returns the value of attribute target_date.
Instance Method Summary collapse
- #activity_rank ⇒ Object
- #add_predecessor(work_item, cross_group:) ⇒ Object
- #add_resolved_dependency(ref, doc, anchor, label) ⇒ Object
- #add_successor(work_item) ⇒ Object
-
#cross_record_predecessors ⇒ Object
Resolved Depends On edges into other records (in-group or cross-group alike).
-
#cross_record_violation? ⇒ Boolean
A started row whose resolved cross-record predecessor is not yet Done.
- #done? ⇒ Boolean
-
#fully_kitted? ⇒ Boolean
Kitted when every predecessor — intra- and cross-record, regardless of the in-group / cross-group tag — is Done; trivially kitted when it has none.
- #id ⇒ Object
-
#initialize(record_id:, step:, activity:, owner:, status:, depends_on_refs:, focused_estimate: 0.0, safe_estimate: 0.0, record_sequence: 0, start_date: nil, target_date: nil) ⇒ WorkItem
constructor
rubocop:disable Metrics/ParameterLists.
-
#intra_record_predecessors ⇒ Object
Same-record, lower-numbered steps — the intra-record (phase-order) edges.
-
#phase_order_violation? ⇒ Boolean
A started row with an unfinished lower-numbered step in the same record.
- #predecessor_items ⇒ Object
-
#row_anchor ⇒ Object
The anchor of this work item's row in its rendered Scope table — the deep-link target a dependent record points at.
-
#started? ⇒ Boolean
A row is "started" once it leaves To Do; both In-Progress and Done count, so a Done row whose predecessor never finished is still flagged as a violation.
- #successor_items ⇒ Object
Constructor Details
#initialize(record_id:, step:, activity:, owner:, status:, depends_on_refs:, focused_estimate: 0.0, safe_estimate: 0.0, record_sequence: 0, start_date: nil, target_date: nil) ⇒ WorkItem
rubocop:disable Metrics/ParameterLists
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/almirah/doc_items/work_item.rb', line 25 def initialize(record_id:, step:, activity:, owner:, status:, depends_on_refs:, # rubocop:disable Metrics/ParameterLists focused_estimate: 0.0, safe_estimate: 0.0, record_sequence: 0, start_date: nil, target_date: nil) @record_id = record_id @step = step @activity = activity.to_s.strip @owner = owner.to_s.strip @status = status.to_s.strip @depends_on_refs = depends_on_refs # array of record ref strings, e.g. ["ADR-193"] # The row's authored committed window (ADR-213): the Scope Start Date and # Target Date as parsed Dates (nil when absent/unparseable). Distinct from the # computed schedule -- these are the author's intent, drawn on the tracking lane. @start_date = start_date @target_date = target_date # Per-row scheduling estimates in working days (ADR-195); the focused estimate # is the scheduling duration, safe - focused the safety aggregated into the # project buffer. record_sequence is the owning record's number, used only as # a deterministic priority tiebreak in the critical-chain scheduler. @focused_estimate = focused_estimate @safe_estimate = safe_estimate @record_sequence = record_sequence @predecessors = [] @successors = [] @cross_group_predecessor_labels = [] # One entry per resolved Depends On reference, keyed by the authored ref: # { ref => { doc:, anchor:, label: } }. `anchor` is the target's resolved # work-item row anchor (nil when the target has no `#` step column, so the # link opens the record page); `label` is the resolved work item's id, for # the link tooltip. Used to render the Depends On cell as deep links. @resolved_dependencies = {} end |
Instance Attribute Details
#activity ⇒ Object (readonly)
Returns the value of attribute activity.
21 22 23 |
# File 'lib/almirah/doc_items/work_item.rb', line 21 def activity @activity end |
#cross_group_predecessor_labels ⇒ Object
Returns the value of attribute cross_group_predecessor_labels.
23 24 25 |
# File 'lib/almirah/doc_items/work_item.rb', line 23 def cross_group_predecessor_labels @cross_group_predecessor_labels end |
#depends_on_refs ⇒ Object (readonly)
Returns the value of attribute depends_on_refs.
21 22 23 |
# File 'lib/almirah/doc_items/work_item.rb', line 21 def depends_on_refs @depends_on_refs end |
#focused_estimate ⇒ Object (readonly)
Returns the value of attribute focused_estimate.
21 22 23 |
# File 'lib/almirah/doc_items/work_item.rb', line 21 def focused_estimate @focused_estimate end |
#owner ⇒ Object (readonly)
Returns the value of attribute owner.
21 22 23 |
# File 'lib/almirah/doc_items/work_item.rb', line 21 def owner @owner end |
#predecessors ⇒ Object
Returns the value of attribute predecessors.
23 24 25 |
# File 'lib/almirah/doc_items/work_item.rb', line 23 def predecessors @predecessors end |
#record_id ⇒ Object (readonly)
Returns the value of attribute record_id.
21 22 23 |
# File 'lib/almirah/doc_items/work_item.rb', line 21 def record_id @record_id end |
#record_sequence ⇒ Object (readonly)
Returns the value of attribute record_sequence.
21 22 23 |
# File 'lib/almirah/doc_items/work_item.rb', line 21 def record_sequence @record_sequence end |
#resolved_dependencies ⇒ Object
Returns the value of attribute resolved_dependencies.
23 24 25 |
# File 'lib/almirah/doc_items/work_item.rb', line 23 def resolved_dependencies @resolved_dependencies end |
#safe_estimate ⇒ Object (readonly)
Returns the value of attribute safe_estimate.
21 22 23 |
# File 'lib/almirah/doc_items/work_item.rb', line 21 def safe_estimate @safe_estimate end |
#start_date ⇒ Object (readonly)
Returns the value of attribute start_date.
21 22 23 |
# File 'lib/almirah/doc_items/work_item.rb', line 21 def start_date @start_date end |
#status ⇒ Object (readonly)
Returns the value of attribute status.
21 22 23 |
# File 'lib/almirah/doc_items/work_item.rb', line 21 def status @status end |
#step ⇒ Object (readonly)
Returns the value of attribute step.
21 22 23 |
# File 'lib/almirah/doc_items/work_item.rb', line 21 def step @step end |
#successors ⇒ Object
Returns the value of attribute successors.
23 24 25 |
# File 'lib/almirah/doc_items/work_item.rb', line 23 def successors @successors end |
#target_date ⇒ Object (readonly)
Returns the value of attribute target_date.
21 22 23 |
# File 'lib/almirah/doc_items/work_item.rb', line 21 def target_date @target_date end |
Instance Method Details
#activity_rank ⇒ Object
73 74 75 |
# File 'lib/almirah/doc_items/work_item.rb', line 73 def activity_rank ACTIVITY_ORDER.index(@activity) || ACTIVITY_ORDER.length end |
#add_predecessor(work_item, cross_group:) ⇒ Object
87 88 89 90 |
# File 'lib/almirah/doc_items/work_item.rb', line 87 def add_predecessor(work_item, cross_group:) @predecessors << { work_item.id => work_item } @cross_group_predecessor_labels << work_item.id if cross_group end |
#add_resolved_dependency(ref, doc, anchor, label) ⇒ Object
69 70 71 |
# File 'lib/almirah/doc_items/work_item.rb', line 69 def add_resolved_dependency(ref, doc, anchor, label) @resolved_dependencies[ref] = { doc: doc, anchor: anchor, label: label } end |
#add_successor(work_item) ⇒ Object
92 93 94 |
# File 'lib/almirah/doc_items/work_item.rb', line 92 def add_successor(work_item) @successors << { work_item.id => work_item } end |
#cross_record_predecessors ⇒ Object
Resolved Depends On edges into other records (in-group or cross-group alike).
110 111 112 |
# File 'lib/almirah/doc_items/work_item.rb', line 110 def cross_record_predecessors predecessor_items.reject { |p| p.record_id == @record_id } end |
#cross_record_violation? ⇒ Boolean
A started row whose resolved cross-record predecessor is not yet Done.
126 127 128 |
# File 'lib/almirah/doc_items/work_item.rb', line 126 def cross_record_violation? started? && cross_record_predecessors.any? { |p| !p.done? } end |
#done? ⇒ Boolean
83 84 85 |
# File 'lib/almirah/doc_items/work_item.rb', line 83 def done? @status == 'Done' end |
#fully_kitted? ⇒ Boolean
Kitted when every predecessor — intra- and cross-record, regardless of the in-group / cross-group tag — is Done; trivially kitted when it has none.
116 117 118 |
# File 'lib/almirah/doc_items/work_item.rb', line 116 def fully_kitted? predecessor_items.all?(&:done?) end |
#id ⇒ Object
57 58 59 |
# File 'lib/almirah/doc_items/work_item.rb', line 57 def id "#{@record_id}.#{@step}.#{@activity}" end |
#intra_record_predecessors ⇒ Object
Same-record, lower-numbered steps — the intra-record (phase-order) edges.
105 106 107 |
# File 'lib/almirah/doc_items/work_item.rb', line 105 def intra_record_predecessors predecessor_items.select { |p| p.record_id == @record_id } end |
#phase_order_violation? ⇒ Boolean
A started row with an unfinished lower-numbered step in the same record.
121 122 123 |
# File 'lib/almirah/doc_items/work_item.rb', line 121 def phase_order_violation? started? && intra_record_predecessors.any? { |p| !p.done? } end |
#predecessor_items ⇒ Object
96 97 98 |
# File 'lib/almirah/doc_items/work_item.rb', line 96 def predecessor_items @predecessors.map { |edge| edge.values.first } end |
#row_anchor ⇒ Object
The anchor of this work item's row in its rendered Scope table — the deep-link
target a dependent record points at. Namespaced with .scope. so it never
collides with the Affected Documents controlled table, whose rows anchor on
the same <record>.<step> scheme on the same page.
65 66 67 |
# File 'lib/almirah/doc_items/work_item.rb', line 65 def row_anchor "#{@record_id}.scope.#{@step}" end |
#started? ⇒ Boolean
A row is "started" once it leaves To Do; both In-Progress and Done count, so a Done row whose predecessor never finished is still flagged as a violation.
79 80 81 |
# File 'lib/almirah/doc_items/work_item.rb', line 79 def started? @status == 'In-Progress' || @status == 'Done' end |
#successor_items ⇒ Object
100 101 102 |
# File 'lib/almirah/doc_items/work_item.rb', line 100 def successor_items @successors.map { |edge| edge.values.first } end |