Engineering
| Name | Title | Department | Type | Cycle (days) | Status | Close Month |
|---|---|---|---|---|---|---|
| Loading… | ||||||
| Department | Tickets | Median Cycle (d) | Weighted Hours | Unique Assignees | Hours / Person | Rework % |
|---|---|---|---|---|---|---|
| Loading… | ||||||
| Department | Open Tickets |
|---|---|
| Loading… | |
ITSC Phased Execution.xlsx workbook.
Every row of the canonical "ITSC Plan" sheet maps to one project
record. Add a project to create a new row; click any row to open
the detail view (with the brief and intake scoring matrix);
edit inline from the form.
| Priority | Feature | Department | Status | LOE | Product Owner | IT Lead | Launch Target | Actions |
|---|---|---|---|---|---|---|---|---|
| Loading… | ||||||||
Dual-write integration plan
Supersedes the v1 architecture recommendation. Locks in the
Ticket__c + Strategic Initiative record
type direction, fills the gaps v1 silently dropped (voter total,
four-panel brief, exec sponsor, intake metadata), and defines the
dual-write contract between the DataOS /dept/engineering
ITSC tab and Salesforce.
1. Overview
The ITSC Phased Execution workbook has already been replaced by a
form-based UI at /dept/engineering?tab=itsc, backed by a
Firestore collection (itsc_projects) with 50 imported
records. This v2 spec moves the system-of-record to
Salesforce by extending the existing Ticket__c object
with a Strategic Initiative record type, while
keeping the DataOS form as the system-of-entry through a
deterministic dual-write.
DataOS form ← user types ──► dual-write service ──► Firestore (cache) + Salesforce (SoR) Reports / Power BI / SF users ← SOQL ──► Salesforce (SoR)
Both sides see the same data. Either side can edit. Conflicts are
resolved by LastModifiedDate.
2. Architecture
Use the existing Ticket__c object with a new
Strategic Initiative record type. This decision
(carried forward from v1) avoids a duplicate object hierarchy,
inherits ticket lifecycle / ownership / sharing for free, and keeps
reporting in one universe.
Three things that are different in v2:
- Dual-write contract (§13) — the DataOS form remains the operational UI; the Firestore document is a cache, not the system of record.
- Three additional brief fields (§4) — the workbook's per-project one-pager has 4 panels, not 1, and v1 only mapped one of them.
- Total score + executive sponsor + intake metadata (§4) — preserves the upstream nomination/scoring artifacts the steering committee uses.
3. Record Type Configuration
New Record Type: Strategic Initiative
Represents strategic roadmap initiatives, cross-functional programs, and operational improvement efforts. Does not replace standard development / Salesforce-ops tickets, bug tracking, or support workflows — those keep their existing record types.
- Profile assignment: Initial access to Engineering Leadership, IT, and Strategy users; broader once the workflow is validated.
- Page layout: see §7.
- Default record-type behavior: new Ticket created from
/dept/engineeringalways carries this record type ID.
4. Field Additions on Ticket__c
20 new fields. Bold = additions beyond the v1 spec. Italic = clarifications.
4a. Strategic context
| Field Label | API Name | Type | Notes |
|---|---|---|---|
| Strategic Group | Strategic_Group__c | Picklist | Retention & Intelligence · Demand Gen & Efficiency · Cross-Functional · Operational AI Layer · Operational Excellence · Operational Reliability · AI & Engagement · AI & Personalization · AI & Decision Intelligence |
| Strategic Value | Strategic_Value__c | Text(255) | Expected business value (e.g. "Lead quality ↑, faster follow-up") |
| Launch Target Date | Launch_Target__c | Date | Target delivery date. Nullable — see Launch_Target_Raw__c for sentinel handling. |
| Launch Target Raw | Launch_Target_Raw__c | Text(16) | Preserves sentinels (?, TBD, N/A) the committee uses when the date is intentionally undecided. Formula populates Launch_Target__c only when this is a valid ISO date. |
| Level of Effort | Level_of_Effort__c | Picklist | High · Medium · Low (plain text — emoji stripped during migration) |
| Sort Order | Sort_Order__c | Number(3,0) | Manual within-band ordering for the roadmap table |
4b. Alignment flags (5 booleans, unchanged from v1)
| Field Label | API Name | Type |
|---|---|---|
| Alignment | Alignment__c | Checkbox |
| High Impact Work | High_Impact_Work__c | Checkbox |
| Retention Focus | Retention_Focus__c | Checkbox |
| Thought Leadership | Thought_Leadership__c | Checkbox |
| AI Ways of Working | AI_Ways_of_Working__c | Checkbox |
4c. Brief one-pager new in v2 (four panels)
The workbook stores a four-panel one-pager per project. v1 mapped
only the first panel to the existing Description field.
v2 adds the missing three.
| Field Label | API Name | Type | Notes |
|---|---|---|---|
| Why It Matters | Why_It_Matters__c | Long Text Area (8000) | "What's broken today" — the cost / pain / hours-wasted justification. |
| Business Impact | Business_Impact__c | Long Text Area (8000) | Concrete outcomes once shipped — retention lift, lead quality, hours saved. |
| Punchline | Punchline__c | Text(500) | The one-line metaphor the committee uses verbatim ("Think of this as fixing the plumbing"). |
| What It Does | (reuses Description) | (existing) | No change. |
4d. Intake / scoring new in v2
| Field Label | API Name | Type | Notes |
|---|---|---|---|
| Executive Sponsor | Executive_Sponsor__c | Lookup(User) | Non-negotiable for leadership reporting. Free-text fallback acceptable until SF user reconciliation lands. |
| Submitted By | Submitted_By__c | Lookup(User) | Person who originally nominated the project (distinct from CreatedBy, which is the SF DML actor). |
| Total Score | Total_Score__c | Number(3,0) | Sum of voter scores from the nomination matrix. Recomputed by DataOS on every write and pushed to SF. Per-voter detail stays in the DataOS workflow today; can become a child object later (§8) without breaking this field. |
| Primary System | Primary_System__c | Picklist | Salesforce · CMS · Navigator · GTZenda · Hubspot · Other. The primary platform the work touches. |
| Dev T-Shirt | Dev_T_Shirt__c | Picklist | XS · S · M · L · XL. Engineering's effort estimate; complements Level_of_Effort__c (which is steering-committee LOE). |
| Dev Readiness | Dev_Readiness__c | Percent (0-100) | Confidence the work is scoped enough to start. Validation: 0 ≤ value ≤ 100. |
| Intake Document URL | Intake_Document_URL__c | URL | SharePoint / Google Doc link to the full nomination write-up. |
| Reviewer Comments | Reviewer_Comments__c | Long Text Area (8000) | Free-form steering-committee notes — merge suggestions, dependency call-outs, duplicate flags. Distinct from Project_Notes. |
4e. Hierarchy + identity
| Field Label | API Name | Type | Notes |
|---|---|---|---|
| Parent Initiative | Parent_Initiative__c | Lookup(Ticket__c) | Self-lookup. Filter on RecordType = Strategic Initiative. |
| DataOS External ID | DataOS_Project_Id__c | Text(32) — Unique, External ID, indexed | Holds the Firestore project_id. Join key for the dual-write upsert (see §13). |
| IT Lead | IT_Lead__c | Lookup(User) | Typo fix from v1 — added __c suffix. |
4f. Audit (preserve original attribution through migration)
| Field Label | API Name | Type | Notes |
|---|---|---|---|
| Imported Created By | Imported_Created_By__c | Text(200) | Original created_by email — preserved because the Bulk API upsert overwrites CreatedById with the integration user. |
| Imported Updated By | Imported_Updated_By__c | Text(200) | Same rationale for updated_by. |
5. Existing Fields to Reuse
| DataOS field | Existing Ticket__c field | Action |
|---|---|---|
feature_name | Title (or Subject) | direct map |
status | Status | direct map after picklist expansion (§9a) |
priority | Priority | direct map after picklist expansion (§9b) |
department | Department | direct map — kept distinct from Strategic_Group__c (§10) |
brief.what_it_does | Description | direct map |
| (existing notes channel) | Project_Notes | unchanged — DataOS form does not write this |
6. Parent / Child Initiative Structure
Parent_Initiative__c is a self-lookup on
Ticket__c filtered to the Strategic Initiative record
type. Validated needs from the 50 imported records:
🧩 Feedback Platform (v1)↔(v2)🌐 Event Segmentation (v1)↔(v2)📱 Event App : PWA – In-House (v1)↔(v2)⚡ BidSpeed (cloverleaf)↔⚡ BidSpeed (euna)(siblings under a new "BidSpeed" parent record)📊 Sponsor Portal Automation (Pre-Event)↔(Post-Event)- 3 ×
🤖 Agent Phase 2(Tell Me When Alerts / Proposal Generator / Personal Document Library) under a new "Agent Phase 2" parent - 3 × GTZenda items (Process Optimization / Full Autonomy / Grants Data API Integration) under a new "GTZenda" parent
Backfill creates the umbrella parent records where one doesn't
already exist; assigns Parent_Initiative__c for each
child during the same migration pass.
7. Page Layout
Sections, in order:
- Initiative Details — Title, Record Type, Status, Priority, Sort Order, Owner, IT Lead, Launch Target Raw, Launch Target Date (formula), Department, Strategic Group
- Strategic Context — Strategic Value, Level of Effort, Dev T-Shirt, Dev Readiness, Total Score, Primary System
- Goal Alignment — Alignment, High Impact Work, Retention Focus, Thought Leadership, AI Ways of Working (5 checkboxes inline)
- Brief — Description ("What It Does"), Why It Matters, Business Impact, Punchline
- Intake — Submitted By, Executive Sponsor, Intake Document URL, Reviewer Comments
- Hierarchy — Parent Initiative, Related list: Child Initiatives (filtered self-lookup)
- System — DataOS Project Id, Imported Created/Updated By, standard audit fields (collapsed by default)
8. Voter Scoring — Decision and Future Path
Total_Score__c syncs to Salesforce.
Rationale: the per-voter scoring exercise is upstream of becoming a
real Ticket__c — six voters per nominee, scores 1-5,
the committee tallies and picks. The total is what leadership reads;
the per-voter detail is committee-internal. Putting per-voter rows
in SF today would require a child object that only DataOS writes
to.
Future path (additive, no migration of
Total_Score__c): if SF needs per-voter history later,
add an ITSC_Voter_Score__c master-detail child with
Voter_Name__c / Voter_User__c /
Score__c / Recorded_At__c, and convert
Total_Score__c to a Roll-Up Summary. The DataOS sync
then writes child rows instead of just the rolled-up total. Zero
impact on existing reports.
9. Picklist Expansions
Validated against the 50 records currently in Firestore.
9a. Status
| Value | Current count | Map from |
|---|---|---|
| Yet to Start | 25 | direct |
| In Design | 3 | direct |
| In Development | 6 | direct |
| In QA | 0 | (new — replaces "In Proof") |
| In Progress | 5 | direct (distinct from In Development per workbook usage) |
| Completed | 5 | add |
| Paused | 1 | add |
| Unknown | 3 | maps from ? |
| N/A | 1 | direct |
9b. Priority
| Value | Current count | Map from |
|---|---|---|
| P1 | 15 | direct (drop ⭐ emoji) |
| P2 | 14 | direct (drop 🔶 emoji) |
| TBD | 12 | direct (drop ⚪ emoji) |
| Not yet Prioritized | 9 | add — TBD ("we will decide") and Not yet Prioritized ("we haven't looked") mean different things to the committee |
9c. Level of Effort
Plain High / Medium / Low.
Emoji stripped at migration; no data loss (clean 50-of-50 map).
10. Department vs. Strategic Group — Two-Field Model
These are different concepts and stay in different fields:
Department(existing, free-text or picklist) = operational owner. The 50 records have 32 distinct values like "Product / Events / Sales Ops" or "Marketing / Demand Gen". Preserved as-is.Strategic_Group__c(new picklist, §4a) = strategic lens. One project can be in dept "Marketing / Demand Gen" AND strategic group "Retention & Intelligence".
This avoids the lossy force-fit of 32 free-text departments into 9 strategic-group picklist values.
11. List Views
- All Strategic Initiatives — RecordType = Strategic Initiative, sort by
PriorityASC,Sort_Order__cASC,Launch_Target__cASC NULLS LAST - P1 Active — Priority = P1 AND Status NOT IN (Completed, N/A)
- P2 Pipeline — Priority = P2 AND Status NOT IN (Completed, N/A)
- Not Yet Prioritized — Priority IN (TBD, Not yet Prioritized)
- Needs Attention — Status IN (Paused, Unknown) OR (Launch_Target__c < TODAY AND Status NOT IN (Completed, N/A))
- Upcoming 90d — Launch_Target__c BETWEEN TODAY AND TODAY+90, Status NOT IN (Completed, N/A)
12. Validation Rules
Launch_Target_Raw_Valid—Launch_Target_Raw__cis blank OR matches^\d{4}-\d{2}-\d{2}$OR ∈ {?,TBD,N/A}Dev_Readiness_Range— 0 ≤Dev_Readiness__c≤ 100Total_Score_NonNeg—Total_Score__c≥ 0Parent_Cannot_Be_Self—Parent_Initiative__c≠Id
13. Dual-Write Contract (DataOS ⇄ Salesforce)
This is the v2-specific addition. The DataOS form remains the
system of entry; Salesforce is the system of record. Both stay
consistent through a deterministic dual-write keyed on
DataOS_Project_Id__c.
13a. Write path (DataOS form → SF)
User submits the form at /dept/engineering │ ▼ services/itsc_roadmap.py::create_project / update_project / delete_project │ (existing: validates + persists to Firestore) ▼ services/itsc_sf_sync.py::push_to_sf(project_id) ← NEW MODULE │ - simple-salesforce upsert against Ticket__c using │ DataOS_Project_Id__c as the external ID │ - field map lives in one dict (mirrors §4) │ - on success: stores SF Id back on the Firestore doc │ - on failure: logged + queued for retry, does NOT fail the user request ▼ SF Ticket__c (Strategic Initiative record type) — system of record
- Idempotent: upsert by external ID, safe to replay.
- Fail-open from the user's perspective: a transient SF outage doesn't block the form save. The retry worker (scheduled every 15 min via the existing ETL scheduler) drains the queue.
- Voter scores: when the form submits, the recomputed
total_scoreis what gets pushed. Per-voter rows are NOT pushed (see §8).
13b. Read path (today: Firestore; tomorrow: SF)
Phase 1 (immediate after backfill): reads continue
from Firestore for sub-50ms latency in the
/dept/engineering tab. SF is shadow-of-truth.
Phase 2 (once SF UI exists and is in steady use):
a nightly reconciliation job pulls every Ticket__c
with RecordType = Strategic Initiative, diffs against Firestore by
DataOS_Project_Id__c, and applies SF-side edits back
into Firestore. Conflict resolution: LastModifiedDate
wins.
Phase 3 (optional, future): cut over reads to
SOQL directly, decommission the Firestore collection. Service
signature doesn't change, only the loader behind
services/itsc_roadmap.py::list_projects does.
13c. Reverse path (SF → DataOS, Phase 2 onward)
- Triggered by either:
- A scheduled reconciliation (15-min cadence), OR
- A SF Outbound Message / Platform Event on
Ticket__cupdate (if SF ops is comfortable adding it)
- For each SF record where
LastModifiedDate > Firestore.updated_at, write the SF state back to Firestore. - Skips records where DataOS write happened in the last 60 seconds (debounce so a DataOS write doesn't immediately echo back as a SF→DataOS overwrite).
13d. Source of truth for each field
| Field | Authoritative side | Notes |
|---|---|---|
| All §4 fields, all §5 reuse fields, audit | Whichever side wrote last (LastModifiedDate wins) | Single source of truth: the conflict-resolution rule |
DataOS_Project_Id__c | DataOS (immutable after first write) | Never changes |
CreatedById / CreatedDate | SF | Standard; DataOS preserves original via Imported_Created_By__c |
14. Data Migration
Migration target: the 50 records currently in itsc_projects Firestore.
Steps:
- Export Firestore → flat CSV via a one-shot
scripts/export_itsc_to_sf_csv.py(writesitsc_to_sf.csvwith columns = SF API names per §4 + §5; emojis stripped from Priority and LOE; status remapped per §9a). - Identify the 7 parent-record umbrellas from §6 — create them in SF first (manually or as separate CSV rows), capture their SF Ids.
- Backfill
parent_idcolumn initsc_to_sf.csvusing the umbrella SF Ids. - Bulk upsert into
Ticket__ckeyed onDataOS_Project_Id__c. Validate row count = 50 + umbrella count. - Spot-check the 5 emoji-heavy records (Custom Communication, Health Dashboard, both Feedback Platforms, GTZenda variants) to confirm round-trip.
- Turn on dual-write in DataOS (env flag
ITSC_SF_SYNC_ENABLED=1). From that moment, all DataOS writes also push to SF. - Run a one-time reconciliation read (SF → Firestore) to confirm parity.
Rollback: disable ITSC_SF_SYNC_ENABLED.
DataOS reverts to Firestore-only operation. SF records remain but
go stale until re-enabled.
15. Phasing / Rollout
| Phase | Owner | Deliverables | Gate to next |
|---|---|---|---|
| 1. SF object build | SF ops | All §4 fields, validation rules (§12), page layout (§7), list views (§11), record type assignments | Sandbox sign-off from steering committee |
| 2. DataOS sync wiring | DataOS eng | services/itsc_sf_sync.py, retry queue, ITSC_SF_SYNC_ENABLED env flag (off by default), unit tests against simple-salesforce mock | All 50 records dual-write cleanly in sandbox |
| 3. Backfill | DataOS eng + SF ops | 50 records imported via §14 steps, parent umbrellas linked, spot-check sign-off | Steering committee verifies parity in SF |
| 4. Production cut-over | DataOS eng | Flip ITSC_SF_SYNC_ENABLED=1 in production, monitor for 1 week | Zero sync failures over a week |
| 5. SF-as-read-source (optional, future) | DataOS eng | Reverse-sync + Ticket__c reader in services/itsc_roadmap.py | Steering committee actively using SF Lightning record pages |
16. Benefits of This Approach
- No duplicate object hierarchy — uses existing
Ticket__clifecycle, ownership, sharing, audit. - Single source of truth in Salesforce — Power BI, SF reports, and the rest of the company's data universe see initiatives in the same place they see tickets.
- DataOS form remains the operational UI — the steering committee keeps the fast, purpose-built /dept/engineering tab they're already using.
- Zero data loss from the current workbook — every field that today has a non-trivial value (brief panels, voter total, exec sponsor, intake metadata) has a home.
- Additive future path for voter detail — when/if SF needs per-voter rows, it's an additive child object, not a migration.
- Fail-soft on SF outage — user writes never block on SF availability.
17. Open Questions for Steering / SF Ops
In Progressvs.In Development— are these two genuinely different statuses, or did the workbook accidentally accumulate both? Currently 5 records useIn Progressand 6 useIn Development. Recommend keeping both (committee call).Submitted_By__cvs. ownership — is the submitter the same as the eventual owner in 90% of cases? If yes, we can defaultSubmitted_By__ctoOwnerIdon insert and skip the extra picker in the form.- Intake docs — keep
Intake_Document_URL__cas a URL field, or move to native SF Files (ContentDocument)? Files give versioning and access control; URL is simpler for the SharePoint links the committee already uses. - Reviewer comments —
Reviewer_Comments__cfield, or Chatter? Chatter gives threading and notifications but is harder to migrate from the workbook's free-text field. - Strategic_Group picklist values — the 9 listed are from v1. Should the committee add / rename / drop any before deployment, while picklist changes are still cheap?
18. Changes from V1
For anyone who's already read v1:
| Change | Why |
|---|---|
3 new brief fields — Why_It_Matters__c, Business_Impact__c, Punchline__c | The workbook's one-pager has 4 panels; v1 only mapped 1 |
8 new intake fields — Executive_Sponsor__c, Submitted_By__c, Total_Score__c, Primary_System__c, Dev_T_Shirt__c, Dev_Readiness__c, Intake_Document_URL__c, Reviewer_Comments__c | Preserves the Sheet2 nomination matrix that drives committee decisions |
Status picklist expanded to include Completed, Paused; In Proof becomes In QA | 7 of 50 records would otherwise be unmappable |
Priority picklist expanded to include Not yet Prioritized | 9 of 50 records would otherwise be unmappable |
Two-field department model — keep Department as-is, add Strategic_Group__c as a separate strategic lens | Avoids force-fitting 32 free-text departments into 9 picklist values |
Launch_Target_Raw__c text + Launch_Target__c formula date | The workbook genuinely uses ? / TBD / N/A as launch-target values |
DataOS_Project_Id__c external ID | Required join key for the dual-write upsert |
| Section 13: Dual-write contract | The whole "DataOS form remains operational UI, SF is system of record" model is new in v2 |
IT_Lead → IT_Lead__c | Typo fix |