Strona główna / Artykuły / Szef sztabu – krótka prezentacja dla agentów: warstwowa architektura na skalę przedsiębiorstwa

Szef sztabu – krótka prezentacja dla agentów: warstwowa architektura na skalę przedsiębiorstwa

Szczegółowy przewodnik dotyczący briefingu dla szefa sztabu: architektura warstwowa na skalę przedsiębiorstwa – umowy, mechanizmy weryfikacji oraz miejsca na kod dostępne dla zespołów stosujących ten wzorzec.

4574 słów

To przewodnictwo pokazuje, jak odbudować proces od surowców do działającego systemu w ramach projektu: Chief of Staff Executive Briefing Agent: warstwowa architektura na skalę przedsiębiorstwa do automatycznego generowania informacji. Główny nacisk kładziony jest na konkretne kroki operacyjne, jasne sprawdzenia oraz kod, który można bez problemu umieścić w repozytorium, nie musząc zgadywać intencji twórcy. Na etapie przeglądu należy zdefiniować dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed jakimikolwiek zmianami w kodzie. Operatorzy powinni móc ponownie uruchomić dany krok na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu systemu. Należy udokumentować zarówno prawidłowy przebieg procesu, jak i ścieżki naprawcze. Próby ponownego wykonania, kontrole ludzkie oraz obsługa wiadomości błędowych stanowią integralną część produktu, a nie elementy dodawane później.

Przegląd projektu rozwiązania

Gdy przechodzisz przez etap opracowania ogólnego planu rozwiązania, najpierw zapisz specyfikację interfejsu: wymagane dane wejściowe, sygnał pomyślności oraz to, co dzieje się w przypadku częściowego niepowodzenia. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Wolno preferować małe, testowalne jednostki zamiast rozbudowanych skryptów. Gdy jakiś krok się nie powiedzie, błąd powinien wskazywać na konkretną odpowiedzialność, a nie na skomplikowany łańcuch operacji. Ustalaj punkty kontrolne po kosztownych krokach. System powinien unikać ponownego pobierania opłat za tę samą funkcję LLM, gdy operator próbuje ponownie wykonać późniejszy element procesu.

Szczególna warstwa: Zintegrowanie danych przedsiębiorstwa pod kontrolą

Gdy przechodzisz przez etap przedsiębiorstwa zarządzanego w warstwie Foundation, najpierw zapisz umowę: wymagane dane wejściowe, sygnał sukcesu oraz to, co się dzieje w przypadku częściowego niepowodzenia. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Traktuj ten etap jako umowę pomiędzy danymi wejściowymi a zweryfikowanymi wynikami. Nadaj nazwy poszczególnym elementom, zdefiniuj kryteria sukcesu i odrzuć możliwość cichego, częściowego ukończenia zadania. Ustal punkty kontrolne po kosztownych krokach. System powrotu nie powinien ponownie naliczać opłat za tę samą wywołanie LLM, gdy operator próbuje ponownie uruchomić późniejszy węzeł.

Warstwa danych: silnik analityki operacyjnej optymalizowany pod kątem korzystania z API

Gdy pracujesz nad warstwą danych w fazie operacyjnej, najpierw zapisz umowę: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego niepowodzenia. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Zapisz czasy wykonywania operacji oraz koszt tokenów lub zapytań obok wyników funkcjonalnych. Wczesna widoczność kosztów zapobiega niespodziewanym rachunkom, gdy ścieżka przechodzi z wersji demonstracyjnej do środowisk współdzielonych. Ustal punkty kontrolne po kosztownych krokach. System powrotu nie powinien ponownie naliczać opłat za tę samą wywołanie LLM, gdy operator próbuje ponownie uruchomić późniejszy węzeł. Gdy pracujesz nad warstwą danych w fazie operacyjnej, najpierw zapisz umowę: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego niepowodzenia. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Zdokumentuj zarówno ścieżkę prawidłowego działania, jak i ścieżkę naprawczą. Próby ponownych wywołań, mechanizmy ludzkiej kontroli oraz obsługa wiadomości błędowych stanowią część produktu, a nie elementy dodawane później.

     --Accounts Table - Primary Business Entity

CREATE TABLE [aieo].[Accounts] (

    [Id] INT IDENTITY(1,1) PRIMARY KEY,

    [TPID] BIGINT NOT NULL,

    [AccountName] NVARCHAR(255) NOT NULL,

    [AccountNumber] NVARCHAR(50),

    [SearchTokens] NVARCHAR(500),

    [Segment] NVARCHAR(100),

    [Industry] NVARCHAR(100),

    [ACR_FY25] DECIMAL(15,2),

    [RevenueRank] INT,

    [CreatedDate] DATETIME2 DEFAULT GETUTCDATE(),

    [LastSync] DATETIME2,

    [IsActive] BIT DEFAULT 1

);



CREATE CLUSTERED INDEX IX_Accounts_TPID ON [aieo].[Accounts]([TPID]);

