SOF-STD-3

Configuration management
standards for
ING Observing Systems

Guy Rixon

Issue 4.1; 16th May 1996




Royal Greenwich Observatory,
Madingley Road,
Cambridge CB3 0EZ

Telephone (0223) 374000
Fax (0223) 374700
Internet gtr@mail.ast.cam.ac.uk

1 Introduction

1.1 Purpose of this document

Procedures are described for version control of source-files, programs, sub-systems and systems involved in ING observing systems. The principles described here have been evolved during production of the INT DAS and were later accepted by ING computing staff as the basis of an ING standard. All programmers intending to deliver code to ING should read this document.

This document supersedes document INT-PF-3.

1.2 Scope of the software

These procedures are intended to apply ING observing systems; that is to all software written specifically for ING in direct support of observing. Data-reduction packages such as IRAF are not controlled in this way and neither are infrastructure packages such as DRAMA.

The current scheme can only be applied to software that is stored in a Unix file-system. Hence, FORTH systems, VAX-ADAM systems and the TCS do not conform.

1.3 Glossary

An assembly is a piece of software produced by processing source components. See section 4.

A baseline is a more-general case of an assembly. (This is the industry-standard term.)

A bill of materials defines how an assembly is built out of components. That is, it is a script, in the BOM language, defining a baseline.

BOM is the special scripting-language used to define assemblies. See [1].

bom is the interpreter for bom.

A component is any part of a system stored in a repository; in the current scheme, that is anything stored in SCCS. See section 3.

A configuration item is a component or an assembly. (This is the industry-standard term.)

csh> is used in code examples to imply the shell prompt.

Observing system implies a basic unity of purpose: `all the software that you need to do observations'.

A repository is a place where components are stored under version control. In the current scheme it means an SCCS library.

SCCS is the Source Code Control System that is supplied free with Solaris and some other Unices. Try man sccs for details.

An SCCS library is a directory in the Unix file-system holding files specific to SCCS. Particular components are are said to be stored `in' a particular library and that library holds all the records needed for version control of its components.

An SCCS history-file is the vehicle of version control for one component.

A sub-system is a semi-autonomous set of software within the observing system.

A tag is a line of text in a component that labels it with its version. See section 3.3.1.

A tag-file is a source component, generated by bom, that labels an assembly with its version number.

1.4 References

[1] BOM: a configuration-control language
ING/RGO document SOF-BOM-1 by Guy Rixon.

2 Goals

Observing-systems for ING telescopes are noted for large-scale reuse of code (consider the D-tasks in the WHT ADAM-system), frequent, minor changes, and the critical interdependencies between sub-systems. These systems rapidly decay and fail if proper version-control is not applied.

Experience on the WHT tells us some attributes of a good version-control system:

z All versions of each basic component are retained in a library. On the WHT, this has been done through DEC's Code Management System (CMS). Each version of a component has a generation number and the generation/file-name pair uniquely identifies the state of a component at the time it was returned to the library.

