Back to New Initiative Scoping & Approval

Developer Handover Pack

Everything needed to build the automation from scratch: current state, full agent specs, data flow, and the build stack.

4 pagesPDF · Technical
FS-DOC-04Technical

Developer Handover Pack

New Initiative Scoping and Approval

[YourCompany.com] · Management Department · Prepared by FullSpec · [Today's Date]

This document is the primary technical reference for the FullSpec team building the New Initiative Scoping and Approval automation. It covers the full current-state step map, detailed agent specifications with IO contracts, the end-to-end data flow trace, and the recommended build stack. Everything a builder needs to scope, configure, and validate the three-agent system is contained here. No external parties are involved: FullSpec handles all build, integration, and testing work. Where you or your team have responsibilities, for example supplying API credentials or confirming routing categories, those are called out explicitly.

01Process snapshot

Step
Name
Description
1
Idea or Request Surfaces
A team member raises an initiative idea verbally, in Slack, or by email. No standard format exists, so the detail captured varies widely. Time cost: 10 min.
2
Scoping Template Sent or Found
The receiving manager locates the scoping template, if one exists, and forwards it to the proposer. Template versions vary and are often outdated. Time cost: 15 min.
3
Proposer Completes Scoping Document
The proposer fills in the scope, estimated effort, budget requirement, and strategic rationale. Frequently takes multiple attempts due to unclear instructions. BOTTLENECK. Time cost: 60 min.
4
Document Shared for Initial Review
The completed document is emailed or shared via Slack to the relevant reviewer. No formal acknowledgement or deadline is set. Time cost: 10 min.
5
Reviewer Reads and Requests Clarifications
The reviewer reads the document, identifies missing information, and replies with questions. Back-and-forth can take several days. BOTTLENECK. Time cost: 45 min.
6
Proposer Revises and Resubmits
The proposer updates the document based on feedback and resubmits. Versioning is manual and earlier drafts cause confusion. Time cost: 30 min.
7
Cost and Resource Estimate Added
The operations lead adds or validates a budget estimate and assigns a resource category. Often skipped or done informally. Time cost: 20 min.
8
Escalated to Leadership for Approval
The document is forwarded to the founder or leadership team for a go, no-go, or hold decision. No formal deadline or scoring rubric applied. Time cost: 10 min.
9
Leadership Reviews and Decides
Leadership reads the proposal, checks it against current priorities and budget headroom, and makes a decision from memory. BOTTLENECK. Time cost: 40 min.
10
Decision Communicated and Logged
The decision is communicated back to the proposer and someone manually updates a tracker. Logging is inconsistent and often skipped. Time cost: 15 min.
Time cost summary: Total manual time per cycle is 255 minutes (4 hours 15 min) across 10 steps. At a volume of 8 to 15 submissions per month this equates to 6 to 9 hours of manual effort per week, benchmarked at 7 hours/week. The automation replaces steps 2, 3, 4, 6, 7, 8, 9, and 10. Steps 3 (proposer completing a structured form) and 5 (reviewer submitting a structured assessment) remain human but are constrained by validated templates. Step 1 (idea surfaces) remains a manual trigger via Google Forms. Net automated time reduction eliminates the majority of the 255-minute cycle.
Developer Handover PackPage 1 of 4
FS-DOC-04Technical

02Agent specifications

Intake Validation Agent

Fires immediately when a Google Forms submission is received via webhook. The agent evaluates each response field against a completeness checklist: presence, minimum word count (strategic rationale must be at least 30 words; estimated budget and estimated effort must be non-null numeric values; affected departments must have at least one selection). If any field fails, the agent composes a targeted rejection message listing the specific failing fields by name and sends it to the proposer via Slack DM and Gmail. The initiative is not logged or forwarded until all fields pass. If all fields pass, the agent emits a validated payload to the Scoping and Routing Agent. Estimated build time: 8 hours. Complexity: Moderate.

Trigger
Google Forms webhook fires on new submission
Tools
Google Forms, Slack, Gmail
Replaces steps
Steps 2 and 3 (template dispatch and completeness checking)
Estimated build
8 hours — Moderate
// Input
form_response: {
  proposer_name: string,
  proposer_email: string,
  initiative_title: string,
  strategic_rationale: string,       // min 30 words
  estimated_effort_days: number,
  estimated_budget_usd: number,
  affected_departments: string[],    // min 1 item
  initiative_category: string        // must match routing table enum
}

// Validation rules
required_fields: [strategic_rationale, estimated_effort_days,
  estimated_budget_usd, affected_departments, initiative_category]
word_count_min: { strategic_rationale: 30 }
numeric_min: { estimated_effort_days: 0.5, estimated_budget_usd: 0 }

// Output (pass)
validated_payload: {
  ...form_response,
  validation_status: 'passed',
  validated_at: ISO8601_timestamp
}

// Output (fail)
rejection_message: {
  channel: 'slack_dm + gmail',
  recipient_email: proposer_email,
  failing_fields: string[],
  message_template: 'INTAKE_REJECTION_V1'
}
  • Google Forms must be on a Google Workspace account with Pub/Sub or Apps Script webhook configured. A free personal Gmail account does not support reliable push notifications; confirm Workspace tier before build.
  • The initiative_category field in the form must use a dropdown with a fixed enum list. This list must be finalised and locked before build starts because the Scoping and Routing Agent routing table is keyed against it.
  • Slack DM delivery requires the Slack bot to be installed in the workspace with chat:write and users:read.email OAuth scopes. The bot must be able to look up the proposer's Slack user ID by email address.
  • Gmail send from the validation agent requires a dedicated service account or an OAuth2 credential scoped to gmail.send. Do not reuse the digest sender credential to avoid rate limit collisions.
  • Dedupe: if the same proposer_email submits the same initiative_title within a 24-hour window, suppress the second trigger and log a duplicate_suppressed event to the error log table. Do not send a second rejection or pass.
  • Fallback: if the Slack DM fails to deliver (user not found by email), fall back to Gmail only and log a slack_dm_failed event.
Scoping and Routing Agent

Fires after the Intake Validation Agent emits a validated payload. This agent performs three sequential actions: it creates a structured Notion scoping page using the locked page template, populating all fields from the validated payload and stamping a unique reference ID in the format INIT-YYYY-MM-NNN; it appends a new row to the Google Sheets initiative tracker; and it determines the correct reviewer from the routing table keyed on initiative_category, calculates a review deadline of three business days from submission_date (Monday to Friday calendar, no public holidays adjustment by default), and sends a Slack channel message to the assigned reviewer's DM with the Notion page URL and the deadline date. Estimated build time: 14 hours. Complexity: Complex.

Trigger
Validated payload received from Intake Validation Agent
Tools
Notion, Google Sheets, Slack
Replaces steps
Steps 4, 6, and 7 (routing, revision loop, and resource estimate logging)
Estimated build
14 hours — Complex
// Input
validated_payload: {
  proposer_name: string,
  proposer_email: string,
  initiative_title: string,
  strategic_rationale: string,
  estimated_effort_days: number,
  estimated_budget_usd: number,
  affected_departments: string[],
  initiative_category: string,
  validation_status: 'passed',
  validated_at: ISO8601_timestamp
}

// Notion page created
notion_page: {
  reference_id: 'INIT-YYYY-MM-NNN',
  title: initiative_title,
  proposer: proposer_name,
  strategic_rationale: strategic_rationale,
  estimated_effort_days: estimated_effort_days,
  estimated_budget_usd: estimated_budget_usd,
  affected_departments: affected_departments,
  category: initiative_category,
  status: 'Pending Review',
  submitted_at: validated_at,
  reviewer_name: string,            // resolved from routing table
  review_deadline: ISO8601_date
}

// Google Sheets row appended
sheets_row: {
  reference_id, proposer_name, proposer_email,
  initiative_title, initiative_category,
  estimated_budget_usd, submission_date,
  reviewer_name, review_deadline,
  status: 'Pending Review',
  notion_page_url: string
}

// Slack notification sent
slack_message: {
  recipient: reviewer_slack_id,
  notion_url: string,
  review_deadline: ISO8601_date,
  template: 'REVIEWER_NOTIFY_V1'
}
  • Notion integration requires an internal integration token with insert content and read content permissions on the parent database. The locked scoping page template must be duplicated as a database template in Notion, not a standalone page, so the API can create instances from it.
  • The Notion database property names used in the API call must match the template exactly (case-sensitive). Confirm the final template field names before writing the page creation step. If the template is updated post-launch, field mappings must be updated in the agent configuration.
  • The routing table (initiative_category to reviewer_name and reviewer_slack_id) must be stored in a separate Google Sheets tab named ROUTING_TABLE with columns: category, reviewer_name, reviewer_email, reviewer_slack_id. The agent reads this tab at runtime.
  • Business day calculation for the three-day review deadline must use a helper function that skips Saturday and Sunday. If the business operates non-standard calendars, the public holiday list must be supplied as a configuration array before build.
  • Google Sheets API requires the sheets service account to have Editor access on the tracker spreadsheet. Confirm the spreadsheet ID and the exact tab name (suggested: INITIATIVE_TRACKER) before build.
  • Fallback: if Notion page creation fails, the agent must not write the Sheets row or send the Slack message. Log a notion_create_failed event with the full payload so the run can be retried without data duplication.
Approval Digest Agent

Runs on a scheduled trigger every weekday at 08:00 AM in the business's local timezone. The agent queries the Google Sheets tracker for all rows where the status column equals 'Awaiting Leadership Decision'. If the result set is empty, the agent exits silently. If one or more rows are found, the agent fetches the corresponding Notion page for each to retrieve the reviewer recommendation, reviewer notes, and estimated budget. It compiles a formatted HTML digest email listing each initiative with its reference ID, title, reviewer recommendation, reviewer notes, estimated budget, and a direct link to the Notion page. It calculates the total pipeline budget from the estimated_budget_usd values of all pending rows and includes this figure in the digest header. The digest is sent to the configured leadership recipient (founder or CEO) via Gmail. Estimated build time: 10 hours. Complexity: Moderate.

Trigger
Scheduled: Monday to Friday, 08:00 AM local timezone
Tools
Google Sheets, Notion, Gmail
Replaces steps
Steps 8, 9, and 10 (escalation chase, leadership collation, and decision logging)
Estimated build
10 hours — Moderate
// Input (from Google Sheets query)
pending_rows: [
  {
    reference_id: string,
    initiative_title: string,
    proposer_name: string,
    estimated_budget_usd: number,
    reviewer_name: string,
    notion_page_url: string,
    status: 'Awaiting Leadership Decision'
  }
]

// Input (from Notion per page, fetched at runtime)
notion_review_data: {
  reviewer_recommendation: 'Approve' | 'Revise' | 'Decline',
  reviewer_notes: string,
  review_completed_at: ISO8601_timestamp
}

// Output: Gmail digest
gmail_send: {
  to: leadership_email,            // configured at build time
  subject: 'Initiative Digest: [N] decisions pending — [Date]',
  body_format: 'HTML',
  template: 'LEADERSHIP_DIGEST_V1',
  fields_per_item: [reference_id, initiative_title, proposer_name,
    reviewer_recommendation, reviewer_notes,
    estimated_budget_usd, notion_page_url],
  digest_header: { total_pending: number, total_pipeline_budget_usd: number }
}

// On leadership decision recorded in Notion
// (triggered by Notion database automation or webhook)
decision_writeback: {
  sheets_row_update: { reference_id, status: 'Approved|Revised|Declined',
    decision_date: ISO8601_date, decision_notes: string },
  slack_notify_proposer: {
    recipient: proposer_slack_id,
    outcome: string,
    conditions: string,
    next_steps: string,
    template: 'PROPOSER_OUTCOME_V1'
  }
}
  • The digest Gmail sender must be a shared mailbox or service account, not a personal Gmail. Configure an OAuth2 credential with gmail.send scope. Confirm the leadership recipient email address before build and store it as an environment variable, not hardcoded.
  • The Notion query to retrieve reviewer_recommendation and reviewer_notes requires that these fields exist as select and text properties respectively on the scoping page database. Confirm property names during template finalisation.
  • The decision writeback to Google Sheets and Slack must be triggered by a Notion database property change event (status field moving to 'Approved', 'Revised', or 'Declined'). Configure a Notion webhook or poll on a 15-minute interval as a fallback if webhooks are not available on the current Notion plan.
  • If the pending_rows result set is empty at 08:00 AM, the agent must exit without sending any email. Do not send a 'nothing pending' digest to leadership.
  • Gmail send rate limit is 100 messages per 100 seconds per user. The digest is a single message so rate limits are not a concern, but confirm the service account is not shared with other automation sends.
  • Timezone configuration: the 08:00 AM schedule must be set in the automation platform using the business's local timezone (IANA format, e.g. America/New_York). Confirm with the process owner before build.
Developer Handover PackPage 2 of 4
FS-DOC-04Technical

03End-to-end data flow

Full trigger-to-output data flow with field names and agent handoff points
// ============================================================
// NEW INITIATIVE SCOPING AND APPROVAL — END-TO-END DATA FLOW
// ============================================================

// TRIGGER
// Proposer submits Google Forms intake form
GOOGLE_FORMS.submission -> {
  proposer_name: string,
  proposer_email: string,
  initiative_title: string,
  strategic_rationale: string,
  estimated_effort_days: number,
  estimated_budget_usd: number,
  affected_departments: string[],
  initiative_category: string,
  submitted_at: ISO8601_timestamp
}

// ============================================================
// AGENT 1: INTAKE VALIDATION AGENT
// ============================================================
// Receives raw form payload via webhook
// Validates completeness against required field checklist

INTAKE_VALIDATION_AGENT.run(
  input: GOOGLE_FORMS.submission
)

// Branch A: validation fails
if validation_status == 'failed' {
  failing_fields: string[]              // e.g. ['strategic_rationale', 'estimated_budget_usd']
  SLACK.send_dm(recipient: proposer_slack_id,
                template: 'INTAKE_REJECTION_V1',
                fields: failing_fields)
  GMAIL.send(to: proposer_email,
             template: 'INTAKE_REJECTION_V1',
             fields: failing_fields)
  -> EXIT (no downstream agents triggered)
}

// Branch B: validation passes
if validation_status == 'passed' {
  validated_payload: {
    ...GOOGLE_FORMS.submission,
    validation_status: 'passed',
    validated_at: ISO8601_timestamp
  }
  -> HANDOFF TO AGENT 2
}

// ============================================================
// AGENT 2: SCOPING AND ROUTING AGENT
// ============================================================
// Receives validated_payload from Agent 1

SCOPING_AND_ROUTING_AGENT.run(
  input: validated_payload
)

// Step 2a: Generate unique reference ID
reference_id = 'INIT-' + YYYY + '-' + MM + '-' + NNN  // NNN = zero-padded sequence

// Step 2b: Create Notion scoping page
NOTION.pages.create({
  database_id: INITIATIVE_DB_ID,
  properties: {
    'Reference ID': reference_id,
    'Title': initiative_title,
    'Proposer': proposer_name,
    'Proposer Email': proposer_email,
    'Strategic Rationale': strategic_rationale,
    'Estimated Effort (Days)': estimated_effort_days,
    'Estimated Budget (USD)': estimated_budget_usd,
    'Affected Departments': affected_departments,
    'Category': initiative_category,
    'Status': 'Pending Review',
    'Submitted At': validated_at,
    'Reviewer': reviewer_name,          // resolved from ROUTING_TABLE
    'Review Deadline': review_deadline  // validated_at + 3 business days
  }
}) -> notion_page_url: string

// Step 2c: Append row to Google Sheets tracker
GOOGLE_SHEETS.rows.append({
  spreadsheet_id: TRACKER_SPREADSHEET_ID,
  sheet_name: 'INITIATIVE_TRACKER',
  row: {
    reference_id, proposer_name, proposer_email,
    initiative_title, initiative_category,
    estimated_budget_usd, submission_date: validated_at,
    reviewer_name, review_deadline,
    status: 'Pending Review',
    notion_page_url
  }
})

// Step 2d: Resolve reviewer from routing table
GOOGLE_SHEETS.rows.query({
  sheet_name: 'ROUTING_TABLE',
  filter: { category: initiative_category }
}) -> { reviewer_name, reviewer_email, reviewer_slack_id }

// Step 2e: Notify reviewer via Slack
SLACK.send_dm({
  recipient: reviewer_slack_id,
  template: 'REVIEWER_NOTIFY_V1',
  fields: { reference_id, initiative_title, notion_page_url, review_deadline }
})

// -> HUMAN STEP: Reviewer completes structured Google Form assessment
// (Google Form linked from Notion page; no agent involvement until submission)

// On reviewer form submission:
GOOGLE_FORMS.reviewer_submission -> {
  reference_id: string,
  reviewer_recommendation: 'Approve' | 'Revise' | 'Decline',
  reviewer_notes: string,
  resource_feasibility_flag: boolean,
  review_completed_at: ISO8601_timestamp
}

// Step 2f: Write reviewer outcome back to Notion
NOTION.pages.update({
  page_id: resolved_from_reference_id,
  properties: {
    'Reviewer Recommendation': reviewer_recommendation,
    'Reviewer Notes': reviewer_notes,
    'Resource Feasibility': resource_feasibility_flag,
    'Review Completed At': review_completed_at,
    'Status': 'Awaiting Leadership Decision'  // if Approve or Revise
  }
})

// Step 2g: Update Google Sheets status
GOOGLE_SHEETS.rows.update({
  filter: { reference_id },
  fields: { status: 'Awaiting Leadership Decision' }
})

// ============================================================
// AGENT 3: APPROVAL DIGEST AGENT
// ============================================================
// Scheduled trigger: Monday to Friday, 08:00 AM local timezone

APPROVAL_DIGEST_AGENT.run()

// Step 3a: Query tracker for pending leadership decisions
GOOGLE_SHEETS.rows.query({
  sheet_name: 'INITIATIVE_TRACKER',
  filter: { status: 'Awaiting Leadership Decision' }
}) -> pending_rows: [{ reference_id, initiative_title, proposer_name,
                        estimated_budget_usd, reviewer_name, notion_page_url }]

// Step 3b: Fetch reviewer data from Notion per initiative
for each row in pending_rows:
  NOTION.pages.retrieve({ page_id: resolved_from_reference_id })
  -> { reviewer_recommendation, reviewer_notes, review_completed_at }

// Step 3c: Compile and send Gmail digest
GMAIL.send({
  to: LEADERSHIP_EMAIL,
  subject: 'Initiative Digest: [N] decisions pending — [Date]',
  body: HTML compiled from LEADERSHIP_DIGEST_V1 template,
  digest_header: {
    total_pending: pending_rows.length,
    total_pipeline_budget_usd: SUM(pending_rows.estimated_budget_usd)
  }
})

// -> HUMAN STEP: Leadership records decision in Notion
// (Status field updated to 'Approved', 'Revised', or 'Declined')

// Step 3d: On Notion status change -> decision writeback
NOTION.webhook(event: 'page.property_updated', property: 'Status') -> {
  reference_id, new_status, decision_notes, decision_date
}

// Step 3e: Update Google Sheets tracker
GOOGLE_SHEETS.rows.update({
  filter: { reference_id },
  fields: { status: new_status, decision_date, decision_notes }
})

// Step 3f: Notify proposer via Slack
SLACK.send_dm({
  recipient: proposer_slack_id,  // looked up from proposer_email
  template: 'PROPOSER_OUTCOME_V1',
  fields: { initiative_title, new_status, decision_notes, next_steps }
})

// ============================================================
// END OF FLOW
// ============================================================
Developer Handover PackPage 3 of 4
FS-DOC-04Technical

04Recommended build stack

Orchestration layer
A workflow automation tool (platform to be confirmed at build start). One workflow per agent: Intake Validation Workflow, Scoping and Routing Workflow, and Approval Digest Workflow. All three workflows share a single credential store to avoid duplicated API keys. Credentials are stored as environment variables or a secrets vault within the platform, never hardcoded in workflow logic.
Webhook configuration
Google Forms submissions delivered via Google Apps Script webhook or Google Cloud Pub/Sub push subscription to the Intake Validation Workflow endpoint. The endpoint URL must be registered in the Forms trigger before go-live. Notion property change events delivered via Notion webhook (requires Notion API integration with read content and receive webhooks capability). A 15-minute polling fallback on the INITIATIVE_TRACKER Google Sheets tab should be configured in case Notion webhooks are unavailable on the active plan tier.
Templating approach
Three message templates stored as versioned strings in the orchestration layer: INTAKE_REJECTION_V1 (Slack DM and Gmail), REVIEWER_NOTIFY_V1 (Slack DM), LEADERSHIP_DIGEST_V1 (HTML Gmail body), and PROPOSER_OUTCOME_V1 (Slack DM). Templates use named variable placeholders (e.g. {{initiative_title}}, {{review_deadline}}). All template versions are incremented, not overwritten, so rollback is possible without a code change.
Error logging
All agent errors and suppressed events written to a Supabase table named automation_error_log with columns: id (uuid), workflow_name, error_type, payload_snapshot (jsonb), created_at (timestamptz). Error types include: notion_create_failed, sheets_append_failed, slack_dm_failed, duplicate_suppressed, reviewer_not_found. A Slack alert is sent to the designated ops channel (suggested: #automation-alerts) for any error_type that is not duplicate_suppressed. Alert includes workflow_name, error_type, reference_id where available, and a link to the Supabase log row.
Testing approach
All agent workflows are built and tested against sandbox instances first: a separate Google Form (non-production), a Notion sandbox database, a Google Sheets test tab named INITIATIVE_TRACKER_TEST, and a Slack test channel. Gmail sends during testing are routed to a designated test mailbox, not the live leadership recipient. Sandbox credentials are stored separately from production credentials in the credential store. Five full end-to-end pilot runs are completed with real reviewers before the production credential swap and go-live.
Estimated total build time
Intake Validation Agent: 8 hours. Scoping and Routing Agent: 14 hours. Approval Digest Agent: 10 hours. End-to-end integration testing and pilot runs: 6 hours. Total: 38 hours across approximately 4 to 5 weeks, consistent with the Standard build timeline.
Before build can begin, the following must be confirmed by your team: (1) Google Workspace tier confirmed to support Apps Script webhooks or Pub/Sub. (2) Notion plan tier confirmed to support webhook events or polling fallback agreed. (3) Final initiative_category enum list locked and ROUTING_TABLE populated. (4) Leadership recipient email address confirmed and stored as environment variable. (5) Slack bot installed in workspace with chat:write and users:read.email scopes. (6) Supabase project provisioned and automation_error_log table schema applied. Contact support@gofullspec.com to confirm these items and schedule the build start date.
Developer Handover PackPage 4 of 4

More documents for this process

Every document generated for New Initiative Scoping & Approval.

Launch Plan
Operations · Owner
View
ROI and Business Case
Finance · Owner
View
Process Runbook / SOP
Operations · Owner
View
Integration and API Spec
Technical · Developer
View
Test and QA Plan
Quality · Developer
View