CREATE NONCLUSTERED INDEX IX_Accounts_Name ON [aieo].[Accounts](
-- Revenue Table - Historical and Forecast Data

CREATE TABLE [aieo].[Revenue] (

    [TPID] BIGINT,

    [FiscalYear] NVARCHAR(10),

    [RevenueType] NVARCHAR(20),

    [Amount] DECIMAL(15,2),

    [LastUpdated] DATETIME2

);

CREATE INDEX IX_Revenue_TPID_FY ON [aieo].[Revenue]([TPID], [FiscalYear]);
-- AI Usage Table - Product Adoption Metrics

CREATE TABLE [aieo].[AIUsage] (

    [TPID] BIGINT,

    [ProductCategory] NVARCHAR(50),

    [UsageLevel] NVARCHAR(20),

    [SeatCount] INT,

    [AdoptionRate] DECIMAL(5,2),

    [LastUpdated] DATETIME2

);

CREATE INDEX IX_AIUsage_TPID_Product ON [aieo].[AIUsage]([TPID], [ProductCategory]);
--Account Search Procedure - Revenue-Prioritized Discovery

CREATE OR ALTER PROCEDURE [aieo].[SearchAccounts]

    @searchTerm NVARCHAR(255),

    @top INT = 5

AS

BEGIN

    SET NOCOUNT ON;



    DECLARE @likeTerm NVARCHAR(257) = '%' + REPLACE(REPLACE(@searchTerm, '[', '[[]'), '%', '[%]') + '%'



    SELECT TOP (@top)

        a.TPID,

        a.AccountName,

        a.AccountNumber,

        ISNULL(acr.ACR_YTD, 0) as ACR_YTD

    FROM [aieo].[Accounts] a

    LEFT JOIN [aieo].[ACR] acr ON a.TPID = acr.TPID

    WHERE

        a.AccountName LIKE @likeTerm

        OR CAST(a.TPID AS NVARCHAR) = @searchTerm

        OR a.AccountNumber LIKE @likeTerm

    ORDER BY

        ISNULL(acr.ACR_YTD, 0) DESC,

        a.AccountName ASC

    FOR JSON PATH;

END;
--Account Details Retrieval Procedure - Comprehensive Intelligence Aggregation

CREATE PROCEDURE [aieo].[GetAccountDetails]

(@TPID int)

AS

BEGIN

    SET NOCOUNT ON;

    SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;



    SELECT TOP 1

        JSON_QUERY(ap.[AccountProfile]) AS [Account],

        JSON_QUERY(ai.[AIUsage]) AS [AI],

        JSON_QUERY(acr.[Data]) AS [ACR],

        deal.[Deals.AgreementValue],

        deal.[Deals.DealType],

        deal.[Deals.Term],

        deal.[Deals.Remaining],

        deal.[Deals.EndDate],

        ecif.[ECIF.Committed],

        aco.[ACO.IncrementalRevenue],

        aco.[ACO.Discount],

        aco.[ACO.ACO],

        JSON_QUERY(bot.[Data]) AS [BoT],

        JSON_QUERY(inv.[Data]) AS [Investments],

        JSON_QUERY(rev.[Data]) AS [Revenue]

    FROM [dbo].[vw_Customer] P

    OUTER APPLY (

        SELECT TOP 1

            a.[TPID],

            a.[CRMAccountName] AS [AccountName],

            a.[Segment],

            a.[Industry],

            a.[EOU],

            a.[OU],

            LOWER(TRIM(c.[Value])) AS [ATU_Manager.Alias],

            aau.[Mail] AS [ATU_Manager.Email],

            [dbo].[RemoveJobTitle](aau.[DisplayName]) AS [ATU_Manager.DisplayName],

            NULLIF(TRIM(aau.[BusinessPhone]), '') AS [ATU_Manager.PhoneNumber],

            JSON_QUERY([am].[Data]) AS [AM],

            JSON_QUERY([atum].[Data]) AS [ATUM]

        FROM [dbo].[vw_Customer] A

        OUTER APPLY STRING_SPLIT(a.[AM], ',', 1) C

        LEFT JOIN [cm].[vw_AAD_User] AAU ON LOWER(TRIM(C.[Value])) = LOWER(AAU.[UserPrincipalName])

        WHERE A.TPID = P.TPID

    ) ap

    WHERE P.TPID = @TPID;

END;
--Template Management Procedure - Role-Based Access Control

CREATE OR ALTER PROCEDURE [aieo].[GetBriefingTemplate]

(

    @UserAlias NVARCHAR(200),

    @BriefingType NVARCHAR(200)

)

AS

BEGIN

    SET @UserAlias = IIF(CHARINDEX('@', @UserAlias) > 0,

                        LEFT(@UserAlias, CHARINDEX('@', @UserAlias) - 1),

                        @UserAlias)



    SELECT DISTINCT

        [BriefingTemplateId],[TemplateDescription],[BriefingType],

        [UserAlias],FullName,[Filename],[FileType],[PreviewFilename]

    FROM [hr].[DimPerson] p

    INNER JOIN [aieo].[ExecutiveOfficeMember] eom ON eom.[PersonnelNumber] = p.[PersonnelNumber]

    INNER JOIN [aieo].[ExecutiveOffice] o ON o.[ExecutiveOfficeId] = eom.[ExecutiveOfficeId]

    INNER JOIN [aieo].[BriefingTemplate] bt ON bt.[ExecutiveOfficeId] = o.[ExecutiveOfficeId]



    UNION



    SELECT DISTINCT

        [BriefingTemplateId],[TemplateDescription],[BriefingType],

        p.EmailName As UserAlias,p.FullName,[Filename],[FileType],[PreviewFilename]

    FROM [aieo].[BriefingTemplate] bt

    CROSS JOIN [hr].[DimPerson] p

    WHERE bt.[UserAlias] = 'ALL' AND p.EmailName = @UserAlias

        AND bt.BriefingType = @BriefingType;

END;
GRANT EXECUTE ON SCHEMA::[aieo] TO [service_identity];
 - No direct table access permitted

Szczegóły warstwy usługowej: bezstanowa orkiestracja i granice wykonywania

Etap bezstanowej orkiestracji w warstwie usługowej funkcjonuje najlepiej, gdy jest traktowany jako mierzalna powierzchnia do analizy. Zapisz jeden idealny przykład działania, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia działań, zanim rozszerzysz zakres analizy. Wolno preferować małe, testowalne jednostki zamiast rozbudowanych skryptów. Gdy jakiś krok zawiedzie, awaria powinna wskazywać na konkretną odpowiedzialność, a nie na skomplikowany łańcuch operacji. Utrzymuj stan grafu w formie prostych, typowanych struktur. Wtórne elementy ukrywają informację o tym, który węzeł zapisał dane do którego pola, co utrudnia kontynuację pracy po przerwach.

from pydantic import BaseModel
from typing import Optional
class BriefingRequest(BaseModel):
account_name_or_tpid: str
meeting_datetime: Optional[str] = None
meeting_objective: Optional[str] = None
ms_attendees: Optional[str] = None
template_type: Optional[str] = None

Szczegóły warstwy doświadczeń użytkownika: silnik inteligencji konwersacyjnej Copilot Studio

Szczególnie dobrze funkcjonuje etap Copilot Studio w warstwie doświadczeń, gdy traktowany jest jako mierzalna powierzchnia. Zanim rozszerzysz zakres, zapisz jeden idealny przepis działania, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia zmian. Traktuj ten etap jako umowę pomiędzy danymi wejściowymi a zweryfikowanymi wynikami. Nadaj nazwy poszczególnym elementom, zdefiniuj kryteria sukcesu i odrzucaj ciche, częściowe ukończenie zadań. Utrzymuj stan grafu w prostej formie i z określonym typem danych. Wplecione elementy ukrywają informację o tym, który węzeł zapisał dane do którego pola, co powoduje przerwanie kontynuacji po przerwach.

kind: AdaptiveDialog

inputs:

  - kind: AutomaticTaskInput

    propertyName: Account_Name_or_TPID

    name: Account Name or TPID

    description: The account/customer TPID (unique identifier) or name

    shouldPromptUser: true



modelDescription: Create briefing document to prepare for meeting with customer

beginDialog:

  kind: OnRecognizedIntent

  intent:

    displayName: Topic for creating briefing document to prepare for meeting with customer

    triggerQueries:

      - Generate a briefing document for account Accenture

      - I need a briefing for Amazon

      - Create briefing for Apple

      - I have a meeting with JPMorgan Chase at 4PM
- kind: SetVariable

  id: setVariable_IsNumeric

  variable: Topic.IsNumeric

  value: =IsNumeric(Topic.UserInput)



- kind: ConditionGroup

  id: conditionGroup_InputType

  conditions:

    - id: condition_IsTPID

      condition: =Topic.IsNumeric

      actions:

        - kind: SetVariable

          variable: Topic.Account_TPID

          value: =Topic.UserInput
- kind: HttpRequestAction

  id: httpRequest_SearchAccounts

  displayName: Search Accounts by Name

  url: =Global.ApiBaseUrl & "/api/mssales/search/" & EncodeUrl(Topic.UserInput)

  headers:

    Ocp-Apim-Subscription-Key: =Global.ApiKey

  response: Topic.SearchResults

  responseSchema:

    kind: Record

    properties:

      accounts:

        type:

          kind: Table

          properties:

            account_name: String

            tpid: String

      total_count: Number
- kind: AdaptiveCardPrompt

  id: adaptiveCard_SelectAccount

  card: "=Concatenate('{

    \"$schema\":\"https://adaptivecards.io/schemas/adaptive-card.json\",

    \"type\":\"AdaptiveCard\",\"version\":\"1.5\",

    \"body\":[

      {\"type\":\"TextBlock\",\"text\":\"Multiple accounts found\",\"weight\":\"Bolder\"},

      {\"type\":\"Input.ChoiceSet\",\"id\":\"selectedAccount\",\"isRequired\":true,

       \"choices\":',

       JSON(ForAll(Topic.SearchResults.accounts,

         {title: Concatenate(account_name, \" (TPID: \", tpid, \")\"), value: tpid})),

       '}],

    \"actions\":[{\"type\":\"Action.Submit\",\"title\":\"Continue\"}]

  }')"
- kind: HttpRequestAction

  id: httpRequest_GetUserTemplates

  url: =Global.ApiBaseUrl & "/api/briefings/templates?user_alias=" &

       EncodeUrl(System.User.PrincipalName) & "&briefing_type=Customer"

  headers:

    Ocp-Apim-Subscription-Key: =Global.ApiKey

  response: Topic.UserTemplates
- kind: AdaptiveCardPrompt

  id: adaptiveCard_MeetingDetails

  card: "=Concatenate('{

    \"$schema\":\"https://adaptivecards.io/schemas/adaptive-card.json\",

    \"type\":\"AdaptiveCard\",\"version\":\"1.5\",

    \"body\":[

      {\"type\":\"TextBlock\",\"text\":\"Create Executive Briefing Document\",

       \"weight\":\"Bolder\",\"size\":\"Large\",\"color\":\"Accent\"},

      {\"type\":\"Input.Date\",\"id\":\"meetingDate\",\"isRequired\":true,

       \"label\":\"Meeting Date\"},

      {\"type\":\"Input.Time\",\"id\":\"meetingTime\",\"value\":\"09:00\"},

      {\"type\":\"Input.Text\",\"id\":\"msAttendees\",\"isVisible\":false,

       \"label\":\"Microsoft Attendees\"}

    ],

    \"actions\":[

      {\"type\":\"Action.ToggleVisibility\",\"title\":\"Additional Options ▼\",

       \"targetElements\":[\"msAttendees\"]},

      {\"type\":\"Action.Submit\",\"title\":\"Generate Briefing\"}

    ]

  }')"
// Ephemeral Logic App Security Pattern
const createSearchLogicApp = async (userAlias, searchQuery) => {
const logicAppName = `Researcher-${userAlias}`;
// Create Logic App with SAS trigger
const logicApp = await armClient.logicApps.createOrUpdate({
resourceGroupName: 'Azure_OpenAI',
workflowName: logicAppName,
definition: buildResearchWorkflow(userAlias)
});
// Execute search via SAS URL
const searchResults = await triggerLogicApp(logicApp.triggerUrl, searchQuery);
// Immediate cleanup for security
await armClient.logicApps.delete(logicAppName);
return searchResults;
};
# Logic App Parallel Execute Pattern

HTTP_Trigger_SAS_Secured:

  Email_Branch:

    - Get_Emails: Office365_Connector.Mail (top=250)



  Teams_Branch_Parallel:

    - Get_Teams_Chats_Page1: Teams_Connector.Chats (top=50)

    - Get_Teams_Chats_Page2: Teams_Connector.Chats (skip=50, top=50)

    - For_Each_Chat:

        concurrency: 10

        actions:

          - Get_Chat_Messages: Teams_Connector.Messages (top=50)

          - Append_Chat_Data: Variable_Accumulation



  Response_Assembly:

    - Combine: Email_Results + Teams_Results + Metadata

    - Return: JSON_Structured_Response
// Per-User Connection Provisioning

const provisionUserConnections = async (userAlias) => {

    const connections = [

        {

            name: `office365-${userAlias}`,

            api: '/providers/Microsoft.PowerApps/apis/shared_office365',

            scopes: ['Mail.ReadWrite']

        },

        {

            name: `teams-${userAlias}`,

            api: '/providers/Microsoft.PowerApps/apis/shared_teams',

            scopes: ['Chat.Read']

        }

    ];



    for (const conn of connections) {

        await armClient.connections.createOrUpdate({

            resourceGroupName: 'Azure_OpenAI',

            connectionName: conn.name,

            properties: {

                displayName: conn.name,

                api: { id: conn.api },

                parameterValues: {}

            }

        });

    }



    return generateConsentUrls(connections);

};
# Organizational Intelligence Synthesis

async def synthesize_organizational_context(filtered_data, account_context):

    synthesis_prompt = """

    Analyze the following organizational communications for executive briefing preparation:



    Account Context: {account_name}

    Email Communications: {email_count} relevant messages

    Teams Discussions: {chat_count} relevant conversations

    Generate executive intelligence focusing on:
    Financial performance, earnings trends, and capital allocation signals.
    Corporate strategy, market positioning, and competitive landscape.
    AI strategy, digital transformation initiatives, and cloud ecosystem alignment.
    Recent material developments (≤ 90 days) with actionable insights for executive engagement.

    Format as structured JSON with executive_summary, stakeholder_analysis, recent_activities, and recommended_actions.

    """



    response = await azure_openai_client.chat.completions.create(

        model="gpt-4-1106-preview",

        messages=[{

            "role": "system",

            "content": "You are an executive intelligence analyst."

        }, {

            "role": "user",

            "content": synthesis_prompt.format(**filtered_data, **account_context)

        }],

        temperature=0.1,

        max_tokens=2000

    )



    return parse_structured_intelligence(response.choices[0].message.content)
# Enhanced Copilot Studio Parallel Execution

- kind: ParallelExecution

  id: parallelExecution_ComprehensiveIntelligence

  branches:

    - account_data:

        kind: HttpRequestAction

        url: =Global.ApiBaseUrl & "/api/accounts/" & Topic.Account_TPID

    - organizational_intelligence:

        kind: HttpRequestAction

        url: =Global.ApiBaseUrl & "/api/search?q=" & EncodeUrl(Topic.Account_Name) & "&alias=" & System.User.PrincipalName

        requestTimeoutInMilliseconds: 60000

        continueOnError: true

    - market_intelligence:

        kind: HttpRequestAction

        url: =Global.FoundryBaseUrl & "/bingnews/api/AgentFunction"



- kind: SetVariable

  id: setVariable_CombinedIntelligence

  variable: Topic.BriefingContext

  value: ={

    account_details: Topic.AccountData,

    organizational_context: Topic.OrganizationalIntelligence,

    market_insights: Topic.MarketIntelligence

  }
// Enterprise Governance and Cleanup

const implementGovernanceControls = async () => {

    // Automated stale connection cleanup

    const staleThreshold = 80; // days

    const allConnections = await listManagedConnections();



    const staleConnections = allConnections.filter(connection => {

        const lastUsed = parseISO(connection.properties.lastConnection);

        const daysSinceUse = differenceInDays(new Date(), lastUsed);

        return daysSinceUse > staleThreshold;

    });



    // Compliance audit logging

    for (const connection of staleConnections) {

        await auditLogger.log({

            action: 'CONNECTION_CLEANUP',

            userAlias: connection.userAlias,

            reason: 'AUTOMATED_GOVERNANCE',

            retentionPolicy: `${staleThreshold}_DAYS_INACTIVE`,

            timestamp: new Date().toISOString()

        });



        await deleteUserResources(connection.userAlias);

    }

};
// Fault-Tolerant Execution Pattern

const executeOrganizationalIntelligence = async (searchQuery, userAlias) => {

    const executionTimeout = 60000; // 60 second maximum

    const fallbackResponse = { summary: "Organizational context unavailable", status: "fallback" };



    try {

        // Health check before expensive operations

        const connectionsHealthy = await verifyConnectionHealth(userAlias);

        if (!connectionsHealthy) {

            return fallbackResponse;

        }



        // Execute with timeout boundary

        const intelligencePromise = gatherOrganizationalIntelligence(searchQuery, userAlias);

        const timeoutPromise = new Promise((_, reject) =>

            setTimeout(() => reject(new Error('TIMEOUT')), executionTimeout)

        );



        return await Promise.race([intelligencePromise, timeoutPromise]);



    } catch (error) {

        // Graceful degradation logging

        await logger.warn(`M365 Researcher fallback: ${error.message}`, {

            userAlias,

            searchQuery,

            fallbackMode: true

        });



        return fallbackResponse;

    }

};
- kind: HttpRequestAction

  id: p4tceX

  method: Post

  url: =Global.ApiBaseUrl & "/api/briefings/" & Topic.templateId & "/accounts/" & Topic.Account_TPID

  body:

    kind: JsonRequestContent

    content: "={

      user_alias: Topic.SenderEmail,

      MeetingDateTime: Topic.MeetingDateTime,

      msAttendees: Topic.msAttendees,

      FoundryResponse: Topic.FoundryResponse

    }"

  requestTimeoutInMilliseconds: 60000

  response: Topic.BriefingDocument
- kind: InvokeConnectorAction

  id: invokeConnectorAction_YKkMK4

  input:

    binding:

      dataset: https://microsoft.sharepoint.com/teams/MCAPSAIIncubationHub

      folderPath: /Shared Documents/General/AI Prototypes & Solutions/AI Executive Office Use Cases/Published Cust Template/

      name: =Topic.CustomFilename

      file: =Global.File
- kind: SetVariable

  id: setVariable_CustomFilename

  variable: Topic.CustomFilename

  value: =Concatenate(

    Substitute(Topic.Account_Name, " ", "_"), "_",

    Topic.ExecutiveName, "_Brief_",

    Text(Topic.meetingDate, "yyyy-MM-dd"), ".docx"

  )
- kind: ConditionGroup

  id: conditionGroup_CheckBriefingError

  conditions:

    - condition: =!IsBlank(Topic.BriefingDocument.error) && Topic.BriefingDocument.error.error_code = "TEMPLATE_ACCESS_DENIED"

      actions:

        - kind: AdaptiveCardPrompt

          card: ={

            "$schema":"https://adaptivecards.io/schemas/adaptive-card.json",

            "type":"AdaptiveCard","version":"1.5",

            "body":[{

              "type":"Container","style":"warning",

              "items":[{

                "type":"TextBlock","text":"Template Access Required",

                "weight":"Bolder","color":"Attention"

              },{

                "type":"TextBlock","wrap":true,

                "text": Topic.BriefingDocument.error.user_message

              }]

            }]

          }
- kind: ConditionGroup

  id: conditionGroup_ValidateInputs

  conditions:

    - condition: =Topic.meetingDate < Today()

      actions:

        - kind: SendActivity

          activity: The meeting date cannot be in the past. Please start over and enter a future date.

        - kind: EndConversation
- kind: SetVariable

  id: setVariable_ClearUserInput

  variable: Topic.UserInput

  value: =Blank()



- kind: SetVariable

  id: setVariable_ClearAccountDetails

  variable: Topic.AccountDetails

  value: =Blank()



- kind: SetVariable

  id: setVariable_ClearFoundryResponse

  variable: Topic.FoundryResponse

  value: =Blank()



- kind: SetVariable

  id: setVariable_ClearBriefingDocument

  variable: Topic.BriefingDocument

  value: =Blank()
# Environment-aware authentication pattern

def get_credential():

    if is_azure_environment():

        return ManagedIdentityCredential(client_id=os.getenv('AZURE_CLIENT_ID'))

    else:

        return AzureCliCredential()
Structured exception hierarchy

class AIExecutiveOfficeError(Exception):

    def __init__(self, message: str, error_code: str = None, details: dict = None):

        self.message = message

        self.error_code = error_code or self.__class__.__name__

        self.details = details or {}

        self.timestamp = datetime.utcnow()

Ramy oceny i weryfikacja jakości

Ramka oceny i etap jakości działają najlepiej, gdy traktuje się je jako mierzalną powierzchnię. Zapisz jeden idealny zapis transkrypcji, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia działań, zanim rozszerzysz zakres. Zapisuj czasy wykonywania operacji oraz koszt tokenów lub zapytań obok wyników funkcjonalnych. Wczesna widoczność kosztów zapobiega niespodziewanym rachunkom, gdy proces przechodzi z środowiska demonstracyjnego do współdzielonych środowisk. Utrzymuj stan grafu w prostej formie i z określonym typem danych. Wplecione elementy ukrywają informację o tym, który węzeł zapisał dane do którego pola, i powodują przerwanie kontynuacji po przerwach. Ramka oceny i etap jakości działają najlepiej, gdy traktuje się je jako mierzalną powierzchnię. Zapisz jeden idealny zapis transkrypcji, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia działań, zanim rozszerzysz zakres. Zdokumentuj zarówno ścieżkę prawidłowego działania, jak i ścieżkę naprawczą. Próby ponownych działań, kontrolne punkty ludzkie oraz obsługa wiadomości nieodebranych stanowią część produktu, a nie elementy dodawane później.

Kolejne kroki: migracja do Microsoft Agent Framework (MAF)

Aby przejść do kolejnych kroków migracji, zdefiniuj wprowadzane dane, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed modyfikacją kodu. Operatorzy powinni móc ponownie uruchomić dany krok na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Wolno preferować małe, testowalne jednostki zamiast rozbudowanych skryptów. Gdy dany krok zawiedzie, powinien wskazywać na konkretną odpowiedzialność, a nie na skomplikowany proces. Wprowadź ludzką aprobatę w przypadkach, gdy dochodzi do wydawania pieniędzy lub modyfikacji danych produkcyjnych. Połączenia realizowane w czasie kompilacji nie równają się kompletności biznesowej.

Wniosek

W fazie podsumowania należy zdefiniować dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed modyfikacją kodu. Operatorzy powinni móc ponownie uruchomić ten krok od znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Traktuj tę fazę jako umowę pomiędzy danymi wejściowymi a zweryfikowanymi wynikami. Nadaj nazwy poszczególnym elementom, zdefiniuj kryteria sukcesu i odrzuć przypadki częściowego ukończenia bez żadnych informacji. Wymagaj ludzkiej aprobaty w przypadkach, gdy dochodzi do wydawania pieniędzy lub zmiany danych produkcyjnych. Połączenia realizowane w czasie kompilacji nie równają się pełnej kompletności procesu biznesowego.

Lista kontrolna operacyjna

Faza listy kontrolnej operacyjnej działa najlepiej, gdy jest traktowana jako mierzalna struktura. Zapisz jeden idealny przepis działania, jeden przypadek awarii oraz notatkę dotyczącą odwrócenia działań, zanim rozszerzysz zakres pracy.

Zachowaj konfigurację poza kodem aplikacji. Pliki środowiskowe, magazyny tajnych danych oraz flagi funkcjonalne powinny znajdować się w jednym miejscu, które operatorzy mogą sprawdzić, nie musząc czytać całej struktury.

Zachowuj prostą i typowaną strukturę stanu grafu. Wkładki nawarstwione ukrywają informację o tym, który węzeł zapisał dane do którego pola, i powodują przerwanie kontynuacji działania po przerwach.

Gdy budżet na to pozwala, dodaj test sprawdzający kluczową ścieżkę w procesie CI przy użyciu fixitów, a nie rzeczywistych, płatnych API.

Dokumentuj zarówno prawidłową ścieżkę działania, jak i ścieżkę przywracania. Próby ponownych działań, kontrola przez ludzi oraz obsługa wiadomości błędnych stanowią część produktu, a nie element późniejszej optymalizacji.

Zachowuj prostą i typowaną strukturę stanu grafu. Wkładki nawarstwione ukrywają informację o tym, który węzeł zapisał dane do którego pola, i powodują przerwanie kontynuacji działania po przerwach.

Zanim zastosujesz nową architekturę, zamroź wersje produktu, utwórz dokładny zapis działań na kluczowej ścieżce i potwierdź kroki konieczne do cofnięcia zmian. Środowiska współdzielone wymagają ograniczeń szybkości, weryfikacji uprawnień oraz wyraźnego odpowiedzialnego za rotację haseł. Wolisz nudną niezawodność od pomysłowych, jednorazowych demonstracji.

Uwaga dotycząca partii dla 8b1aa812f08c: unikaj przechowywania kluczy dostawcy w repozytorium, ustaw ograniczenie liczby tokenów na sesję oraz przechowuj transkrypcje obok narzędzi do oceny, aby późniejsze zmiany modeli pozostały porównywalne.

Uwaga dotycząca wzmocnienia bezpieczeństwa na etapie 0 działa najlepiej, gdy jest traktowana jako mierzalna powierzchnia do analizy. Zapisz jedną idealną transkrypcję, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia zmian przed rozszerzaniem zakresu. Zapisuj również czasy wykonywania zadań oraz koszt tokenów lub zapytań obok wyników funkcjonalnych. Wczesna widoczność kosztów zapobiega nieoczekiwanym rachunkom podczas przechodzenia z środowiska demonstracyjnego do współdzielonych środowisk.

Szczegół wzmocnienia bezpieczeństwa 0/857: zmierz czas wykonywania zadań, klasę błędu oraz zużycie tokenów dla tej notatki, a następnie zdecyduj, czy zachować zmianę na podstawie ustalonego zestawu pytań, a nie jedynie informacji anegdotycznych.

Dla pierwszego etapu ulepszeń związanych z wzmacnianiem bezpieczeństwa należy określić dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed modyfikacją kodu. Operatorzy powinni móc ponownie wykonać ten krok na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Należy udokumentować zarówno prawidłowy przebieg operacji, jak i ścieżkę naprawczą. Próby ponownych działań, kontrolne punkty ludzkie oraz obsługa wiadomości błędnych stanowią część produktu, a nie elementy dodawane później.

Szczegół 1/857 dotyczący wzmacniania bezpieczeństwa: należy zmierzyć czas wykonywania operacji, klasę błędu oraz zużycie tokenów dla tego przypadku, a następnie zdecydować o utrzymaniu zmiany na podstawie ustalonego zestawu pytań, a nie opisów incydentów.

Gdy przechodzisz przez drugi etap notatki dotyczącej wzmocnienia bezpieczeństwa, najpierw zapisz umowę: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego niepowodzenia. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Traktuj ten etap jako umowę pomiędzy danymi wejściowymi a zweryfikowanymi wynikami. Nadaj nazwy poszczególnym elementom, zdefiniuj kryteria sukcesu i odrzuć przypadki częściowego ukończenia bez żadnych informacji.

Szczegół 2/857 dotyczący wzmocnienia bezpieczeństwa: zmierz czas wykonywania, klasę błędu oraz zużycie tokenów dla tej notatki, a następnie zdecyduj, czy zachować zmianę na podstawie ustalonego zestawu pytań, a nie jedynie informacji anegdotycznych.

Etap trzeci notatki o wzmocnieniu bezpieczeństwa działa najlepiej, gdy jest traktowany jako mierzalna powierzchnia do analizy. Zapisz jeden idealny przykład działania, jeden przypadek niepowodzenia oraz notatkę dotyczącą cofnięcia zmian, zanim rozszerzysz zakres prac. Utrzymuj konfigurację poza kodem aplikacji. Pliki środowiskowe, magazyny tajnych danych oraz flagi funkcjonalne powinny znajdować się w jednym miejscu, które operatorzy mogą sprawdzić bez konieczności przeglądania całej struktury.

Szczegół wzmocnienia 3/857: zmierz czas wykonywania, klasę błędu oraz zużycie tokenów dla tej notatki, a następnie zdecyduj, czy zachować zmianę na podstawie ustalonego zestawu pytań, a nie jedynie anegdoty.

W czwartym etapie notatki dotyczącej wzmocnienia określ dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed modyfikacją kodu. Operatorzy powinni móc ponownie uruchomić ten krok od znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Należy preferować małe, testowalne jednostki zamiast rozbudowanych skryptów. Gdy dany krok zawiedzie, powód awarii powinien wskazywać na konkretną odpowiedzialność, a nie na skomplikowany proces.

Szczegół wzmocnienia 4/857: zmierz czas wykonywania, klasę błędu oraz zużycie tokenów dla tej notatki, a następnie zdecyduj, czy zachować zmianę na podstawie ustalonego zestawu pytań, a nie jedynie anegdoty.

Gdy przechodzisz przez etap nr 5 notatki dotyczącej wzmocnienia bezpieczeństwa, najpierw zapisz warunki umowy: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego awarii. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Obok wyników funkcjonalnych zapisz czas wykonywania oraz koszt tokena lub zapytania. Jasna widoczność kosztów zapobiega niespodziewanym rachunkom, gdy ścieżka przechodzi z środowiska demonstracyjnego do współdzielonych środowisk.

Szczegóły wzmocnienia bezpieczeństwa 5/857: zmierz czas wykonywania, klasę błędu oraz zużycie tokenów dla tej notatki, a następnie zdecyduj, czy zachować zmianę na podstawie ustalonego zestawu pytań, a nie jedynie osobistych obserwacji.

Etap nr 6 notatki dotyczącej wzmocnienia bezpieczeństwa działa najlepiej, gdy traktuje się go jako mierzalną powierzchnię do analizy. Zanim rozszerzysz zakres, zapisz jeden idealny przepływ działania, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia zmian. Zdokumentuj razem ścieżkę prawidłowego działania oraz ścieżkę naprawczą. Próby ponownych działań, kontrolne punkty ludzkie oraz obsługa wiadomości błędnych stanowią część produktu, a nie elementy dodawane później.

Szczegół wzmocnienia 6/857: zmierz czas wykonywania, klasę błędu oraz zużycie tokenów dla tej notatki, a następnie zdecyduj, czy zachować zmianę na podstawie ustalonego zestawu pytań, a nie jedynie anegdoty.

W fazie 7 notatki dotyczącej wzmocnienia określ dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed modyfikacją kodu. Operatorzy powinni móc ponownie wykonać ten krok na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Traktuj tę fazę jako umowę pomiędzy danymi wejściowymi a zweryfikowanymi wynikami. Nadaj nazwy artefaktom, zdefiniuj sprawdzenia sukcesu i odrzuć ciche, częściowe ukończenie zadania.

Szczegół wzmocnienia 7/857: zmierz czas wykonywania, klasę błędu oraz zużycie tokenów dla tej notatki, a następnie zdecyduj, czy zachować zmianę na podstawie ustalonego zestawu pytań, a nie jedynie anegdoty.

Gdy przechodzisz przez etap nr 8 notatki dotyczącej wzmocnienia bezpieczeństwa, najpierw zapisz warunki umowy: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego awarii. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Przechowuj konfigurację poza kodem aplikacji. Pliki środowiskowe, magazyny tajnych danych oraz flagi funkcjonalne powinny znajdować się w jednym miejscu, które operatorzy mogą sprawdzić bez konieczności czytania całej struktury.

Szczegół nr 8/857 dotyczący wzmocnienia bezpieczeństwa: zmierz czas wykonywania, klasę błędu oraz zużycie tokenów dla tej notatki, a następnie zdecyduj, czy zachować zmianę na podstawie ustalonego zestawu pytań, a nie jedynie osobistych obserwacji.

Etap nr 9 notatki dotyczącej wzmocnienia bezpieczeństwa działa najlepiej, gdy traktuje się go jako mierzalną powierzchnię do analizy. Zapisz jeden idealny przepis działania, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia zmian, zanim rozszerzysz zakres prac. Wolij małe, testowalne jednostki nad rozbudowane skrypty. Gdy jakiś krok zawiedzie, awaria powinna wskazywać na konkretną odpowiedzialność, a nie na skomplikowaną sekwencję działań.

Szczegóły wzmocnienia bezpieczeństwa 9/857: zmierz czas wykonywania, klasę błędu oraz zużycie tokenów dla tej notatki, a następnie zdecyduj, czy zachować zmianę na podstawie ustalonego zestawu pytań, a nie jedynie anegdoty.

W etapie 10 notatki dotyczącej wzmocnienia bezpieczeństwa zdefiniuj dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed modyfikacją kodu. Operatorzy powinni móc ponownie wykonać ten krok od znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Zapisuj czas wykonywania oraz koszt tokenów lub zapytań obok wyników funkcjonalnych. Wczesna widoczność kosztów zapobiega niespodziewanym rachunkom, gdy ścieżka przechodzi z środowiska demonstracyjnego do współdzielonych środowisk.

Szczegóły wzmocnienia bezpieczeństwa 10/857: zmierz czas wykonywania, klasę błędu oraz zużycie tokenów dla tej notatki, a następnie zdecyduj, czy zachować zmianę na podstawie ustalonego zestawu pytań, a nie jedynie anegdoty.

Gdy przechodzisz przez etap 11 notatki dotyczącej wzmocnienia bezpieczeństwa, najpierw zapisz umowę: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego awarii. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Zdokumentuj zarówno ścieżkę prawidłowego działania, jak i ścieżkę przywracania stanu. Próby ponownych działań, kontrola przez ludzi oraz obsługa wiadomości błędowych stanowią część produktu, a nie elementy dodawane później.

Szczegół 11/857 dotyczący wzmocnienia bezpieczeństwa: zmierz czas wykonywania operacji, klasę błędu oraz zużycie tokenów dla tej notatki, a następnie zdecyduj, czy zachować zmianę na podstawie ustalonego zestawu pytań, a nie jedynie informacji anegdotycznych.

Etap 12 notatki dotyczącej wzmocnienia bezpieczeństwa działa najlepiej, gdy traktuje się go jako mierzalną powierzchnię do poprawek. Zapisz jeden idealny przepływ operacji, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia zmian, zanim rozszerzysz zakres prac. Traktuj ten etap jako umowę pomiędzy danymi wejściowymi a zweryfikowanymi wynikami. Nadaj nazwy poszczególnym elementom, zdefiniuj kryteria sukcesu i odrzuć przypadki cichego, częściowego ukończenia zadania.

Szczegół wzmocnienia 12/857: zmierz czas wykonywania, klasę błędu oraz zużycie tokenów dla tej notatki, a następnie zdecyduj, czy zachować zmianę na podstawie ustalonego zestawu pytań, a nie jedynie anegdoty.

W fazie 13 notatki dotyczącej wzmocnienia określ dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed modyfikacją kodu. Operatorzy powinni móc ponownie uruchomić ten krok od znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Konfigurację należy przechowywać poza kodem aplikacji. Pliki środowiskowe, magazyny tajnych danych oraz flagi funkcjonalne powinny znajdować się w jednym miejscu, które operatorzy mogą sprawdzić, nie musząc czytać całej struktury.

Szczegół wzmocnienia 13/857: zmierz czas wykonywania, klasę błędu oraz zużycie tokenów dla tej notatki, a następnie zdecyduj, czy zachować zmianę na podstawie ustalonego zestawu pytań, a nie jedynie anegdoty.

Gdy przechodzisz przez etap 14 notatki dotyczącej wzmocnienia bezpieczeństwa, najpierw zapisz warunki kontraktu: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego awarii. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Wolno preferować małe, testowalne jednostki zamiast rozbudowanych skryptów. Gdy jakiś krok zawiedzie, awaria powinna wskazywać na konkretną odpowiedzialność, a nie na skomplikowany łańcuch operacji.

Szczegół 14/857 dotyczący wzmocnienia bezpieczeństwa: zmierz czas wykonywania, klasę błędu oraz zużycie tokenów dla tej notatki, a następnie zdecyduj, czy zachować zmianę na podstawie ustalonego zestawu pytań, a nie jedynie informacji anegdotycznych.

Etap 15 notatki dotyczącej wzmocnienia bezpieczeństwa działa najlepiej, gdy traktuje się go jako mierzalną powierzchnię do analizy. Zapisz jeden idealny przykład działania, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia zmian, zanim rozszerzysz zakres prac. Zapisuj czasy wykonywania oraz koszt tokenów lub zapytań obok wyników funkcjonalnych. Wczesna widoczność kosztów zapobiega nieoczekiwanym rachunkom, gdy przechodzi się od środowiska demonstracyjnego do wspólnych środowisk.

Szczegół wzmocnienia 15/857: zmierz czas wykonywania, klasę błędu oraz zużycie tokenów dla tej notatki, a następnie zdecyduj, czy zachować zmianę na podstawie ustalonego zestawu pytań, a nie jedynie anegdoty.

W fazie 16 notatki dotyczącej wzmocnienia określ dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed modyfikacją kodu. Operatorzy powinni móc ponownie wykonać ten krok od znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Zdokumentuj zarówno prawidłowy przebieg działania, jak i ścieżkę naprawczą. Próby ponowne, kontrolne punkty ludzkie oraz obsługa wiadomości błędnych stanowią część produktu, a nie element późniejszej dopracowywania.

Szczegół wzmocnienia 16/857: zmierz czas wykonywania, klasę błędu oraz zużycie tokenów dla tej notatki, a następnie zdecyduj, czy zachować zmianę na podstawie ustalonego zestawu pytań, a nie jedynie anegdoty.

Gdy przechodzisz przez etap 17 notatki dotyczącej wzmocnienia bezpieczeństwa, najpierw zapisz umowę: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego niepowodzenia. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Traktuj ten etap jako umowę pomiędzy danymi wejściowymi a zweryfikowanymi wynikami. Nadaj nazwy poszczególnym elementom, zdefiniuj kryteria sukcesu i odrzuć możliwość cichego, częściowego ukończenia zadania.

Szczegóły wzmocnienia bezpieczeństwa 17/857: zmierz czas wykonywania, klasę błędu oraz zużycie tokenów dla tej notatki, a następnie zdecyduj, czy zachować zmianę na podstawie ustalonego zestawu pytań, a nie jedynie informacji anegdotycznych.

Etap 18 notatki dotyczącej wzmocnienia bezpieczeństwa funkcjonuje najlepiej, gdy jest traktowany jako mierzalna powierzchnia do analizy. Zapisz jeden idealny przykład działania, jeden przypadek niepowodzenia oraz notatkę dotyczącą cofnięcia zmian, zanim rozszerzysz zakres prac. Utrzymuj konfigurację poza kodem aplikacji. Pliki środowiskowe, magazyny tajnych danych oraz flagi funkcjonalne powinny znajdować się w jednym miejscu, które operatorzy mogą sprawdzić bez konieczności przeglądania całej struktury.

Szczegół wzmocnienia 18/857: zmierz czas wykonywania, klasę błędu oraz zużycie tokenów dla tej notatki, a następnie zdecyduj, czy zachować zmianę na podstawie ustalonego zestawu pytań, a nie jedynie anegdoty.

W fazie notatki dotyczącej wzmocnienia 19 zdefiniuj dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed modyfikacją kodu. Operatorzy powinni móc ponownie uruchomić ten krok od znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Wolno preferować małe, testowalne jednostki zamiast rozbudowanych skryptów. Gdy krok zawiedzie, powód awarii powinien wskazywać na konkretną odpowiedzialność, a nie na skomplikowany proces.

Szczegół wzmocnienia 19/857: zmierz czas wykonywania, klasę błędu oraz zużycie tokenów dla tej notatki, a następnie zdecyduj, czy zachować zmianę na podstawie ustalonego zestawu pytań, a nie jedynie anegdoty.

Gdy przechodzisz przez etap 20 notatki dotyczącej wzmocnienia bezpieczeństwa, najpierw zapisz warunki kontraktu: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego awarii. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Obok wyników funkcjonalnych zapisz czas wykonywania oraz koszt tokena lub zapytania. Jasna widoczność kosztów zapobiega niespodziewanym rachunkom, gdy ścieżka przechodzi z środowiska demonstracyjnego do współdzielonych środowisk.

Szczegóły wzmocnienia bezpieczeństwa 20/857: zmierz czas wykonywania, klasę błędu oraz zużycie tokenów dla tej notatki, a następnie zdecyduj, czy zachować zmianę na podstawie ustalonego zestawu pytań, a nie jedynie osobistych obserwacji.

Etap 21 notatki dotyczącej wzmocnienia bezpieczeństwa działa najlepiej, gdy traktuje się go jako mierzalną powierzchnię do analizy. Zanim rozszerzysz zakres, zapisz jeden idealny przepływ działania, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia zmian. Zdokumentuj razem ścieżkę prawidłowego działania oraz ścieżkę naprawczą. Próby ponownych działań, kontrolne punkty ludzkie oraz obsługa wiadomości błędnych stanowią część produktu, a nie elementy dodawane później.

Szczegóły wzmocnienia 21/857: zmierz czas wykonywania, klasę błędu oraz zużycie tokenów dla tej notatki, a następnie zdecyduj, czy zachować zmianę na podstawie ustalonego zestawu pytań, a nie jedynie anegdoty.

W fazie notatki dotyczącej wzmocnienia 22 określ dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed modyfikacją kodu. Operatorzy powinni móc ponownie wykonać ten krok od znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Traktuj tę fazę jako umowę pomiędzy danymi wejściowymi a zweryfikowanymi wynikami. Nadaj nazwy artefaktom, zdefiniuj sprawdzenia sukcesu i odrzuć ciche, częściowe ukończenie zadania.

Szczegóły wzmocnienia 22/857: zmierz czas wykonywania, klasę błędu oraz zużycie tokenów dla tej notatki, a następnie zdecyduj, czy zachować zmianę na podstawie ustalonego zestawu pytań, a nie jedynie anegdoty.

Literatura pokrewna