z Where a program is built from a selection of components, the program itself has a version number (a `class' in CMS) which translates to a unique set of component versions.

z When a program is built for operational use, a specific version is built by an automatic system that supports the version-control standards.

z Any component fetched from the library for building includes its version number in the data. The CMS system does not provide this.

z A built program (object code) can be decomposed to recover the versions of its components. The CMS system doesn't provide this either.

z The version-control libraries are flexible and components can easily be moved between libraries.

z Safeguards are provided against simultaneous changes by two developers. Normally, only one person has write access to each component, but two components from the same library can be changed in parallel.

z Parallel libraries can be maintained at RGO and ING. (Duplicating the libraries is undesirable, but without superlative network performance between Cambridge and La Palma, it's essential.) The libraries can be regularly merged to provide the most recent generations of all files in each copy. This process is not compromised if changes are made to both libraries, provided that no one component is changed in both libraries.

z Once a version of the system is built, it is stored in such a way that a user can easily find the correct programs and there is no chance of executing the wrong version of a program. Ideally, all executable files for a system version are in the same directory.

z Running versions of the system can be patched for emergency maintenance and for testing. Patches never remove files from an operational system, but occlude certain programs and data-files with altered copies. It is easy for an engineer to add and remove patches. Any user can easily determine which patches are in use.

It has been agreed between RGO and ING that version and build control for the observing systems based on Unix machines will employ SCCS, make and the Bill-of-Materials system [1], for defining baselines. These techniques, with the procedures defined below, satisfy all the requirements in the list above. The procedures can be categorized as

z management of software components, or version control;

z management of programs and sub-systems, or build control;

z deployment of programs in systems, or installation control.

3 Version control

Any non-trivial software-systems is built from a number of source-code components. Configuration management requires that system versions be capable of analysis into versions of components and that all versions of the components remain available for inspection and re-use.

3.1 Definition of `component'

For the Unix-based observing systems, a component is a file in the Unix file-system. Files become system components if they are delivered with the system or generated during installation. For example, each file of source code is a component, and each object module; however, a list of user preferences generated during observations is not a component.

Each component has one version number. Where several subroutines or functions are contained in one file, they are one component and share the same version number.

3.2 Storage of components

Text and source-code components are stored in SCCS libraries, which are simply directories containing an SCCS history-file for each component. When a component is first entered, SCCS writes its text verbatim to the history file. When updates to the component are entered, SCCS records only the differences from the previous generation. Hence, a history file contains all generations of a component. History files are independent of each other and can be moved freely between libraries (but see the notes on `checked-out' files below).

Binary components, such as object code compiled from source components, are not normally stored in SCCS. It is assumed that any such file can either by recovered from source or is outside the version-control system. Where a component only exits in binary form, it can be stored by uuencoding the data.

The contents of history files should only be processed by SCCS or by trusted, SCCS-compatible software. Operating-system commands should only be used on history files if they preserve the contents of the file.

SCCS has an upper limit on line-length, usually 132 characters, which may vary between implementations. The last line of a component must end in the new-line character.

In its base state, a component only exists as its SCCS history-file. A component may extracted for reference or for system building; in this case, SCCS creates a read-only copy outside the library and makes no change to the history file. The component may also be `checked out' for changes in which case SCCS creates a writeable copy outside the library and a lock-file inside the library. A checked-out component cannot be retrieved for system building or checked out by a second programmer. Removing the lock file with rm, or moving the history file without the lock-file defeats the lock. Moving the history file and the lock file together preserves the lock.

The primary SCCS library is /ing/src/SCCS. All source-components for ING sub-systems are kept here. Test materials are stored separately in /ing/test/SCCS. and some general tools (those that fall outside the scope of the observing system) are kept in /ing/tools/SCCS.

Parallel copies of the libraries exist at RGO and ING. Sets of history files may be copied between the two sites by tar. When using tar it is necessary to check carefully that generations are not lost when a history file is over-written. A tool to check this is planned. History files should never be copied or updated while the elements concerned are checked out for editing from either library.

In each library there should exist a component called Inventory that lists and defines the other components.

3.3 Version numbers

SCCS assigns version numbers to components using the Dewy decimal system. Each version number (the SCCS manual calls them SIDs) has at least a major part and a minor part separated by a decimal point. The manual pages for SCCS call the major part the `release' and the minor part the `level'. By default, the first generation of a component is numbered 1.1 and SCCS adds one to the level for each new generation entered. When creating a new generation, you can choose to increase the release number, but cannot control

the level number; SCCS will not allow a level of zero in any release.

Occasionally, branches in the line of descent are created by entering changes to a generation that is not the most recent. In this case, generations in the branch have version-numbers with four numeric parts separated by decimal points. Because of this, version numbers must be processed as strings in the most general case and cannot be handled as real numbers.

3.3.1 Version-number tags

When a component is retrieved for a build, the developer chooses which generation to retrieve. SCCS provides a way of marking the component's text with the chosen generation such that generations cannot be confused. A `tag'

containing `ID keywords' can be embedded in the text which SCCS expands to include current information. The value of the tag can be retrieved from the component by the SCCS command what, which searches for the escape sequence @(#) and then reports all following characters up to end-of-line.

The standard is to use the keywords %M% (module name) and %I% (version number), %P% (history-file), %E% (date of last modification) and %U% (time of last modification) on one line in a specific syntax:

@(#) Component %M% %I% %P% %E% %U%
Tags of this form

are recognized by the bom utility described in section 4.4 [1]. A tag is said to be `unexpanded' when it has the literal form above and `expanded' if the values of the keywords have been filled in.

For a data-file, the tag can go in any line. For a C source-file, the tag should be put in the initializer of a static array of characters:

static const char comp_c_v[] = "@(#) Component %M% %I% %P% %E% %U%";
When the tag is included thus, it is copied to the object file during compilation and what can then analyze a linked program into its components. This ability is vital to the system. The convention is to name the variable after the component with the dot before the file-name extension commuted to an underscore: in the example above, the variable name can be read as `the version-number for the component comp.c. The minimum requirement is that all tags, including those in include files, be unique in a given compilation. Hence, calling all the tags version will fail as soon as a file is included.

For documents, the issue number should be made the same as the SCCS version number wherever possible (hence, most documents start at issue 1.1). Since all well-written documents include the issue number in the visible text, the automatic tagging may be omitted.

In interpreted languages such as PERL, the tag can either be assigned to a variable or can be included in a comment.

3.4 Version control procedures

3.4.1 Accessing the right library

Before using SCCS commands, check that you will operate on the correct library and that you are working from a suitable directory. If a component does get into the wrong library you can move it later, but if you apply changes to the wrong component you may lose information.

Either set the environment variable PROJECTDIR to be the path-name of the library or unset PROJECTDIR and cd to the parent directory of the library. In general, you need write access to the SCCS library, to the history files for the components you are working with and to the directory in which you are working.

It is best not to cd into the SCCS library itself.

3.4.2 Creating a new component

When the text of a component has been typed in and checked, ensure that there are no lines longer than SCCS' upper limit and that the last line ends with a new-line character. If the component is a document, check that it displays issue number 1.1.

Add the version-control tag. Consider whether the component might be exempt from tagging (e.g., it is a document).

Move or copy the candidate component

to the current working directory; note that this file will be destroyed in the process of creating the component, but that you can later recover the data from the library. Use the SCCS command enter to create the history file:

csh> sccs enter component
where component is the path-name of the file containing the new component. SCCS will create, in the library, the history file s.component and will rename the file from which it read the component's text to ,component. The latter file can be deleted if the SCCS command completed without errors.

The component is now recorded at version 1.1.

Instead of sccs enter you can use sccs create. The two commands are the same except that sccs create automatically retrieves a read-only copy of version 1.1.

3.4.3 Retrieving (`checking out') a component for editing

Consider the name of the component: any file with the same name in the current working directory will be over-written when your retrieve the new copy. Consider also that retrieving the component locks it until you check in your changes. (If necessary, you can later abandon your changes and remove the lock.)

Use the command sccs edit to retrieve the component:

csh> sccs edit [-rrelease] component
If you intend to create a new minor version - e.g. to upgrade from v2.1 to v2.2 - omit the -r version switch. SCCS will assign the new version-number automatically. Use the -r switch if you intend to create a new major version. For example, to go from v2.2 to v3.1, give the command

csh> sccs edit -r3 component
The minor part of the version-number is not given in the command: SCCS sets this to one automatically. No space should be typed between -r and the number as SCCS does not accept that syntax. Users of CMS should note that SCCS assigns the new version when the component is checked out, not when it is checked back in.

SCCS creates component in the current working directory and allows you write access to it. The component in the library is now locked. If the component is tagged, its ID keywords are not expanded.

You cannot change the version of the edited component while it is checked out, but you can check it in without changes (c.f. CMS unreserve) and then check it out again as a different release. See `unlocking a checked-out component', below.

3.4.4 Retrieving a component for building

Consider the name of the component: any file with the same name in the current working directory will be over-written when your retrieve the new copy.

Use the SCCS command get to retrieve the component:

csh> sccs get component
SCCS creates component in the current working directory and denies you write access to it (you can use chmod to get write access later if necessary). The component in the library is not locked. If the component is tagged, its ID keywords are expanded.

Most builds are done under the control of the bom utility as described below. In this case there is no need to retrieve the components manually.

3.4.5 Recording (`checking in') a new version of a component

Check the line-length of the component and that the last line ends with the new-line character. Pause and consider whether it's really time to record a new version. Note that SCCS will delete the external copy of the component that you are entering and that you need write access to this file.

Use the command sccs delta to enter the new version in the library:

csh> sccs delta component
SCCS deletes the external copy of the new version and unlocks the history file. You cannot use sccs delta on a component that has not been checked out for editing.

3.4.6 Unlocking a checked-out component

If you have a component checked out, and hence locked, you can release the lock with the command sccs unedit:

csh> sccs unedit component
This operation deletes any unprotected copy of the component in the current directory, and replaces it with the highest-numbered version in the SCCS history-file. The lock is removed from the history file and the version-number allocated at check-out is forgotten; you can re-use this number when you next check out the component.

3.4.7 Installing components and synchronizing libraries

Components should never be edited at ING and RGO at the same time as merging the changes is difficult and unsafe. With current working practices, parallel changes are not likely.

Libraries should be brought into line by exchanging individual components. It is usually not possible to export an entire library between sites as some components are typically maintained at each site: neither library contains the most recent versions of all the components.

The components to be exchanged can be determined by comparing listings of the two libraries. The command

csh> ls -1 /ing/src/SCCS | sccs prt -y > src_sccs.lisp
produces a listing of the most recent version of each component in the order in which the history files appear in an ls listing. Comparing the listings for the two sites (sdiff -s is recommended) indicates which components should be transferred and in which direction. Note that the simpler command

csh> sccs prt -y /ing/src/SCCS
which also lists the version of all components in the library, is not equivalent to the piped command above. The unpiped command lists the components in the order in which they were entered into the library which may not be the same at both sites

Components to be exchanged should be checked in at both sites.

To transfer components, make a tar file of the history files and copy it to the other site. The file-names in the tar file should be relative paths. That is

csh> cd /ing/src
csh> tar cvf ing.tar SCCS/s.component.c
is good but

csh> cd tar cvf ing.tar /ing/src/SCCS/s.component.c
will cause problems.

To install the transferred files, unpack the tar file into the target library e.g.

csh> cd /ing/src
csh> tar xvf ing.tar
to unpack the tar file from the example above. (You must cd to a directory equivalent to that in which the tar file was made so that the relative file-names are appropriate.) Be careful: this process will destroy utterly any existing history files for the transferred components in the target library and any versions in the target library but not in the tar file will be lost forever. If you are not absolutely sure that the version in the tar file include and supersede those in the target library

, do not alter the target library. Instead, unpack the tar file into some other directory and check the versions first. You can move history files individually into the library using mv.

4 Build control

Sub-systems within the observing system need configuration management to the same degree as software components. At this level, versions and revisions start to become visible to managers and end-users.

The ING standard for build control extends the version numbering scheme for components to `assemblies' (as defined below) by means of the Bill-Of-Materials Language (BOM).

4.1 Definition of `assembly'

An `assembly' is a special case of a configuration-management baseline. It may be any group of inter-related components, or something made from those components. Examples are:

z A compiled and linked program.

z An object-code library.

z A shell-script.

z A configuration file written at compile-time or time of coding.

z A package of related scripts or programs within a sub-system.

z A separately-released sub-system.

z A complete observing system.

The version-number of an assembly defines uniquely the set of components from which the assembly is derived and also the manner in which the assembly is built

. The definition is encoded in the assembly's bill of materials.

4.2 Definition of `bill of materials'

A bill of materials is an executable script in the BOM language, as described in [1]. Bills are readable by engineers (the language is interpreted and the bills are text files), and can be used as instructions for manual building of a sub-system. Normally, however, a bill is executed by the utility bom to build an assembly from source components. The execution involves fetching components from SCCS, executing the makefile and applying version-numbering to the assembly.

Execution of bills is hierarchical: a statement in one bill can invoke the processing of subordinate bills for lower-level assemblies. In this way, an observing-system may be defined in terms of versions of sub-systems and the sub-systems may be progressively decomposed into lower-level assemblies and finally into source components: the version-number of the system defines uniquely the building of the entire system.

Each bill is a version-controlled component. The version-number of an assembly is the version-number of the bill that defines it

A bill may define more than one assembly

. In this case, each assembly has the same version-number.

The file-name of the bill is generally the name of the assembly with the suffix .bom. For example, the executable program obslog would be specified by the bill obslog.bom, while the bill for the object library fits.a would be fits.a.bom.

4.3 Creating a bill of materials

A bill should always contain the following statements:

z A brief comment giving the purpose of the bill plus any preconditions for executing the bill. Here is an example:

# Bill of materials to build autolog at 
v%I%.


# Set ${ING} to the root of the source tree before building.
z A component-version tag. (Bills are components and should be marked up as such.) For example:

# @(#) Component %M% %I% %P% %E% %U%
z One Component statement for each source component. This section must include such things as makefiles and any subordinate bills that are to be executed. The component statements are usually grouped together at the start of the bill and hence are executed before any makefiles. The component statements should each specify a repository by a relative path, as discussed in [1]. For example:

Component autolog.c   2.6   sccs   ${ING}/src
Component autolog.dat 1.1   sccs   ${ING}/src
Component autolog.mk  4.18  sccs   ${ING}/src
z Assembly statements for any pre-existing assemblies referenced in the build: these provide checks on cross-compatibility between assemblies. For example:

Assembly  loglib     42.8   ${OBSSYS}/lib/loglib.a
z Tag statements providing version numbers for use in the build by make. The following line generates a source-file autolog.TAG.c to be compiled and linked by autolog.mk:

Tag       autolog     %I%   C      autolog.TAG.c
z Makefile statements for each assembly built by the bill stating the name of the makefile and the make target. For example:

Makefile  autolog.mk  autolog
Most source-components come from the library /ing/src/SCCS. The parent directory of this library, src, is sufficiently standard that it can be hard-coded into the bills. The mount-point of the source-tree, /ing, is considered less stable and is normally referred to through the environment variable ING. This allows a dubious release of a sub-system to be installed and built in a separate library before being merged into the main library.

It is trivial to write a bill of materials with a text editor if you already have a listing of the version of each component. An easy way to generate such a listing is to run the SCCS program what on a previously-built copy of each assembly and to concatenate the results.

The SCCS program what extracts version tags from any file (binary or text) and writes then to standard output. When used on an assembly built from tagged components, what writes out a list of component versions required to recreate the assembly. Typically, the version of the makefile, and possibly a few other components, must be added in a separate run of what. For example:

csh> what autolog     | grep Component >  autolog.bom
csh> what autolog.dat | grep Component >> autolog.bom
csh> what autolog.mk  | grep Component >> autolog.bom
records the component versions of the (executable) program autolog in the file autolog.bom and then appends the versions of the supporting file autolog.dat and the makefile autolog.mk. Grepping for Component eliminates reports of system-supplied include-files (try what without grep to see what this means). The bill created by what does not have the correct BOM syntax: it must be edited to correct the repository locations.

For the bill to be complete and valid, all components referenced must be checked in to the SCCS library. If what is run on an assembly that includes uncontrolled components, these will not appear in the bill. Any components that were built into the assembly while checked out will appear with their ID keywords unexpanded, e.g.

Component %M% %I% %P% %E% %U%
A check using grep %I% is recommended.

4.4 Building sub-systems with the bom utility

Normally, a system will be rebuilt by sub-systems. For example, the das sub-system (meaning the set of programs and utilities concerned specifically with the Data-Cell interface) is defined by das.bom which is itself defined in terms of dasn.bom, dasm.bom and das_clients.bom. Building this sub-system generates five executable programs from the three lower-level bills.

The recommended procedure is as follows.

1. Create a clean directory for the build (or clean out an old directory). This directory should not be in the release tree.

2. Set the environment variable OBSSYS to define the version of the observing system (see section 5). Unset OBSSYSPATH.

3. Set ING to define the root of the source tree.

4. Unset PROJECTDIR. This prevents make from fetching files from SCCS and reduces the chance of building in a rogue component.

5. Fetch from SCCS the bill of materials, e.g.

csh> sccs -d /ing/src get -r2.4 autolog.bom
6. Execute the bill and log the results:

csh> bom autolog.bom >& autolog.bom.results
7. Check the results. If satisfied, install the results in the release tree of the observing system as described in section 5.

8. Wipe the build directory, but keep the log of results for quality assurance.

4.5 Building systems

The master bill of materials for the observing system is obssys.bom. In principle, executing this bill will build and install the entire system. In practice, some sub-systems require others to be pre-installed before their makefiles can operate (e.g. das requires libcia to be installed) and the bom utility cannot currently achieve this. Currently, executing obssys.bom fetches bills for versions of sub-systems to be built manually. This situation will be improved in due course.

4.6 Standard targets for makefiles

The principal make-targets that build the assemblies are stated in their respective bills and so need not have standard names. It is conventional to provide the standard targets install to move assemblies into the release tree, deinstall to strip assemblies out of the release tree and clean to wipe the build directory.

5 Installation in an observing system

5.1 Assigning the version number

The version number of the entire system is important; it is the only version number that the end-user is likely to know about and so tends to feature in feed-back and bug reports. It helps if the system's version corresponds to meaningful changes in behaviour. In particular, it sours relations between users and support staff if `system a.b' changes behaviour because of an undisclosed change in some assembly. Hence, any planned change to the system should increment at least the minor part of the version number.

As discussed in the previous section, the system is the highest-level assembly in a hierarchy of assemblies, and its version number is the version number of its bill of materials. Typically, the major part of the system version tracks changes in specification (e.g. the addition of new functions), while the minor part tracks bug-fixes, or changes that are not apparent to the end user.

5.2 The release tree

Each version of the system is installed independently and depends from a particular directory. For example, the first system, version s1.1, depends from /ing/s1.1. It is anticipated that all systems will be installed in the /ing tree but this need not be the case; in general, software should not rely on this installation.

Below the system's directory, e.g. s1.1, are directories bin (for executable programs and scripts), lib (for object libraries and loadable Tcl modules), inc (for include files), and etc (for data-files needed at run-time). This arrangement is standard and applications (and their makefiles) can rely on it.

The release tree also contains directory structures for patches, as defined below. Patch directories have the standard naming pn, where n is the number of the patch. They contain the same sub-directories as systems.

The tree looks like this:

As well as the system and patch directories, /ing also contains the src directory where the components live and a tools branch containing tools needed at build-time but not at run-time. (For example, /ing/tool/bin is where bom lives.) /ing/bin and /ing/etc contain files needed at run-time that are not part of any observing system.

5.3 Environment variables

The environment variables OBSSYS and/or OBSSYSPATH must be set when running an observing system: they allow programs within the system to traverse the system tree without being aware of which system they are in or where that system tree is mounted.

OBSSYS should always be set to indicate the root of the system tree, e.g.

csh> setenv OBSSYS /ing/s1.1
This setting applies both at compile-time and at run-time. OBSSYSPATH, if set, over-rides OBSSYS with a path of patch trees and system trees, e.g.

csh> setenv OBSSYSPATH /ing/p6:/ing/p2:/ing/s1.1
The last directory in OBSSYSPATH must always be a full system. OBSSYSPATH should not be set at compile-time. It is only needed at run-time if a system is being run with patches; otherwise, OBSSYS is sufficient. If both are set, OBSSYS should name the last directory in OBSSYSPATH.

There are standard components available to programs in the observing system that search for a file along OBSSYSPATH or in OBSSYS if OBSSYSPATH is not set. A program might ask for the location of "etc/prog.settings" and be given "/ing/p2/etc/prog.settings" or "/ing/s1.1/etc/prog.settings" according to the values of the environment variables.

When setting OBSSYS and OBSSYSPATH, PATH should also be set to include the bin sub-directory of the base system and every patch in the list.

The script obssys is routinely used by observers to select a system and a set of patches. It is kept in /ing/bin (i.e. outside any observing system) and needs to be source'd by the user. The version of the base system is hard-coded into obssys and any arguments supplied are taken as the numbers of patches. Obssys always sets OBSSYS and PATH and sets OBSSYSPATH if any patches were requested. The entries in PATH for the system and patches are put at the front.

The environment variable ING is not used at run-time.

5.4 Patches

In a system with more than a few major assemblies, defining and building a system version may be a lot of work. Certainly, one does not want to define and install a complete system just to try out a new feature in engineering time. Some mechanism is needed whereby certain parts of the system can be temporarily patched.

A patch is a partial observing system and is assumed to replace and occlude certain files in a base system. Typically, new versions are supplied for a handful of programs or data-files. Since each patch lives in its own tree, as described above, creating a patch does not permanently alter the observing system to which it applies. Patching at run-time is explicit: the user must request patches by number.

Each patch is identified by a single number. It is convenient, for purposes of recording, to count from one and never to re-use patch numbers. In any case, it is impossible to have two patches with the same number in the release tree at once.

Patches are mainly intended as a suitable environment for trying out new versions of sub-systems. They may also be used as quick fixes: it is reasonable to say to an observer `You are still using system s2.3 but you'll need to load patch number 42 to fix the bug we saw last night'. It is less reasonable to run the same set of patches night after night; patches that are fixes should be consolidated in a new version of the system as soon as they have been tested. Requiring the observer to load dozens of patches (all in the right order of precedence) and then varying the set each night is evil. Varying the contents of a patch without telling the observer is doubly evil.

Appendix A. Document History

Issue 1.1 01/12/94 Original issue as INT-PF-3, produced for review by DRM. Nothing in this issue was actually implemented.

Issue 2.1 06/01/95 Revised and expanded: new format for bills of materials; new implementation for bom. The section on system structure and building made more definite. Appendices B and C added.

Issue 3.1 11/01/95 The Bill entry introduced; description of system building changed. Better examples in appendix C.

Issue 4.1 16/05/96 Rewritten as a general standard (previous issues addressed only the INT WFC project). Glossary added; section on patches made formal; section on build control extended, but details of BOM and bom devolved to [1]. Appendices C and D deleted. Document reclassified SOF-STD-3.